diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-04-06 04:02:46 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-04-07 01:39:45 +0300 |
commit | 672021943c453c4ae04bf131ccf155a7d4f967ab (patch) | |
tree | b0a9943a9c08188386cda6f46fbb2877d348b72c /drivers/net/ethernet/faraday | |
parent | d72e01a0430f8a1ae7adb3cbf0b2e73fcd99252e (diff) | |
download | linux-672021943c453c4ae04bf131ccf155a7d4f967ab.tar.xz |
ftgmac100: Cleanup rx checksum handling
Read the descriptor field only once and check for IP header
checksum errors as well
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/faraday')
-rw-r--r-- | drivers/net/ethernet/faraday/ftgmac100.c | 63 |
1 files changed, 25 insertions, 38 deletions
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 876f54aa42f7..6277f6e70f6b 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -352,31 +352,11 @@ static dma_addr_t ftgmac100_rxdes_get_dma_addr(struct ftgmac100_rxdes *rxdes) return le32_to_cpu(rxdes->rxdes3); } -static bool ftgmac100_rxdes_is_tcp(struct ftgmac100_rxdes *rxdes) +static inline bool ftgmac100_rxdes_csum_err(struct ftgmac100_rxdes *rxdes) { - return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) == - cpu_to_le32(FTGMAC100_RXDES1_PROT_TCPIP); -} - -static bool ftgmac100_rxdes_is_udp(struct ftgmac100_rxdes *rxdes) -{ - return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) == - cpu_to_le32(FTGMAC100_RXDES1_PROT_UDPIP); -} - -static bool ftgmac100_rxdes_tcpcs_err(struct ftgmac100_rxdes *rxdes) -{ - return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR); -} - -static bool ftgmac100_rxdes_udpcs_err(struct ftgmac100_rxdes *rxdes) -{ - return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_UDP_CHKSUM_ERR); -} - -static bool ftgmac100_rxdes_ipcs_err(struct ftgmac100_rxdes *rxdes) -{ - return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_IP_CHKSUM_ERR); + return !!(rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR | + FTGMAC100_RXDES1_UDP_CHKSUM_ERR | + FTGMAC100_RXDES1_IP_CHKSUM_ERR)); } static inline struct page **ftgmac100_rxdes_page_slot(struct ftgmac100 *priv, @@ -486,11 +466,6 @@ static bool ftgmac100_rx_packet_error(struct ftgmac100 *priv, netdev->stats.rx_crc_errors++; error = true; - } else if (unlikely(ftgmac100_rxdes_ipcs_err(rxdes))) { - if (net_ratelimit()) - netdev_info(netdev, "rx IP checksum err\n"); - - error = true; } if (unlikely(ftgmac100_rxdes_frame_too_long(rxdes))) { @@ -582,14 +557,23 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) if (unlikely(ftgmac100_rxdes_multicast(rxdes))) netdev->stats.multicast++; - /* - * It seems that HW does checksum incorrectly with fragmented packets, - * so we are conservative here - if HW checksum error, let software do - * the checksum again. + /* If the HW found checksum errors, bounce it to software. + * + * If we didn't, we need to see if the packet was recognized + * by HW as one of the supported checksummed protocols before + * we accept the HW test results. */ - if ((ftgmac100_rxdes_is_tcp(rxdes) && !ftgmac100_rxdes_tcpcs_err(rxdes)) || - (ftgmac100_rxdes_is_udp(rxdes) && !ftgmac100_rxdes_udpcs_err(rxdes))) - skb->ip_summed = CHECKSUM_UNNECESSARY; + if (netdev->features & NETIF_F_RXCSUM) { + __le32 csum_vlan = rxdes->rxdes1; + __le32 err_bits = cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR | + FTGMAC100_RXDES1_UDP_CHKSUM_ERR | + FTGMAC100_RXDES1_IP_CHKSUM_ERR); + if ((csum_vlan & err_bits) || + !(csum_vlan & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK))) + skb->ip_summed = CHECKSUM_NONE; + else + skb->ip_summed = CHECKSUM_UNNECESSARY; + } map = ftgmac100_rxdes_get_dma_addr(rxdes); @@ -621,7 +605,10 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) netdev->stats.rx_bytes += skb->len; /* push packet to protocol stack */ - napi_gro_receive(&priv->napi, skb); + if (skb->ip_summed == CHECKSUM_NONE) + netif_receive_skb(skb); + else + napi_gro_receive(&priv->napi, skb); (*processed)++; return true; @@ -1575,7 +1562,7 @@ static int ftgmac100_probe(struct platform_device *pdev) * when NCSI is enabled on the interface. It doesn't work * in that case. */ - netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO; + netdev->features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_GRO; if (priv->use_ncsi && of_get_property(pdev->dev.of_node, "no-hw-checksum", NULL)) netdev->features &= ~NETIF_F_IP_CSUM; |