wil6210: drop Rx packets with L2 error indication from HW

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>
This commit is contained in:
Dedy Lansky 2018-07-24 10:44:23 +03:00 committed by Kalle Valo
parent 1bd82ee09a
commit e15af41c05
4 changed files with 55 additions and 39 deletions

View 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);

View 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;
}

View 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;
}

View 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
*