xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: target_if_vdev_mgr_rx_ops.c
21  *
22  * This file provide definition for APIs registered through events received
23  * from FW
24  */
25 #include <target_if_vdev_mgr_rx_ops.h>
26 #include <target_if_vdev_mgr_tx_ops.h>
27 #include <wlan_vdev_mgr_tgt_if_rx_defs.h>
28 #include <wlan_vdev_mgr_tgt_if_tx_defs.h>
29 #include <wmi_unified_param.h>
30 #include <wlan_mlme_dbg.h>
31 #include <target_if.h>
32 #include <qdf_platform.h>
33 #include <wlan_vdev_mlme_main.h>
34 
35 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg)
36 {
37 	struct wlan_objmgr_vdev *vdev = arg;
38 	struct wlan_objmgr_psoc *psoc;
39 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
40 	struct vdev_response_timer *vdev_rsp;
41 	struct crash_inject param;
42 	struct wmi_unified *wmi_handle;
43 	struct vdev_start_response start_rsp = {0};
44 	struct vdev_stop_response stop_rsp = {0};
45 	struct vdev_delete_response del_rsp = {0};
46 	uint8_t vdev_id;
47 
48 	vdev_id = wlan_vdev_get_id(vdev);
49 	mlme_debug("Response timer expired for VDEV %d", vdev_id);
50 
51 	psoc = wlan_vdev_get_psoc(vdev);
52 	if (!psoc) {
53 		mlme_err("PSOC is NULL");
54 		return;
55 	}
56 
57 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
58 	if (!rx_ops || !rx_ops->vdev_mgr_get_response_timer_info) {
59 		mlme_err("No Rx Ops");
60 		return;
61 	}
62 
63 	vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev);
64 	if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
65 	    !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
66 	    !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
67 	    !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status)) {
68 		mlme_debug("No response bit is set, ignoring actions");
69 		return;
70 	}
71 
72 	if (target_if_vdev_mgr_is_driver_unloading() || qdf_is_recovering() ||
73 	    qdf_is_fw_down()) {
74 		/* this ensures stop timer will not be done in target_if */
75 		vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT;
76 		if (qdf_atomic_test_bit(START_RESPONSE_BIT,
77 					&vdev_rsp->rsp_status) ||
78 		    qdf_atomic_test_bit(RESTART_RESPONSE_BIT,
79 					&vdev_rsp->rsp_status)) {
80 			start_rsp.vdev_id = wlan_vdev_get_id(vdev);
81 			start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT;
82 			if (qdf_atomic_test_bit(START_RESPONSE_BIT,
83 						&vdev_rsp->rsp_status))
84 				start_rsp.resp_type =
85 					WMI_HOST_VDEV_START_RESP_EVENT;
86 			else
87 				start_rsp.resp_type =
88 					WMI_HOST_VDEV_RESTART_RESP_EVENT;
89 
90 			rx_ops->vdev_mgr_start_response(psoc, &start_rsp);
91 		}
92 
93 		if (qdf_atomic_test_bit(STOP_RESPONSE_BIT,
94 					&vdev_rsp->rsp_status)) {
95 			stop_rsp.vdev_id = wlan_vdev_get_id(vdev);
96 			rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp);
97 		}
98 
99 		if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT,
100 					&vdev_rsp->rsp_status)) {
101 			del_rsp.vdev_id = wlan_vdev_get_id(vdev);
102 			rx_ops->vdev_mgr_delete_response(psoc, &del_rsp);
103 		}
104 
105 		return;
106 	}
107 
108 	if (target_if_vdev_mgr_is_panic_on_bug()) {
109 		QDF_DEBUG_PANIC("PSOC_%d VDEV_%d: Panic on bug, rsp status:%d",
110 				wlan_psoc_get_id(psoc),
111 			        vdev_id, vdev_rsp->rsp_status);
112 	} else {
113 		mlme_err("PSOC_%d VDEV_%d: Trigger Self recovery, rsp status%d",
114 			 wlan_psoc_get_id(psoc),
115 			 vdev_id, vdev_rsp->rsp_status);
116 		wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev);
117 
118 		qdf_mem_set(&param, sizeof(param), 0);
119 		/* RECOVERY_SIM_SELF_RECOVERY*/
120 		param.type = 0x08;
121 		wmi_crash_inject(wmi_handle, &param);
122 	}
123 }
124 
125 static int target_if_vdev_mgr_start_response_handler(
126 					ol_scn_t scn,
127 					uint8_t *data,
128 					uint32_t datalen)
129 {
130 	QDF_STATUS status;
131 	struct wlan_objmgr_psoc *psoc;
132 	struct wmi_unified *wmi_handle;
133 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
134 	struct vdev_start_response rsp = {0};
135 	wmi_host_vdev_start_resp vdev_start_resp;
136 
137 	if (!scn || !data) {
138 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
139 		return -EINVAL;
140 	}
141 
142 	psoc = target_if_get_psoc_from_scn_hdl(scn);
143 	if (!psoc) {
144 		mlme_err("PSOC is NULL");
145 		return -EINVAL;
146 	}
147 
148 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
149 	if (!rx_ops || !rx_ops->vdev_mgr_start_response) {
150 		mlme_err("No Rx Ops");
151 		return -EINVAL;
152 	}
153 
154 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
155 	if (!wmi_handle) {
156 		mlme_err("wmi_handle is null");
157 		return -EINVAL;
158 	}
159 
160 	if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) {
161 		mlme_err("WMI extract failed");
162 		return -EINVAL;
163 	}
164 
165 	rsp.vdev_id = vdev_start_resp.vdev_id;
166 	rsp.requestor_id = vdev_start_resp.requestor_id;
167 	rsp.status = vdev_start_resp.status;
168 	rsp.resp_type = vdev_start_resp.resp_type;
169 	rsp.chain_mask = vdev_start_resp.chain_mask;
170 	rsp.smps_mode = vdev_start_resp.smps_mode;
171 	rsp.mac_id = vdev_start_resp.mac_id;
172 	rsp.cfgd_tx_streams = vdev_start_resp.cfgd_tx_streams;
173 	rsp.cfgd_rx_streams = vdev_start_resp.cfgd_rx_streams;
174 
175 	status = rx_ops->vdev_mgr_start_response(psoc, &rsp);
176 
177 	return qdf_status_to_os_return(status);
178 }
179 
180 static int target_if_vdev_mgr_stop_response_handler(
181 						ol_scn_t scn,
182 						uint8_t *data,
183 						uint32_t datalen)
184 {
185 	QDF_STATUS status;
186 	struct wlan_objmgr_psoc *psoc;
187 	struct wmi_unified *wmi_handle;
188 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
189 	struct vdev_stop_response rsp = {0};
190 	uint32_t vdev_id;
191 
192 	if (!scn || !data) {
193 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
194 		return -EINVAL;
195 	}
196 
197 	psoc = target_if_get_psoc_from_scn_hdl(scn);
198 	if (!psoc) {
199 		mlme_err("PSOC is NULL");
200 		return -EINVAL;
201 	}
202 
203 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
204 	if (!rx_ops || !rx_ops->vdev_mgr_stop_response) {
205 		mlme_err("No Rx Ops");
206 		return -EINVAL;
207 	}
208 
209 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
210 	if (!wmi_handle) {
211 		mlme_err("wmi_handle is null");
212 		return -EINVAL;
213 	}
214 
215 	if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) {
216 		mlme_err("WMI extract failed");
217 		return -EINVAL;
218 	}
219 
220 	rsp.vdev_id = vdev_id;
221 	status = rx_ops->vdev_mgr_stop_response(psoc, &rsp);
222 
223 	return qdf_status_to_os_return(status);
224 }
225 
226 static int target_if_vdev_mgr_delete_response_handler(
227 						ol_scn_t scn,
228 						uint8_t *data,
229 						uint32_t datalen)
230 {
231 	QDF_STATUS status;
232 	struct wlan_objmgr_psoc *psoc;
233 	struct wmi_unified *wmi_handle;
234 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
235 	struct vdev_delete_response rsp = {0};
236 	struct wmi_host_vdev_delete_resp vdev_del_resp;
237 
238 	if (!scn || !data) {
239 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
240 		return -EINVAL;
241 	}
242 
243 	psoc = target_if_get_psoc_from_scn_hdl(scn);
244 	if (!psoc) {
245 		mlme_err("PSOC is NULL");
246 		return -EINVAL;
247 	}
248 
249 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
250 	if (!rx_ops || !rx_ops->vdev_mgr_stop_response ||
251 	    !rx_ops->vdev_mgr_get_response_timer_info) {
252 		mlme_err("No Rx Ops");
253 		return -EINVAL;
254 	}
255 
256 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
257 	if (!wmi_handle) {
258 		mlme_err("wmi_handle is null");
259 		return -EINVAL;
260 	}
261 
262 	if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) {
263 		mlme_err("WMI extract failed");
264 		return -EINVAL;
265 	}
266 
267 	rsp.vdev_id = vdev_del_resp.vdev_id;
268 	status = rx_ops->vdev_mgr_delete_response(psoc, &rsp);
269 
270 	return qdf_status_to_os_return(status);
271 }
272 
273 static int target_if_vdev_mgr_offload_bcn_tx_status_handler(
274 							ol_scn_t scn,
275 							uint8_t *data,
276 							uint32_t datalen)
277 {
278 	QDF_STATUS status;
279 	struct wlan_objmgr_psoc *psoc;
280 	struct wmi_unified *wmi_handle;
281 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
282 	uint32_t vdev_id, tx_status;
283 
284 	if (!scn || !data) {
285 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
286 		return -EINVAL;
287 	}
288 	psoc = target_if_get_psoc_from_scn_hdl(scn);
289 	if (!psoc) {
290 		mlme_err("PSOC is NULL");
291 		return -EINVAL;
292 	}
293 
294 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
295 	if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) {
296 		mlme_err("No Rx Ops");
297 		return -EINVAL;
298 	}
299 
300 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
301 	if (!wmi_handle) {
302 		mlme_err("wmi_handle is null");
303 		return -EINVAL;
304 	}
305 
306 	if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data,
307 						  &vdev_id, &tx_status)) {
308 		mlme_err("WMI extract failed");
309 		return -EINVAL;
310 	}
311 
312 	status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle(
313 								vdev_id,
314 								tx_status);
315 
316 	return qdf_status_to_os_return(status);
317 }
318 
319 static int target_if_vdev_mgr_tbttoffset_update_handler(
320 						ol_scn_t scn,
321 						uint8_t *data,
322 						uint32_t datalen)
323 {
324 	QDF_STATUS status;
325 	struct wlan_objmgr_psoc *psoc;
326 	struct wmi_unified *wmi_handle;
327 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
328 	uint32_t num_vdevs = 0;
329 
330 	if (!scn || !data) {
331 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
332 		return -EINVAL;
333 	}
334 	psoc = target_if_get_psoc_from_scn_hdl(scn);
335 	if (!psoc) {
336 		mlme_err("PSOC is NULL");
337 		return -EINVAL;
338 	}
339 
340 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
341 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
342 		mlme_err("No Rx Ops");
343 		return -EINVAL;
344 	}
345 
346 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
347 	if (!wmi_handle) {
348 		mlme_err("wmi_handle is null");
349 		return -EINVAL;
350 	}
351 
352 	if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) {
353 		mlme_err("WMI extract failed");
354 		return -EINVAL;
355 	}
356 
357 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, false);
358 
359 	return qdf_status_to_os_return(status);
360 }
361 
362 static int target_if_vdev_mgr_ext_tbttoffset_update_handler(
363 						ol_scn_t scn,
364 						uint8_t *data,
365 						uint32_t datalen)
366 {
367 	QDF_STATUS status;
368 	struct wlan_objmgr_psoc *psoc;
369 	struct wmi_unified *wmi_handle;
370 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
371 	uint32_t num_vdevs = 0;
372 
373 	if (!scn || !data) {
374 		mlme_err("scn: 0x%pK, data: 0x%pK", scn, data);
375 		return -EINVAL;
376 	}
377 	psoc = target_if_get_psoc_from_scn_hdl(scn);
378 	if (!psoc) {
379 		mlme_err("PSOC is NULL");
380 		return -EINVAL;
381 	}
382 
383 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
384 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
385 		mlme_err("No Rx Ops");
386 		return -EINVAL;
387 	}
388 
389 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
390 	if (!wmi_handle) {
391 		mlme_err("wmi_handle is null");
392 		return -EINVAL;
393 	}
394 
395 	if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data,
396 						 &num_vdevs)) {
397 		mlme_err("WMI extract failed");
398 		return -EINVAL;
399 	}
400 
401 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, true);
402 
403 	return qdf_status_to_os_return(status);
404 }
405 
406 QDF_STATUS target_if_vdev_mgr_wmi_event_register(
407 				struct wlan_objmgr_psoc *psoc)
408 {
409 	int retval = 0;
410 	struct wmi_unified *wmi_handle;
411 
412 	if (!psoc) {
413 		mlme_err("PSOC is NULL");
414 		return QDF_STATUS_E_NULL_VALUE;
415 	}
416 
417 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
418 	if (!wmi_handle) {
419 		mlme_err("wmi_handle is null");
420 		return QDF_STATUS_E_INVAL;
421 	}
422 
423 	retval = wmi_unified_register_event_handler(
424 				wmi_handle,
425 				wmi_vdev_stopped_event_id,
426 				target_if_vdev_mgr_stop_response_handler,
427 				WMI_RX_UMAC_CTX);
428 	if (retval)
429 		mlme_err("failed to register for stop response");
430 
431 	retval = wmi_unified_register_event_handler(
432 				wmi_handle,
433 				wmi_vdev_delete_resp_event_id,
434 				target_if_vdev_mgr_delete_response_handler,
435 				WMI_RX_UMAC_CTX);
436 	if (retval)
437 		mlme_err("failed to register for delete response");
438 
439 	retval = wmi_unified_register_event_handler(
440 				wmi_handle,
441 				wmi_vdev_start_resp_event_id,
442 				target_if_vdev_mgr_start_response_handler,
443 				WMI_RX_UMAC_CTX);
444 	if (retval)
445 		mlme_err("failed to register for start response");
446 
447 	return qdf_status_from_os_return(retval);
448 }
449 
450 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister(
451 					struct wlan_objmgr_psoc *psoc)
452 {
453 	struct wmi_unified *wmi_handle;
454 
455 	if (!psoc) {
456 		mlme_err("PSOC is NULL");
457 		return QDF_STATUS_E_INVAL;
458 	}
459 
460 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
461 	if (!wmi_handle) {
462 		mlme_err("wmi_handle is null");
463 		return QDF_STATUS_E_INVAL;
464 	}
465 
466 	wmi_unified_unregister_event_handler(wmi_handle,
467 					     wmi_vdev_stopped_event_id);
468 
469 	wmi_unified_unregister_event_handler(wmi_handle,
470 					     wmi_vdev_delete_resp_event_id);
471 
472 	wmi_unified_unregister_event_handler(wmi_handle,
473 					     wmi_vdev_start_resp_event_id);
474 
475 	return QDF_STATUS_SUCCESS;
476 }
477