wil6210: fix report of rx packet checksum in edma mode
authorAhmad Masri <amasri@codeaurora.org>
Thu, 28 Feb 2019 09:34:59 +0000 (11:34 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 3 Apr 2019 12:44:38 +0000 (15:44 +0300)
Update the rx packet checksum of received packet according to edma
HW spec:

No need to calculate checksum in the following cases:
L4_status=0 and L3_status=0 - No L3 and no L4 known protocols found
L4_status=0 and L3_status=1 - L3 was found, and checksum check passed.
No known L4 protocol was found.
L4_status=1 - L4 was found, and checksum check passed.

Recalculate checksum in the following cases:
L4_status=3 and L3_status=1 - It means that L3 protocol was found,
and checksum passed, but L4 checksum failed.
L4_status=3 and L3_status=2 - Both L3 and L4 checksum check failed.

Signed-off-by: Ahmad Masri <amasri@codeaurora.org>
Signed-off-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/wil6210/txrx_edma.c
drivers/net/wireless/ath/wil6210/txrx_edma.h

index 48098ae626771bc69fcdbdb3df74ebceac7c7624..492f7bdf39d9382de4f1643ad688a7ca26ee3257 100644 (file)
@@ -807,18 +807,9 @@ static int wil_rx_error_check_edma(struct wil6210_priv *wil,
                                   struct sk_buff *skb,
                                   struct wil_net_stats *stats)
 {
-       int error;
        int l2_rx_status;
-       int l3_rx_status;
-       int l4_rx_status;
        void *msg = wil_skb_rxstatus(skb);
 
-       error = wil_rx_status_get_error(msg);
-       if (!error) {
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               return 0;
-       }
-
        l2_rx_status = wil_rx_status_get_l2_rx_status(msg);
        if (l2_rx_status != 0) {
                wil_dbg_txrx(wil, "L2 RX error, l2_rx_status=0x%x\n",
@@ -847,17 +838,7 @@ static int wil_rx_error_check_edma(struct wil6210_priv *wil,
                return -EFAULT;
        }
 
-       l3_rx_status = wil_rx_status_get_l3_rx_status(msg);
-       l4_rx_status = wil_rx_status_get_l4_rx_status(msg);
-       if (!l3_rx_status && !l4_rx_status)
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-       /* If HW reports bad checksum, let IP stack re-check it
-        * For example, HW don't understand Microsoft IP stack that
-        * mis-calculates TCP checksum - if it should be 0x0,
-        * it writes 0xffff in violation of RFC 1624
-        */
-       else
-               stats->rx_csum_err++;
+       skb->ip_summed = wil_rx_status_get_checksum(msg, stats);
 
        return 0;
 }
index 343516a03a1e4098dc9c561845c358b25e3c460f..9cf9ecf6e8cfdea4a3ba9cba8721f35c9a90b817 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016,2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016,2018-2019, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -511,6 +511,45 @@ static inline int wil_rx_status_get_l4_rx_status(void *msg)
                            5, 6);
 }
 
+/* L4  L3      Expected result
+ * 0   0       Ok. No L3 and no L4 known protocols found.
+ *             Treated as L2 packet. (no offloads on this packet)
+ * 0   1       Ok. It means that L3 was found, and checksum check passed.
+ *             No known L4 protocol was found.
+ * 0   2       It means that L3 protocol was found, and checksum check failed.
+ *             No L4 known protocol was found.
+ * 1   any     Ok. It means that L4 was found, and checksum check passed.
+ * 3   0       Not a possible scenario.
+ * 3   1       Recalculate. It means that L3 protocol was found, and checksum
+ *             passed. But L4 checksum failed. Need to see if really failed,
+ *             or due to fragmentation.
+ * 3   2       Both L3 and L4 checksum check failed.
+ */
+static inline int wil_rx_status_get_checksum(void *msg,
+                                            struct wil_net_stats *stats)
+{
+       int l3_rx_status = wil_rx_status_get_l3_rx_status(msg);
+       int l4_rx_status = wil_rx_status_get_l4_rx_status(msg);
+
+       if (l4_rx_status == 1)
+               return CHECKSUM_UNNECESSARY;
+
+       if (l4_rx_status == 0 && l3_rx_status == 1)
+               return CHECKSUM_UNNECESSARY;
+
+       if (l3_rx_status == 0 && l4_rx_status == 0)
+               /* L2 packet */
+               return CHECKSUM_NONE;
+
+       /* If HW reports bad checksum, let IP stack re-check it
+        * For example, HW doesn't understand Microsoft IP stack that
+        * mis-calculates TCP checksum - if it should be 0x0,
+        * it writes 0xffff in violation of RFC 1624
+        */
+       stats->rx_csum_err++;
+       return CHECKSUM_NONE;
+}
+
 static inline int wil_rx_status_get_security(void *msg)
 {
        return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,