Commit 099978b434d4924594516db540ccc50652e7cc94
Committed by
David S. Miller
1 parent
4d7b6b5d24
Exists in
master
and in
39 other branches
bnx2x: LSO code was broken on BE platforms
Make the LSO code work on BE platforms: parsing_data field of a parsing BD (PBD) for 57712 was improperly composed which made FW read wrong values for TCP header's length and offset and, as a result, the corresponding PCI device was performing bad DMA reads triggering EEH. Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 26 additions and 16 deletions Side-by-side Diff
drivers/net/bnx2x/bnx2x_cmn.c
... | ... | @@ -1782,15 +1782,15 @@ |
1782 | 1782 | } |
1783 | 1783 | #endif |
1784 | 1784 | |
1785 | -static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, | |
1786 | - struct eth_tx_parse_bd_e2 *pbd, | |
1787 | - u32 xmit_type) | |
1785 | +static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data, | |
1786 | + u32 xmit_type) | |
1788 | 1787 | { |
1789 | - pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) << | |
1790 | - ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT; | |
1788 | + *parsing_data |= (skb_shinfo(skb)->gso_size << | |
1789 | + ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) & | |
1790 | + ETH_TX_PARSE_BD_E2_LSO_MSS; | |
1791 | 1791 | if ((xmit_type & XMIT_GSO_V6) && |
1792 | 1792 | (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6)) |
1793 | - pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR; | |
1793 | + *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR; | |
1794 | 1794 | } |
1795 | 1795 | |
1796 | 1796 | /** |
1797 | 1797 | |
1798 | 1798 | |
... | ... | @@ -1835,15 +1835,15 @@ |
1835 | 1835 | * @return header len |
1836 | 1836 | */ |
1837 | 1837 | static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb, |
1838 | - struct eth_tx_parse_bd_e2 *pbd, | |
1839 | - u32 xmit_type) | |
1838 | + u32 *parsing_data, u32 xmit_type) | |
1840 | 1839 | { |
1841 | - pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) << | |
1842 | - ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT; | |
1840 | + *parsing_data |= ((tcp_hdrlen(skb)/4) << | |
1841 | + ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) & | |
1842 | + ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW; | |
1843 | 1843 | |
1844 | - pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) - | |
1845 | - skb->data) / 2) << | |
1846 | - ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT; | |
1844 | + *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) << | |
1845 | + ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) & | |
1846 | + ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W; | |
1847 | 1847 | |
1848 | 1848 | return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data; |
1849 | 1849 | } |
... | ... | @@ -1912,6 +1912,7 @@ |
1912 | 1912 | struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL; |
1913 | 1913 | struct eth_tx_parse_bd_e1x *pbd_e1x = NULL; |
1914 | 1914 | struct eth_tx_parse_bd_e2 *pbd_e2 = NULL; |
1915 | + u32 pbd_e2_parsing_data = 0; | |
1915 | 1916 | u16 pkt_prod, bd_prod; |
1916 | 1917 | int nbd, fp_index; |
1917 | 1918 | dma_addr_t mapping; |
... | ... | @@ -2033,8 +2034,9 @@ |
2033 | 2034 | memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); |
2034 | 2035 | /* Set PBD in checksum offload case */ |
2035 | 2036 | if (xmit_type & XMIT_CSUM) |
2036 | - hlen = bnx2x_set_pbd_csum_e2(bp, | |
2037 | - skb, pbd_e2, xmit_type); | |
2037 | + hlen = bnx2x_set_pbd_csum_e2(bp, skb, | |
2038 | + &pbd_e2_parsing_data, | |
2039 | + xmit_type); | |
2038 | 2040 | } else { |
2039 | 2041 | pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x; |
2040 | 2042 | memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); |
2041 | 2043 | |
... | ... | @@ -2076,10 +2078,18 @@ |
2076 | 2078 | bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd, |
2077 | 2079 | hlen, bd_prod, ++nbd); |
2078 | 2080 | if (CHIP_IS_E2(bp)) |
2079 | - bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type); | |
2081 | + bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data, | |
2082 | + xmit_type); | |
2080 | 2083 | else |
2081 | 2084 | bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type); |
2082 | 2085 | } |
2086 | + | |
2087 | + /* Set the PBD's parsing_data field if not zero | |
2088 | + * (for the chips newer than 57711). | |
2089 | + */ | |
2090 | + if (pbd_e2_parsing_data) | |
2091 | + pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data); | |
2092 | + | |
2083 | 2093 | tx_data_bd = (struct eth_tx_bd *)tx_start_bd; |
2084 | 2094 | |
2085 | 2095 | /* Handle fragmented skb */ |