1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: target_if_mgmt_txrx_rx_reo.c
20 * This file contains definitions of management rx re-ordering related APIs.
21 */
22
23 #include <wlan_objmgr_psoc_obj.h>
24 #include <wlan_objmgr_pdev_obj.h>
25 #include <qdf_status.h>
26 #include <target_if.h>
27 #include <wlan_mgmt_txrx_rx_reo_public_structs.h>
28 #include <target_if_mgmt_txrx_rx_reo.h>
29 #include <wlan_lmac_if_api.h>
30 #include <init_deinit_lmac.h>
31 #include <wlan_mlo_mgr_setup.h>
32 #include <qdf_platform.h>
33
34 /**
35 * target_if_mgmt_rx_reo_fw_consumed_event_handler() - WMI event handler to
36 * process MGMT Rx FW consumed event handler
37 * @scn: Pointer to scn object
38 * @data: Pointer to event buffer
39 * @datalen: Length of event buffer
40 *
41 * Return: 0 for success, else failure
42 */
43 static int
target_if_mgmt_rx_reo_fw_consumed_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)44 target_if_mgmt_rx_reo_fw_consumed_event_handler(
45 ol_scn_t scn, uint8_t *data, uint32_t datalen)
46 {
47 struct wlan_objmgr_psoc *psoc;
48 struct wlan_objmgr_pdev *pdev;
49 struct wmi_unified *wmi_handle;
50 QDF_STATUS status;
51 struct mgmt_rx_reo_params params;
52 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops;
53
54 psoc = target_if_get_psoc_from_scn_hdl(scn);
55 if (!psoc) {
56 mgmt_rx_reo_err("null psoc");
57 return -EINVAL;
58 }
59
60 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
61 if (!wmi_handle) {
62 mgmt_rx_reo_err("wmi_handle is NULL");
63 return -EINVAL;
64 }
65
66 status = wmi_extract_mgmt_rx_fw_consumed(wmi_handle, data, ¶ms);
67 if (QDF_IS_STATUS_ERROR(status)) {
68 mgmt_rx_reo_err("Failed to extract mgmt rx params");
69 return -EINVAL;
70 }
71
72 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc);
73 if (!mgmt_rx_reo_rx_ops) {
74 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL");
75 return -EINVAL;
76 }
77
78 if (!mgmt_rx_reo_rx_ops->fw_consumed_event_handler) {
79 mgmt_rx_reo_err("FW consumed event handler is NULL");
80 return -EINVAL;
81 }
82
83 /* Take the pdev reference */
84 pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id,
85 WLAN_MGMT_SB_ID);
86 if (!pdev) {
87 mgmt_rx_reo_err("Couldn't get pdev for pdev_id: %d"
88 "on psoc: %pK", params.pdev_id, psoc);
89 return -EINVAL;
90 }
91
92 status = mgmt_rx_reo_rx_ops->fw_consumed_event_handler(pdev, ¶ms);
93 if (QDF_IS_STATUS_ERROR(status)) {
94 mgmt_rx_reo_warn_rl("FW consumed event handling failed");
95 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID);
96 return -EINVAL;
97 }
98
99 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID);
100 return 0;
101 }
102
target_if_mgmt_rx_reo_release_frames(void * arg)103 void target_if_mgmt_rx_reo_release_frames(void *arg)
104 {
105 ol_scn_t scn = arg;
106 struct wlan_objmgr_psoc *psoc;
107 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops;
108 QDF_STATUS status;
109
110 psoc = target_if_get_psoc_from_scn_hdl(scn);
111 if (!psoc) {
112 mgmt_rx_reo_err("null psoc");
113 return;
114 }
115
116 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc);
117 if (!mgmt_rx_reo_rx_ops) {
118 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL");
119 return;
120 }
121
122 status = mgmt_rx_reo_rx_ops->release_frames(psoc);
123 if (QDF_IS_STATUS_ERROR(status)) {
124 mgmt_rx_reo_err("Failed to release entries, ret = %d", status);
125 return;
126 }
127 }
128
129 QDF_STATUS
target_if_mgmt_rx_reo_register_event_handlers(struct wlan_objmgr_psoc * psoc)130 target_if_mgmt_rx_reo_register_event_handlers(struct wlan_objmgr_psoc *psoc)
131 {
132 struct wmi_unified *wmi_handle;
133 QDF_STATUS status;
134
135 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
136 if (!wmi_handle) {
137 mgmt_rx_reo_err("Invalid WMI handle");
138 return QDF_STATUS_E_INVAL;
139 }
140
141 status = wmi_unified_register_event_handler(
142 wmi_handle,
143 wmi_mgmt_rx_fw_consumed_eventid,
144 target_if_mgmt_rx_reo_fw_consumed_event_handler,
145 WMI_RX_UMAC_CTX);
146
147 if (QDF_IS_STATUS_ERROR(status)) {
148 mgmt_rx_reo_err("Register Rx FW consumed event cb errcode %d",
149 status);
150 if (status == QDF_STATUS_E_NOSUPPORT)
151 status = QDF_STATUS_SUCCESS;
152 }
153
154 return status;
155 }
156
157 QDF_STATUS
target_if_mgmt_rx_reo_unregister_event_handlers(struct wlan_objmgr_psoc * psoc)158 target_if_mgmt_rx_reo_unregister_event_handlers(struct wlan_objmgr_psoc *psoc)
159 {
160 struct wmi_unified *wmi_handle;
161 QDF_STATUS status;
162
163 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
164 if (!wmi_handle) {
165 mgmt_rx_reo_err("Invalid WMI handle");
166 return QDF_STATUS_E_INVAL;
167 }
168
169 status = wmi_unified_unregister_event_handler(
170 wmi_handle,
171 wmi_mgmt_rx_fw_consumed_eventid);
172
173 if (QDF_IS_STATUS_ERROR(status)) {
174 mgmt_rx_reo_err("Unregister Rx FW consumed event cb errcode %d",
175 status);
176 if (status == QDF_STATUS_E_NOSUPPORT)
177 status = QDF_STATUS_SUCCESS;
178 }
179
180 return status;
181 }
182
183 /**
184 * target_if_mgmt_rx_reo_get_num_active_hw_links() - Get number of active MLO HW
185 * links
186 * @psoc: Pointer to psoc object
187 * @num_active_hw_links: pointer to number of active MLO HW links
188 *
189 * Get number of active MLO HW links from the MLO global shared memory arena.
190 *
191 * Return: QDF_STATUS
192 */
193 static QDF_STATUS
target_if_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc * psoc,int8_t * num_active_hw_links)194 target_if_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc,
195 int8_t *num_active_hw_links)
196 {
197 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
198 uint8_t grp_id;
199
200 if (!psoc) {
201 mgmt_rx_reo_err("psoc is null");
202 return QDF_STATUS_E_NULL_VALUE;
203 }
204
205 if (!num_active_hw_links) {
206 mgmt_rx_reo_err("Pointer to num_active_hw_links is null");
207 return QDF_STATUS_E_NULL_VALUE;
208 }
209
210 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
211 mgmt_rx_reo_err("Failed to get valid MLO Group id");
212 return QDF_STATUS_E_INVAL;
213 }
214
215 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc);
216
217 if (!low_level_ops) {
218 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
219 return QDF_STATUS_E_NULL_VALUE;
220 }
221
222 if (!low_level_ops->implemented) {
223 mgmt_rx_reo_err("Low level ops not implemented");
224 return QDF_STATUS_E_INVAL;
225 }
226
227 *num_active_hw_links = low_level_ops->get_num_links(grp_id);
228
229 return QDF_STATUS_SUCCESS;
230 }
231
232 /**
233 * target_if_mgmt_rx_reo_get_valid_hw_link_bitmap() - Get valid MLO HW link
234 * bitmap
235 * @psoc: Pointer to psoc object
236 * @valid_hw_link_bitmap: Pointer to valid MLO HW link bitmap
237 *
238 * Get valid MLO HW link bitmap from the MLO global shared memory arena.
239 *
240 * Return: QDF_STATUS
241 */
242 QDF_STATUS
target_if_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc * psoc,uint16_t * valid_hw_link_bitmap)243 target_if_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc,
244 uint16_t *valid_hw_link_bitmap)
245 {
246 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
247 uint8_t grp_id;
248
249 if (!psoc) {
250 mgmt_rx_reo_err("psoc is null");
251 return QDF_STATUS_E_NULL_VALUE;
252 }
253
254 if (!valid_hw_link_bitmap) {
255 mgmt_rx_reo_err("Pointer to valid_hw_link_bitmap is null");
256 return QDF_STATUS_E_NULL_VALUE;
257 }
258
259 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
260 mgmt_rx_reo_err("Failed to get valid MLO Group id");
261 return QDF_STATUS_E_INVAL;
262 }
263
264 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc);
265
266 if (!low_level_ops) {
267 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
268 return QDF_STATUS_E_NULL_VALUE;
269 }
270
271 if (!low_level_ops->implemented) {
272 mgmt_rx_reo_err("Low level ops not implemented");
273 return QDF_STATUS_E_INVAL;
274 }
275
276 *valid_hw_link_bitmap = low_level_ops->get_valid_link_bitmap(grp_id);
277
278 return QDF_STATUS_SUCCESS;
279 }
280
281 /**
282 * target_if_mgmt_rx_reo_read_snapshot_raw() - Read raw value of management
283 * rx-reorder snapshot
284 * @pdev: pointer to pdev object
285 * @snapshot_address: snapshot address
286 * @mgmt_rx_reo_snapshot_low: Pointer to lower 32 bits of snapshot value
287 * @mgmt_rx_reo_snapshot_high: Pointer to higher 32 bits of snapshot value
288 * @snapshot_version: snapshot version
289 * @raw_snapshot: Raw snapshot data
290 *
291 * Read raw value of management rx-reorder snapshots.
292 *
293 * Return: QDF_STATUS
294 */
295 static QDF_STATUS
target_if_mgmt_rx_reo_read_snapshot_raw(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_shared_snapshot * snapshot_address,uint32_t * mgmt_rx_reo_snapshot_low,uint32_t * mgmt_rx_reo_snapshot_high,uint8_t snapshot_version,struct mgmt_rx_reo_shared_snapshot * raw_snapshot)296 target_if_mgmt_rx_reo_read_snapshot_raw
297 (struct wlan_objmgr_pdev *pdev,
298 struct mgmt_rx_reo_shared_snapshot *snapshot_address,
299 uint32_t *mgmt_rx_reo_snapshot_low,
300 uint32_t *mgmt_rx_reo_snapshot_high,
301 uint8_t snapshot_version,
302 struct mgmt_rx_reo_shared_snapshot *raw_snapshot)
303 {
304 uint32_t prev_snapshot_low;
305 uint32_t prev_snapshot_high;
306 uint32_t cur_snapshot_low;
307 uint32_t cur_snapshot_high;
308 uint8_t retry_count = 0;
309
310 if (snapshot_version == 1) {
311 *mgmt_rx_reo_snapshot_low =
312 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low);
313 *mgmt_rx_reo_snapshot_high =
314 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high);
315 raw_snapshot->mgmt_rx_reo_snapshot_low =
316 *mgmt_rx_reo_snapshot_low;
317 raw_snapshot->mgmt_rx_reo_snapshot_high =
318 *mgmt_rx_reo_snapshot_high;
319 return QDF_STATUS_SUCCESS;
320 }
321
322 prev_snapshot_low =
323 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low);
324 prev_snapshot_high =
325 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high);
326 raw_snapshot->mgmt_rx_reo_snapshot_low = prev_snapshot_low;
327 raw_snapshot->mgmt_rx_reo_snapshot_high = prev_snapshot_high;
328
329 for (; retry_count < (MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1);
330 retry_count++) {
331 cur_snapshot_low =
332 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low);
333 cur_snapshot_high =
334 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high);
335
336 raw_snapshot[retry_count + 1].mgmt_rx_reo_snapshot_low =
337 cur_snapshot_low;
338 raw_snapshot[retry_count + 1].mgmt_rx_reo_snapshot_high =
339 cur_snapshot_high;
340
341 if (prev_snapshot_low == cur_snapshot_low &&
342 prev_snapshot_high == cur_snapshot_high)
343 break;
344
345 prev_snapshot_low = cur_snapshot_low;
346 prev_snapshot_high = cur_snapshot_high;
347 }
348
349 if (retry_count ==
350 (MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1)) {
351 enum qdf_hang_reason reason;
352
353 reason = QDF_MGMT_RX_REO_INCONSISTENT_SNAPSHOT;
354 mgmt_rx_reo_err("Triggering self recovery, inconsistent SS");
355 qdf_trigger_self_recovery(wlan_pdev_get_psoc(pdev), reason);
356 }
357
358 *mgmt_rx_reo_snapshot_low = cur_snapshot_low;
359 *mgmt_rx_reo_snapshot_high = cur_snapshot_high;
360
361 return QDF_STATUS_SUCCESS;
362 }
363
364 /**
365 * target_if_mgmt_rx_reo_read_snapshot() - Read management rx-reorder snapshot
366 * @pdev: pdev pointer
367 * @snapshot_info: Snapshot info
368 * @id: Snapshot ID
369 * @snapshot_value: Pointer to snapshot value
370 * @raw_snapshot: Raw snapshot data
371 *
372 * Read management rx-reorder snapshots from target.
373 *
374 * Return: QDF_STATUS
375 */
376 static QDF_STATUS
target_if_mgmt_rx_reo_read_snapshot(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_snapshot_info * snapshot_info,enum mgmt_rx_reo_shared_snapshot_id id,struct mgmt_rx_reo_snapshot_params * snapshot_value,struct mgmt_rx_reo_shared_snapshot (* raw_snapshot)[MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT])377 target_if_mgmt_rx_reo_read_snapshot(
378 struct wlan_objmgr_pdev *pdev,
379 struct mgmt_rx_reo_snapshot_info *snapshot_info,
380 enum mgmt_rx_reo_shared_snapshot_id id,
381 struct mgmt_rx_reo_snapshot_params *snapshot_value,
382 struct mgmt_rx_reo_shared_snapshot (*raw_snapshot)
383 [MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT])
384 {
385 bool snapshot_valid;
386 uint16_t mgmt_pkt_ctr;
387 uint32_t global_timestamp;
388 uint32_t mgmt_rx_reo_snapshot_low;
389 uint32_t mgmt_rx_reo_snapshot_high;
390 uint8_t retry_count;
391 QDF_STATUS status;
392 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
393 struct mgmt_rx_reo_shared_snapshot *snapshot_address;
394 uint8_t snapshot_version;
395
396 if (!snapshot_info) {
397 mgmt_rx_reo_err("Mgmt Rx REO snapshot info null");
398 return QDF_STATUS_E_INVAL;
399 }
400
401 snapshot_address = snapshot_info->address;
402 if (!snapshot_address) {
403 mgmt_rx_reo_err("Mgmt Rx REO snapshot address null");
404 return QDF_STATUS_E_INVAL;
405 }
406
407 snapshot_version = snapshot_info->version;
408
409 if (!snapshot_value) {
410 mgmt_rx_reo_err("Mgmt Rx REO snapshot null");
411 return QDF_STATUS_E_INVAL;
412 }
413
414 qdf_mem_zero(snapshot_value, sizeof(*snapshot_value));
415
416 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(
417 wlan_pdev_get_psoc(pdev));
418
419 if (!low_level_ops) {
420 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
421 return QDF_STATUS_E_FAILURE;
422 }
423
424 /* Make sure that function pointers are populated */
425 if (!low_level_ops->implemented) {
426 mgmt_rx_reo_err("Low level ops not implemented");
427 return QDF_STATUS_E_INVAL;
428 }
429
430 switch (id) {
431 case MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW:
432 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED:
433 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED:
434 retry_count = 0;
435 for (; retry_count < MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT;
436 retry_count++) {
437 status = target_if_mgmt_rx_reo_read_snapshot_raw
438 (pdev, snapshot_address,
439 &mgmt_rx_reo_snapshot_low,
440 &mgmt_rx_reo_snapshot_high,
441 snapshot_version,
442 raw_snapshot[retry_count]);
443
444 if (QDF_IS_STATUS_ERROR(status)) {
445 mgmt_rx_reo_err("Failed to read snapshot %d",
446 id);
447 return QDF_STATUS_E_FAILURE;
448 }
449
450 snapshot_valid = low_level_ops->snapshot_is_valid(
451 mgmt_rx_reo_snapshot_low,
452 snapshot_version);
453
454 if (!snapshot_valid) {
455 mgmt_rx_reo_info("Invalid REO snapshot value");
456 snapshot_value->valid = false;
457 snapshot_value->mgmt_pkt_ctr =
458 low_level_ops->snapshot_get_mgmt_pkt_ctr
459 (mgmt_rx_reo_snapshot_low,
460 snapshot_version);
461 snapshot_value->global_timestamp =
462 low_level_ops->snapshot_get_global_timestamp
463 (mgmt_rx_reo_snapshot_low,
464 mgmt_rx_reo_snapshot_high,
465 snapshot_version);
466 snapshot_value->retry_count = retry_count + 1;
467 return QDF_STATUS_SUCCESS;
468 }
469
470 if (low_level_ops->snapshot_is_consistent
471 (mgmt_rx_reo_snapshot_low,
472 mgmt_rx_reo_snapshot_high,
473 snapshot_version)) {
474 global_timestamp =
475 low_level_ops->snapshot_get_global_timestamp
476 (mgmt_rx_reo_snapshot_low,
477 mgmt_rx_reo_snapshot_high,
478 snapshot_version);
479 mgmt_pkt_ctr =
480 low_level_ops->snapshot_get_mgmt_pkt_ctr
481 (mgmt_rx_reo_snapshot_low,
482 snapshot_version);
483 break;
484 }
485 mgmt_rx_reo_info("Inconsistent snapshot %d, version=%u, low=0x%x, high=0x%x, retry=%u",
486 id, snapshot_version,
487 mgmt_rx_reo_snapshot_low,
488 mgmt_rx_reo_snapshot_high,
489 retry_count);
490 }
491
492 if (retry_count == MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) {
493 enum qdf_hang_reason reason;
494
495 mgmt_rx_reo_err("Read retry limit, id = %d, ver = %u",
496 id, snapshot_version);
497 snapshot_value->valid = false;
498 snapshot_value->mgmt_pkt_ctr = 0xFFFF;
499 snapshot_value->global_timestamp = 0xFFFFFFFF;
500 snapshot_value->retry_count = retry_count;
501 reason = QDF_MGMT_RX_REO_INCONSISTENT_SNAPSHOT;
502 mgmt_rx_reo_err("Triggering self recovery, retry fail");
503 qdf_trigger_self_recovery(wlan_pdev_get_psoc(pdev),
504 reason);
505 return QDF_STATUS_E_FAILURE;
506 }
507
508 snapshot_value->valid = true;
509 snapshot_value->mgmt_pkt_ctr = mgmt_pkt_ctr;
510 snapshot_value->global_timestamp = global_timestamp;
511 snapshot_value->retry_count = retry_count + 1;
512 status = QDF_STATUS_SUCCESS;
513 break;
514
515 default:
516 mgmt_rx_reo_err("Invalid snapshot id %d", id);
517 status = QDF_STATUS_E_INVAL;
518 break;
519 }
520
521 return status;
522 }
523
524 /**
525 * target_if_mgmt_rx_reo_get_snapshot_info() - Get information related to
526 * management rx-reorder snapshot
527 * @pdev: Pointer to pdev object
528 * @id: Snapshot ID
529 * @snapshot_info: Pointer to snapshot info
530 *
531 * Return: QDF_STATUS
532 */
533 static QDF_STATUS
target_if_mgmt_rx_reo_get_snapshot_info(struct wlan_objmgr_pdev * pdev,enum mgmt_rx_reo_shared_snapshot_id id,struct mgmt_rx_reo_snapshot_info * snapshot_info)534 target_if_mgmt_rx_reo_get_snapshot_info
535 (struct wlan_objmgr_pdev *pdev,
536 enum mgmt_rx_reo_shared_snapshot_id id,
537 struct mgmt_rx_reo_snapshot_info *snapshot_info)
538 {
539 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
540 int8_t link_id;
541 int8_t snapshot_version;
542 uint8_t grp_id;
543 struct wlan_objmgr_psoc *psoc;
544
545 if (!pdev) {
546 mgmt_rx_reo_err("pdev is null");
547 return QDF_STATUS_E_NULL_VALUE;
548 }
549
550 psoc = wlan_pdev_get_psoc(pdev);
551 if (!psoc) {
552 mgmt_rx_reo_err("psoc is null");
553 return QDF_STATUS_E_NULL_VALUE;
554 }
555
556 if (id >= MGMT_RX_REO_SHARED_SNAPSHOT_MAX) {
557 mgmt_rx_reo_err("Mgmt RX REO snapshot id invalid %d", id);
558 return QDF_STATUS_E_INVAL;
559 }
560
561 if (!snapshot_info) {
562 mgmt_rx_reo_err("Ref to mgmt RX REO snapshot info is null");
563 return QDF_STATUS_E_NULL_VALUE;
564 }
565
566 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
567 mgmt_rx_reo_err("Failed to get valid MLO Group id");
568 return QDF_STATUS_E_INVAL;
569 }
570
571 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc);
572
573 if (!low_level_ops) {
574 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
575 return QDF_STATUS_E_FAILURE;
576 }
577
578 if (!low_level_ops->implemented) {
579 mgmt_rx_reo_err("Low level ops not implemented");
580 return QDF_STATUS_E_INVAL;
581 }
582
583 link_id = wlan_get_mlo_link_id_from_pdev(pdev);
584 if (link_id < 0) {
585 mgmt_rx_reo_err("Invalid link id %d", link_id);
586 return QDF_STATUS_E_INVAL;
587 }
588
589 snapshot_info->address =
590 low_level_ops->get_snapshot_address(grp_id,
591 link_id, id);
592
593 snapshot_version = low_level_ops->get_snapshot_version(grp_id, id);
594 if (snapshot_version < 0) {
595 mgmt_rx_reo_err("Invalid snapshot version %d MLO Group id %d",
596 snapshot_version, grp_id);
597 return QDF_STATUS_E_INVAL;
598 }
599
600 snapshot_info->version = snapshot_version;
601
602 return QDF_STATUS_SUCCESS;
603 }
604
605 /**
606 * target_if_mgmt_rx_reo_filter_config() - Configure MGMT Rx REO filter
607 * @pdev: Pointer to pdev objmgr
608 * @filter: Pointer to MGMT Rx REO filter
609 *
610 * Return: QDF_STATUS_SUCCESS for success or error code
611 */
612 static QDF_STATUS
target_if_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_filter * filter)613 target_if_mgmt_rx_reo_filter_config(
614 struct wlan_objmgr_pdev *pdev,
615 struct mgmt_rx_reo_filter *filter)
616 {
617 QDF_STATUS status;
618 struct wmi_unified *wmi_handle;
619 uint8_t pdev_id;
620
621 wmi_handle = lmac_get_pdev_wmi_handle(pdev);
622 if (!wmi_handle) {
623 mgmt_rx_reo_err("Invalid WMI handle");
624 return QDF_STATUS_E_INVAL;
625 }
626 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
627
628 status = wmi_unified_mgmt_rx_reo_filter_config_cmd(wmi_handle, pdev_id,
629 filter);
630 if (QDF_IS_STATUS_ERROR(status))
631 mgmt_rx_reo_err("Unable to send MGMT Rx REO Filter config cmd");
632
633 return status;
634 }
635
636 QDF_STATUS
target_if_mgmt_rx_reo_extract_reo_params(wmi_unified_t wmi_handle,void * evt_buf,struct mgmt_rx_event_params * params)637 target_if_mgmt_rx_reo_extract_reo_params(
638 wmi_unified_t wmi_handle, void *evt_buf,
639 struct mgmt_rx_event_params *params)
640 {
641 struct wlan_objmgr_psoc *psoc;
642
643 if (!wmi_handle) {
644 mgmt_rx_reo_err("wmi_handle is null");
645 return QDF_STATUS_E_NULL_VALUE;
646 }
647
648 psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
649 if (!psoc) {
650 mgmt_rx_reo_err("null psoc");
651 return QDF_STATUS_E_NULL_VALUE;
652 }
653
654 /* If REO feature is not enabled in FW, no need to extract REO params */
655 if (!wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_MGMT_RX_REO_CAPABLE))
656 return QDF_STATUS_SUCCESS;
657
658 if (!params) {
659 mgmt_rx_reo_err("MGMT Rx event parameters is NULL");
660 return QDF_STATUS_E_NULL_VALUE;
661 }
662
663 return wmi_extract_mgmt_rx_reo_params(wmi_handle, evt_buf,
664 params->reo_params);
665 }
666
667 /**
668 * target_if_mgmt_rx_reo_schedule_delivery() - Schedule the delivery of
669 * management frames of the given psoc
670 * @psoc: Pointer to psoc object
671 *
672 * Return: QDF_STATUS
673 */
674 static QDF_STATUS
target_if_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc * psoc)675 target_if_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc *psoc)
676 {
677 struct wmi_unified *wmi_handle;
678 QDF_STATUS status;
679 HTC_ENDPOINT_ID wmi_endpoint_id;
680 HTC_HANDLE htc_handle;
681
682 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
683 if (!wmi_handle) {
684 mgmt_rx_reo_err("wmi_handle is NULL");
685 return QDF_STATUS_E_NULL_VALUE;
686 }
687
688 htc_handle = lmac_get_htc_hdl(psoc);
689 if (!htc_handle) {
690 mgmt_rx_reo_err("HTC_handle is NULL");
691 return QDF_STATUS_E_NULL_VALUE;
692 }
693
694 wmi_endpoint_id = wmi_get_endpoint(wmi_handle);
695
696 status = htc_enable_custom_cb(htc_handle, wmi_endpoint_id);
697 if (QDF_IS_STATUS_ERROR(status)) {
698 mgmt_rx_reo_err("Failed to schedule delivery");
699 return status;
700 }
701
702 return QDF_STATUS_SUCCESS;
703 }
704
705 /**
706 * target_if_mgmt_rx_reo_cancel_scheduled_delivery() - Cancel the scheduled
707 * delivery of management frames of the given psoc
708 * @psoc: Pointer to psoc object
709 *
710 * Return: QDF_STATUS
711 */
712 static QDF_STATUS
target_if_mgmt_rx_reo_cancel_scheduled_delivery(struct wlan_objmgr_psoc * psoc)713 target_if_mgmt_rx_reo_cancel_scheduled_delivery(struct wlan_objmgr_psoc *psoc)
714 {
715 struct wmi_unified *wmi_handle;
716 QDF_STATUS status;
717 HTC_ENDPOINT_ID wmi_endpoint_id;
718 HTC_HANDLE htc_handle;
719
720 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
721 if (!wmi_handle) {
722 mgmt_rx_reo_err("wmi_handle is NULL");
723 return QDF_STATUS_E_NULL_VALUE;
724 }
725
726 htc_handle = lmac_get_htc_hdl(psoc);
727 if (!htc_handle) {
728 mgmt_rx_reo_err("HTC_handle is NULL");
729 return QDF_STATUS_E_NULL_VALUE;
730 }
731
732 wmi_endpoint_id = wmi_get_endpoint(wmi_handle);
733
734 status = htc_disable_custom_cb(htc_handle, wmi_endpoint_id);
735 if (QDF_IS_STATUS_ERROR(status)) {
736 mgmt_rx_reo_err("Failed to cancel scheduled delivery");
737 return status;
738 }
739
740 return QDF_STATUS_SUCCESS;
741 }
742
743 QDF_STATUS
target_if_mgmt_rx_reo_tx_ops_register(struct wlan_lmac_if_mgmt_txrx_tx_ops * mgmt_txrx_tx_ops)744 target_if_mgmt_rx_reo_tx_ops_register(
745 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops)
746 {
747 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_tx_ops;
748
749 if (!mgmt_txrx_tx_ops) {
750 mgmt_rx_reo_err("mgmt_txrx txops NULL");
751 return QDF_STATUS_E_FAILURE;
752 }
753 mgmt_rx_reo_tx_ops = &mgmt_txrx_tx_ops->mgmt_rx_reo_tx_ops;
754 mgmt_rx_reo_tx_ops->get_num_active_hw_links =
755 target_if_mgmt_rx_reo_get_num_active_hw_links;
756 mgmt_rx_reo_tx_ops->get_valid_hw_link_bitmap =
757 target_if_mgmt_rx_reo_get_valid_hw_link_bitmap;
758 mgmt_rx_reo_tx_ops->read_mgmt_rx_reo_snapshot =
759 target_if_mgmt_rx_reo_read_snapshot;
760 mgmt_rx_reo_tx_ops->get_mgmt_rx_reo_snapshot_info =
761 target_if_mgmt_rx_reo_get_snapshot_info;
762 mgmt_rx_reo_tx_ops->mgmt_rx_reo_filter_config =
763 target_if_mgmt_rx_reo_filter_config;
764 mgmt_rx_reo_tx_ops->schedule_delivery =
765 target_if_mgmt_rx_reo_schedule_delivery;
766 mgmt_rx_reo_tx_ops->cancel_scheduled_delivery =
767 target_if_mgmt_rx_reo_cancel_scheduled_delivery;
768
769 return QDF_STATUS_SUCCESS;
770 }
771
772 QDF_STATUS
target_if_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_event_params * params)773 target_if_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev,
774 struct mgmt_rx_event_params *params)
775 {
776 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops;
777
778 if (!pdev) {
779 mgmt_rx_reo_err("pdev is null");
780 return QDF_STATUS_E_NULL_VALUE;
781 }
782
783 if (!params) {
784 mgmt_rx_reo_err("mgmt rx event params are null");
785 return QDF_STATUS_E_NULL_VALUE;
786 }
787
788 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(
789 wlan_pdev_get_psoc(pdev));
790 if (!mgmt_rx_reo_rx_ops) {
791 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL");
792 return QDF_STATUS_E_NULL_VALUE;
793 }
794
795 return mgmt_rx_reo_rx_ops->host_drop_handler(pdev, params->reo_params);
796 }
797