1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3 * Copyright (C) 2024-2025 Intel Corporation
4 */
5 #include "agg.h"
6 #include "sta.h"
7 #include "hcmd.h"
8
9 static void
iwl_mld_reorder_release_frames(struct iwl_mld * mld,struct ieee80211_sta * sta,struct napi_struct * napi,struct iwl_mld_baid_data * baid_data,struct iwl_mld_reorder_buffer * reorder_buf,u16 nssn)10 iwl_mld_reorder_release_frames(struct iwl_mld *mld, struct ieee80211_sta *sta,
11 struct napi_struct *napi,
12 struct iwl_mld_baid_data *baid_data,
13 struct iwl_mld_reorder_buffer *reorder_buf,
14 u16 nssn)
15 {
16 struct iwl_mld_reorder_buf_entry *entries =
17 &baid_data->entries[reorder_buf->queue *
18 baid_data->entries_per_queue];
19 u16 ssn = reorder_buf->head_sn;
20
21 while (ieee80211_sn_less(ssn, nssn)) {
22 int index = ssn % baid_data->buf_size;
23 struct sk_buff_head *skb_list = &entries[index].frames;
24 struct sk_buff *skb;
25
26 ssn = ieee80211_sn_inc(ssn);
27
28 /* Empty the list. Will have more than one frame for A-MSDU.
29 * Empty list is valid as well since nssn indicates frames were
30 * received.
31 */
32 while ((skb = __skb_dequeue(skb_list))) {
33 iwl_mld_pass_packet_to_mac80211(mld, napi, skb,
34 reorder_buf->queue,
35 sta);
36 reorder_buf->num_stored--;
37 }
38 }
39 reorder_buf->head_sn = nssn;
40 }
41
iwl_mld_release_frames_from_notif(struct iwl_mld * mld,struct napi_struct * napi,u8 baid,u16 nssn,int queue)42 static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
43 struct napi_struct *napi,
44 u8 baid, u16 nssn, int queue)
45 {
46 struct iwl_mld_reorder_buffer *reorder_buf;
47 struct iwl_mld_baid_data *ba_data;
48 struct ieee80211_link_sta *link_sta;
49 u32 sta_id;
50
51 IWL_DEBUG_HT(mld, "Frame release notification for BAID %u, NSSN %d\n",
52 baid, nssn);
53
54 if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
55 baid >= ARRAY_SIZE(mld->fw_id_to_ba)))
56 return;
57
58 rcu_read_lock();
59
60 ba_data = rcu_dereference(mld->fw_id_to_ba[baid]);
61 if (!ba_data) {
62 IWL_DEBUG_HT(mld, "BAID %d not found in map\n", baid);
63 goto out_unlock;
64 }
65
66 /* pick any STA ID to find the pointer */
67 sta_id = ffs(ba_data->sta_mask) - 1;
68 link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
69 if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
70 goto out_unlock;
71
72 reorder_buf = &ba_data->reorder_buf[queue];
73
74 iwl_mld_reorder_release_frames(mld, link_sta->sta, napi, ba_data,
75 reorder_buf, nssn);
76 out_unlock:
77 rcu_read_unlock();
78 }
79
iwl_mld_handle_frame_release_notif(struct iwl_mld * mld,struct napi_struct * napi,struct iwl_rx_packet * pkt,int queue)80 void iwl_mld_handle_frame_release_notif(struct iwl_mld *mld,
81 struct napi_struct *napi,
82 struct iwl_rx_packet *pkt, int queue)
83 {
84 struct iwl_frame_release *release = (void *)pkt->data;
85 u32 pkt_len = iwl_rx_packet_payload_len(pkt);
86
87 if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
88 "Unexpected frame release notif size %u (expected %zu)\n",
89 pkt_len, sizeof(*release)))
90 return;
91
92 iwl_mld_release_frames_from_notif(mld, napi, release->baid,
93 le16_to_cpu(release->nssn),
94 queue);
95 }
96
iwl_mld_handle_bar_frame_release_notif(struct iwl_mld * mld,struct napi_struct * napi,struct iwl_rx_packet * pkt,int queue)97 void iwl_mld_handle_bar_frame_release_notif(struct iwl_mld *mld,
98 struct napi_struct *napi,
99 struct iwl_rx_packet *pkt,
100 int queue)
101 {
102 struct iwl_bar_frame_release *release = (void *)pkt->data;
103 struct iwl_mld_baid_data *baid_data;
104 unsigned int baid, nssn, sta_id, tid;
105 u32 pkt_len = iwl_rx_packet_payload_len(pkt);
106
107 if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
108 "Unexpected frame release notif size %u (expected %zu)\n",
109 pkt_len, sizeof(*release)))
110 return;
111
112 baid = le32_get_bits(release->ba_info,
113 IWL_BAR_FRAME_RELEASE_BAID_MASK);
114 nssn = le32_get_bits(release->ba_info,
115 IWL_BAR_FRAME_RELEASE_NSSN_MASK);
116 sta_id = le32_get_bits(release->sta_tid,
117 IWL_BAR_FRAME_RELEASE_STA_MASK);
118 tid = le32_get_bits(release->sta_tid,
119 IWL_BAR_FRAME_RELEASE_TID_MASK);
120
121 if (IWL_FW_CHECK(mld, baid >= ARRAY_SIZE(mld->fw_id_to_ba),
122 "BAR release: invalid BAID (%x)\n", baid))
123 return;
124
125 rcu_read_lock();
126 baid_data = rcu_dereference(mld->fw_id_to_ba[baid]);
127 if (!baid_data) {
128 IWL_DEBUG_HT(mld,
129 "Got valid BAID %d but not allocated\n",
130 baid);
131 goto out_unlock;
132 }
133
134 if (IWL_FW_CHECK(mld, tid != baid_data->tid ||
135 sta_id > mld->fw->ucode_capa.num_stations ||
136 !(baid_data->sta_mask & BIT(sta_id)),
137 "BAID 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",
138 baid, baid_data->sta_mask, baid_data->tid, sta_id,
139 tid))
140 goto out_unlock;
141
142 IWL_DEBUG_DROP(mld, "Received a BAR, expect packet loss: nssn %d\n",
143 nssn);
144
145 iwl_mld_release_frames_from_notif(mld, napi, baid, nssn, queue);
146 out_unlock:
147 rcu_read_unlock();
148 }
149
iwl_mld_del_ba(struct iwl_mld * mld,int queue,struct iwl_mld_delba_data * data)150 void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
151 struct iwl_mld_delba_data *data)
152 {
153 struct iwl_mld_baid_data *ba_data;
154 struct iwl_mld_reorder_buffer *reorder_buf;
155 struct ieee80211_link_sta *link_sta;
156 u8 baid = data->baid;
157 u32 sta_id;
158
159 if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
160 return;
161
162 rcu_read_lock();
163
164 ba_data = rcu_dereference(mld->fw_id_to_ba[baid]);
165 if (WARN_ON_ONCE(!ba_data))
166 goto out_unlock;
167
168 /* pick any STA ID to find the pointer */
169 sta_id = ffs(ba_data->sta_mask) - 1;
170 link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
171 if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
172 goto out_unlock;
173
174 reorder_buf = &ba_data->reorder_buf[queue];
175
176 /* release all frames that are in the reorder buffer to the stack */
177 iwl_mld_reorder_release_frames(mld, link_sta->sta, NULL,
178 ba_data, reorder_buf,
179 ieee80211_sn_add(reorder_buf->head_sn,
180 ba_data->buf_size));
181 out_unlock:
182 rcu_read_unlock();
183 }
184
185 /* Returns true if the MPDU was buffered\dropped, false if it should be passed
186 * to upper layer.
187 */
188 enum iwl_mld_reorder_result
iwl_mld_reorder(struct iwl_mld * mld,struct napi_struct * napi,int queue,struct ieee80211_sta * sta,struct sk_buff * skb,struct iwl_rx_mpdu_desc * desc)189 iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
190 int queue, struct ieee80211_sta *sta,
191 struct sk_buff *skb, struct iwl_rx_mpdu_desc *desc)
192 {
193 struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
194 struct iwl_mld_baid_data *baid_data;
195 struct iwl_mld_reorder_buffer *buffer;
196 struct iwl_mld_reorder_buf_entry *entries;
197 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
198 struct iwl_mld_link_sta *mld_link_sta;
199 u32 reorder = le32_to_cpu(desc->reorder_data);
200 bool amsdu, last_subframe, is_old_sn, is_dup;
201 u8 tid = ieee80211_get_tid(hdr);
202 u8 baid;
203 u16 nssn, sn;
204 u32 sta_mask = 0;
205 int index;
206 u8 link_id;
207
208 baid = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_BAID_MASK);
209
210 /* This also covers the case of receiving a Block Ack Request
211 * outside a BA session; we'll pass it to mac80211 and that
212 * then sends a delBA action frame.
213 * This also covers pure monitor mode, in which case we won't
214 * have any BA sessions.
215 */
216 if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
217 return IWL_MLD_PASS_SKB;
218
219 /* no sta yet */
220 if (WARN_ONCE(!sta,
221 "Got valid BAID without a valid station assigned\n"))
222 return IWL_MLD_PASS_SKB;
223
224 /* not a data packet */
225 if (!ieee80211_is_data_qos(hdr->frame_control) ||
226 is_multicast_ether_addr(hdr->addr1))
227 return IWL_MLD_PASS_SKB;
228
229 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
230 return IWL_MLD_PASS_SKB;
231
232 baid_data = rcu_dereference(mld->fw_id_to_ba[baid]);
233 if (!baid_data) {
234 IWL_DEBUG_HT(mld,
235 "Got valid BAID but no baid allocated, bypass re-ordering (BAID=%d reorder=0x%x)\n",
236 baid, reorder);
237 return IWL_MLD_PASS_SKB;
238 }
239
240 for_each_mld_link_sta(mld_sta, mld_link_sta, link_id)
241 sta_mask |= BIT(mld_link_sta->fw_id);
242
243 /* verify the BAID is correctly mapped to the sta and tid */
244 if (IWL_FW_CHECK(mld,
245 tid != baid_data->tid ||
246 !(sta_mask & baid_data->sta_mask),
247 "BAID 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
248 baid, baid_data->sta_mask, baid_data->tid,
249 sta_mask, tid))
250 return IWL_MLD_PASS_SKB;
251
252 buffer = &baid_data->reorder_buf[queue];
253 entries = &baid_data->entries[queue * baid_data->entries_per_queue];
254
255 is_old_sn = !!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN);
256
257 if (!buffer->valid && is_old_sn)
258 return IWL_MLD_PASS_SKB;
259
260 buffer->valid = true;
261
262 is_dup = !!(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE));
263
264 /* drop any duplicated or outdated packets */
265 if (is_dup || is_old_sn)
266 return IWL_MLD_DROP_SKB;
267
268 sn = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_SN_MASK);
269 nssn = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_NSSN_MASK);
270 amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
271 last_subframe = desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME;
272
273 /* release immediately if allowed by nssn and no stored frames */
274 if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
275 if (!amsdu || last_subframe)
276 buffer->head_sn = nssn;
277 return IWL_MLD_PASS_SKB;
278 }
279
280 /* release immediately if there are no stored frames, and the sn is
281 * equal to the head.
282 * This can happen due to reorder timer, where NSSN is behind head_sn.
283 * When we released everything, and we got the next frame in the
284 * sequence, according to the NSSN we can't release immediately,
285 * while technically there is no hole and we can move forward.
286 */
287 if (!buffer->num_stored && sn == buffer->head_sn) {
288 if (!amsdu || last_subframe)
289 buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
290 return IWL_MLD_PASS_SKB;
291 }
292
293 /* put in reorder buffer */
294 index = sn % baid_data->buf_size;
295 __skb_queue_tail(&entries[index].frames, skb);
296 buffer->num_stored++;
297
298 /* We cannot trust NSSN for AMSDU sub-frames that are not the last. The
299 * reason is that NSSN advances on the first sub-frame, and may cause
300 * the reorder buffer to advance before all the sub-frames arrive.
301 *
302 * Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with
303 * SN 1. NSSN for first sub frame will be 3 with the result of driver
304 * releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is
305 * already ahead and it will be dropped.
306 * If the last sub-frame is not on this queue - we will get frame
307 * release notification with up to date NSSN.
308 */
309 if (!amsdu || last_subframe)
310 iwl_mld_reorder_release_frames(mld, sta, napi, baid_data,
311 buffer, nssn);
312
313 return IWL_MLD_BUFFERED_SKB;
314 }
315 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_reorder);
316
iwl_mld_rx_agg_session_expired(struct timer_list * t)317 static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
318 {
319 struct iwl_mld_baid_data *data =
320 timer_container_of(data, t, session_timer);
321 struct iwl_mld_baid_data __rcu **rcu_ptr = data->rcu_ptr;
322 struct iwl_mld_baid_data *ba_data;
323 struct ieee80211_link_sta *link_sta;
324 struct iwl_mld_sta *mld_sta;
325 unsigned long timeout;
326 unsigned int sta_id;
327
328 rcu_read_lock();
329
330 ba_data = rcu_dereference(*rcu_ptr);
331 if (WARN_ON(!ba_data))
332 goto unlock;
333
334 if (WARN_ON(!ba_data->timeout))
335 goto unlock;
336
337 timeout = ba_data->last_rx_timestamp +
338 TU_TO_JIFFIES(ba_data->timeout * 2);
339 if (time_is_after_jiffies(timeout)) {
340 mod_timer(&ba_data->session_timer, timeout);
341 goto unlock;
342 }
343
344 /* timer expired, pick any STA ID to find the pointer */
345 sta_id = ffs(ba_data->sta_mask) - 1;
346 link_sta = rcu_dereference(ba_data->mld->fw_id_to_link_sta[sta_id]);
347
348 /* sta should be valid unless the following happens:
349 * The firmware asserts which triggers a reconfig flow, but
350 * the reconfig fails before we set the pointer to sta into
351 * the fw_id_to_link_sta pointer table. mac80211 can't stop
352 * A-MPDU and hence the timer continues to run. Then, the
353 * timer expires and sta is NULL.
354 */
355 if (IS_ERR_OR_NULL(link_sta) || WARN_ON(!link_sta->sta))
356 goto unlock;
357
358 mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
359 ieee80211_rx_ba_timer_expired(mld_sta->vif, link_sta->sta->addr,
360 ba_data->tid);
361 unlock:
362 rcu_read_unlock();
363 }
364
365 static int
iwl_mld_stop_ba_in_fw(struct iwl_mld * mld,struct ieee80211_sta * sta,int tid)366 iwl_mld_stop_ba_in_fw(struct iwl_mld *mld, struct ieee80211_sta *sta, int tid)
367 {
368 struct iwl_rx_baid_cfg_cmd cmd = {
369 .action = cpu_to_le32(IWL_RX_BAID_ACTION_REMOVE),
370 .remove.sta_id_mask =
371 cpu_to_le32(iwl_mld_fw_sta_id_mask(mld, sta)),
372 .remove.tid = cpu_to_le32(tid),
373
374 };
375 int ret;
376
377 ret = iwl_mld_send_cmd_pdu(mld,
378 WIDE_ID(DATA_PATH_GROUP,
379 RX_BAID_ALLOCATION_CONFIG_CMD),
380 &cmd);
381 if (ret)
382 return ret;
383
384 IWL_DEBUG_HT(mld, "RX BA Session stopped in fw\n");
385
386 return ret;
387 }
388
389 static int
iwl_mld_start_ba_in_fw(struct iwl_mld * mld,struct ieee80211_sta * sta,int tid,u16 ssn,u16 buf_size)390 iwl_mld_start_ba_in_fw(struct iwl_mld *mld, struct ieee80211_sta *sta,
391 int tid, u16 ssn, u16 buf_size)
392 {
393 struct iwl_rx_baid_cfg_cmd cmd = {
394 .action = cpu_to_le32(IWL_RX_BAID_ACTION_ADD),
395 .alloc.sta_id_mask =
396 cpu_to_le32(iwl_mld_fw_sta_id_mask(mld, sta)),
397 .alloc.tid = tid,
398 .alloc.ssn = cpu_to_le16(ssn),
399 .alloc.win_size = cpu_to_le16(buf_size),
400 };
401 struct iwl_host_cmd hcmd = {
402 .id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD),
403 .flags = CMD_WANT_SKB,
404 .len[0] = sizeof(cmd),
405 .data[0] = &cmd,
406 };
407 struct iwl_rx_baid_cfg_resp *resp;
408 struct iwl_rx_packet *pkt;
409 u32 resp_len;
410 int ret, baid;
411
412 BUILD_BUG_ON(sizeof(*resp) != sizeof(baid));
413
414 ret = iwl_mld_send_cmd(mld, &hcmd);
415 if (ret)
416 return ret;
417
418 pkt = hcmd.resp_pkt;
419
420 resp_len = iwl_rx_packet_payload_len(pkt);
421 if (IWL_FW_CHECK(mld, resp_len != sizeof(*resp),
422 "BAID_ALLOC_CMD: unexpected response length %d\n",
423 resp_len)) {
424 ret = -EIO;
425 goto out;
426 }
427
428 IWL_DEBUG_HT(mld, "RX BA Session started in fw\n");
429
430 resp = (void *)pkt->data;
431 baid = le32_to_cpu(resp->baid);
432
433 if (IWL_FW_CHECK(mld, baid < 0 || baid >= ARRAY_SIZE(mld->fw_id_to_ba),
434 "BAID_ALLOC_CMD: invalid BAID response %d\n", baid)) {
435 ret = -EINVAL;
436 goto out;
437 }
438
439 ret = baid;
440 out:
441 iwl_free_resp(&hcmd);
442 return ret;
443 }
444
iwl_mld_init_reorder_buffer(struct iwl_mld * mld,struct iwl_mld_baid_data * data,u16 ssn)445 static void iwl_mld_init_reorder_buffer(struct iwl_mld *mld,
446 struct iwl_mld_baid_data *data,
447 u16 ssn)
448 {
449 for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
450 struct iwl_mld_reorder_buffer *reorder_buf =
451 &data->reorder_buf[i];
452 struct iwl_mld_reorder_buf_entry *entries =
453 &data->entries[i * data->entries_per_queue];
454
455 reorder_buf->head_sn = ssn;
456 reorder_buf->queue = i;
457
458 for (int j = 0; j < data->buf_size; j++)
459 __skb_queue_head_init(&entries[j].frames);
460 }
461 }
462
iwl_mld_free_reorder_buffer(struct iwl_mld * mld,struct iwl_mld_baid_data * data)463 static void iwl_mld_free_reorder_buffer(struct iwl_mld *mld,
464 struct iwl_mld_baid_data *data)
465 {
466 struct iwl_mld_delba_data delba_data = {
467 .baid = data->baid,
468 };
469
470 iwl_mld_sync_rx_queues(mld, IWL_MLD_RXQ_NOTIF_DEL_BA,
471 &delba_data, sizeof(delba_data));
472
473 for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
474 struct iwl_mld_reorder_buffer *reorder_buf =
475 &data->reorder_buf[i];
476 struct iwl_mld_reorder_buf_entry *entries =
477 &data->entries[i * data->entries_per_queue];
478
479 if (likely(!reorder_buf->num_stored))
480 continue;
481
482 /* This shouldn't happen in regular DELBA since the RX queues
483 * sync internal DELBA notification should trigger a release
484 * of all frames in the reorder buffer.
485 */
486 WARN_ON(1);
487
488 for (int j = 0; j < data->buf_size; j++)
489 __skb_queue_purge(&entries[j].frames);
490 }
491 }
492
iwl_mld_ampdu_rx_start(struct iwl_mld * mld,struct ieee80211_sta * sta,int tid,u16 ssn,u16 buf_size,u16 timeout)493 int iwl_mld_ampdu_rx_start(struct iwl_mld *mld, struct ieee80211_sta *sta,
494 int tid, u16 ssn, u16 buf_size, u16 timeout)
495 {
496 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
497 struct iwl_mld_baid_data *baid_data = NULL;
498 u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
499 int ret, baid;
500 u32 sta_mask;
501
502 lockdep_assert_wiphy(mld->wiphy);
503
504 if (mld->num_rx_ba_sessions >= IWL_MAX_BAID) {
505 IWL_DEBUG_HT(mld,
506 "Max num of RX BA sessions reached; blocking new session\n");
507 return -ENOSPC;
508 }
509
510 sta_mask = iwl_mld_fw_sta_id_mask(mld, sta);
511 if (WARN_ON(!sta_mask))
512 return -EINVAL;
513
514 /* sparse doesn't like the __align() so don't check */
515 #ifndef __CHECKER__
516 /* The division below will be OK if either the cache line size
517 * can be divided by the entry size (ALIGN will round up) or if
518 * the entry size can be divided by the cache line size, in which
519 * case the ALIGN() will do nothing.
520 */
521 BUILD_BUG_ON(SMP_CACHE_BYTES % sizeof(baid_data->entries[0]) &&
522 sizeof(baid_data->entries[0]) % SMP_CACHE_BYTES);
523 #endif
524
525 /* Upward align the reorder buffer size to fill an entire cache
526 * line for each queue, to avoid sharing cache lines between
527 * different queues.
528 */
529 reorder_buf_size = ALIGN(reorder_buf_size, SMP_CACHE_BYTES);
530
531 /* Allocate here so if allocation fails we can bail out early
532 * before starting the BA session in the firmware
533 */
534 baid_data = kzalloc(sizeof(*baid_data) +
535 mld->trans->info.num_rxqs * reorder_buf_size,
536 GFP_KERNEL);
537 if (!baid_data)
538 return -ENOMEM;
539
540 /* This division is why we need the above BUILD_BUG_ON(),
541 * if that doesn't hold then this will not be right.
542 */
543 baid_data->entries_per_queue =
544 reorder_buf_size / sizeof(baid_data->entries[0]);
545
546 baid = iwl_mld_start_ba_in_fw(mld, sta, tid, ssn, buf_size);
547 if (baid < 0) {
548 ret = baid;
549 goto out_free;
550 }
551
552 mld->num_rx_ba_sessions++;
553 mld_sta->tid_to_baid[tid] = baid;
554
555 baid_data->baid = baid;
556 baid_data->mld = mld;
557 baid_data->tid = tid;
558 baid_data->buf_size = buf_size;
559 baid_data->sta_mask = sta_mask;
560 baid_data->timeout = timeout;
561 baid_data->last_rx_timestamp = jiffies;
562 baid_data->rcu_ptr = &mld->fw_id_to_ba[baid];
563
564 iwl_mld_init_reorder_buffer(mld, baid_data, ssn);
565
566 timer_setup(&baid_data->session_timer, iwl_mld_rx_agg_session_expired,
567 0);
568 if (timeout)
569 mod_timer(&baid_data->session_timer,
570 TU_TO_EXP_TIME(timeout * 2));
571
572 IWL_DEBUG_HT(mld, "STA mask=0x%x (tid=%d) is assigned to BAID %d\n",
573 baid_data->sta_mask, tid, baid);
574
575 /* protect the BA data with RCU to cover a case where our
576 * internal RX sync mechanism will timeout (not that it's
577 * supposed to happen) and we will free the session data while
578 * RX is being processed in parallel
579 */
580 WARN_ON(rcu_access_pointer(mld->fw_id_to_ba[baid]));
581 rcu_assign_pointer(mld->fw_id_to_ba[baid], baid_data);
582
583 return 0;
584
585 out_free:
586 kfree(baid_data);
587 return ret;
588 }
589
iwl_mld_ampdu_rx_stop(struct iwl_mld * mld,struct ieee80211_sta * sta,int tid)590 int iwl_mld_ampdu_rx_stop(struct iwl_mld *mld, struct ieee80211_sta *sta,
591 int tid)
592 {
593 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
594 int baid = mld_sta->tid_to_baid[tid];
595 struct iwl_mld_baid_data *baid_data;
596 int ret;
597
598 lockdep_assert_wiphy(mld->wiphy);
599
600 /* during firmware restart, do not send the command as the firmware no
601 * longer recognizes the session. instead, only clear the driver BA
602 * session data.
603 */
604 if (!mld->fw_status.in_hw_restart) {
605 ret = iwl_mld_stop_ba_in_fw(mld, sta, tid);
606 if (ret)
607 return ret;
608 }
609
610 if (!WARN_ON(mld->num_rx_ba_sessions == 0))
611 mld->num_rx_ba_sessions--;
612
613 baid_data = wiphy_dereference(mld->wiphy, mld->fw_id_to_ba[baid]);
614 if (WARN_ON(!baid_data))
615 return -EINVAL;
616
617 if (timer_pending(&baid_data->session_timer))
618 timer_shutdown_sync(&baid_data->session_timer);
619
620 iwl_mld_free_reorder_buffer(mld, baid_data);
621
622 RCU_INIT_POINTER(mld->fw_id_to_ba[baid], NULL);
623 kfree_rcu(baid_data, rcu_head);
624
625 IWL_DEBUG_HT(mld, "BAID %d is free\n", baid);
626
627 return 0;
628 }
629
iwl_mld_update_sta_baids(struct iwl_mld * mld,u32 old_sta_mask,u32 new_sta_mask)630 int iwl_mld_update_sta_baids(struct iwl_mld *mld,
631 u32 old_sta_mask,
632 u32 new_sta_mask)
633 {
634 struct iwl_rx_baid_cfg_cmd cmd = {
635 .action = cpu_to_le32(IWL_RX_BAID_ACTION_MODIFY),
636 .modify.old_sta_id_mask = cpu_to_le32(old_sta_mask),
637 .modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
638 };
639 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
640 int baid;
641
642 /* mac80211 will remove sessions later, but we ignore all that */
643 if (mld->fw_status.in_hw_restart)
644 return 0;
645
646 BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
647
648 for (baid = 0; baid < ARRAY_SIZE(mld->fw_id_to_ba); baid++) {
649 struct iwl_mld_baid_data *data;
650 int ret;
651
652 data = wiphy_dereference(mld->wiphy, mld->fw_id_to_ba[baid]);
653 if (!data)
654 continue;
655
656 if (!(data->sta_mask & old_sta_mask))
657 continue;
658
659 WARN_ONCE(data->sta_mask != old_sta_mask,
660 "BAID data for %d corrupted - expected 0x%x found 0x%x\n",
661 baid, old_sta_mask, data->sta_mask);
662
663 cmd.modify.tid = cpu_to_le32(data->tid);
664
665 ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
666 if (ret)
667 return ret;
668 data->sta_mask = new_sta_mask;
669 }
670
671 return 0;
672 }
673