diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2011-11-04 05:15:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-04 17:31:47 -0400 |
commit | ba1142e4fb291c7bf124d93596351dca8d226a0f (patch) | |
tree | dc20e27d52a515cfad594d2d137e61a3983d7de5 /drivers | |
parent | b9e454826f22e17d1945bd282834c87aef8d0f95 (diff) |
tg3: Fix 4k skb error recovery path
On the error recovery resource unwind path, it is possible for the
driver to attempt to unmap a fragment that hadn't been mapped. This
patch fixes the problem by correcting the "last" parameter supplied.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 507b73b979fe..3a7517910eed 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -6507,7 +6507,7 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last) | |||
6507 | txb = &tnapi->tx_buffers[entry]; | 6507 | txb = &tnapi->tx_buffers[entry]; |
6508 | } | 6508 | } |
6509 | 6509 | ||
6510 | for (i = 0; i < last; i++) { | 6510 | for (i = 0; i <= last; i++) { |
6511 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 6511 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
6512 | 6512 | ||
6513 | entry = NEXT_TX(entry); | 6513 | entry = NEXT_TX(entry); |
@@ -6568,7 +6568,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, | |||
6568 | if (tg3_tx_frag_set(tnapi, entry, budget, new_addr, | 6568 | if (tg3_tx_frag_set(tnapi, entry, budget, new_addr, |
6569 | new_skb->len, base_flags, | 6569 | new_skb->len, base_flags, |
6570 | mss, vlan)) { | 6570 | mss, vlan)) { |
6571 | tg3_tx_skb_unmap(tnapi, save_entry, 0); | 6571 | tg3_tx_skb_unmap(tnapi, save_entry, -1); |
6572 | dev_kfree_skb(new_skb); | 6572 | dev_kfree_skb(new_skb); |
6573 | ret = -1; | 6573 | ret = -1; |
6574 | } | 6574 | } |
@@ -6758,11 +6758,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
6758 | 6758 | ||
6759 | if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags | | 6759 | if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags | |
6760 | ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), | 6760 | ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), |
6761 | mss, vlan)) | 6761 | mss, vlan)) { |
6762 | would_hit_hwbug = 1; | 6762 | would_hit_hwbug = 1; |
6763 | |||
6764 | /* Now loop through additional data fragments, and queue them. */ | 6763 | /* Now loop through additional data fragments, and queue them. */ |
6765 | if (skb_shinfo(skb)->nr_frags > 0) { | 6764 | } else if (skb_shinfo(skb)->nr_frags > 0) { |
6766 | u32 tmp_mss = mss; | 6765 | u32 tmp_mss = mss; |
6767 | 6766 | ||
6768 | if (!tg3_flag(tp, HW_TSO_1) && | 6767 | if (!tg3_flag(tp, HW_TSO_1) && |
@@ -6831,7 +6830,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
6831 | return NETDEV_TX_OK; | 6830 | return NETDEV_TX_OK; |
6832 | 6831 | ||
6833 | dma_error: | 6832 | dma_error: |
6834 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); | 6833 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i); |
6835 | tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; | 6834 | tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; |
6836 | drop: | 6835 | drop: |
6837 | dev_kfree_skb(skb); | 6836 | dev_kfree_skb(skb); |
@@ -7284,7 +7283,8 @@ static void tg3_free_rings(struct tg3 *tp) | |||
7284 | if (!skb) | 7283 | if (!skb) |
7285 | continue; | 7284 | continue; |
7286 | 7285 | ||
7287 | tg3_tx_skb_unmap(tnapi, i, skb_shinfo(skb)->nr_frags); | 7286 | tg3_tx_skb_unmap(tnapi, i, |
7287 | skb_shinfo(skb)->nr_frags - 1); | ||
7288 | 7288 | ||
7289 | dev_kfree_skb_any(skb); | 7289 | dev_kfree_skb_any(skb); |
7290 | } | 7290 | } |
@@ -11523,7 +11523,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) | |||
11523 | break; | 11523 | break; |
11524 | } | 11524 | } |
11525 | 11525 | ||
11526 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, 0); | 11526 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, -1); |
11527 | dev_kfree_skb(skb); | 11527 | dev_kfree_skb(skb); |
11528 | 11528 | ||
11529 | if (tx_idx != tnapi->tx_prod) | 11529 | if (tx_idx != tnapi->tx_prod) |