xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mgmt_txrx/src/target_if_mgmt_txrx_rx_reo.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  *  DOC: target_if_mgmt_txrx_rx_reo.c
19  *  This file contains definitions of management rx re-ordering related APIs.
20  */
21 
22 #include <wlan_objmgr_psoc_obj.h>
23 #include <wlan_objmgr_pdev_obj.h>
24 #include <qdf_status.h>
25 #include <target_if.h>
26 #include <wlan_mgmt_txrx_rx_reo_public_structs.h>
27 #include <target_if_mgmt_txrx_rx_reo.h>
28 #include <wlan_lmac_if_api.h>
29 #include <init_deinit_lmac.h>
30 
31 /**
32  * target_if_mgmt_rx_reo_fw_consumed_event_handler() - WMI event handler to
33  * process MGMT Rx FW consumed event handler
34  * @scn: Pointer to scn object
35  * @data_buf: Pointer to event buffer
36  * @data_len: Length of event buffer
37  *
38  * Return: 0 for success, else failure
39  */
40 static int
41 target_if_mgmt_rx_reo_fw_consumed_event_handler(
42 	ol_scn_t scn, uint8_t *data, uint32_t datalen)
43 {
44 	struct wlan_objmgr_psoc *psoc;
45 	struct wlan_objmgr_pdev *pdev;
46 	struct wmi_unified *wmi_handle;
47 	QDF_STATUS status;
48 	struct mgmt_rx_reo_params params;
49 	struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops;
50 
51 	psoc = target_if_get_psoc_from_scn_hdl(scn);
52 	if (!psoc) {
53 		mgmt_rx_reo_err("null psoc");
54 		return -EINVAL;
55 	}
56 
57 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
58 	if (!wmi_handle) {
59 		mgmt_rx_reo_err("wmi_handle is NULL");
60 		return -EINVAL;
61 	}
62 
63 	status = wmi_extract_mgmt_rx_fw_consumed(wmi_handle, data, &params);
64 	if (QDF_IS_STATUS_ERROR(status)) {
65 		mgmt_rx_reo_err("Failed to extract mgmt rx params");
66 		return -EINVAL;
67 	}
68 
69 	mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc);
70 	if (!mgmt_rx_reo_rx_ops) {
71 		mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL");
72 		return -EINVAL;
73 	}
74 
75 	if (!mgmt_rx_reo_rx_ops->fw_consumed_event_handler) {
76 		mgmt_rx_reo_err("FW consumed event handler is NULL");
77 		return -EINVAL;
78 	}
79 
80 	/* Take the pdev reference */
81 	pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id,
82 					  WLAN_MGMT_SB_ID);
83 	if (!pdev) {
84 		mgmt_rx_reo_err("Couldn't get pdev for pdev_id: %d"
85 				"on psoc: %pK", params.pdev_id, psoc);
86 		return -EINVAL;
87 	}
88 
89 	status = mgmt_rx_reo_rx_ops->fw_consumed_event_handler(pdev, &params);
90 	if (QDF_IS_STATUS_ERROR(status)) {
91 		mgmt_rx_reo_err("FW consumed event handling failed");
92 		wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID);
93 		return -EINVAL;
94 	}
95 
96 	wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID);
97 	return 0;
98 }
99 
100 QDF_STATUS
101 target_if_mgmt_rx_reo_register_event_handlers(struct wlan_objmgr_psoc *psoc)
102 {
103 	struct wmi_unified *wmi_handle;
104 	QDF_STATUS status;
105 
106 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
107 	if (!wmi_handle) {
108 		mgmt_rx_reo_err("Invalid WMI handle");
109 		return QDF_STATUS_E_INVAL;
110 	}
111 
112 	status = wmi_unified_register_event_handler(
113 			wmi_handle,
114 			wmi_mgmt_rx_fw_consumed_eventid,
115 			target_if_mgmt_rx_reo_fw_consumed_event_handler,
116 			WMI_RX_UMAC_CTX);
117 
118 	if (QDF_IS_STATUS_ERROR(status))
119 		mgmt_rx_reo_err("Registering for MGMT Rx FW consumed event failed");
120 
121 	return status;
122 }
123 
124 QDF_STATUS
125 target_if_mgmt_rx_reo_unregister_event_handlers(struct wlan_objmgr_psoc *psoc)
126 {
127 	struct wmi_unified *wmi_handle;
128 	QDF_STATUS status;
129 
130 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
131 	if (!wmi_handle) {
132 		mgmt_rx_reo_err("Invalid WMI handle");
133 		return QDF_STATUS_E_INVAL;
134 	}
135 
136 	status = wmi_unified_unregister_event_handler(
137 			wmi_handle,
138 			wmi_mgmt_rx_fw_consumed_eventid);
139 
140 	if (QDF_IS_STATUS_ERROR(status))
141 		mgmt_rx_reo_err("Unregistering for MGMT Rx FW consumed event failed");
142 
143 	return status;
144 }
145 
146 /**
147  * target_if_mgmt_rx_reo_read_snapshot() - Read management rx-reorder snapshot
148  * @pdev: pdev pointer
149  * @snapshot_address: Snapshot address
150  * @id: Snapshot ID
151  * @snapshot_value: Pointer to snapshot value
152  *
153  * Read management rx-reorder snapshots from target.
154  *
155  * Return: QDF_STATUS
156  */
157 static QDF_STATUS
158 target_if_mgmt_rx_reo_read_snapshot(
159 			struct wlan_objmgr_pdev *pdev,
160 			struct mgmt_rx_reo_snapshot *snapshot_address,
161 			enum mgmt_rx_reo_shared_snapshot_id id,
162 			struct mgmt_rx_reo_snapshot_params *snapshot_value)
163 {
164 	bool snapshot_valid;
165 	uint16_t mgmt_pkt_ctr;
166 	uint16_t redundant_mgmt_pkt_ctr;
167 	uint32_t global_timestamp;
168 	uint32_t mgmt_rx_reo_snapshot_low;
169 	uint32_t mgmt_rx_reo_snapshot_high;
170 	uint8_t retry_count;
171 	QDF_STATUS status;
172 	struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
173 
174 	if (!snapshot_address) {
175 		mgmt_rx_reo_err("Mgmt Rx REO snapshot address null");
176 		return QDF_STATUS_E_INVAL;
177 	}
178 
179 	if (!snapshot_value) {
180 		mgmt_rx_reo_err("Mgmt Rx REO snapshot null");
181 		return QDF_STATUS_E_INVAL;
182 	}
183 
184 	low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(
185 				wlan_pdev_get_psoc(pdev));
186 
187 	if (!low_level_ops) {
188 		mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
189 		return QDF_STATUS_E_FAILURE;
190 	}
191 
192 	/* Make sure that function pointers are populated */
193 	qdf_assert_always(low_level_ops->implemented);
194 
195 	switch (id) {
196 	case MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW:
197 	case MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED:
198 	case MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWADED:
199 		retry_count = 0;
200 		for (; retry_count < MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT;
201 		     retry_count++) {
202 			mgmt_rx_reo_snapshot_low =
203 				snapshot_address->mgmt_rx_reo_snapshot_low;
204 			mgmt_rx_reo_snapshot_high =
205 				snapshot_address->mgmt_rx_reo_snapshot_high;
206 
207 			snapshot_valid = low_level_ops->snapshot_is_valid(
208 						mgmt_rx_reo_snapshot_low);
209 			if (!snapshot_valid) {
210 				mgmt_rx_reo_debug("Invalid REO snapshot value");
211 				snapshot_value->valid = false;
212 				return QDF_STATUS_SUCCESS;
213 			}
214 
215 			global_timestamp =
216 				low_level_ops->snapshot_get_global_timestamp(
217 					mgmt_rx_reo_snapshot_low,
218 					mgmt_rx_reo_snapshot_high);
219 			mgmt_pkt_ctr =
220 				low_level_ops->snapshot_get_mgmt_pkt_ctr(
221 					mgmt_rx_reo_snapshot_low);
222 
223 			redundant_mgmt_pkt_ctr =
224 			     low_level_ops->snapshot_get_redundant_mgmt_pkt_ctr(
225 					mgmt_rx_reo_snapshot_high);
226 
227 			if (low_level_ops->snapshot_is_consistent(
228 					mgmt_pkt_ctr, redundant_mgmt_pkt_ctr))
229 				break;
230 
231 			mgmt_rx_reo_info("Inconsistent snapshot value low=0x%x high=0x%x",
232 					 mgmt_rx_reo_snapshot_low,
233 					 mgmt_rx_reo_snapshot_high);
234 		}
235 
236 		if (retry_count == MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) {
237 			mgmt_rx_reo_debug("Read retry limit reached");
238 			snapshot_value->valid = false;
239 			return QDF_STATUS_SUCCESS;
240 		}
241 
242 		snapshot_value->valid = true;
243 		snapshot_value->mgmt_pkt_ctr = mgmt_pkt_ctr;
244 		snapshot_value->global_timestamp = global_timestamp;
245 		status = QDF_STATUS_SUCCESS;
246 		break;
247 
248 	default:
249 		mgmt_rx_reo_err("Invalid snapshot id %d", id);
250 		status = QDF_STATUS_E_INVAL;
251 		break;
252 	}
253 
254 	return status;
255 }
256 
257 /**
258  * target_if_mgmt_rx_reo_get_snapshot_address() - Get management rx-reorder
259  * snapshot address(virtual address) in host memory
260  * @pdev: Pointer to pdev object
261  * @id: Snapshot ID
262  * @snapshot_address: Pointer to snapshot address where the address needs
263  * to be written
264  *
265  * Return: QDF_STATUS
266  */
267 static QDF_STATUS
268 target_if_mgmt_rx_reo_get_snapshot_address(
269 			struct wlan_objmgr_pdev *pdev,
270 			enum mgmt_rx_reo_shared_snapshot_id id,
271 			struct mgmt_rx_reo_snapshot **snapshot_address)
272 {
273 	struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops;
274 	uint8_t link_id;
275 
276 	if (!pdev) {
277 		mgmt_rx_reo_err("pdev is null");
278 		return QDF_STATUS_E_NULL_VALUE;
279 	}
280 
281 	if (id >= MGMT_RX_REO_SHARED_SNAPSHOT_MAX) {
282 		mgmt_rx_reo_err("Mgmt RX REO snapshot id invalid %d", id);
283 		return QDF_STATUS_E_INVAL;
284 	}
285 
286 	if (!snapshot_address) {
287 		mgmt_rx_reo_err("Ref to mgmt RX REO snapshot address is null");
288 		return QDF_STATUS_E_NULL_VALUE;
289 	}
290 
291 	low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(
292 				wlan_pdev_get_psoc(pdev));
293 
294 	if (!low_level_ops) {
295 		mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null");
296 		return QDF_STATUS_E_FAILURE;
297 	}
298 
299 	qdf_assert_always(low_level_ops->implemented);
300 
301 	link_id = wlan_get_mlo_link_id_from_pdev(pdev);
302 	*snapshot_address = low_level_ops->get_snapshot_address(link_id, id);
303 
304 	return QDF_STATUS_SUCCESS;
305 }
306 
307 /**
308  * target_if_mgmt_rx_reo_filter_config() - Configure MGMT Rx REO filter
309  * @pdev: Pointer to pdev objmgr
310  * @filter: Pointer to MGMT Rx REO filter
311  *
312  * Return: QDF_STATUS_SUCCESS for success or error code
313  */
314 static QDF_STATUS
315 target_if_mgmt_rx_reo_filter_config(
316 	struct wlan_objmgr_pdev *pdev,
317 	struct mgmt_rx_reo_filter *filter)
318 {
319 	QDF_STATUS status;
320 	struct wmi_unified *wmi_handle;
321 	uint8_t pdev_id;
322 
323 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
324 	if (!wmi_handle) {
325 		mgmt_rx_reo_err("Invalid WMI handle");
326 		return QDF_STATUS_E_INVAL;
327 	}
328 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
329 
330 	status = wmi_unified_mgmt_rx_reo_filter_config_cmd(wmi_handle, pdev_id,
331 							   filter);
332 	if (QDF_IS_STATUS_ERROR(status))
333 		mgmt_rx_reo_err("Unable to send MGMT Rx REO Filter config cmd");
334 
335 	return status;
336 }
337 
338 QDF_STATUS
339 target_if_mgmt_rx_reo_extract_reo_params(
340 	wmi_unified_t wmi_handle, void *evt_buf,
341 	struct mgmt_rx_event_params *params)
342 {
343 	if (!params) {
344 		mgmt_rx_reo_err("MGMT Rx event parameters is NULL");
345 		return QDF_STATUS_E_INVAL;
346 	}
347 
348 	return wmi_extract_mgmt_rx_reo_params(wmi_handle, evt_buf,
349 					      params->reo_params);
350 }
351 
352 QDF_STATUS
353 target_if_mgmt_rx_reo_tx_ops_register(
354 			struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops)
355 {
356 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_tx_ops;
357 
358 	if (!mgmt_txrx_tx_ops) {
359 		mgmt_rx_reo_err("mgmt_txrx txops NULL");
360 		return QDF_STATUS_E_FAILURE;
361 	}
362 	mgmt_rx_reo_tx_ops = &mgmt_txrx_tx_ops->mgmt_rx_reo_tx_ops;
363 	mgmt_rx_reo_tx_ops->read_mgmt_rx_reo_snapshot =
364 				target_if_mgmt_rx_reo_read_snapshot;
365 	mgmt_rx_reo_tx_ops->get_mgmt_rx_reo_snapshot_address =
366 				target_if_mgmt_rx_reo_get_snapshot_address;
367 	mgmt_rx_reo_tx_ops->mgmt_rx_reo_filter_config =
368 					target_if_mgmt_rx_reo_filter_config;
369 
370 	return QDF_STATUS_SUCCESS;
371 }
372 
373 QDF_STATUS
374 target_if_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev,
375 					struct mgmt_rx_event_params *params)
376 {
377 	struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops;
378 
379 	if (!pdev) {
380 		mgmt_rx_reo_err("pdev is null");
381 		return QDF_STATUS_E_NULL_VALUE;
382 	}
383 
384 	if (!params) {
385 		mgmt_rx_reo_err("mgmt rx event params are null");
386 		return QDF_STATUS_E_NULL_VALUE;
387 	}
388 
389 	mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(
390 					wlan_pdev_get_psoc(pdev));
391 	if (!mgmt_rx_reo_rx_ops) {
392 		mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL");
393 		return QDF_STATUS_E_NULL_VALUE;
394 	}
395 
396 	return mgmt_rx_reo_rx_ops->host_drop_handler(pdev, params->reo_params);
397 }
398