drivers/net: use tasklet_kill in device remove/close process
Some driver uses tasklet_disable in device remove/close process, tasklet_disable will inc tasklet->count and return. If the tasklet is not handled yet because some softirq pressure, the tasklet will placed on the tasklet_vec, never have a chance to excute. This might lead to ksoftirqd heavy loaded, wakeup with pending_softirq, but tasklet is disabled. tasklet_kill should be used in this case. Signed-off-by: Xiaotian Feng <dannyfeng@tencent.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								d145f7ec23
							
						
					
				
			
			
				commit
				
					
						175c0dffef
					
				
			
		
					 5 changed files with 9 additions and 9 deletions
				
			
		|  | @ -1948,10 +1948,10 @@ jme_close(struct net_device *netdev) | ||||||
| 
 | 
 | ||||||
| 	JME_NAPI_DISABLE(jme); | 	JME_NAPI_DISABLE(jme); | ||||||
| 
 | 
 | ||||||
| 	tasklet_disable(&jme->linkch_task); | 	tasklet_kill(&jme->linkch_task); | ||||||
| 	tasklet_disable(&jme->txclean_task); | 	tasklet_kill(&jme->txclean_task); | ||||||
| 	tasklet_disable(&jme->rxclean_task); | 	tasklet_kill(&jme->rxclean_task); | ||||||
| 	tasklet_disable(&jme->rxempty_task); | 	tasklet_kill(&jme->rxempty_task); | ||||||
| 
 | 
 | ||||||
| 	jme_disable_rx_engine(jme); | 	jme_disable_rx_engine(jme); | ||||||
| 	jme_disable_tx_engine(jme); | 	jme_disable_tx_engine(jme); | ||||||
|  |  | ||||||
|  | @ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) | ||||||
| 	dev0 = hw->dev[0]; | 	dev0 = hw->dev[0]; | ||||||
| 	unregister_netdev(dev0); | 	unregister_netdev(dev0); | ||||||
| 
 | 
 | ||||||
| 	tasklet_disable(&hw->phy_task); | 	tasklet_kill(&hw->phy_task); | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irq(&hw->hw_lock); | 	spin_lock_irq(&hw->hw_lock); | ||||||
| 	hw->intr_mask = 0; | 	hw->intr_mask = 0; | ||||||
|  |  | ||||||
|  | @ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev) | ||||||
| 		/* Delay for receive task to stop scheduling itself. */ | 		/* Delay for receive task to stop scheduling itself. */ | ||||||
| 		msleep(2000 / HZ); | 		msleep(2000 / HZ); | ||||||
| 
 | 
 | ||||||
| 		tasklet_disable(&hw_priv->rx_tasklet); | 		tasklet_kill(&hw_priv->rx_tasklet); | ||||||
| 		tasklet_disable(&hw_priv->tx_tasklet); | 		tasklet_kill(&hw_priv->tx_tasklet); | ||||||
| 		free_irq(dev->irq, hw_priv->dev); | 		free_irq(dev->irq, hw_priv->dev); | ||||||
| 
 | 
 | ||||||
| 		transmit_cleanup(hw_priv, 0); | 		transmit_cleanup(hw_priv, 0); | ||||||
|  |  | ||||||
|  | @ -990,7 +990,7 @@ static int axienet_stop(struct net_device *ndev) | ||||||
| 	axienet_setoptions(ndev, lp->options & | 	axienet_setoptions(ndev, lp->options & | ||||||
| 			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); | 			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); | ||||||
| 
 | 
 | ||||||
| 	tasklet_disable(&lp->dma_err_tasklet); | 	tasklet_kill(&lp->dma_err_tasklet); | ||||||
| 
 | 
 | ||||||
| 	free_irq(lp->tx_irq, ndev); | 	free_irq(lp->tx_irq, ndev); | ||||||
| 	free_irq(lp->rx_irq, ndev); | 	free_irq(lp->rx_irq, ndev); | ||||||
|  |  | ||||||
|  | @ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue) | ||||||
| { | { | ||||||
| 	struct b43legacy_pio_txpacket *packet, *tmp_packet; | 	struct b43legacy_pio_txpacket *packet, *tmp_packet; | ||||||
| 
 | 
 | ||||||
| 	tasklet_disable(&queue->txtask); | 	tasklet_kill(&queue->txtask); | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) | 	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) | ||||||
| 		free_txpacket(packet, 0); | 		free_txpacket(packet, 0); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Xiaotian Feng
				Xiaotian Feng