Commit 2b8b2b26 authored by Eran Ben Elisha's avatar Eran Ben Elisha Committed by Greg Kroah-Hartman

net/mlx5e: When RXFCS is set, add FCS data into checksum calculation

[ Upstream commit 902a5459 ]

When RXFCS feature is enabled, the HW do not strip the FCS data,
however it is not present in the checksum calculated by the HW.

Fix that by manually calculating the FCS checksum and adding it to the SKB
checksum field.

Add helper function to find the FCS data for all SKB forms (linear,
one fragment or more).

Fixes: 102722fc ("net/mlx5e: Add support for RXFCS feature flag")
Signed-off-by: default avatarEran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 155cd575
......@@ -635,6 +635,45 @@ static inline bool is_first_ethertype_ip(struct sk_buff *skb)
return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
}
static __be32 mlx5e_get_fcs(struct sk_buff *skb)
{
int last_frag_sz, bytes_in_prev, nr_frags;
u8 *fcs_p1, *fcs_p2;
skb_frag_t *last_frag;
__be32 fcs_bytes;
if (!skb_is_nonlinear(skb))
return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
nr_frags = skb_shinfo(skb)->nr_frags;
last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
last_frag_sz = skb_frag_size(last_frag);
/* If all FCS data is in last frag */
if (last_frag_sz >= ETH_FCS_LEN)
return *(__be32 *)(skb_frag_address(last_frag) +
last_frag_sz - ETH_FCS_LEN);
fcs_p2 = (u8 *)skb_frag_address(last_frag);
bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
/* Find where the other part of the FCS is - Linear or another frag */
if (nr_frags == 1) {
fcs_p1 = skb_tail_pointer(skb);
} else {
skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
fcs_p1 = skb_frag_address(prev_frag) +
skb_frag_size(prev_frag);
}
fcs_p1 -= bytes_in_prev;
memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
return fcs_bytes;
}
static inline void mlx5e_handle_csum(struct net_device *netdev,
struct mlx5_cqe64 *cqe,
struct mlx5e_rq *rq,
......@@ -653,6 +692,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
if (is_first_ethertype_ip(skb)) {
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
if (unlikely(netdev->features & NETIF_F_RXFCS))
skb->csum = csum_add(skb->csum,
(__force __wsum)mlx5e_get_fcs(skb));
rq->stats.csum_complete++;
return;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment