diff options
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx_edma.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 6 |
7 files changed, 40 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 58ce044b1130..7d621264ddd0 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1640,6 +1640,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) int i; u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; unsigned long long drop_dup = r->drop_dup, drop_old = r->drop_old; + unsigned long long drop_dup_mcast = r->drop_dup_mcast; seq_printf(s, "([%2d]) 0x%03x [", r->buf_size, r->head_seq_num); for (i = 0; i < r->buf_size; i++) { @@ -1649,9 +1650,9 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_'); } seq_printf(s, - "] total %llu drop %llu (dup %llu + old %llu) last 0x%03x\n", - r->total, drop_dup + drop_old, drop_dup, drop_old, - r->ssn_last_drop); + "] total %llu drop %llu (dup %llu + old %llu + dup mcast %llu) last 0x%03x\n", + r->total, drop_dup + drop_old + drop_dup_mcast, drop_dup, + drop_old, drop_dup_mcast, r->ssn_last_drop); } static void wil_print_rxtid_crypto(struct seq_file *s, int tid, diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 22475a1ddb7f..ba4e93f53b4a 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -95,7 +95,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { struct wil6210_vif *vif; struct net_device *ndev; - int tid, cid, mid, mcast; + int tid, cid, mid, mcast, retry; u16 seq; struct wil_sta_info *sta; struct wil_tid_ampdu_rx *r; @@ -103,7 +103,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) int index; wil->txrx_ops.get_reorder_params(wil, skb, &tid, &cid, &mid, &seq, - &mcast); + &mcast, &retry); sta = &wil->sta[cid]; wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n", @@ -117,11 +117,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) } ndev = vif_to_ndev(vif); - if (unlikely(mcast)) { - wil_netif_rx_any(skb, ndev); - return; - } - spin_lock(&sta->tid_rx_lock); r = sta->tid_rx[tid]; @@ -130,6 +125,19 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) goto out; } + if (unlikely(mcast)) { + if (retry && seq == r->mcast_last_seq) { + r->drop_dup_mcast++; + wil_dbg_txrx(wil, "Rx drop: dup mcast seq 0x%03x\n", + seq); + dev_kfree_skb(skb); + goto out; + } + r->mcast_last_seq = seq; + wil_netif_rx_any(skb, ndev); + goto out; + } + r->total++; hseq = r->head_seq_num; @@ -262,6 +270,7 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, r->buf_size = size; r->stored_mpdu_num = 0; r->first_time = true; + r->mcast_last_seq = U16_MAX; return r; } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 2098f3cc1cec..ad40a96821ed 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -2180,7 +2180,7 @@ static inline void wil_tx_fini(struct wil6210_priv *wil) {} static void wil_get_reorder_params(struct wil6210_priv *wil, struct sk_buff *skb, int *tid, int *cid, - int *mid, u16 *seq, int *mcast) + int *mid, u16 *seq, int *mcast, int *retry) { struct vring_rx_desc *d = wil_skb_rxdesc(skb); @@ -2189,6 +2189,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil, *mid = wil_rxdesc_mid(d); *seq = wil_rxdesc_seq(d); *mcast = wil_rxdesc_mcast(d); + *retry = wil_rxdesc_retry(d); } void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index f361423628f5..3dfd7f916137 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -500,6 +500,11 @@ static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 28, 31); } +static inline int wil_rxdesc_retry(struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d0, 31, 31); +} + static inline int wil_rxdesc_key_id(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d1, 4, 5); diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 95f38e65d969..194034779b9f 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -503,7 +503,7 @@ out_free: static void wil_get_reorder_params_edma(struct wil6210_priv *wil, struct sk_buff *skb, int *tid, int *cid, int *mid, u16 *seq, - int *mcast) + int *mcast, int *retry) { struct wil_rx_status_extended *s = wil_skb_rxstatus(skb); @@ -512,6 +512,7 @@ static void wil_get_reorder_params_edma(struct wil6210_priv *wil, *mid = wil_rx_status_get_mid(s); *seq = le16_to_cpu(wil_rx_status_get_seq(wil, s)); *mcast = wil_rx_status_get_mcast(s); + *retry = wil_rx_status_get_retry(s); } static void wil_get_netif_rx_params_edma(struct sk_buff *skb, int *cid, diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h index e86fc2dc0ce0..a7fe9292fda3 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.h +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h @@ -471,6 +471,12 @@ static inline __le16 wil_rx_status_get_seq(struct wil6210_priv *wil, void *msg) return ((struct wil_rx_status_extended *)msg)->ext.seq_num; } +static inline u8 wil_rx_status_get_retry(void *msg) +{ + /* retry bit is missing in EDMA HW. return 1 to be on the safe side */ + return 1; +} + static inline int wil_rx_status_get_mid(void *msg) { if (!(((struct wil_rx_status_compressed *)msg)->d0 & diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index d963c76b679e..9b1467c49ccc 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -572,7 +572,7 @@ struct wil_txrx_ops { u16 agg_wsize, u16 timeout); void (*get_reorder_params)(struct wil6210_priv *wil, struct sk_buff *skb, int *tid, int *cid, - int *mid, u16 *seq, int *mcast); + int *mid, u16 *seq, int *mcast, int *retry); 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); @@ -625,6 +625,8 @@ struct pci_dev; * @drop_dup: duplicate frames dropped for this reorder buffer * @drop_old: old frames dropped for this reorder buffer * @first_time: true when this buffer used 1-st time + * @mcast_last_seq: sequence number (SN) of last received multicast packet + * @drop_dup_mcast: duplicate multicast frames dropped for this reorder buffer */ struct wil_tid_ampdu_rx { struct sk_buff **reorder_buf; @@ -638,6 +640,8 @@ struct wil_tid_ampdu_rx { unsigned long long drop_dup; unsigned long long drop_old; bool first_time; /* is it 1-st time this buffer used? */ + u16 mcast_last_seq; /* multicast dup detection */ + unsigned long long drop_dup_mcast; }; /** |