Commit ba84525b authored by Russell King's avatar Russell King

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 885767ca
...@@ -602,9 +602,7 @@ static void sa1100_irda_txdma_irq(void *id) ...@@ -602,9 +602,7 @@ static void sa1100_irda_txdma_irq(void *id)
{ {
struct net_device *dev = id; struct net_device *dev = id;
struct sa1100_irda *si = netdev_priv(dev); struct sa1100_irda *si = netdev_priv(dev);
struct sk_buff *skb = si->dma_tx.skb; struct sk_buff *skb;
si->dma_tx.skb = NULL;
/* /*
* Wait for the transmission to complete. Unfortunately, * Wait for the transmission to complete. Unfortunately,
...@@ -636,14 +634,15 @@ static void sa1100_irda_txdma_irq(void *id) ...@@ -636,14 +634,15 @@ static void sa1100_irda_txdma_irq(void *id)
*/ */
sa1100_irda_rx_dma_start(si); sa1100_irda_rx_dma_start(si);
/* /* Account and free the packet. */
* Account and free the packet. skb = si->dma_tx.skb;
*/
if (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_packets ++;
dev->stats.tx_bytes += skb->len; dev->stats.tx_bytes += skb->len;
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
si->dma_tx.skb = NULL;
} }
/* /*
...@@ -841,21 +840,31 @@ static int sa1100_irda_start(struct net_device *dev) ...@@ -841,21 +840,31 @@ static int sa1100_irda_start(struct net_device *dev)
static int sa1100_irda_stop(struct net_device *dev) static int sa1100_irda_stop(struct net_device *dev)
{ {
struct sa1100_irda *si = netdev_priv(dev); struct sa1100_irda *si = netdev_priv(dev);
struct sk_buff *skb;
disable_irq(dev->irq); disable_irq(dev->irq);
sa1100_irda_shutdown(si); 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. * 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_unmap_single(si->dev, si->dma_rx.dma, HPSIR_MAX_RXLEN,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
dev_kfree_skb(si->dma_rx.skb); dev_kfree_skb(skb);
si->dma_rx.skb = NULL; 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 */ /* Stop IrLAP */
if (si->irlap) { if (si->irlap) {
irlap_close(si->irlap); irlap_close(si->irlap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment