bna: SKB PCI UNMAP Fix
Change details: - Found a leak in sk_buff unmapping of PCI dma addresses where boundary conditions are not properly handled in freeing all Tx buffers. Freeing of all Tx buffers is done considering sk_buffs data and fragments can be mapped at the boundary. Signed-off-by: Gurunatha Karaje <gkaraje@brocade.com> Signed-off-by: Rasesh Mody <rmody@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
41eb5ba42d
commit
938fa48843
1 changed files with 8 additions and 27 deletions
|
@ -137,39 +137,20 @@ bnad_free_all_txbufs(struct bnad *bnad,
|
||||||
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
|
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
|
||||||
struct bnad_skb_unmap *unmap_array;
|
struct bnad_skb_unmap *unmap_array;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
int i;
|
int q;
|
||||||
|
|
||||||
unmap_array = unmap_q->unmap_array;
|
unmap_array = unmap_q->unmap_array;
|
||||||
|
|
||||||
unmap_cons = 0;
|
for (q = 0; q < unmap_q->q_depth; q++) {
|
||||||
while (unmap_cons < unmap_q->q_depth) {
|
skb = unmap_array[q].skb;
|
||||||
skb = unmap_array[unmap_cons].skb;
|
if (!skb)
|
||||||
if (!skb) {
|
|
||||||
unmap_cons++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
unmap_array[unmap_cons].skb = NULL;
|
|
||||||
|
|
||||||
dma_unmap_single(&bnad->pcidev->dev,
|
unmap_cons = q;
|
||||||
dma_unmap_addr(&unmap_array[unmap_cons],
|
unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array,
|
||||||
dma_addr), skb_headlen(skb),
|
unmap_cons, unmap_q->q_depth, skb,
|
||||||
DMA_TO_DEVICE);
|
skb_shinfo(skb)->nr_frags);
|
||||||
|
|
||||||
dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
|
|
||||||
if (++unmap_cons >= unmap_q->q_depth)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
|
||||||
dma_unmap_page(&bnad->pcidev->dev,
|
|
||||||
dma_unmap_addr(&unmap_array[unmap_cons],
|
|
||||||
dma_addr),
|
|
||||||
skb_shinfo(skb)->frags[i].size,
|
|
||||||
DMA_TO_DEVICE);
|
|
||||||
dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
|
|
||||||
0);
|
|
||||||
if (++unmap_cons >= unmap_q->q_depth)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue