diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-08 15:38:15 +0000 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-02-09 15:37:53 +0000 | 
| commit | ba84525bd9015e7dd20f7c97a2a96b0a238b0223 (patch) | |
| tree | 1d1ff025ff9793cee4ae7e8bebec0837cff274fc /drivers/net/irda | |
| parent | 885767ca4ce0800c5d02eb66cc10a0494b7bf312 (diff) | |
NET: sa11x0-ir: fix leak of tx skb
Ensure that we unmap and free a pending transmit skb when the interface
is stopped.  We rearrange the code a little bit to give all places a
similar layout when freeing the skb in both the completion and interface
stop paths - this gives some consistency to the code.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/net/irda')
| -rw-r--r-- | drivers/net/irda/sa1100_ir.c | 29 | 
1 files changed, 19 insertions, 10 deletions
| diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index adb7fea78c2d..9dc564830c9d 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -602,9 +602,7 @@ static void sa1100_irda_txdma_irq(void *id)  {  	struct net_device *dev = id;  	struct sa1100_irda *si = netdev_priv(dev); -	struct sk_buff *skb = si->dma_tx.skb; - -	si->dma_tx.skb = NULL; +	struct sk_buff *skb;  	/*  	 * Wait for the transmission to complete.  Unfortunately, @@ -636,14 +634,15 @@ static void sa1100_irda_txdma_irq(void *id)  	 */  	sa1100_irda_rx_dma_start(si); -	/* -	 * Account and free the packet. -	 */ +	/* Account and free the packet. */ +	skb = si->dma_tx.skb;  	if (skb) { -		dma_unmap_single(si->dev, si->dma_tx.dma, skb->len, DMA_TO_DEVICE); +		dma_unmap_single(si->dev, si->dma_tx.dma, skb->len, +				 DMA_TO_DEVICE);  		dev->stats.tx_packets ++;  		dev->stats.tx_bytes += skb->len;  		dev_kfree_skb_irq(skb); +		si->dma_tx.skb = NULL;  	}  	/* @@ -841,21 +840,31 @@ err_irq:  static int sa1100_irda_stop(struct net_device *dev)  {  	struct sa1100_irda *si = netdev_priv(dev); +	struct sk_buff *skb;  	disable_irq(dev->irq);  	sa1100_irda_shutdown(si);  	/* -	 * If we have been doing DMA receive, make sure we +	 * If we have been doing any DMA activity, make sure we  	 * tidy that up cleanly.  	 */ -	if (si->dma_rx.skb) { +	skb = si->dma_rx.skb; +	if (skb) {  		dma_unmap_single(si->dev, si->dma_rx.dma, HPSIR_MAX_RXLEN,  				 DMA_FROM_DEVICE); -		dev_kfree_skb(si->dma_rx.skb); +		dev_kfree_skb(skb);  		si->dma_rx.skb = NULL;  	} +	skb = si->dma_tx.skb; +	if (skb) { +		dma_unmap_single(si->dev, si->dma_tx.dma, skb->len, +				 DMA_TO_DEVICE); +		dev_kfree_skb(skb); +		si->dma_tx.skb = NULL; +	} +  	/* Stop IrLAP */  	if (si->irlap) {  		irlap_close(si->irlap); | 
