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

!14247 [OLK-5.10] fix wangxun 1G/10G drivers hardware tx unit hang.

Merge Pull Request from: @duanqiangwen 
 
bugzilla: https://gitee.com/openeuler/kernel/issues/IBCASR?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/14247

 

Reviewed-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
Reviewed-by: default avatarLi Nan <linan122@huawei.com>
Reviewed-by: default avatarzhenpengzheng <zhenpengzheng@net-swift.com>
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
parents 243d2e96 f91e04dd
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -858,9 +858,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 *netdev, u32 features);

+79 −42
Original line number Diff line number Diff line
@@ -2784,7 +2784,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;
@@ -2820,7 +2820,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;
@@ -2843,6 +2843,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
@@ -2938,10 +2957,11 @@ 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;
		e_dev_warn("uc count is %d, available mac entry is %d, enable promisc mode\n",
			   netdev_uc_count(netdev), ngbe_available_rars(adapter));
	}

	/* Write addresses to the MTA, if the attempt fails
@@ -5141,36 +5161,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;
@@ -5183,6 +5173,9 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f
	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;
@@ -5195,7 +5188,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f
			ptype = NGBE_PTYPE_TUN_IPV4;
			break;
		case 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 = NGBE_PTYPE_TUN_IPV6;
@@ -5204,7 +5203,8 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f
			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) {
@@ -5222,8 +5222,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f
			}
			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;
@@ -5246,7 +5251,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f
			break;
#ifdef NETIF_F_IPV6_CSUM
		case 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 = NGBE_PTYPE_PKT_IP | NGBE_PTYPE_PKT_IPV6;
			if (l4_prot == NEXTHDR_FRAGMENT) {
				ptype |= NGBE_PTYPE_TYP_IPFRAG;
@@ -5308,6 +5319,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;
@@ -5373,7 +5387,12 @@ static int ngbe_tso(struct ngbe_ring *tx_ring,
			first->tx_flags |= NGBE_TX_FLAGS_OUTER_IPV4;
			break;
		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;
@@ -5398,6 +5417,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;
@@ -5432,6 +5452,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;
@@ -5439,6 +5460,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;
@@ -5459,7 +5484,13 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring,
				tun_prot = ip_hdr(skb)->protocol;
				break;
			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())) {
@@ -5489,6 +5520,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) <<
@@ -5514,7 +5546,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;
@@ -5534,7 +5570,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
@@ -1078,9 +1078,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);

+72 −48
Original line number Diff line number Diff line
@@ -3220,7 +3220,7 @@ 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;
@@ -3267,7 +3267,7 @@ 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;
@@ -3303,6 +3303,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
@@ -3426,10 +3445,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;
	}

	/*
@@ -6022,37 +6040,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;
@@ -6062,11 +6049,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;
@@ -6079,7 +6067,12 @@ 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;
@@ -6088,7 +6081,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) {
@@ -6135,8 +6129,12 @@ 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;
@@ -6160,7 +6158,13 @@ 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;
@@ -6222,8 +6226,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;
@@ -6296,7 +6302,12 @@ 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;
@@ -6321,6 +6332,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;
@@ -6350,12 +6362,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;
@@ -6363,6 +6374,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;
@@ -6384,7 +6398,12 @@ 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())) {
@@ -6414,6 +6433,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) <<
@@ -6439,7 +6459,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;
@@ -6447,7 +6471,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;
@@ -6460,7 +6483,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 */