mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
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>
This commit is contained in:
parent
885767ca4c
commit
ba84525bd9
1 changed files with 19 additions and 10 deletions
|
@ -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 @@ static int sa1100_irda_start(struct net_device *dev)
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue