be2net: workaround to fix a bug in BE
Subsystems (3)
PATCH 2/2 be2net: workaround to fix a bug in BE
disable Tx vlan offloading in certain cases.
Signed-off-by Ajit Khaparde <[email protected]>
--- drivers/net/ethernet/emulex/benet/be_main.c | 46 ++++++++++++++++++++++----- 1 files changed, 38 insertions(+), 8 deletions(-)
drivers/net/ethernet/emulex/benet/be_main.c +38 -8
@@ -552,11 +552,26 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) wrb->frag_len = len Ð_WRB_FRAG_LEN_MASK ; } +static inline u16 be_get_tx_vlan_tag (struct be_adapter *adapter, +struct sk_buff *skb) +{ +u8 vlan_prio; +u16 vlan_tag; + + vlan_tag =vlan_tx_tag_get (skb); + vlan_prio = (vlan_tag &VLAN_PRIO_MASK ) >>VLAN_PRIO_SHIFT ; +/* If vlan priority provided by OS is NOT in available bmap */ +if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) + vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK ) | + adapter->recommended_prio; + +return vlan_tag; +} +static void wrb_fill_hdr (struct be_adapter *adapter,struct be_eth_hdr_wrb *hdr,struct sk_buff *skb,u32 wrb_cnt,u32 len) { -u8 vlan_prio =0 ; -u16 vlan_tag =0 ; +u16 vlan_tag;memset (hdr,0 ,sizeof (*hdr));
@@ -587,12 +602,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,if (vlan_tx_tag_present (skb)) { AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); - vlan_tag =vlan_tx_tag_get (skb); - vlan_prio = (vlan_tag &VLAN_PRIO_MASK ) >>VLAN_PRIO_SHIFT ; -/* If vlan priority provided by OS is NOT in available bmap */ -if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) - vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK ) | - adapter->recommended_prio; + vlan_tag =be_get_tx_vlan_tag (adapter, skb); AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag); }
@@ -695,6 +705,25 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,u32 start = txq->head;bool dummy_wrb, stopped = false; +/* For vlan tagged pkts, BE +* 1) calculates checksum even when CSO is not requested +* 2) calculates checksum wrongly for padded pkt less than +* 60 bytes long. +* As a workaround disable TX vlan offloading in such cases. +*/ +if (unlikely (vlan_tx_tag_present (skb) && + (skb->ip_summed !=CHECKSUM_PARTIAL || skb->len <=60 ))) { + skb =skb_share_check (skb,GFP_ATOMIC ); +if (unlikely (!skb)) + goto tx_drop; + + skb =__vlan_put_tag (skb,be_get_tx_vlan_tag (adapter, skb)); +if (unlikely (!skb)) + goto tx_drop; + + skb->vlan_tci =0 ; + } + wrb_cnt =wrb_cnt_for_skb (adapter, skb, &dummy_wrb); copied =make_tx_wrbs (adapter, txq, skb, wrb_cnt, dummy_wrb);
@@ -722,6 +751,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, txq->head = start;dev_kfree_skb_any (skb); } +tx_drop:return NETDEV_TX_OK ; }
Signature · 1 line
1.7.5.4
From: Ajit Khaparde <[email protected]>
Date: Fri, 9 Dec 2011 17:53:17 -0600
Quoted 3 lines
disable Tx vlan offloading in certain cases.
Signed-off-by Ajit Khaparde <[email protected]>
Applied.