diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 27 | 
1 files changed, 20 insertions, 7 deletions
| diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 9293675df7ba..3010080cfeee 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7831,6 +7831,14 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,  	return ret;  } +static bool tg3_tso_bug_gso_check(struct tg3_napi *tnapi, struct sk_buff *skb) +{ +	/* Check if we will never have enough descriptors, +	 * as gso_segs can be more than current ring size +	 */ +	return skb_shinfo(skb)->gso_segs < tnapi->tx_pending / 3; +} +  static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);  /* Use GSO to workaround all TSO packets that meet HW bug conditions @@ -7934,14 +7942,19 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)  		 * vlan encapsulated.  		 */  		if (skb->protocol == htons(ETH_P_8021Q) || -		    skb->protocol == htons(ETH_P_8021AD)) -			return tg3_tso_bug(tp, tnapi, txq, skb); +		    skb->protocol == htons(ETH_P_8021AD)) { +			if (tg3_tso_bug_gso_check(tnapi, skb)) +				return tg3_tso_bug(tp, tnapi, txq, skb); +			goto drop; +		}  		if (!skb_is_gso_v6(skb)) {  			if (unlikely((ETH_HLEN + hdr_len) > 80) && -			    tg3_flag(tp, TSO_BUG)) -				return tg3_tso_bug(tp, tnapi, txq, skb); - +			    tg3_flag(tp, TSO_BUG)) { +				if (tg3_tso_bug_gso_check(tnapi, skb)) +					return tg3_tso_bug(tp, tnapi, txq, skb); +				goto drop; +			}  			ip_csum = iph->check;  			ip_tot_len = iph->tot_len;  			iph->check = 0; @@ -8073,7 +8086,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)  	if (would_hit_hwbug) {  		tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); -		if (mss) { +		if (mss && tg3_tso_bug_gso_check(tnapi, skb)) {  			/* If it's a TSO packet, do GSO instead of  			 * allocating and copying to a large linear SKB  			 */ @@ -12016,7 +12029,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,  	int ret;  	u32 offset, len, b_offset, odd_len;  	u8 *buf; -	__be32 start, end; +	__be32 start = 0, end;  	if (tg3_flag(tp, NO_NVRAM) ||  	    eeprom->magic != TG3_EEPROM_MAGIC) | 
