Unverified Commit fdf62dff authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!14254 [openEuler-1.0-LTS]fix wangxun 1G/10G drivers hardware tx unit hang.

Merge Pull Request from: @duanqiangwen 
 
bugzilla: https://gitee.com/openeuler/kernel/issues/IBCARJ?from=project-issue

fix icmpv6 port unreachable packets or extension headers ipv6 packets
may cause wangxun 1G/10G NIC hardware tx unit hang. 
 
Link:https://gitee.com/openeuler/kernel/pulls/14254 
parents 5089b895 c60b240e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -880,9 +880,9 @@ int ngbe_get_settings(struct net_device *netdev,
int ngbe_write_uc_addr_list(struct net_device *netdev, int pool);
void ngbe_full_sync_mac_table(struct ngbe_adapter *adapter);
int ngbe_add_mac_filter(struct ngbe_adapter *adapter,
				u8 *addr, u16 pool);
				const u8 *addr, u16 pool);
int ngbe_del_mac_filter(struct ngbe_adapter *adapter,
				u8 *addr, u16 pool);
				const u8 *addr, u16 pool);
int ngbe_available_rars(struct ngbe_adapter *adapter);
void ngbe_vlan_mode(struct net_device *, u32);

+89 −48
Original line number Diff line number Diff line
@@ -2841,7 +2841,7 @@ static void ngbe_mac_set_default_filter(struct ngbe_adapter *adapter,
			    NGBE_PSR_MAC_SWC_AD_H_AV);
}

int ngbe_add_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool)
int ngbe_add_mac_filter(struct ngbe_adapter *adapter, const u8 *addr, u16 pool)
{
	struct ngbe_hw *hw = &adapter->hw;
	u32 i;
@@ -2877,7 +2877,7 @@ static void ngbe_flush_sw_mac_table(struct ngbe_adapter *adapter)
	ngbe_sync_mac_table(adapter);
}

int ngbe_del_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool)
int ngbe_del_mac_filter(struct ngbe_adapter *adapter, const u8 *addr, u16 pool)
{
	/* search table for addr, if found, set to 0 and sync */
	u32 i;
@@ -2900,6 +2900,25 @@ int ngbe_del_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool)
	return -ENOMEM;
}

static int ngbe_uc_sync(struct net_device *netdev, const unsigned char *addr)
{
	struct ngbe_adapter *adapter = netdev_priv(netdev);
	int ret;

	ret = ngbe_add_mac_filter(adapter, addr, VMDQ_P(0));

	return min_t(int, ret, 0);
}

static int ngbe_uc_unsync(struct net_device *netdev, const unsigned char *addr)
{
	struct ngbe_adapter *adapter = netdev_priv(netdev);

	ngbe_del_mac_filter(adapter, addr, VMDQ_P(0));

	return 0;
}

/**
 * ngbe_write_uc_addr_list - write unicast addresses to RAR table
 * @netdev: network interface device structure
@@ -2995,10 +3014,9 @@ void ngbe_set_rx_mode(struct net_device *netdev)
	 * sufficient space to store all the addresses then enable
	 * unicast promiscuous mode
	 */
	count = ngbe_write_uc_addr_list(netdev, VMDQ_P(0));
	if (count < 0) {
	if (__dev_uc_sync(netdev, ngbe_uc_sync, ngbe_uc_unsync)) {
		vmolr &= ~NGBE_PSR_VM_L2CTL_ROPE;
		vmolr |= NGBE_PSR_VM_L2CTL_UPE;
		fctrl |= NGBE_PSR_CTL_UPE;
	}

	/*
@@ -5146,37 +5164,6 @@ static void ngbe_service_task(struct work_struct *work)
	ngbe_service_event_complete(adapter);
}

static u8 get_ipv6_proto(struct sk_buff *skb, int offset)
{
	struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset);
	u8 nexthdr = hdr->nexthdr;

	offset += sizeof(struct ipv6hdr);

	while (ipv6_ext_hdr(nexthdr)) {
		struct ipv6_opt_hdr _hdr, *hp;

		if (nexthdr == NEXTHDR_NONE)
			break;

		hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr);
		if (!hp)
			break;

		if (nexthdr == NEXTHDR_FRAGMENT) {
			break;
		} else if (nexthdr == NEXTHDR_AUTH) {
			offset +=  ipv6_authlen(hp);
		} else {
			offset +=  ipv6_optlen(hp);
		}

		nexthdr = hp->nexthdr;
	}

	return nexthdr;
}

union network_header {
	struct iphdr *ipv4;
	struct ipv6hdr *ipv6;
@@ -5189,6 +5176,10 @@ static ngbe_dptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *first)
	u8 tun_prot = 0;
	u8 l4_prot = 0;
	u8 ptype = 0;
	unsigned char *exthdr;
	unsigned char *l4_hdr;
	__be16 frag_off;
	u32 len = 0;

	if (skb->encapsulation) {
		union network_header hdr;
@@ -5200,8 +5191,15 @@ static ngbe_dptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *first)
				goto encap_frag;
			ptype = NGBE_PTYPE_TUN_IPV4;
			break;
		case __constant_htons(ETH_P_IPV6):
			tun_prot = get_ipv6_proto(skb, skb_network_offset(skb));
		case htons(ETH_P_IPV6):
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			tun_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &tun_prot, &frag_off);

			if (tun_prot == NEXTHDR_FRAGMENT)
				goto encap_frag;
			ptype = NGBE_PTYPE_TUN_IPV6;
@@ -5210,7 +5208,8 @@ static ngbe_dptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *first)
			goto exit;
		}

		if (tun_prot == IPPROTO_IPIP) {
		if (tun_prot == IPPROTO_IPIP ||
		    tun_prot == IPPROTO_IPV6) {
			hdr.raw = (void *)inner_ip_hdr(skb);
			ptype |= NGBE_PTYPE_PKT_IPIP;
		} else if (tun_prot == IPPROTO_UDP) {
@@ -5228,8 +5227,14 @@ static ngbe_dptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *first)
			}
			break;
		case 6:
			l4_prot = get_ipv6_proto(skb,
						 skb_inner_network_offset(skb));
			l4_hdr = skb_inner_transport_header(skb);
			exthdr = skb_inner_network_header(skb) +
						sizeof(struct ipv6hdr);
			l4_prot = inner_ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);

			ptype |= NGBE_PTYPE_PKT_IPV6;
			if (l4_prot == NEXTHDR_FRAGMENT) {
				ptype |= NGBE_PTYPE_TYP_IPFRAG;
@@ -5251,8 +5256,15 @@ static ngbe_dptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *first)
			}
			break;
#ifdef NETIF_F_IPV6_CSUM
		case __constant_htons(ETH_P_IPV6):
			l4_prot = get_ipv6_proto(skb, skb_network_offset(skb));
		case htons(ETH_P_IPV6):
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			l4_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);

			ptype = NGBE_PTYPE_PKT_IP | NGBE_PTYPE_PKT_IPV6;
			if (l4_prot == NEXTHDR_FRAGMENT) {
				ptype |= NGBE_PTYPE_TYP_IPFRAG;
@@ -5314,6 +5326,9 @@ static int ngbe_tso(struct ngbe_ring *tx_ring,
	struct iphdr *iph;
	u32 tunhdr_eiplen_tunlen = 0;
	u8 tun_prot = 0;
	unsigned char *exthdr;
	unsigned char *l4_hdr;
	__be16 frag_off;
	bool enc = skb->encapsulation;

	struct ipv6hdr *ipv6h;
@@ -5379,8 +5394,14 @@ static int ngbe_tso(struct ngbe_ring *tx_ring,
			tun_prot = ip_hdr(skb)->protocol;
			first->tx_flags |= NGBE_TX_FLAGS_OUTER_IPV4;
			break;
		case __constant_htons(ETH_P_IPV6):
		case htons(ETH_P_IPV6):
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			tun_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &tun_prot, &frag_off);
			break;
		default:
			break;
@@ -5405,6 +5426,7 @@ static int ngbe_tso(struct ngbe_ring *tx_ring,
					NGBE_TXD_TUNNEL_LEN_SHIFT);
			break;
		case IPPROTO_IPIP:
		case IPPROTO_IPV6:
			tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) -
						(char *)ip_hdr(skb)) >> 2) <<
						NGBE_TXD_OUTER_IPLEN_SHIFT;
@@ -5438,6 +5460,7 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
	u32 type_tucmd;

	if (skb->ip_summed != CHECKSUM_PARTIAL) {
csum_failed:
		if (!(first->tx_flags & NGBE_TX_FLAGS_HW_VLAN) &&
		    !(first->tx_flags & NGBE_TX_FLAGS_CC))
			return;
@@ -5445,6 +5468,10 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
				  NGBE_TXD_MACLEN_SHIFT;
	} else {
		u8 l4_prot = 0;
		unsigned char *exthdr;
		unsigned char *l4_hdr;
		__be16 frag_off;

		union {
			struct iphdr *ipv4;
			struct ipv6hdr *ipv6;
@@ -5464,8 +5491,16 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
			case __constant_htons(ETH_P_IP):
				tun_prot = ip_hdr(skb)->protocol;
				break;
			case __constant_htons(ETH_P_IPV6):
			case htons(ETH_P_IPV6):
				l4_hdr = skb_transport_header(skb);
				exthdr = skb_network_header(skb) +
							sizeof(struct ipv6hdr);
				tun_prot = ipv6_hdr(skb)->nexthdr;
				if (l4_hdr != exthdr)
					ipv6_skip_exthdr(skb,
							 exthdr - skb->data,
							 &tun_prot, &frag_off);

				break;
			default:
				if (unlikely(net_ratelimit())) {
@@ -5495,6 +5530,7 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
					NGBE_TXD_TUNNEL_LEN_SHIFT);
				break;
			case IPPROTO_IPIP:
			case IPPROTO_IPV6:
				tunhdr_eiplen_tunlen =
					(((char *)inner_ip_hdr(skb)-
					(char *)ip_hdr(skb)) >> 2) <<
@@ -5520,7 +5556,11 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
		case 6:
			vlan_macip_lens |=
				(transport_hdr.raw - network_hdr.raw) >> 1;
			exthdr = network_hdr.raw + sizeof(struct ipv6hdr);
			l4_prot = network_hdr.ipv6->nexthdr;
			if (transport_hdr.raw != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);
			break;
		default:
			break;
@@ -5540,7 +5580,8 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
					NGBE_TXD_L4LEN_SHIFT;
			break;
		default:
			break;
			skb_checksum_help(skb);
			goto csum_failed;
		}

		/* update TX checksum flag */
+2 −2
Original line number Diff line number Diff line
@@ -987,9 +987,9 @@ int txgbe_get_settings(struct net_device *netdev,
int txgbe_write_uc_addr_list(struct net_device *netdev, int pool);
void txgbe_full_sync_mac_table(struct txgbe_adapter *adapter);
int txgbe_add_mac_filter(struct txgbe_adapter *adapter,
				u8 *addr, u16 pool);
				const u8 *addr, u16 pool);
int txgbe_del_mac_filter(struct txgbe_adapter *adapter,
				u8 *addr, u16 pool);
				const u8 *addr, u16 pool);
int txgbe_available_rars(struct txgbe_adapter *adapter);
void txgbe_vlan_mode(struct net_device *, u32);

+80 −48
Original line number Diff line number Diff line
@@ -3207,7 +3207,8 @@ static void txgbe_mac_set_default_filter(struct txgbe_adapter *adapter,
			    TXGBE_PSR_MAC_SWC_AD_H_AV);
}

int txgbe_add_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool)
int txgbe_add_mac_filter(struct txgbe_adapter *adapter,
			 const u8 *addr, u16 pool)
{
	struct txgbe_hw *hw = &adapter->hw;
	u32 i;
@@ -3243,7 +3244,8 @@ static void txgbe_flush_sw_mac_table(struct txgbe_adapter *adapter)
	txgbe_sync_mac_table(adapter);
}

int txgbe_del_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool)
int txgbe_del_mac_filter(struct txgbe_adapter *adapter,
			 const u8 *addr, u16 pool)
{
	/* search table for addr, if found, set to 0 and sync */
	u32 i;
@@ -3266,6 +3268,25 @@ int txgbe_del_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool)
	return -ENOMEM;
}

static int txgbe_uc_sync(struct net_device *netdev, const unsigned char *addr)
{
	struct txgbe_adapter *adapter = netdev_priv(netdev);
	int ret;

	ret = txgbe_add_mac_filter(adapter, addr, VMDQ_P(0));

	return min_t(int, ret, 0);
}

static int txgbe_uc_unsync(struct net_device *netdev, const unsigned char *addr)
{
	struct txgbe_adapter *adapter = netdev_priv(netdev);

	txgbe_del_mac_filter(adapter, addr, VMDQ_P(0));

	return 0;
}

/**
 * txgbe_write_uc_addr_list - write unicast addresses to RAR table
 * @netdev: network interface device structure
@@ -3392,10 +3413,9 @@ void txgbe_set_rx_mode(struct net_device *netdev)
	 * sufficient space to store all the addresses then enable
	 * unicast promiscuous mode
	 */
	count = txgbe_write_uc_addr_list(netdev, VMDQ_P(0));
	if (count < 0) {
	if (__dev_uc_sync(netdev, txgbe_uc_sync, txgbe_uc_unsync)) {
		vmolr &= ~TXGBE_PSR_VM_L2CTL_ROPE;
		vmolr |= TXGBE_PSR_VM_L2CTL_UPE;
		fctrl |= TXGBE_PSR_CTL_UPE;
	}

	/*
@@ -5902,37 +5922,6 @@ static void txgbe_service_task(struct work_struct *work)
	txgbe_service_event_complete(adapter);
}

static u8 get_ipv6_proto(struct sk_buff *skb, int offset)
{
	struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset);
	u8 nexthdr = hdr->nexthdr;

	offset += sizeof(struct ipv6hdr);

	while (ipv6_ext_hdr(nexthdr)) {
		struct ipv6_opt_hdr _hdr, *hp;

		if (nexthdr == NEXTHDR_NONE)
			break;

		hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr);
		if (!hp)
			break;

		if (nexthdr == NEXTHDR_FRAGMENT) {
			break;
		} else if (nexthdr == NEXTHDR_AUTH) {
			offset +=  ipv6_authlen(hp);
		} else {
			offset +=  ipv6_optlen(hp);
		}

		nexthdr = hp->nexthdr;
	}

	return nexthdr;
}

union network_header {
	struct iphdr *ipv4;
	struct ipv6hdr *ipv6;
@@ -5942,11 +5931,12 @@ union network_header {
static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first)
{
	struct sk_buff *skb = first->skb;

	u8 tun_prot = 0;

	u8 l4_prot = 0;
	u8 ptype = 0;
	unsigned char *exthdr;
	unsigned char *l4_hdr;
	__be16 frag_off;

	if (skb->encapsulation) {
		union network_header hdr;
@@ -5959,7 +5949,13 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first)
			ptype = TXGBE_PTYPE_TUN_IPV4;
			break;
		case __constant_htons(ETH_P_IPV6):
			tun_prot = get_ipv6_proto(skb, skb_network_offset(skb));
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			tun_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &tun_prot, &frag_off);
			if (tun_prot == NEXTHDR_FRAGMENT)
				goto encap_frag;
			ptype = TXGBE_PTYPE_TUN_IPV6;
@@ -5968,7 +5964,8 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first)
			goto exit;
		}

		if (tun_prot == IPPROTO_IPIP) {
		if (tun_prot == IPPROTO_IPIP ||
		    tun_prot == IPPROTO_IPV6) {
			hdr.raw = (void *)inner_ip_hdr(skb);
			ptype |= TXGBE_PTYPE_PKT_IPIP;
		} else if (tun_prot == IPPROTO_UDP) {
@@ -6015,8 +6012,13 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first)
			}
			break;
		case 6:
			l4_prot = get_ipv6_proto(skb,
						 skb_inner_network_offset(skb));
			l4_hdr = skb_inner_transport_header(skb);
			exthdr = skb_inner_network_header(skb) +
						sizeof(struct ipv6hdr);
			l4_prot = inner_ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);
			ptype |= TXGBE_PTYPE_PKT_IPV6;
			if (l4_prot == NEXTHDR_FRAGMENT) {
				ptype |= TXGBE_PTYPE_TYP_IPFRAG;
@@ -6040,7 +6042,14 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first)
			break;
#ifdef NETIF_F_IPV6_CSUM
		case __constant_htons(ETH_P_IPV6):
			l4_prot = get_ipv6_proto(skb, skb_network_offset(skb));
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			l4_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);

			ptype = TXGBE_PTYPE_PKT_IP | TXGBE_PTYPE_PKT_IPV6;
			if (l4_prot == NEXTHDR_FRAGMENT) {
				ptype |= TXGBE_PTYPE_TYP_IPFRAG;
@@ -6102,8 +6111,10 @@ static int txgbe_tso(struct txgbe_ring *tx_ring,
	struct tcphdr *tcph;
	struct iphdr *iph;
	u32 tunhdr_eiplen_tunlen = 0;

	u8 tun_prot = 0;
	unsigned char *exthdr;
	unsigned char *l4_hdr;
	__be16 frag_off;
	bool enc = skb->encapsulation;

		struct ipv6hdr *ipv6h;
@@ -6176,7 +6187,13 @@ static int txgbe_tso(struct txgbe_ring *tx_ring,
			first->tx_flags |= TXGBE_TX_FLAGS_OUTER_IPV4;
			break;
		case __constant_htons(ETH_P_IPV6):
			l4_hdr = skb_transport_header(skb);
			exthdr = skb_network_header(skb) +
						sizeof(struct ipv6hdr);
			tun_prot = ipv6_hdr(skb)->nexthdr;
			if (l4_hdr != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &tun_prot, &frag_off);
			break;
		default:
			break;
@@ -6201,6 +6218,7 @@ static int txgbe_tso(struct txgbe_ring *tx_ring,
					TXGBE_TXD_TUNNEL_LEN_SHIFT);
			break;
		case IPPROTO_IPIP:
		case IPPROTO_IPV6:
			tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb)-
						(char *)ip_hdr(skb)) >> 2) <<
						TXGBE_TXD_OUTER_IPLEN_SHIFT;
@@ -6230,12 +6248,11 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
	u32 vlan_macip_lens = 0;
	u32 mss_l4len_idx = 0;
	u32 tunhdr_eiplen_tunlen = 0;

	u8 tun_prot = 0;

	u32 type_tucmd;

	if (skb->ip_summed != CHECKSUM_PARTIAL) {
csum_failed:
		if (!(first->tx_flags & TXGBE_TX_FLAGS_HW_VLAN) &&
		    !(first->tx_flags & TXGBE_TX_FLAGS_CC))
			return;
@@ -6243,6 +6260,9 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
				  TXGBE_TXD_MACLEN_SHIFT;
	} else {
		u8 l4_prot = 0;
		unsigned char *exthdr;
		unsigned char *l4_hdr;
		__be16 frag_off;

		union {
			struct iphdr *ipv4;
@@ -6264,7 +6284,14 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
				tun_prot = ip_hdr(skb)->protocol;
				break;
			case __constant_htons(ETH_P_IPV6):
				l4_hdr = skb_transport_header(skb);
				exthdr = skb_network_header(skb) +
							sizeof(struct ipv6hdr);
				tun_prot = ipv6_hdr(skb)->nexthdr;
				if (l4_hdr != exthdr)
					ipv6_skip_exthdr(skb,
							 exthdr - skb->data,
							 &tun_prot, &frag_off);
				break;
			default:
				if (unlikely(net_ratelimit())) {
@@ -6294,6 +6321,7 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
					TXGBE_TXD_TUNNEL_LEN_SHIFT);
				break;
			case IPPROTO_IPIP:
			case IPPROTO_IPV6:
				tunhdr_eiplen_tunlen =
					(((char *)inner_ip_hdr(skb)-
					(char *)ip_hdr(skb)) >> 2) <<
@@ -6319,7 +6347,11 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
		case 6:
			vlan_macip_lens |=
				(transport_hdr.raw - network_hdr.raw) >> 1;
			exthdr = network_hdr.raw + sizeof(struct ipv6hdr);
			l4_prot = network_hdr.ipv6->nexthdr;
			if (transport_hdr.raw != exthdr)
				ipv6_skip_exthdr(skb, exthdr - skb->data,
						 &l4_prot, &frag_off);
			break;
		default:
			break;
@@ -6327,7 +6359,6 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,

		switch (l4_prot) {
		case IPPROTO_TCP:

		mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
				TXGBE_TXD_L4LEN_SHIFT;
			break;
@@ -6340,7 +6371,8 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring,
					TXGBE_TXD_L4LEN_SHIFT;
			break;
		default:
			break;
			skb_checksum_help(skb);
			goto csum_failed;
		}

		/* update TX checksum flag */