Commit ba1142e4 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller

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: default avatarMatt Carlson <mcarlson@broadcom.com>
Reviewed-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9e45482
...@@ -6507,7 +6507,7 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last) ...@@ -6507,7 +6507,7 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last)
txb = &tnapi->tx_buffers[entry]; txb = &tnapi->tx_buffers[entry];
} }
for (i = 0; i < last; i++) { for (i = 0; i <= last; i++) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
entry = NEXT_TX(entry); entry = NEXT_TX(entry);
...@@ -6568,7 +6568,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, ...@@ -6568,7 +6568,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
if (tg3_tx_frag_set(tnapi, entry, budget, new_addr, if (tg3_tx_frag_set(tnapi, entry, budget, new_addr,
new_skb->len, base_flags, new_skb->len, base_flags,
mss, vlan)) { mss, vlan)) {
tg3_tx_skb_unmap(tnapi, save_entry, 0); tg3_tx_skb_unmap(tnapi, save_entry, -1);
dev_kfree_skb(new_skb); dev_kfree_skb(new_skb);
ret = -1; ret = -1;
} }
...@@ -6758,11 +6758,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -6758,11 +6758,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags | if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags |
((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),
mss, vlan)) mss, vlan)) {
would_hit_hwbug = 1; would_hit_hwbug = 1;
/* Now loop through additional data fragments, and queue them. */ /* Now loop through additional data fragments, and queue them. */
if (skb_shinfo(skb)->nr_frags > 0) { } else if (skb_shinfo(skb)->nr_frags > 0) {
u32 tmp_mss = mss; u32 tmp_mss = mss;
if (!tg3_flag(tp, HW_TSO_1) && 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,7 +6830,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
dma_error: dma_error:
tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i);
tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
drop: drop:
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -7284,7 +7283,8 @@ static void tg3_free_rings(struct tg3 *tp) ...@@ -7284,7 +7283,8 @@ static void tg3_free_rings(struct tg3 *tp)
if (!skb) if (!skb)
continue; continue;
tg3_tx_skb_unmap(tnapi, i, skb_shinfo(skb)->nr_frags); tg3_tx_skb_unmap(tnapi, i,
skb_shinfo(skb)->nr_frags - 1);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} }
...@@ -11523,7 +11523,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) ...@@ -11523,7 +11523,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
break; break;
} }
tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, 0); tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, -1);
dev_kfree_skb(skb); dev_kfree_skb(skb);
if (tx_idx != tnapi->tx_prod) if (tx_idx != tnapi->tx_prod)
......
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