diff options
author | Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 2014-02-27 09:20:44 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-28 14:33:30 -0500 |
commit | b4490f423c0e61b77461be6557c62e533b8c60e3 (patch) | |
tree | c8e9c97285e48817737b4ac5c22afb7d16092f80 | |
parent | 3df2cd361871eb4636c8ce9cf97e6899c90c588c (diff) |
wil6210: Block ACK
When running multiple connections, hardware can't do BACK reordering
and it should be done on the host.
Model after mac80211's implementation. Drop RCU for now;
to be re-added when BACK will be stabilized
BACK handshaking is not implemented yet in the hardware,
pretend it was done to support the way FW operating
Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/wil6210/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 177 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 47 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 22 |
8 files changed, 290 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 990dd42ae79e..c7a3465fd02a 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -9,6 +9,7 @@ wil6210-y += wmi.o | |||
9 | wil6210-y += interrupt.o | 9 | wil6210-y += interrupt.o |
10 | wil6210-y += txrx.o | 10 | wil6210-y += txrx.o |
11 | wil6210-y += debug.o | 11 | wil6210-y += debug.o |
12 | wil6210-y += rx_reorder.o | ||
12 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o | 13 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o |
13 | 14 | ||
14 | # for tracing framework to find trace.h | 15 | # for tracing framework to find trace.h |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index f12aa0b1e1df..729e774ee96d 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -598,11 +598,24 @@ static const struct file_operations fops_temp = { | |||
598 | }; | 598 | }; |
599 | 599 | ||
600 | /*---------Station matrix------------*/ | 600 | /*---------Station matrix------------*/ |
601 | static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) | ||
602 | { | ||
603 | int i; | ||
604 | u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; | ||
605 | seq_printf(s, "0x%03x [", r->head_seq_num); | ||
606 | for (i = 0; i < r->buf_size; i++) { | ||
607 | if (i == index) | ||
608 | seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); | ||
609 | else | ||
610 | seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_'); | ||
611 | } | ||
612 | seq_puts(s, "]\n"); | ||
613 | } | ||
601 | 614 | ||
602 | static int wil_sta_debugfs_show(struct seq_file *s, void *data) | 615 | static int wil_sta_debugfs_show(struct seq_file *s, void *data) |
603 | { | 616 | { |
604 | struct wil6210_priv *wil = s->private; | 617 | struct wil6210_priv *wil = s->private; |
605 | int i; | 618 | int i, tid; |
606 | 619 | ||
607 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 620 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
608 | struct wil_sta_info *p = &wil->sta[i]; | 621 | struct wil_sta_info *p = &wil->sta[i]; |
@@ -619,6 +632,16 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) | |||
619 | break; | 632 | break; |
620 | } | 633 | } |
621 | seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); | 634 | seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); |
635 | |||
636 | if (p->status == wil_sta_connected) { | ||
637 | for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { | ||
638 | struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; | ||
639 | if (r) { | ||
640 | seq_printf(s, "[%2d] ", tid); | ||
641 | wil_print_rxtid(s, r); | ||
642 | } | ||
643 | } | ||
644 | } | ||
622 | } | 645 | } |
623 | 646 | ||
624 | return 0; | 647 | return 0; |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index f68481de0ad7..38906f1bc769 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
19 | 19 | ||
20 | #include "wil6210.h" | 20 | #include "wil6210.h" |
21 | #include "txrx.h" | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Due to a hardware issue, | 24 | * Due to a hardware issue, |
@@ -54,11 +55,20 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | |||
54 | 55 | ||
55 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | 56 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) |
56 | { | 57 | { |
57 | uint i; | 58 | uint i, cid; |
58 | struct net_device *ndev = wil_to_ndev(wil); | 59 | struct net_device *ndev = wil_to_ndev(wil); |
59 | 60 | ||
60 | wil_dbg_misc(wil, "%s()\n", __func__); | 61 | wil_dbg_misc(wil, "%s()\n", __func__); |
61 | 62 | ||
63 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) { | ||
64 | struct wil_sta_info *sta = &wil->sta[cid]; | ||
65 | for (i = 0; i < WIL_STA_TID_NUM; i++) { | ||
66 | struct wil_tid_ampdu_rx *r = sta->tid_rx[i]; | ||
67 | sta->tid_rx[i] = NULL; | ||
68 | wil_tid_ampdu_rx_free(wil, r); | ||
69 | } | ||
70 | } | ||
71 | |||
62 | wil_link_off(wil); | 72 | wil_link_off(wil); |
63 | if (test_bit(wil_status_fwconnected, &wil->status)) { | 73 | if (test_bit(wil_status_fwconnected, &wil->status)) { |
64 | clear_bit(wil_status_fwconnected, &wil->status); | 74 | clear_bit(wil_status_fwconnected, &wil->status); |
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c new file mode 100644 index 000000000000..d04629fe053f --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c | |||
@@ -0,0 +1,177 @@ | |||
1 | #include "wil6210.h" | ||
2 | #include "txrx.h" | ||
3 | |||
4 | #define SEQ_MODULO 0x1000 | ||
5 | #define SEQ_MASK 0xfff | ||
6 | |||
7 | static inline int seq_less(u16 sq1, u16 sq2) | ||
8 | { | ||
9 | return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); | ||
10 | } | ||
11 | |||
12 | static inline u16 seq_inc(u16 sq) | ||
13 | { | ||
14 | return (sq + 1) & SEQ_MASK; | ||
15 | } | ||
16 | |||
17 | static inline u16 seq_sub(u16 sq1, u16 sq2) | ||
18 | { | ||
19 | return (sq1 - sq2) & SEQ_MASK; | ||
20 | } | ||
21 | |||
22 | static inline int reorder_index(struct wil_tid_ampdu_rx *r, u16 seq) | ||
23 | { | ||
24 | return seq_sub(seq, r->ssn) % r->buf_size; | ||
25 | } | ||
26 | |||
27 | static void wil_release_reorder_frame(struct wil6210_priv *wil, | ||
28 | struct wil_tid_ampdu_rx *r, | ||
29 | int index) | ||
30 | { | ||
31 | struct net_device *ndev = wil_to_ndev(wil); | ||
32 | struct sk_buff *skb = r->reorder_buf[index]; | ||
33 | |||
34 | if (!skb) | ||
35 | goto no_frame; | ||
36 | |||
37 | /* release the frame from the reorder ring buffer */ | ||
38 | r->stored_mpdu_num--; | ||
39 | r->reorder_buf[index] = NULL; | ||
40 | wil_netif_rx_any(skb, ndev); | ||
41 | |||
42 | no_frame: | ||
43 | r->head_seq_num = seq_inc(r->head_seq_num); | ||
44 | } | ||
45 | |||
46 | static void wil_release_reorder_frames(struct wil6210_priv *wil, | ||
47 | struct wil_tid_ampdu_rx *r, | ||
48 | u16 hseq) | ||
49 | { | ||
50 | int index; | ||
51 | |||
52 | while (seq_less(r->head_seq_num, hseq)) { | ||
53 | index = reorder_index(r, r->head_seq_num); | ||
54 | wil_release_reorder_frame(wil, r, index); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static void wil_reorder_release(struct wil6210_priv *wil, | ||
59 | struct wil_tid_ampdu_rx *r) | ||
60 | { | ||
61 | int index = reorder_index(r, r->head_seq_num); | ||
62 | |||
63 | while (r->reorder_buf[index]) { | ||
64 | wil_release_reorder_frame(wil, r, index); | ||
65 | index = reorder_index(r, r->head_seq_num); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | ||
70 | { | ||
71 | struct net_device *ndev = wil_to_ndev(wil); | ||
72 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | ||
73 | int tid = wil_rxdesc_tid(d); | ||
74 | int cid = wil_rxdesc_cid(d); | ||
75 | int mid = wil_rxdesc_mid(d); | ||
76 | u16 seq = wil_rxdesc_seq(d); | ||
77 | struct wil_sta_info *sta = &wil->sta[cid]; | ||
78 | struct wil_tid_ampdu_rx *r = sta->tid_rx[tid]; | ||
79 | u16 hseq; | ||
80 | int index; | ||
81 | |||
82 | wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x\n", | ||
83 | mid, cid, tid, seq); | ||
84 | |||
85 | if (!r) { | ||
86 | wil_netif_rx_any(skb, ndev); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | hseq = r->head_seq_num; | ||
91 | |||
92 | spin_lock(&r->reorder_lock); | ||
93 | |||
94 | /* frame with out of date sequence number */ | ||
95 | if (seq_less(seq, r->head_seq_num)) { | ||
96 | dev_kfree_skb(skb); | ||
97 | goto out; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * If frame the sequence number exceeds our buffering window | ||
102 | * size release some previous frames to make room for this one. | ||
103 | */ | ||
104 | if (!seq_less(seq, r->head_seq_num + r->buf_size)) { | ||
105 | hseq = seq_inc(seq_sub(seq, r->buf_size)); | ||
106 | /* release stored frames up to new head to stack */ | ||
107 | wil_release_reorder_frames(wil, r, hseq); | ||
108 | } | ||
109 | |||
110 | /* Now the new frame is always in the range of the reordering buffer */ | ||
111 | |||
112 | index = reorder_index(r, seq); | ||
113 | |||
114 | /* check if we already stored this frame */ | ||
115 | if (r->reorder_buf[index]) { | ||
116 | dev_kfree_skb(skb); | ||
117 | goto out; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * If the current MPDU is in the right order and nothing else | ||
122 | * is stored we can process it directly, no need to buffer it. | ||
123 | * If it is first but there's something stored, we may be able | ||
124 | * to release frames after this one. | ||
125 | */ | ||
126 | if (seq == r->head_seq_num && r->stored_mpdu_num == 0) { | ||
127 | r->head_seq_num = seq_inc(r->head_seq_num); | ||
128 | wil_netif_rx_any(skb, ndev); | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | /* put the frame in the reordering buffer */ | ||
133 | r->reorder_buf[index] = skb; | ||
134 | r->reorder_time[index] = jiffies; | ||
135 | r->stored_mpdu_num++; | ||
136 | wil_reorder_release(wil, r); | ||
137 | |||
138 | out: | ||
139 | spin_unlock(&r->reorder_lock); | ||
140 | } | ||
141 | |||
142 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, | ||
143 | int size, u16 ssn) | ||
144 | { | ||
145 | struct wil_tid_ampdu_rx *r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
146 | if (!r) | ||
147 | return NULL; | ||
148 | |||
149 | r->reorder_buf = | ||
150 | kcalloc(size, sizeof(struct sk_buff *), GFP_KERNEL); | ||
151 | r->reorder_time = | ||
152 | kcalloc(size, sizeof(unsigned long), GFP_KERNEL); | ||
153 | if (!r->reorder_buf || !r->reorder_time) { | ||
154 | kfree(r->reorder_buf); | ||
155 | kfree(r->reorder_time); | ||
156 | kfree(r); | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | spin_lock_init(&r->reorder_lock); | ||
161 | r->ssn = ssn; | ||
162 | r->head_seq_num = ssn; | ||
163 | r->buf_size = size; | ||
164 | r->stored_mpdu_num = 0; | ||
165 | return r; | ||
166 | } | ||
167 | |||
168 | void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, | ||
169 | struct wil_tid_ampdu_rx *r) | ||
170 | { | ||
171 | if (!r) | ||
172 | return; | ||
173 | wil_release_reorder_frames(wil, r, r->head_seq_num + r->buf_size); | ||
174 | kfree(r->reorder_buf); | ||
175 | kfree(r->reorder_time); | ||
176 | kfree(r); | ||
177 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index eb60023fa217..48d97156f3db 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -472,7 +472,7 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) | |||
472 | * Pass Rx packet to the netif. Update statistics. | 472 | * Pass Rx packet to the netif. Update statistics. |
473 | * Called in softirq context (NAPI poll). | 473 | * Called in softirq context (NAPI poll). |
474 | */ | 474 | */ |
475 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | 475 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
476 | { | 476 | { |
477 | int rc; | 477 | int rc; |
478 | unsigned int len = skb->len; | 478 | unsigned int len = skb->len; |
@@ -515,12 +515,12 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) | |||
515 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 515 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
516 | skb->pkt_type = PACKET_OTHERHOST; | 516 | skb->pkt_type = PACKET_OTHERHOST; |
517 | skb->protocol = htons(ETH_P_802_2); | 517 | skb->protocol = htons(ETH_P_802_2); |
518 | 518 | wil_netif_rx_any(skb, ndev); | |
519 | } else { | 519 | } else { |
520 | skb->protocol = eth_type_trans(skb, ndev); | 520 | skb->protocol = eth_type_trans(skb, ndev); |
521 | wil_rx_reorder(wil, skb); | ||
521 | } | 522 | } |
522 | 523 | ||
523 | wil_netif_rx_any(skb, ndev); | ||
524 | } | 524 | } |
525 | wil_rx_refill(wil, v->size); | 525 | wil_rx_refill(wil, v->size); |
526 | } | 526 | } |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index b3828279204c..bc5706a4f007 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
@@ -436,4 +436,11 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) | |||
436 | return (void *)skb->cb; | 436 | return (void *)skb->cb; |
437 | } | 437 | } |
438 | 438 | ||
439 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); | ||
440 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); | ||
441 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, | ||
442 | int size, u16 ssn); | ||
443 | void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, | ||
444 | struct wil_tid_ampdu_rx *r); | ||
445 | |||
439 | #endif /* WIL6210_TXRX_H */ | 446 | #endif /* WIL6210_TXRX_H */ |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 38df203f723d..304b990295b7 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -215,6 +215,46 @@ enum { /* for wil6210_priv.status */ | |||
215 | 215 | ||
216 | struct pci_dev; | 216 | struct pci_dev; |
217 | 217 | ||
218 | /** | ||
219 | * struct tid_ampdu_rx - TID aggregation information (Rx). | ||
220 | * | ||
221 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | ||
222 | * @reorder_time: jiffies when skb was added | ||
223 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | ||
224 | * @reorder_timer: releases expired frames from the reorder buffer. | ||
225 | * @last_rx: jiffies of last rx activity | ||
226 | * @head_seq_num: head sequence number in reordering buffer. | ||
227 | * @stored_mpdu_num: number of MPDUs in reordering buffer | ||
228 | * @ssn: Starting Sequence Number expected to be aggregated. | ||
229 | * @buf_size: buffer size for incoming A-MPDUs | ||
230 | * @timeout: reset timer value (in TUs). | ||
231 | * @dialog_token: dialog token for aggregation session | ||
232 | * @rcu_head: RCU head used for freeing this struct | ||
233 | * @reorder_lock: serializes access to reorder buffer, see below. | ||
234 | * | ||
235 | * This structure's lifetime is managed by RCU, assignments to | ||
236 | * the array holding it must hold the aggregation mutex. | ||
237 | * | ||
238 | * The @reorder_lock is used to protect the members of this | ||
239 | * struct, except for @timeout, @buf_size and @dialog_token, | ||
240 | * which are constant across the lifetime of the struct (the | ||
241 | * dialog token being used only for debugging). | ||
242 | */ | ||
243 | struct wil_tid_ampdu_rx { | ||
244 | spinlock_t reorder_lock; /* see above */ | ||
245 | struct sk_buff **reorder_buf; | ||
246 | unsigned long *reorder_time; | ||
247 | struct timer_list session_timer; | ||
248 | struct timer_list reorder_timer; | ||
249 | unsigned long last_rx; | ||
250 | u16 head_seq_num; | ||
251 | u16 stored_mpdu_num; | ||
252 | u16 ssn; | ||
253 | u16 buf_size; | ||
254 | u16 timeout; | ||
255 | u8 dialog_token; | ||
256 | }; | ||
257 | |||
218 | struct wil6210_stats { | 258 | struct wil6210_stats { |
219 | u64 tsf; | 259 | u64 tsf; |
220 | u32 snr; | 260 | u32 snr; |
@@ -231,6 +271,9 @@ enum wil_sta_status { | |||
231 | wil_sta_conn_pending = 1, | 271 | wil_sta_conn_pending = 1, |
232 | wil_sta_connected = 2, | 272 | wil_sta_connected = 2, |
233 | }; | 273 | }; |
274 | |||
275 | #define WIL_STA_TID_NUM (16) | ||
276 | |||
234 | /** | 277 | /** |
235 | * struct wil_sta_info - data for peer | 278 | * struct wil_sta_info - data for peer |
236 | * | 279 | * |
@@ -242,6 +285,10 @@ enum wil_sta_status { | |||
242 | struct wil_sta_info { | 285 | struct wil_sta_info { |
243 | u8 addr[ETH_ALEN]; | 286 | u8 addr[ETH_ALEN]; |
244 | enum wil_sta_status status; | 287 | enum wil_sta_status status; |
288 | /* Rx BACK */ | ||
289 | struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM]; | ||
290 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)]; | ||
291 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)]; | ||
245 | }; | 292 | }; |
246 | 293 | ||
247 | struct wil6210_priv { | 294 | struct wil6210_priv { |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 2d602901675d..dfbc239b149d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -563,10 +563,27 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | |||
563 | int len) | 563 | int len) |
564 | { | 564 | { |
565 | struct wmi_vring_ba_status_event *evt = d; | 565 | struct wmi_vring_ba_status_event *evt = d; |
566 | uint cid, i; | ||
566 | 567 | ||
567 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", | 568 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", |
568 | evt->ringid, evt->status ? "N/A" : "OK", evt->agg_wsize, | 569 | evt->ringid, evt->status == WMI_BA_AGREED ? "OK" : "N/A", |
569 | __le16_to_cpu(evt->ba_timeout)); | 570 | evt->agg_wsize, __le16_to_cpu(evt->ba_timeout)); |
571 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) { | ||
572 | struct wil_sta_info *sta = &wil->sta[cid]; | ||
573 | |||
574 | if (sta->status == wil_sta_unused) | ||
575 | continue; | ||
576 | wil_dbg_wmi(wil, "Init BACK for CID %d %pM\n", cid, sta->addr); | ||
577 | for (i = 0; i < WIL_STA_TID_NUM; i++) { | ||
578 | struct wil_tid_ampdu_rx *r = sta->tid_rx[i]; | ||
579 | sta->tid_rx[i] = NULL; | ||
580 | wil_tid_ampdu_rx_free(wil, r); | ||
581 | if ((evt->status == WMI_BA_AGREED) && evt->agg_wsize) | ||
582 | sta->tid_rx[i] = wil_tid_ampdu_rx_alloc(wil, | ||
583 | evt->agg_wsize, 0); | ||
584 | } | ||
585 | } | ||
586 | |||
570 | } | 587 | } |
571 | 588 | ||
572 | static const struct { | 589 | static const struct { |
@@ -949,6 +966,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
949 | }, | 966 | }, |
950 | .mid = 0, /* TODO - what is it? */ | 967 | .mid = 0, /* TODO - what is it? */ |
951 | .decap_trans_type = WMI_DECAP_TYPE_802_3, | 968 | .decap_trans_type = WMI_DECAP_TYPE_802_3, |
969 | .reorder_type = WMI_RX_SW_REORDER, | ||
952 | }; | 970 | }; |
953 | struct { | 971 | struct { |
954 | struct wil6210_mbox_hdr_wmi wmi; | 972 | struct wil6210_mbox_hdr_wmi wmi; |