wil6210: drop Rx packets with L2 error indication from HW
authorDedy Lansky <dlansky@codeaurora.org>
Tue, 24 Jul 2018 07:44:23 +0000 (10:44 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 31 Jul 2018 07:59:41 +0000 (10:59 +0300)
Due to recent change in FW, driver will be notified of corrupted Rx
packets (e.g. MIC error).
Drop such packets before they are delivered to network stack.

Signed-off-by: Dedy Lansky <dlansky@codeaurora.org>
Signed-off-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/txrx_edma.c
drivers/net/wireless/ath/wil6210/wil6210.h

index 7d62126..99b1fc5 100644 (file)
@@ -1734,13 +1734,11 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
                                   p->stats.rx_short_frame,
                                   p->stats.rx_large_frame,
                                   p->stats.rx_replay);
-
-                       if (wil->use_enhanced_dma_hw)
-                               seq_printf(s,
-                                          "mic error  %lu, key error %lu, amsdu error %lu\n",
-                                          p->stats.rx_mic_error,
-                                          p->stats.rx_key_error,
-                                          p->stats.rx_amsdu_error);
+                       seq_printf(s,
+                                  "mic error %lu, key error %lu, amsdu error %lu\n",
+                                  p->stats.rx_mic_error,
+                                  p->stats.rx_key_error,
+                                  p->stats.rx_amsdu_error);
 
                        seq_puts(s, "Rx/MCS:");
                        for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
index ad40a96..9ac8674 100644 (file)
@@ -678,6 +678,21 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
        return 0;
 }
 
+static int wil_rx_error_check(struct wil6210_priv *wil, struct sk_buff *skb,
+                             struct wil_net_stats *stats)
+{
+       struct vring_rx_desc *d = wil_skb_rxdesc(skb);
+
+       if ((d->dma.status & RX_DMA_STATUS_ERROR) &&
+           (d->dma.error & RX_DMA_ERROR_MIC)) {
+               stats->rx_mic_error++;
+               wil_dbg_txrx(wil, "MIC error, dropping packet\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
 static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid,
                                    int *security)
 {
@@ -736,6 +751,12 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
                goto stats;
        }
 
+       /* check errors reported by HW and update statistics */
+       if (unlikely(wil->txrx_ops.rx_error_check(wil, skb, stats))) {
+               dev_kfree_skb(skb);
+               return;
+       }
+
        if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
                if (mcast) {
                        /* send multicast frames both to higher layers in
@@ -2212,6 +2233,7 @@ void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil)
        wil->txrx_ops.get_netif_rx_params =
                wil_get_netif_rx_params;
        wil->txrx_ops.rx_crypto_check = wil_rx_crypto_check;
+       wil->txrx_ops.rx_error_check = wil_rx_error_check;
        wil->txrx_ops.is_rx_idle = wil_is_rx_idle;
        wil->txrx_ops.rx_fini = wil_rx_fini;
 }
index 1940347..b5d399f 100644 (file)
@@ -795,14 +795,15 @@ static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
        return -EAGAIN;
 }
 
-static int wil_rx_edma_check_errors(struct wil6210_priv *wil, void *msg,
-                                   struct wil_net_stats *stats,
-                                   struct sk_buff *skb)
+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) {
@@ -865,7 +866,6 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
        struct wil_net_stats *stats = NULL;
        u16 dmalen;
        int cid;
-       int rc;
        bool eop, headstolen;
        int delta;
        u8 dr_bit;
@@ -937,13 +937,6 @@ again:
                goto skipping;
        }
 
-       /* Check and treat errors reported by HW */
-       rc = wil_rx_edma_check_errors(wil, msg, stats, skb);
-       if (rc) {
-               rxdata->skipping = true;
-               goto skipping;
-       }
-
        if (unlikely(dmalen > sz)) {
                wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
                stats->rx_large_frame++;
@@ -1593,6 +1586,7 @@ void wil_init_txrx_ops_edma(struct wil6210_priv *wil)
        wil->txrx_ops.get_reorder_params = wil_get_reorder_params_edma;
        wil->txrx_ops.get_netif_rx_params = wil_get_netif_rx_params_edma;
        wil->txrx_ops.rx_crypto_check = wil_rx_crypto_check_edma;
+       wil->txrx_ops.rx_error_check = wil_rx_error_check_edma;
        wil->txrx_ops.is_rx_idle = wil_is_rx_idle_edma;
        wil->txrx_ops.rx_fini = wil_rx_fini_edma;
 }
index 9b1467c..002d336 100644 (file)
@@ -543,6 +543,27 @@ struct wil_status_ring {
        struct wil_ring_rx_data rx_data;
 };
 
+#define WIL_STA_TID_NUM (16)
+#define WIL_MCS_MAX (12) /* Maximum MCS supported */
+
+struct wil_net_stats {
+       unsigned long   rx_packets;
+       unsigned long   tx_packets;
+       unsigned long   rx_bytes;
+       unsigned long   tx_bytes;
+       unsigned long   tx_errors;
+       unsigned long   rx_dropped;
+       unsigned long   rx_non_data_frame;
+       unsigned long   rx_short_frame;
+       unsigned long   rx_large_frame;
+       unsigned long   rx_replay;
+       unsigned long   rx_mic_error;
+       unsigned long   rx_key_error; /* eDMA specific */
+       unsigned long   rx_amsdu_error; /* eDMA specific */
+       u16 last_mcs_rx;
+       u64 rx_per_mcs[WIL_MCS_MAX + 1];
+};
+
 /**
  * struct tx_rx_ops - different TX/RX ops for legacy and enhanced
  * DMA flow
@@ -576,6 +597,8 @@ struct wil_txrx_ops {
        void (*get_netif_rx_params)(struct sk_buff *skb,
                                    int *cid, int *security);
        int (*rx_crypto_check)(struct wil6210_priv *wil, struct sk_buff *skb);
+       int (*rx_error_check)(struct wil6210_priv *wil, struct sk_buff *skb,
+                             struct wil_net_stats *stats);
        bool (*is_rx_idle)(struct wil6210_priv *wil);
        irqreturn_t (*irq_rx)(int irq, void *cookie);
 };
@@ -676,27 +699,6 @@ enum wil_sta_status {
        wil_sta_connected = 2,
 };
 
-#define WIL_STA_TID_NUM (16)
-#define WIL_MCS_MAX (12) /* Maximum MCS supported */
-
-struct wil_net_stats {
-       unsigned long   rx_packets;
-       unsigned long   tx_packets;
-       unsigned long   rx_bytes;
-       unsigned long   tx_bytes;
-       unsigned long   tx_errors;
-       unsigned long   rx_dropped;
-       unsigned long   rx_non_data_frame;
-       unsigned long   rx_short_frame;
-       unsigned long   rx_large_frame;
-       unsigned long   rx_replay;
-       unsigned long   rx_mic_error; /* eDMA specific */
-       unsigned long   rx_key_error; /* eDMA specific */
-       unsigned long   rx_amsdu_error; /* eDMA specific */
-       u16 last_mcs_rx;
-       u64 rx_per_mcs[WIL_MCS_MAX + 1];
-};
-
 /**
  * struct wil_sta_info - data for peer
  *