aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-01-08 10:38:15 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-02-09 10:37:53 -0500
commitba84525bd9015e7dd20f7c97a2a96b0a238b0223 (patch)
tree1d1ff025ff9793cee4ae7e8bebec0837cff274fc /drivers/net
parent885767ca4ce0800c5d02eb66cc10a0494b7bf312 (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')
-rw-r--r--drivers/net/irda/sa1100_ir.c29
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)
602{ 602{
603 struct net_device *dev = id; 603 struct net_device *dev = id;
604 struct sa1100_irda *si = netdev_priv(dev); 604 struct sa1100_irda *si = netdev_priv(dev);
605 struct sk_buff *skb = si->dma_tx.skb; 605 struct sk_buff *skb;
606
607 si->dma_tx.skb = NULL;
608 606
609 /* 607 /*
610 * Wait for the transmission to complete. Unfortunately, 608 * Wait for the transmission to complete. Unfortunately,
@@ -636,14 +634,15 @@ static void sa1100_irda_txdma_irq(void *id)
636 */ 634 */
637 sa1100_irda_rx_dma_start(si); 635 sa1100_irda_rx_dma_start(si);
638 636
639 /* 637 /* Account and free the packet. */
640 * Account and free the packet. 638 skb = si->dma_tx.skb;
641 */
642 if (skb) { 639 if (skb) {
643 dma_unmap_single(si->dev, si->dma_tx.dma, skb->len, DMA_TO_DEVICE); 640 dma_unmap_single(si->dev, si->dma_tx.dma, skb->len,
641 DMA_TO_DEVICE);
644 dev->stats.tx_packets ++; 642 dev->stats.tx_packets ++;
645 dev->stats.tx_bytes += skb->len; 643 dev->stats.tx_bytes += skb->len;
646 dev_kfree_skb_irq(skb); 644 dev_kfree_skb_irq(skb);
645 si->dma_tx.skb = NULL;
647 } 646 }
648 647
649 /* 648 /*
@@ -841,21 +840,31 @@ err_irq:
841static int sa1100_irda_stop(struct net_device *dev) 840static int sa1100_irda_stop(struct net_device *dev)
842{ 841{
843 struct sa1100_irda *si = netdev_priv(dev); 842 struct sa1100_irda *si = netdev_priv(dev);
843 struct sk_buff *skb;
844 844
845 disable_irq(dev->irq); 845 disable_irq(dev->irq);
846 sa1100_irda_shutdown(si); 846 sa1100_irda_shutdown(si);
847 847
848 /* 848 /*
849 * If we have been doing DMA receive, make sure we 849 * If we have been doing any DMA activity, make sure we
850 * tidy that up cleanly. 850 * tidy that up cleanly.
851 */ 851 */
852 if (si->dma_rx.skb) { 852 skb = si->dma_rx.skb;
853 if (skb) {
853 dma_unmap_single(si->dev, si->dma_rx.dma, HPSIR_MAX_RXLEN, 854 dma_unmap_single(si->dev, si->dma_rx.dma, HPSIR_MAX_RXLEN,
854 DMA_FROM_DEVICE); 855 DMA_FROM_DEVICE);
855 dev_kfree_skb(si->dma_rx.skb); 856 dev_kfree_skb(skb);
856 si->dma_rx.skb = NULL; 857 si->dma_rx.skb = NULL;
857 } 858 }
858 859
860 skb = si->dma_tx.skb;
861 if (skb) {
862 dma_unmap_single(si->dev, si->dma_tx.dma, skb->len,
863 DMA_TO_DEVICE);
864 dev_kfree_skb(skb);
865 si->dma_tx.skb = NULL;
866 }
867
859 /* Stop IrLAP */ 868 /* Stop IrLAP */
860 if (si->irlap) { 869 if (si->irlap) {
861 irlap_close(si->irlap); 870 irlap_close(si->irlap);