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