diff options
author | stephen hemminger <shemminger@vyatta.com> | 2010-02-01 08:41:47 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-03 21:34:28 -0500 |
commit | f6815077e75c5b7f55b56fc3788e328514d4e72a (patch) | |
tree | a6356dca15692bc527848815a4fea71781d7f5ce /drivers/net/sky2.c | |
parent | 974c37e9d88c3e5a3e56eb98cb9c84232eb2bdcb (diff) |
sky2: fix transmit DMA map leakage
The book keeping structure for transmit always had the flags value
cleared so transmit DMA maps were never released correctly.
Based on patch by Jarek Poplawski, problem observed by Michael Breuer.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 8 |
1 files changed, 3 insertions, 5 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index d760650c5c04..67249c3c9f50 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1025,11 +1025,8 @@ static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr, | |||
1025 | static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot) | 1025 | static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot) |
1026 | { | 1026 | { |
1027 | struct sky2_tx_le *le = sky2->tx_le + *slot; | 1027 | struct sky2_tx_le *le = sky2->tx_le + *slot; |
1028 | struct tx_ring_info *re = sky2->tx_ring + *slot; | ||
1029 | 1028 | ||
1030 | *slot = RING_NEXT(*slot, sky2->tx_ring_size); | 1029 | *slot = RING_NEXT(*slot, sky2->tx_ring_size); |
1031 | re->flags = 0; | ||
1032 | re->skb = NULL; | ||
1033 | le->ctrl = 0; | 1030 | le->ctrl = 0; |
1034 | return le; | 1031 | return le; |
1035 | } | 1032 | } |
@@ -1622,8 +1619,7 @@ static unsigned tx_le_req(const struct sk_buff *skb) | |||
1622 | return count; | 1619 | return count; |
1623 | } | 1620 | } |
1624 | 1621 | ||
1625 | static void sky2_tx_unmap(struct pci_dev *pdev, | 1622 | static void sky2_tx_unmap(struct pci_dev *pdev, struct tx_ring_info *re) |
1626 | const struct tx_ring_info *re) | ||
1627 | { | 1623 | { |
1628 | if (re->flags & TX_MAP_SINGLE) | 1624 | if (re->flags & TX_MAP_SINGLE) |
1629 | pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr), | 1625 | pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr), |
@@ -1633,6 +1629,7 @@ static void sky2_tx_unmap(struct pci_dev *pdev, | |||
1633 | pci_unmap_page(pdev, pci_unmap_addr(re, mapaddr), | 1629 | pci_unmap_page(pdev, pci_unmap_addr(re, mapaddr), |
1634 | pci_unmap_len(re, maplen), | 1630 | pci_unmap_len(re, maplen), |
1635 | PCI_DMA_TODEVICE); | 1631 | PCI_DMA_TODEVICE); |
1632 | re->flags = 0; | ||
1636 | } | 1633 | } |
1637 | 1634 | ||
1638 | /* | 1635 | /* |
@@ -1839,6 +1836,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1839 | dev->stats.tx_packets++; | 1836 | dev->stats.tx_packets++; |
1840 | dev->stats.tx_bytes += skb->len; | 1837 | dev->stats.tx_bytes += skb->len; |
1841 | 1838 | ||
1839 | re->skb = NULL; | ||
1842 | dev_kfree_skb_any(skb); | 1840 | dev_kfree_skb_any(skb); |
1843 | 1841 | ||
1844 | sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size); | 1842 | sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size); |