bnx2x: fix UDP csum offload

Fixed packets parameters for FW in UDP checksum offload flow.

Do not dereference TCP headers on non TCP frames.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Vladislav Zolotarov and committed by David S. Miller e39aece7 13f172ff

+24 -10
+24 -10
drivers/net/bnx2x/bnx2x_cmn.c
··· 2019 2019 static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb, 2020 2020 u32 *parsing_data, u32 xmit_type) 2021 2021 { 2022 - *parsing_data |= ((tcp_hdrlen(skb)/4) << 2023 - ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) & 2024 - ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW; 2022 + *parsing_data |= 2023 + ((((u8 *)skb_transport_header(skb) - skb->data) >> 1) << 2024 + ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) & 2025 + ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W; 2025 2026 2026 - *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) << 2027 - ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) & 2028 - ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W; 2027 + if (xmit_type & XMIT_CSUM_TCP) { 2028 + *parsing_data |= ((tcp_hdrlen(skb) / 4) << 2029 + ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) & 2030 + ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW; 2029 2031 2030 - return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data; 2032 + return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data; 2033 + } else 2034 + /* We support checksum offload for TCP and UDP only. 2035 + * No need to pass the UDP header length - it's a constant. 2036 + */ 2037 + return skb_transport_header(skb) + 2038 + sizeof(struct udphdr) - skb->data; 2031 2039 } 2032 2040 2033 2041 /** ··· 2051 2043 struct eth_tx_parse_bd_e1x *pbd, 2052 2044 u32 xmit_type) 2053 2045 { 2054 - u8 hlen = (skb_network_header(skb) - skb->data) / 2; 2046 + u8 hlen = (skb_network_header(skb) - skb->data) >> 1; 2055 2047 2056 2048 /* for now NS flag is not used in Linux */ 2057 2049 pbd->global_data = ··· 2059 2051 ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT)); 2060 2052 2061 2053 pbd->ip_hlen_w = (skb_transport_header(skb) - 2062 - skb_network_header(skb)) / 2; 2054 + skb_network_header(skb)) >> 1; 2063 2055 2064 - hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2; 2056 + hlen += pbd->ip_hlen_w; 2057 + 2058 + /* We support checksum offload for TCP and UDP only */ 2059 + if (xmit_type & XMIT_CSUM_TCP) 2060 + hlen += tcp_hdrlen(skb) / 2; 2061 + else 2062 + hlen += sizeof(struct udphdr) / 2; 2065 2063 2066 2064 pbd->total_hlen_w = cpu_to_le16(hlen); 2067 2065 hlen = hlen*2;