xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mgmt_txrx/src/target_if_mgmt_txrx_rx_reo.c (revision 105a5fc213414550918220be4f56cabac64e99d8)
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
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, &params);
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, &params);
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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