diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 436f7689a032..bf1638044a7a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c | |||
@@ -574,16 +574,21 @@ static inline __wsum get_fixed_vlan_csum(__wsum hw_checksum, | |||
574 | * header, the HW adds it. To address that, we are subtracting the pseudo | 574 | * header, the HW adds it. To address that, we are subtracting the pseudo |
575 | * header checksum from the checksum value provided by the HW. | 575 | * header checksum from the checksum value provided by the HW. |
576 | */ | 576 | */ |
577 | static void get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb, | 577 | static int get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb, |
578 | struct iphdr *iph) | 578 | struct iphdr *iph) |
579 | { | 579 | { |
580 | __u16 length_for_csum = 0; | 580 | __u16 length_for_csum = 0; |
581 | __wsum csum_pseudo_header = 0; | 581 | __wsum csum_pseudo_header = 0; |
582 | __u8 ipproto = iph->protocol; | ||
583 | |||
584 | if (unlikely(ipproto == IPPROTO_SCTP)) | ||
585 | return -1; | ||
582 | 586 | ||
583 | length_for_csum = (be16_to_cpu(iph->tot_len) - (iph->ihl << 2)); | 587 | length_for_csum = (be16_to_cpu(iph->tot_len) - (iph->ihl << 2)); |
584 | csum_pseudo_header = csum_tcpudp_nofold(iph->saddr, iph->daddr, | 588 | csum_pseudo_header = csum_tcpudp_nofold(iph->saddr, iph->daddr, |
585 | length_for_csum, iph->protocol, 0); | 589 | length_for_csum, ipproto, 0); |
586 | skb->csum = csum_sub(hw_checksum, csum_pseudo_header); | 590 | skb->csum = csum_sub(hw_checksum, csum_pseudo_header); |
591 | return 0; | ||
587 | } | 592 | } |
588 | 593 | ||
589 | #if IS_ENABLED(CONFIG_IPV6) | 594 | #if IS_ENABLED(CONFIG_IPV6) |
@@ -594,17 +599,20 @@ static void get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb, | |||
594 | static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb, | 599 | static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb, |
595 | struct ipv6hdr *ipv6h) | 600 | struct ipv6hdr *ipv6h) |
596 | { | 601 | { |
602 | __u8 nexthdr = ipv6h->nexthdr; | ||
597 | __wsum csum_pseudo_hdr = 0; | 603 | __wsum csum_pseudo_hdr = 0; |
598 | 604 | ||
599 | if (unlikely(ipv6h->nexthdr == IPPROTO_FRAGMENT || | 605 | if (unlikely(nexthdr == IPPROTO_FRAGMENT || |
600 | ipv6h->nexthdr == IPPROTO_HOPOPTS)) | 606 | nexthdr == IPPROTO_HOPOPTS || |
607 | nexthdr == IPPROTO_SCTP)) | ||
601 | return -1; | 608 | return -1; |
602 | hw_checksum = csum_add(hw_checksum, (__force __wsum)htons(ipv6h->nexthdr)); | 609 | hw_checksum = csum_add(hw_checksum, (__force __wsum)htons(nexthdr)); |
603 | 610 | ||
604 | csum_pseudo_hdr = csum_partial(&ipv6h->saddr, | 611 | csum_pseudo_hdr = csum_partial(&ipv6h->saddr, |
605 | sizeof(ipv6h->saddr) + sizeof(ipv6h->daddr), 0); | 612 | sizeof(ipv6h->saddr) + sizeof(ipv6h->daddr), 0); |
606 | csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ipv6h->payload_len); | 613 | csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ipv6h->payload_len); |
607 | csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ntohs(ipv6h->nexthdr)); | 614 | csum_pseudo_hdr = csum_add(csum_pseudo_hdr, |
615 | (__force __wsum)htons(nexthdr)); | ||
608 | 616 | ||
609 | skb->csum = csum_sub(hw_checksum, csum_pseudo_hdr); | 617 | skb->csum = csum_sub(hw_checksum, csum_pseudo_hdr); |
610 | skb->csum = csum_add(skb->csum, csum_partial(ipv6h, sizeof(struct ipv6hdr), 0)); | 618 | skb->csum = csum_add(skb->csum, csum_partial(ipv6h, sizeof(struct ipv6hdr), 0)); |
@@ -627,11 +635,10 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va, | |||
627 | } | 635 | } |
628 | 636 | ||
629 | if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4)) | 637 | if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4)) |
630 | get_fixed_ipv4_csum(hw_checksum, skb, hdr); | 638 | return get_fixed_ipv4_csum(hw_checksum, skb, hdr); |
631 | #if IS_ENABLED(CONFIG_IPV6) | 639 | #if IS_ENABLED(CONFIG_IPV6) |
632 | else if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6)) | 640 | if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6)) |
633 | if (unlikely(get_fixed_ipv6_csum(hw_checksum, skb, hdr))) | 641 | return get_fixed_ipv6_csum(hw_checksum, skb, hdr); |
634 | return -1; | ||
635 | #endif | 642 | #endif |
636 | return 0; | 643 | return 0; |
637 | } | 644 | } |