Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 476c1885 authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

tg3: Work around HW/FW limitations with vlan encapsulated frames



TG3 appears to have an issue performing TSO and checksum offloading
correclty when the frame has been vlan encapsulated (non-accelrated).
In these cases, tcp checksum is not correctly updated.

This patch attempts to work around this issue.  After the patch,
802.1ad vlans start working correctly over tg3 devices.

CC: Prashant Sreedharan <prashant@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
Signed-off-by: default avatarVladislav Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 07d92d5c
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -7914,8 +7914,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)


	entry = tnapi->tx_prod;
	entry = tnapi->tx_prod;
	base_flags = 0;
	base_flags = 0;
	if (skb->ip_summed == CHECKSUM_PARTIAL)
		base_flags |= TXD_FLAG_TCPUDP_CSUM;


	mss = skb_shinfo(skb)->gso_size;
	mss = skb_shinfo(skb)->gso_size;
	if (mss) {
	if (mss) {
@@ -7929,6 +7927,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)


		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;


		/* HW/FW can not correctly segment packets that have been
		 * vlan encapsulated.
		 */
		if (skb->protocol == htons(ETH_P_8021Q) ||
		    skb->protocol == htons(ETH_P_8021AD))
			return tg3_tso_bug(tp, tnapi, txq, skb);

		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))
@@ -7979,6 +7984,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
				base_flags |= tsflags << 12;
				base_flags |= tsflags << 12;
			}
			}
		}
		}
	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
		/* HW/FW can not correctly checksum packets that have been
		 * vlan encapsulated.
		 */
		if (skb->protocol == htons(ETH_P_8021Q) ||
		    skb->protocol == htons(ETH_P_8021AD)) {
			if (skb_checksum_help(skb))
				goto drop;
		} else  {
			base_flags |= TXD_FLAG_TCPUDP_CSUM;
		}
	}
	}


	if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
	if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&