tg3: Modify tg3_tso_bug() to handle multiple TX rings
tg3_tso_bug() was originally designed to handle only HW TX ring 0, Commit
d3f6f3a1d8
("tg3: Prevent page allocation failure
during TSO workaround") changed the driver logic to use tg3_tso_bug() for all
HW TX rings that are enabled. This patch fixes the regression by modifying
tg3_tso_bug() to handle multiple HW TX rings.
Signed-off-by: Prashant Sreedharan <prashant@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2670cc699a
commit
4d8fdc95c6
1 changed files with 12 additions and 10 deletions
|
@ -7830,17 +7830,18 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
|
||||||
|
|
||||||
static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
|
static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
|
||||||
|
|
||||||
/* Use GSO to workaround a rare TSO bug that may be triggered when the
|
/* Use GSO to workaround all TSO packets that meet HW bug conditions
|
||||||
* TSO header is greater than 80 bytes.
|
* indicated in tg3_tx_frag_set()
|
||||||
*/
|
*/
|
||||||
static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
|
static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
|
||||||
|
struct netdev_queue *txq, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct sk_buff *segs, *nskb;
|
struct sk_buff *segs, *nskb;
|
||||||
u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
|
u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
|
||||||
|
|
||||||
/* Estimate the number of fragments in the worst case */
|
/* Estimate the number of fragments in the worst case */
|
||||||
if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) {
|
if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
|
||||||
netif_stop_queue(tp->dev);
|
netif_tx_stop_queue(txq);
|
||||||
|
|
||||||
/* netif_tx_stop_queue() must be done before checking
|
/* netif_tx_stop_queue() must be done before checking
|
||||||
* checking tx index in tg3_tx_avail() below, because in
|
* checking tx index in tg3_tx_avail() below, because in
|
||||||
|
@ -7848,13 +7849,14 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
|
||||||
* netif_tx_queue_stopped().
|
* netif_tx_queue_stopped().
|
||||||
*/
|
*/
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)
|
if (tg3_tx_avail(tnapi) <= frag_cnt_est)
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
|
|
||||||
netif_wake_queue(tp->dev);
|
netif_tx_wake_queue(txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
segs = skb_gso_segment(skb, tp->dev->features & ~(NETIF_F_TSO | NETIF_F_TSO6));
|
segs = skb_gso_segment(skb, tp->dev->features &
|
||||||
|
~(NETIF_F_TSO | NETIF_F_TSO6));
|
||||||
if (IS_ERR(segs) || !segs)
|
if (IS_ERR(segs) || !segs)
|
||||||
goto tg3_tso_bug_end;
|
goto tg3_tso_bug_end;
|
||||||
|
|
||||||
|
@ -7930,7 +7932,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
if (!skb_is_gso_v6(skb)) {
|
if (!skb_is_gso_v6(skb)) {
|
||||||
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
|
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
|
||||||
tg3_flag(tp, TSO_BUG))
|
tg3_flag(tp, TSO_BUG))
|
||||||
return tg3_tso_bug(tp, skb);
|
return tg3_tso_bug(tp, tnapi, txq, skb);
|
||||||
|
|
||||||
ip_csum = iph->check;
|
ip_csum = iph->check;
|
||||||
ip_tot_len = iph->tot_len;
|
ip_tot_len = iph->tot_len;
|
||||||
|
@ -8061,7 +8063,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
iph->tot_len = ip_tot_len;
|
iph->tot_len = ip_tot_len;
|
||||||
}
|
}
|
||||||
tcph->check = tcp_csum;
|
tcph->check = tcp_csum;
|
||||||
return tg3_tso_bug(tp, skb);
|
return tg3_tso_bug(tp, tnapi, txq, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the workaround fails due to memory/mapping
|
/* If the workaround fails due to memory/mapping
|
||||||
|
|
Loading…
Add table
Reference in a new issue