xref: /wlan-driver/qcacld-3.0/components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_bearer_switch.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. 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 #include "wlan_ll_sap_main.h"
18 #include "wlan_ll_lt_sap_bearer_switch.h"
19 #include "wlan_sm_engine.h"
20 #include "wlan_policy_mgr_api.h"
21 #include "wlan_policy_mgr_ll_sap.h"
22 
23 #define BEARER_SWITCH_TIMEOUT 5000
24 #define BS_PREFIX_FMT "BS_SM vdev %d req_id 0x%x: "
25 #define BS_PREFIX_REF(vdev_id, req_id) (vdev_id), (req_id)
26 
27 
ll_lt_sap_bearer_switch_get_id(struct wlan_objmgr_psoc * psoc)28 wlan_bs_req_id ll_lt_sap_bearer_switch_get_id(struct wlan_objmgr_psoc *psoc)
29 {
30 	wlan_bs_req_id request_id = BS_REQ_ID_INVALID;
31 	struct ll_sap_vdev_priv_obj *ll_sap_obj;
32 	struct wlan_objmgr_vdev *vdev;
33 	uint8_t vdev_id;
34 
35 	vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
36 	if (vdev_id == WLAN_INVALID_VDEV_ID)
37 		return request_id;
38 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
39 						    WLAN_LL_SAP_ID);
40 	if (!vdev) {
41 		ll_sap_err(BS_PREFIX_FMT "Vdev is NULL",
42 			   BS_PREFIX_REF(vdev_id, request_id));
43 		return request_id;
44 	}
45 
46 	ll_sap_obj = ll_sap_get_vdev_priv_obj(vdev);
47 	if (!ll_sap_obj) {
48 		ll_sap_err(BS_PREFIX_FMT "ll sap obj is NULL",
49 			   BS_PREFIX_REF(vdev_id, request_id));
50 
51 		goto rel_ref;
52 	}
53 
54 	request_id = qdf_atomic_inc_return(
55 				&ll_sap_obj->bearer_switch_ctx->request_id);
56 
57 	ll_sap_nofl_debug(BS_PREFIX_FMT, BS_PREFIX_REF(vdev_id, request_id));
58 rel_ref:
59 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LL_SAP_ID);
60 
61 	return request_id;
62 }
63 
__ll_lt_sap_is_bs_ctx_valid(struct bearer_switch_info * bs_ctx,const char * func)64 bool __ll_lt_sap_is_bs_ctx_valid(struct bearer_switch_info *bs_ctx,
65 				 const char *func)
66 {
67 	if (!bs_ctx) {
68 		ll_sap_nofl_err("BS_SM context is null (via %s)", func);
69 		return false;
70 	}
71 	return true;
72 }
73 
__ll_lt_sap_is_bs_req_valid(struct wlan_bearer_switch_request * bs_req,const char * func)74 bool __ll_lt_sap_is_bs_req_valid(struct wlan_bearer_switch_request *bs_req,
75 				 const char *func)
76 {
77 	if (!bs_req) {
78 		ll_sap_nofl_err("BS_SM request is null (via %s)", func);
79 		return false;
80 	}
81 
82 	if (bs_req->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
83 		ll_sap_nofl_err("Invalid vdev id %d in BS_SM request",
84 				bs_req->vdev_id);
85 		return false;
86 	}
87 
88 	return true;
89 }
90 
91 /**
92  * ll_lt_sap_deliver_audio_transport_switch_resp_to_fw() - Deliver audio
93  * transport switch response to FW
94  * @vdev: Vdev on which the request is received
95  * @req_type: Transport switch type for which the response is received
96  * @status: Status of the response
97  *
98  * Return: None
99  */
100 static void
ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(struct wlan_objmgr_vdev * vdev,enum bearer_switch_req_type req_type,enum bearer_switch_status status)101 ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(
102 					struct wlan_objmgr_vdev *vdev,
103 					enum bearer_switch_req_type req_type,
104 					enum bearer_switch_status status)
105 {
106 	struct wlan_objmgr_psoc *psoc;
107 	struct ll_sap_psoc_priv_obj *psoc_ll_sap_obj;
108 	struct wlan_ll_sap_tx_ops *tx_ops;
109 
110 	psoc = wlan_vdev_get_psoc(vdev);
111 
112 	psoc_ll_sap_obj = wlan_objmgr_psoc_get_comp_private_obj(
113 						psoc,
114 						WLAN_UMAC_COMP_LL_SAP);
115 
116 	if (!psoc_ll_sap_obj) {
117 		ll_sap_err("psoc_ll_sap_obj is null");
118 		return;
119 	}
120 
121 	tx_ops = &psoc_ll_sap_obj->tx_ops;
122 
123 	if (!tx_ops->send_audio_transport_switch_resp) {
124 		ll_sap_err("deliver_audio_transport_switch_resp op is NULL");
125 		return;
126 	}
127 
128 	tx_ops->send_audio_transport_switch_resp(psoc, req_type, status);
129 }
130 
131 /**
132  * bs_req_timeout_cb() - Callback which will be invoked on bearer switch req
133  * timeout
134  * @user_data: Bearer switch context
135  *
136  * API to handle the timeout for the bearer switch requests
137  *
138  * Return: None
139  */
140 
bs_req_timeout_cb(void * user_data)141 static void bs_req_timeout_cb(void *user_data)
142 {
143 	struct bearer_switch_info *bs_ctx = user_data;
144 	struct wlan_bearer_switch_request *bs_req = NULL;
145 	uint8_t i;
146 	enum wlan_bearer_switch_sm_evt event;
147 
148 	for (i = 0; i < MAX_BEARER_SWITCH_REQUESTERS; i++) {
149 		if (!bs_ctx->requests[i].requester_cb)
150 			continue;
151 
152 		/*
153 		 * It is always the first cached request for which the request
154 		 * to switch the bearer is sent (other requests for bearer
155 		 * switch are just cached) and for the same this timeout has
156 		 * happened
157 		 */
158 		bs_req = &bs_ctx->requests[i];
159 		break;
160 	}
161 	if (!bs_req) {
162 		ll_sap_err("BS_SM No request pending");
163 		return;
164 	}
165 
166 	if (bs_req->req_type == WLAN_BS_REQ_TO_WLAN)
167 		event = WLAN_BS_SM_EV_SWITCH_TO_WLAN_TIMEOUT;
168 	else
169 		event = WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_TIMEOUT;
170 	bs_sm_deliver_event(wlan_vdev_get_psoc(bs_ctx->vdev), event,
171 			    sizeof(*bs_req), bs_req);
172 }
173 
bs_req_timer_init(struct bearer_switch_info * bs_ctx)174 void bs_req_timer_init(struct bearer_switch_info *bs_ctx)
175 {
176 	qdf_mc_timer_init(&bs_ctx->bs_request_timer, QDF_TIMER_TYPE_SW,
177 			  bs_req_timeout_cb, bs_ctx);
178 }
179 
bs_req_timer_deinit(struct bearer_switch_info * bs_ctx)180 void bs_req_timer_deinit(struct bearer_switch_info *bs_ctx)
181 {
182 	if (QDF_TIMER_STATE_RUNNING ==
183 		qdf_mc_timer_get_current_state(&bs_ctx->bs_request_timer))
184 		qdf_mc_timer_stop(&bs_ctx->bs_request_timer);
185 
186 	qdf_mc_timer_destroy(&bs_ctx->bs_request_timer);
187 }
188 
189 /**
190  * ll_lt_sap_stop_bs_timer() - Stop bearer switch timer
191  * @bs_ctx: Bearer switch context
192  * @req_id: Request id for which timer needs to be stopped
193  *
194  * API to stop bearer switch request timer
195  *
196  * Return: None
197  */
ll_lt_sap_stop_bs_timer(struct bearer_switch_info * bs_ctx,uint32_t req_id)198 static void ll_lt_sap_stop_bs_timer(struct bearer_switch_info *bs_ctx,
199 				    uint32_t req_id)
200 {
201 	QDF_STATUS status;
202 
203 	if (QDF_TIMER_STATE_RUNNING ==
204 		qdf_mc_timer_get_current_state(&bs_ctx->bs_request_timer)) {
205 		status = qdf_mc_timer_stop(&bs_ctx->bs_request_timer);
206 		if (QDF_IS_STATUS_ERROR(status))
207 			ll_sap_err(BS_PREFIX_FMT "failed to stop timer",
208 				   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
209 						 req_id));
210 	} else {
211 		ll_sap_err(BS_PREFIX_FMT "timer is not running",
212 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
213 					 req_id));
214 	}
215 }
216 
217 /**
218  * bs_set_state() - Set bearer switch state in the bearer switch state machine
219  * @bs_ctx: Bearer switch context
220  * @state: State which needs to be set
221  *
222  * API to Set the bearer switch state
223  *
224  * Return: None
225  */
bs_set_state(struct bearer_switch_info * bs_ctx,enum wlan_bearer_switch_sm_state state)226 static void bs_set_state(struct bearer_switch_info *bs_ctx,
227 			 enum wlan_bearer_switch_sm_state state)
228 {
229 	if (state < BEARER_SWITCH_MAX)
230 		bs_ctx->sm.bs_state = state;
231 	else
232 		ll_sap_err("BS_SM vdev %d state (%d) is invalid",
233 			   wlan_vdev_get_id(bs_ctx->vdev), state);
234 }
235 
236 /**
237  * bs_sm_state_update() - Update the bearer switch state in the bearer switch
238  * state machine
239  * @bs_ctx: Bearer switch context
240  * @state: State which needs to be set
241  *
242  * API to update the bearer switch state
243  *
244  * Return: None
245  */
bs_sm_state_update(struct bearer_switch_info * bs_ctx,enum wlan_bearer_switch_sm_state state)246 static void bs_sm_state_update(struct bearer_switch_info *bs_ctx,
247 			       enum wlan_bearer_switch_sm_state state)
248 {
249 	if (!ll_lt_sap_is_bs_ctx_valid(bs_ctx))
250 		return;
251 
252 	bs_set_state(bs_ctx, state);
253 }
254 
255 static void
ll_lt_sap_invoke_req_callback_f(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req,QDF_STATUS status,const char * func)256 ll_lt_sap_invoke_req_callback_f(struct bearer_switch_info *bs_ctx,
257 				struct wlan_bearer_switch_request *bs_req,
258 				QDF_STATUS status, const char *func)
259 {
260 	if (!bs_req->requester_cb) {
261 		ll_sap_err("%s BS_SM vdev %d NULL cbk, req_vdev %d src %d req %d arg val %d",
262 			   func, wlan_vdev_get_id(bs_ctx->vdev), bs_req->vdev_id,
263 			   bs_req->source, bs_req->request_id,
264 			   bs_req->arg_value);
265 		return;
266 	}
267 
268 	/* Invoke the requester callback without waiting for the response */
269 	bs_req->requester_cb(wlan_vdev_get_psoc(bs_ctx->vdev), bs_req->vdev_id,
270 			     bs_req->request_id, status, bs_req->arg_value,
271 			     bs_req->arg);
272 }
273 
274 #define ll_lt_sap_invoke_req_callback(bs_ctx, bs_req, status) \
275 	ll_lt_sap_invoke_req_callback_f(bs_ctx, bs_req, status, __func__)
276 
277 /**
278  * ll_lt_sap_bs_increament_ref_count() - Increment the bearer switch ref count
279  * @bs_ctx: Bearer switch context
280  * @bs_req: Bearer switch request corresponding to which the ref count needs to
281  * be incremented
282  *
283  * API to increment the bearer switch ref count
284  *
285  * Return: None
286  */
287 static inline void
ll_lt_sap_bs_increament_ref_count(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)288 ll_lt_sap_bs_increament_ref_count(struct bearer_switch_info *bs_ctx,
289 				  struct wlan_bearer_switch_request *bs_req)
290 {
291 	uint32_t ref_count;
292 	uint32_t total_ref_count;
293 
294 	total_ref_count = qdf_atomic_inc_return(&bs_ctx->total_ref_count);
295 	if (bs_req->source == BEARER_SWITCH_REQ_FW)
296 		ref_count = qdf_atomic_inc_return(&bs_ctx->fw_ref_count);
297 	else
298 		ref_count = qdf_atomic_inc_return(
299 			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
300 
301 	ll_sap_nofl_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count %d Total ref count %d",
302 			  BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
303 					bs_req->request_id),
304 			  bs_req->vdev_id, bs_req->source, ref_count,
305 			  total_ref_count);
306 }
307 
308 /**
309  * ll_lt_sap_bs_decreament_ref_count() - Decreament the bearer switch ref count
310  * @bs_ctx: Bearer switch context
311  * @bs_req: Bearer switch request corresponding to which the ref count needs to
312  * be decremented
313  *
314  * API to decreament the bearer switch ref count
315  *
316  * Return: None
317  */
318 static inline QDF_STATUS
ll_lt_sap_bs_decreament_ref_count(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)319 ll_lt_sap_bs_decreament_ref_count(struct bearer_switch_info *bs_ctx,
320 				  struct wlan_bearer_switch_request *bs_req)
321 {
322 	uint32_t ref_count;
323 	uint32_t total_ref_count;
324 
325 	/*
326 	 * If the ref count is 0 for the requested module, it means that this
327 	 * module did not requested for wlan to non wlan transition earlier, so
328 	 * reject this operation.
329 	 */
330 	if (bs_req->source == BEARER_SWITCH_REQ_FW) {
331 		if (!qdf_atomic_read(&bs_ctx->fw_ref_count)) {
332 			ll_sap_debug(BS_PREFIX_FMT "ref_count is zero for FW",
333 				     BS_PREFIX_REF(
334 						wlan_vdev_get_id(bs_ctx->vdev),
335 						bs_req->request_id));
336 			return QDF_STATUS_E_INVAL;
337 		}
338 		ref_count = qdf_atomic_dec_return(&bs_ctx->fw_ref_count);
339 	} else if (!qdf_atomic_read(
340 			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source])) {
341 		ll_sap_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count is zero",
342 			     BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
343 					   bs_req->request_id),
344 			     bs_req->vdev_id, bs_req->source);
345 		return QDF_STATUS_E_INVAL;
346 	} else {
347 		ref_count = qdf_atomic_dec_return(
348 			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
349 	}
350 	total_ref_count = qdf_atomic_dec_return(&bs_ctx->total_ref_count);
351 	ll_sap_nofl_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count %d Total ref count %d",
352 			  BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
353 					bs_req->request_id),
354 			  bs_req->vdev_id, bs_req->source,
355 			  ref_count, total_ref_count);
356 
357 	return QDF_STATUS_SUCCESS;
358 }
359 
360 /**
361  * ll_lt_sap_cache_bs_request() - Cache the bearer switch request
362  * @bs_ctx: Bearer switch context
363  * @bs_req: Bearer switch request which needs to be cached
364  *
365  * API to cache the bearer switch request in the bearer switch context
366  *
367  * Return: None
368  */
369 static void
ll_lt_sap_cache_bs_request(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)370 ll_lt_sap_cache_bs_request(struct bearer_switch_info *bs_ctx,
371 			   struct wlan_bearer_switch_request *bs_req)
372 {
373 	uint8_t i;
374 
375 	for (i = 0; i < MAX_BEARER_SWITCH_REQUESTERS; i++) {
376 		/*
377 		 * Find the empty slot in the requests array to cache the
378 		 * current request
379 		 */
380 		if (bs_ctx->requests[i].requester_cb)
381 			continue;
382 		ll_sap_debug(BS_PREFIX_FMT "req_vdev %d cache %d request at %d",
383 			     BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
384 					   bs_req->request_id),
385 			     bs_req->vdev_id, bs_req->req_type, i);
386 		bs_ctx->requests[i].vdev_id = bs_req->vdev_id;
387 		bs_ctx->requests[i].request_id = bs_req->request_id;
388 		bs_ctx->requests[i].req_type = bs_req->req_type;
389 		bs_ctx->requests[i].source = bs_req->source;
390 		bs_ctx->requests[i].requester_cb = bs_req->requester_cb;
391 		bs_ctx->requests[i].arg_value = bs_req->arg_value;
392 		bs_ctx->requests[i].arg = bs_req->arg;
393 		break;
394 	}
395 	if (i >= MAX_BEARER_SWITCH_REQUESTERS)
396 		ll_sap_err(BS_PREFIX_FMT "Max number of requests reached",
397 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
398 					 bs_req->request_id));
399 }
400 
401 /*
402  * ll_lt_sap_invoke_bs_requester_cbks() - Invoke callbacks of all the cached
403  * requests
404  * @bs_ctx: Bearer switch context
405  * @Status: Status with which the callbacks needs to be invoked
406  *
407  * API to invoke the callbacks of the cached requests
408  *
409  * Return: None
410  */
411 static void
ll_lt_sap_invoke_bs_requester_cbks(struct bearer_switch_info * bs_ctx,QDF_STATUS status)412 ll_lt_sap_invoke_bs_requester_cbks(struct bearer_switch_info *bs_ctx,
413 				   QDF_STATUS status)
414 {
415 	struct wlan_objmgr_psoc *psoc;
416 	uint8_t i;
417 
418 	psoc = wlan_vdev_get_psoc(bs_ctx->vdev);
419 
420 	if (!psoc) {
421 		ll_sap_err("BS_SM invalid psoc");
422 		return;
423 	}
424 
425 	for (i = 0; i < MAX_BEARER_SWITCH_REQUESTERS; i++) {
426 		if (!bs_ctx->requests[i].requester_cb)
427 			continue;
428 
429 		bs_ctx->requests[i].requester_cb(psoc,
430 						 bs_ctx->requests[i].vdev_id,
431 						 bs_ctx->requests[i].request_id,
432 						 status,
433 						 bs_ctx->requests[i].arg_value,
434 						 bs_ctx->requests[i].arg);
435 		bs_ctx->requests[i].requester_cb = NULL;
436 		bs_ctx->requests[i].arg = NULL;
437 		bs_ctx->requests[i].arg_value = 0;
438 	}
439 }
440 
441 /*
442  * ll_lt_sap_find_first_valid_bs_wlan_req() - Find first valid wlan switch
443  * request from the cached requests
444  * @bs_ctx: Bearer switch context
445  *
446  * API to find first valid wlan switch request from the cached requests
447  *
448  * Return: If found return bearer switch request, else return NULL
449  */
450 static struct wlan_bearer_switch_request *
ll_lt_sap_find_first_valid_bs_wlan_req(struct bearer_switch_info * bs_ctx)451 ll_lt_sap_find_first_valid_bs_wlan_req(struct bearer_switch_info *bs_ctx)
452 {
453 	uint8_t i;
454 
455 	for (i = 0; i < MAX_BEARER_SWITCH_REQUESTERS; i++) {
456 		if (bs_ctx->requests[i].requester_cb &&
457 		    bs_ctx->requests[i].req_type == WLAN_BS_REQ_TO_WLAN)
458 			return &bs_ctx->requests[i];
459 	}
460 	return NULL;
461 }
462 
463 /*
464  * ll_lt_sap_find_first_valid_bs_non_wlan_req() - Find first valid non-wlan
465  * switch request from the cached requests
466  * @bs_ctx: Bearer switch context
467  *
468  * API to find first valid non-wlan switch request from the cached requests
469  *
470  * Return: If found return bearer switch request, else return NULL
471  */
472 static struct wlan_bearer_switch_request *
ll_lt_sap_find_first_valid_bs_non_wlan_req(struct bearer_switch_info * bs_ctx)473 ll_lt_sap_find_first_valid_bs_non_wlan_req(struct bearer_switch_info *bs_ctx)
474 {
475 	uint8_t i;
476 
477 	for (i = 0; i < MAX_BEARER_SWITCH_REQUESTERS; i++) {
478 		if (bs_ctx->requests[i].requester_cb &&
479 		    bs_ctx->requests[i].req_type == WLAN_BS_REQ_TO_NON_WLAN)
480 			return &bs_ctx->requests[i];
481 	}
482 	return NULL;
483 }
484 
485 /*
486  * ll_lt_sap_send_bs_req_to_userspace() - Send bearer switch request to user
487  * space
488  * @vdev: ll_lt sap vdev
489  *
490  * API to send bearer switch request to userspace
491  *
492  * Return: None
493  */
494 static void
ll_lt_sap_send_bs_req_to_userspace(struct wlan_objmgr_vdev * vdev,enum bearer_switch_req_type req_type)495 ll_lt_sap_send_bs_req_to_userspace(struct wlan_objmgr_vdev *vdev,
496 				   enum bearer_switch_req_type req_type)
497 {
498 	struct ll_sap_ops *osif_cbk;
499 
500 	osif_cbk = ll_sap_get_osif_cbk();
501 	if (osif_cbk && osif_cbk->ll_sap_send_audio_transport_switch_req_cb)
502 		osif_cbk->ll_sap_send_audio_transport_switch_req_cb(vdev,
503 								    req_type);
504 }
505 /**
506  * ll_lt_sap_handle_bs_to_wlan_in_non_wlan_state() - API to handle bearer switch
507  * to wlan in non-wlan state.
508  * @bs_ctx: Bearer switch context
509  * @bs_req: Bearer switch request
510  *
511  * If total_ref_count is non-zero, means non-wlan bearer should be there and
512  * no further action is required, just invoke the callback of the requester
513  * with status as success.
514  * If total_ref_count is zero, means none of the module wants to be in the
515  * non-wlan bearer, cache the request and send the wlan bearer switch request
516  * to userspace.
517  * If the last_status is not QDF_STATUS_SUCCESS, means the last request to
518  * switch the bearer to non-wlan was failed/timedout and the state is moved to
519  * non-wlan, irrespective of the last status follow the same flow and send the
520  * request to switch the bearer to wlan
521  *
522  * Return: None
523  */
524 static void
ll_lt_sap_handle_bs_to_wlan_in_non_wlan_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)525 ll_lt_sap_handle_bs_to_wlan_in_non_wlan_state(
526 				struct bearer_switch_info *bs_ctx,
527 				struct wlan_bearer_switch_request *bs_req)
528 {
529 	QDF_STATUS status;
530 
531 	status = ll_lt_sap_bs_decreament_ref_count(bs_ctx, bs_req);
532 	if (QDF_IS_STATUS_ERROR(status))
533 		return;
534 
535 	if (qdf_atomic_read(&bs_ctx->total_ref_count))
536 		goto invoke_requester_cb;
537 
538 	ll_lt_sap_cache_bs_request(bs_ctx, bs_req);
539 
540 	ll_lt_sap_send_bs_req_to_userspace(bs_ctx->vdev, bs_req->req_type);
541 
542 	status = qdf_mc_timer_start(&bs_ctx->bs_request_timer,
543 				    BEARER_SWITCH_TIMEOUT);
544 	if (QDF_IS_STATUS_ERROR(status))
545 		ll_sap_err(BS_PREFIX_FMT "Failed to start timer",
546 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
547 					 bs_req->request_id));
548 
549 	bs_sm_transition_to(bs_ctx, BEARER_WLAN_REQUESTED);
550 
551 invoke_requester_cb:
552 	ll_lt_sap_invoke_req_callback(bs_ctx, bs_req, status);
553 }
554 
555 /**
556  * ll_lt_sap_handle_bs_to_wlan_completed_wlan_in_non_wlan_state() - API to
557  * handle bearer switch to wlan completed event in non-wlan state.
558  * @bs_ctx: Bearer switch context
559  *
560  * This event is possible only if current bearer is non-wlan and user space
561  * switches the bearer to wlan first time after bringing up the LL_LT_SAP.
562  * Since host driver did not request for the bearer switch so there will not
563  * be any valid bearer switch request.
564  *
565  * Return: None
566  */
567 static void
ll_lt_sap_handle_bs_to_wlan_completed_wlan_in_non_wlan_state(struct bearer_switch_info * bs_ctx)568 ll_lt_sap_handle_bs_to_wlan_completed_wlan_in_non_wlan_state(
569 				struct bearer_switch_info *bs_ctx)
570 {
571 	bs_sm_transition_to(bs_ctx, BEARER_WLAN);
572 }
573 
574 /**
575  * ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_state() - API to handle bearer
576  * switch to non-wlan in non-wlan state.
577  * @bs_ctx: Bearer switch context
578  * @bs_req: Bearer switch request
579  *
580  * Increment the ref_count. check last_status, if last status is
581  * QDF_STATUS_SUCCESS, then just invoke the requester callback with success, no
582  * need to cache the request.
583  * If last status is not QDF_STATUS_SUCCESS, it means last request was not
584  * success, so cache this request and send a non-wlan bearer switch request to
585  * userspace.
586  *
587  * Return: None
588  */
589 static void
ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)590 ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_state(
591 				struct bearer_switch_info *bs_ctx,
592 				struct wlan_bearer_switch_request *bs_req)
593 {
594 	QDF_STATUS status;
595 
596 	ll_lt_sap_bs_increament_ref_count(bs_ctx, bs_req);
597 
598 	if (QDF_IS_STATUS_SUCCESS(bs_ctx->last_status))
599 		return ll_lt_sap_invoke_req_callback(bs_ctx, bs_req,
600 						     QDF_STATUS_E_ALREADY);
601 
602 	ll_lt_sap_send_bs_req_to_userspace(bs_ctx->vdev, bs_req->req_type);
603 
604 	status = qdf_mc_timer_start(&bs_ctx->bs_request_timer,
605 				    BEARER_SWITCH_TIMEOUT);
606 	if (QDF_IS_STATUS_ERROR(status))
607 		ll_sap_err(BS_PREFIX_FMT "Failed to start timer",
608 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
609 					 bs_req->request_id));
610 
611 	bs_sm_transition_to(bs_ctx, BEARER_NON_WLAN_REQUESTED);
612 }
613 
614 /**
615  * ll_lt_sap_handle_bs_to_wlan_in_non_wlan_requested_state() - API to handle
616  * bearer switch to wlan in non-wlan requested state
617  * @bs_ctx: Bearer switch context
618  * @bs_req: Bearer switch request
619  *
620  * Decreament the ref_count.
621  * 1) If total_ref_count is non-zero, it means there is some module
622  * which wants to be in the non-wlan state, invoke the caller of current
623  * requester with success and let the ongoing request for non wlan bearer
624  * switch get complete.
625  * 2) If total_ref_count is zero, it means no other module wants to be
626  * in non-wlan state, cache this wlan bearer switch request and invoke the
627  * callback of the caller with status as success, once the response of
628  * ongoign request of the non-wlan switch is received then check the
629  * total_ref_count and if it is 0, then send the request to switch to
630  * wlan in ll_lt_sap_handle_bs_to_non_wlan_completed,
631  * ll_lt_sap_handle_bs_to_non_wlan_failure or in
632  * ll_lt_sap_handle_bs_to_non_wlan_timeout.
633  *
634  * Return: None
635  */
636 static void
ll_lt_sap_handle_bs_to_wlan_in_non_wlan_requested_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)637 ll_lt_sap_handle_bs_to_wlan_in_non_wlan_requested_state(
638 				struct bearer_switch_info *bs_ctx,
639 				struct wlan_bearer_switch_request *bs_req)
640 {
641 	QDF_STATUS status;
642 
643 	status = ll_lt_sap_bs_decreament_ref_count(bs_ctx, bs_req);
644 
645 	if (QDF_IS_STATUS_ERROR(status))
646 		return;
647 
648 	if (!bs_req->requester_cb) {
649 		ll_sap_err(BS_PREFIX_FMT "NULL cbk, req_vdev %d src %d arg val %d",
650 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
651 					 bs_req->request_id),
652 			   bs_req->vdev_id, bs_req->source,
653 			   bs_req->arg_value);
654 		return;
655 	}
656 
657 	ll_lt_sap_cache_bs_request(bs_ctx, bs_req);
658 	ll_lt_sap_invoke_req_callback(bs_ctx, bs_req, status);
659 }
660 
661 /**
662  * ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_requested_state() - API to handle
663  * bearer switch to non wlan in non-wlan requested state.
664  * @bs_ctx: Bearer switch context
665  * @bs_req: Bearer switch request
666  *
667  * Increment the ref_count.
668  * Request to switch the bearer to non-wlan is already sent, cache this request
669  * and on receiving the response of the current non-wlan request invoke the
670  * callbacks of all the requesters in ll_lt_sap_handle_bs_to_non_wlan_completed,
671  * ll_lt_sap_handle_bs_to_non_wlan_failure,
672  * ll_lt_sap_handle_bs_to_non_wlan_timeout
673  * Return: None
674  */
675 static void
ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_requested_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)676 ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_requested_state(
677 				struct bearer_switch_info *bs_ctx,
678 				struct wlan_bearer_switch_request *bs_req)
679 {
680 	ll_lt_sap_bs_increament_ref_count(bs_ctx, bs_req);
681 
682 	ll_lt_sap_cache_bs_request(bs_ctx, bs_req);
683 }
684 
685 /**
686  * ll_lt_sap_handle_bs_to_non_wlan_timeout() - API to handle bearer switch
687  * to non-wlan timeout event.
688  * @bs_ctx: Bearer switch context
689  * @bs_req: Bearer switch request
690  *
691  * Move the bearer state to BEARER_NON_WLAN, even if this request is timedout as
692  * requester of this request needs to invoke the bearer switch to wlan again
693  * to reset the ref counts and in that path the state will be moved to
694  * BEARER_WLAN and the request to switch the bearer to userspace will still be
695  * sent irrespective of last_status and userspace should return success as
696  * the bearer is already wlan
697  * If total_ref_count is non-zero, means non-wlan bearer should be there and
698  * no further action is required.
699  * If total_ref_count is zero, means none of the module wants to be in the
700  * non-wlan bearer and the current module which has requested for non-wlan
701  * bearer also requested for the wlan bearer before this event/response is
702  * received(switch to wlan in non-wlan requested state) and this request for
703  * wlan bearer switch should have been cached get that request and deliver the
704  * event to switch the bearer to wlan.
705  *
706  * Return: None
707  */
708 static void
ll_lt_sap_handle_bs_to_non_wlan_timeout(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)709 ll_lt_sap_handle_bs_to_non_wlan_timeout(
710 				struct bearer_switch_info *bs_ctx,
711 				struct wlan_bearer_switch_request *bs_req)
712 {
713 	struct wlan_bearer_switch_request *first_bs_req;
714 
715 	bs_sm_transition_to(bs_ctx, BEARER_NON_WLAN);
716 
717 	bs_ctx->last_status = QDF_STATUS_E_TIMEOUT;
718 	ll_lt_sap_invoke_bs_requester_cbks(bs_ctx, QDF_STATUS_E_TIMEOUT);
719 
720 	/*
721 	 * If total_ref_count is non-zero, means non-wlan bearer should be
722 	 * there, so no further action is required
723 	 */
724 	if (qdf_atomic_read(&bs_ctx->total_ref_count))
725 		return;
726 
727 	first_bs_req = ll_lt_sap_find_first_valid_bs_wlan_req(bs_ctx);
728 
729 	if (!ll_lt_sap_is_bs_req_valid(first_bs_req)) {
730 		ll_sap_err("BS_SM vdev %d Invalid total ref count %d",
731 			   wlan_vdev_get_id(bs_ctx->vdev),
732 			   qdf_atomic_read(&bs_ctx->total_ref_count));
733 		QDF_BUG(0);
734 	}
735 
736 	bs_sm_deliver_event(wlan_vdev_get_psoc(bs_ctx->vdev),
737 			    WLAN_BS_SM_EV_SWITCH_TO_WLAN,
738 			    sizeof(*first_bs_req), first_bs_req);
739 }
740 
741 /**
742  * ll_lt_sap_handle_bs_to_non_wlan_completed() - API to handle bearer switch
743  * to non-wlan complete event.
744  * @bs_ctx: Bearer switch context
745  * @bs_req: Bearer switch request
746  *
747  * If total_ref_count is non-zero, means non-wlan bearer should be there and
748  * no further action is required.
749  * If total_ref_count is zero, means none of the module wants to be in the
750  * non-wlan bearer and the current module which has requested for non-wlan
751  * bearer also requested for the wlan bearer before this event/response is
752  * received(switch to wlan in non-wlan requested state) and this request for
753  * wlan bearer switch should have been cached get that request and deliver the
754  * event to switch the bearer to wlan.
755  *
756  * Return: None
757  */
758 static void
ll_lt_sap_handle_bs_to_non_wlan_completed(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)759 ll_lt_sap_handle_bs_to_non_wlan_completed(
760 				struct bearer_switch_info *bs_ctx,
761 				struct wlan_bearer_switch_request *bs_req)
762 {
763 	struct wlan_bearer_switch_request *first_bs_req;
764 
765 	ll_lt_sap_stop_bs_timer(bs_ctx, bs_req->request_id);
766 
767 	bs_sm_transition_to(bs_ctx, BEARER_NON_WLAN);
768 
769 	bs_ctx->last_status = QDF_STATUS_SUCCESS;
770 
771 	ll_lt_sap_invoke_bs_requester_cbks(bs_ctx, QDF_STATUS_SUCCESS);
772 
773 	/*
774 	 * If total_ref_count is non-zero, means non-wlan bearer should be
775 	 * there, so no further action is required
776 	 */
777 	if (qdf_atomic_read(&bs_ctx->total_ref_count))
778 		return;
779 
780 	first_bs_req = ll_lt_sap_find_first_valid_bs_wlan_req(bs_ctx);
781 
782 	if (!ll_lt_sap_is_bs_req_valid(first_bs_req)) {
783 		ll_sap_err("BS_SM vdev %d Invalid total ref count %d",
784 			   wlan_vdev_get_id(bs_ctx->vdev),
785 			   qdf_atomic_read(&bs_ctx->total_ref_count));
786 		QDF_BUG(0);
787 	}
788 
789 	bs_sm_deliver_event(wlan_vdev_get_psoc(bs_ctx->vdev),
790 			    WLAN_BS_SM_EV_SWITCH_TO_WLAN,
791 			    sizeof(*first_bs_req), first_bs_req);
792 }
793 
794 /**
795  * ll_lt_sap_handle_bs_to_non_wlan_failure() - API to handle bearer switch
796  * to non-wlan failure event.
797  * @bs_ctx: Bearer switch context
798  * @bs_req: Bearer switch request
799  *
800  * Move the bearer state to BEARER_NON_WLAN, even if this request is failed as
801  * requester of this request needs to invoke the bearer switch to wlan again
802  * to reset the ref counts and in that path the state will be moved to
803  * BEARER_WLAN and the request to switch the bearer to userspace will still be
804  * sent irrespective of last_status and userspace should return success as
805  * the bearer is already wlan
806  * If total_ref_count is non-zero, means non-wlan bearer should be there and
807  * no further action is required.
808  * If total_ref_count is zero, means none of the module wants to be in the
809  * non-wlan bearer and the current module which has requested for non-wlan
810  * bearer also requested for the wlan bearer before this event/response is
811  * received(switch to wlan in non-wlan requested state) and this request for
812  * wlan bearer switch should have been cached get that request and deliver the
813  * event to switch the bearer to wlan.
814  *
815  * Return: None
816  */
817 static void
ll_lt_sap_handle_bs_to_non_wlan_failure(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)818 ll_lt_sap_handle_bs_to_non_wlan_failure(
819 				struct bearer_switch_info *bs_ctx,
820 				struct wlan_bearer_switch_request *bs_req)
821 {
822 	struct wlan_bearer_switch_request *first_bs_req;
823 
824 	ll_lt_sap_stop_bs_timer(bs_ctx, bs_req->request_id);
825 
826 	bs_sm_transition_to(bs_ctx, BEARER_NON_WLAN);
827 
828 	bs_ctx->last_status = QDF_STATUS_E_FAILURE;
829 
830 	ll_lt_sap_invoke_bs_requester_cbks(bs_ctx, QDF_STATUS_E_FAILURE);
831 
832 	/*
833 	 * If total_ref_count is non-zero, means non-wlan bearer should be
834 	 * there, so no further action is required
835 	 */
836 	if (qdf_atomic_read(&bs_ctx->total_ref_count))
837 		return;
838 
839 	first_bs_req = ll_lt_sap_find_first_valid_bs_wlan_req(bs_ctx);
840 
841 	if (!ll_lt_sap_is_bs_req_valid(first_bs_req)) {
842 		ll_sap_err("BS_SM vdev %d Invalid total ref count %d",
843 			   wlan_vdev_get_id(bs_ctx->vdev),
844 			   qdf_atomic_read(&bs_ctx->total_ref_count));
845 		QDF_BUG(0);
846 	}
847 
848 	bs_sm_deliver_event(wlan_vdev_get_psoc(bs_ctx->vdev),
849 			    WLAN_BS_SM_EV_SWITCH_TO_WLAN,
850 			    sizeof(*first_bs_req), first_bs_req);
851 }
852 
853 /**
854  * ll_lt_sap_handle_bs_to_wlan_in_wlan_state() - API to handle bearer switch
855  * to wlan in wlan state.
856  * @bs_ctx: Bearer switch context
857  * @bs_req: Bearer switch request
858  *
859  * Ideally this scenario should not occur, but in any case if this happens then
860  * simply invoke the requester callback with QDF_STATUS_E_ALREADY status
861  *
862  * Return: None
863  */
864 static void
ll_lt_sap_handle_bs_to_wlan_in_wlan_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)865 ll_lt_sap_handle_bs_to_wlan_in_wlan_state(
866 				struct bearer_switch_info *bs_ctx,
867 				struct wlan_bearer_switch_request *bs_req)
868 {
869 	ll_lt_sap_invoke_req_callback(bs_ctx, bs_req, QDF_STATUS_E_ALREADY);
870 }
871 
872 /**
873  * ll_lt_sap_handle_bs_to_non_wlan_in_wlan_state() - API to handle bearer switch
874  * to non-wlan in wlan state.
875  * @bs_ctx: Bearer switch context
876  * @bs_req: Bearer switch request
877  *
878  * Increment the ref count, cache the request, send the non-wlan bearer switch
879  * request to userspace and transition thestate to BEARER_NON_WLAN_REQUESTED
880  *
881  * Return: None
882  */
883 static void
ll_lt_sap_handle_bs_to_non_wlan_in_wlan_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)884 ll_lt_sap_handle_bs_to_non_wlan_in_wlan_state(
885 				struct bearer_switch_info *bs_ctx,
886 				struct wlan_bearer_switch_request *bs_req)
887 {
888 	QDF_STATUS status;
889 
890 	if (!bs_req->requester_cb) {
891 		ll_sap_err(BS_PREFIX_FMT "NULL cbk, req_vdev %d src %d arg val %d",
892 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
893 					 bs_req->request_id),
894 			   bs_req->vdev_id, bs_req->source,
895 			   bs_req->arg_value);
896 		return;
897 	}
898 
899 	ll_lt_sap_bs_increament_ref_count(bs_ctx, bs_req);
900 
901 	ll_lt_sap_cache_bs_request(bs_ctx, bs_req);
902 
903 	/*
904 	 * Todo, Send bearer switch request to userspace
905 	 */
906 
907 	bs_sm_transition_to(bs_ctx, BEARER_NON_WLAN_REQUESTED);
908 
909 	status = qdf_mc_timer_start(&bs_ctx->bs_request_timer,
910 				    BEARER_SWITCH_TIMEOUT);
911 	if (QDF_IS_STATUS_ERROR(status))
912 		ll_sap_err(BS_PREFIX_FMT "Failed to start timer",
913 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
914 					 bs_req->request_id));
915 }
916 
917 /**
918  * ll_lt_sap_handle_bs_to_wlan_in_wlan_req_state() - API to handle bearer switch
919  * to wlan in wlan requested state.
920  * @bs_ctx: Bearer switch context
921  * @bs_req: Bearer switch request
922  *
923  * This scenario is not possible as if already switch to wlan is
924  * requested it means total_ref_count is already zero, so no other
925  * module should request for the bearer to switch to wlan. Hence drop
926  * this request.
927  *
928  * Return: None
929  */
930 static void
ll_lt_sap_handle_bs_to_wlan_in_wlan_req_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)931 ll_lt_sap_handle_bs_to_wlan_in_wlan_req_state(
932 				struct bearer_switch_info *bs_ctx,
933 				struct wlan_bearer_switch_request *bs_req)
934 {
935 }
936 
937 /**
938  * ll_lt_sap_handle_bs_to_non_wlan_in_wlan_req_state() - API to handle bearer
939  * switch to non-wlan in wlan requested state.
940  * @bs_ctx: Bearer switch context
941  * @bs_req: Bearer switch request
942  *
943  * Increment the reference count and cache the request so that on
944  * receiving the response of the ongoing wlan switch request, switch
945  * to non-wlan can be issued from ll_lt_sap_handle_bs_to_wlan_completed,
946  * ll_lt_sap_handle_bs_to_wlan_timeout or from
947  * ll_lt_sap_handle_bs_to_wlan_failure
948  *
949  * Return: None
950  */
951 static void
ll_lt_sap_handle_bs_to_non_wlan_in_wlan_req_state(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)952 ll_lt_sap_handle_bs_to_non_wlan_in_wlan_req_state(
953 				struct bearer_switch_info *bs_ctx,
954 				struct wlan_bearer_switch_request *bs_req)
955 {
956 	ll_lt_sap_bs_increament_ref_count(bs_ctx, bs_req);
957 
958 	ll_lt_sap_cache_bs_request(bs_ctx, bs_req);
959 }
960 
961 /**
962  * ll_lt_sap_switch_to_non_wlan_from_wlan() - API to issue bearer switch
963  * request to non-wlan bearer from wlan-requested state response
964  * @bs_ctx: Bearer switch info
965  *
966  * This function handles the case when someone requested for non-wlan
967  * bearer-switch in between of ongoing non-wlan to wlan bearer switch request.
968  * check if any non-wlan bearer switch request is issued before receiving this
969  * response then switch to non-wlan bearer
970  *
971  * Return: None
972  */
973 static void
ll_lt_sap_switch_to_non_wlan_from_wlan(struct bearer_switch_info * bs_ctx)974 ll_lt_sap_switch_to_non_wlan_from_wlan(struct bearer_switch_info *bs_ctx)
975 {
976 	struct wlan_bearer_switch_request *bs_req;
977 
978 	/* no request for wlan to no-wlan bearer switch */
979 	if (!qdf_atomic_read(&bs_ctx->total_ref_count))
980 		return;
981 
982 	bs_req = ll_lt_sap_find_first_valid_bs_non_wlan_req(bs_ctx);
983 
984 	if (!ll_lt_sap_is_bs_req_valid(bs_req)) {
985 		ll_sap_err("BS_SM vdev %d Invalid total ref count %d",
986 			   wlan_vdev_get_id(bs_ctx->vdev),
987 			   qdf_atomic_read(&bs_ctx->total_ref_count));
988 		QDF_BUG(0);
989 	}
990 
991 	bs_sm_deliver_event(wlan_vdev_get_psoc(bs_ctx->vdev),
992 			    WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN,
993 			    sizeof(*bs_req), bs_req);
994 }
995 
996 /**
997  * ll_lt_sap_handle_bs_to_wlan_timeout() - API to handle bearer switch
998  * to wlan timeout event.
999  * @bs_ctx: Bearer switch context
1000  * @bs_req: Bearer switch request
1001  *
1002  * Transition the state to wlan even in case of timeout as well, because from
1003  * the wlan point of view total_ref_count is 0 which means it is ready for
1004  * wlan bear Update last_status as QDF_STATUS_E_FAILURE and check if any
1005  * non-wlan bearer switch request is issued before receiving this response
1006  * then switch to non-wlan bearer
1007  *
1008  * Return: None
1009  */
1010 static void
ll_lt_sap_handle_bs_to_wlan_timeout(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)1011 ll_lt_sap_handle_bs_to_wlan_timeout(
1012 				struct bearer_switch_info *bs_ctx,
1013 				struct wlan_bearer_switch_request *bs_req)
1014 {
1015 	bs_sm_transition_to(bs_ctx, BEARER_WLAN);
1016 
1017 	if (bs_req->source == BEARER_SWITCH_REQ_FW)
1018 		ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(
1019 							bs_ctx->vdev,
1020 							bs_req->req_type,
1021 							WLAN_BS_STATUS_TIMEOUT);
1022 
1023 	bs_ctx->last_status = QDF_STATUS_E_TIMEOUT;
1024 
1025 	ll_lt_sap_switch_to_non_wlan_from_wlan(bs_ctx);
1026 }
1027 
1028 /**
1029  * ll_lt_sap_handle_bs_to_wlan_completed() - API to handle bearer switch
1030  * to wlan complete event.
1031  * @bs_ctx: Bearer switch context
1032  * @bs_req: Bearer switch request
1033  *
1034  * This event will be delivered by vendor command in the wlan requested state.
1035  * Stop the bearer switch timer, move the state to BEARER_WLAN and update the
1036  * last_status as QDF_STATUS_SUCCESS and check if any non-wlan bearer switch
1037  * request is issued before receiving this response then switch to non-wlan
1038  * bearer
1039  *
1040  * Return: None
1041  */
1042 static void
ll_lt_sap_handle_bs_to_wlan_completed(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)1043 ll_lt_sap_handle_bs_to_wlan_completed(
1044 				struct bearer_switch_info *bs_ctx,
1045 				struct wlan_bearer_switch_request *bs_req)
1046 {
1047 	ll_lt_sap_stop_bs_timer(bs_ctx, bs_req->request_id);
1048 
1049 	bs_sm_transition_to(bs_ctx, BEARER_WLAN);
1050 
1051 	bs_ctx->last_status = QDF_STATUS_SUCCESS;
1052 
1053 	ll_lt_sap_switch_to_non_wlan_from_wlan(bs_ctx);
1054 }
1055 
1056 /**
1057  * ll_lt_sap_handle_bs_to_wlan_failure() - API to handle bearer switch
1058  * to wlan failure event.
1059  * @bs_ctx: Bearer switch context
1060  * @bs_req: Bearer switch request
1061  *
1062  * This event will be delivered by vendor command in the wlan requested state
1063  * Stop the bearer switch timer,transition the state to wlan even in case of
1064  * failure as well, because from the wlan point of view total_ref_count is 0
1065  * which means it is ready for wlan bearer
1066  * Update last_status as QDF_STATUS_E_FAILURE and check if any non-wlan bearer
1067  * switch request is issued before receiving this response then switch to
1068  * non-wlan bearer
1069  *
1070  * Return: None
1071  */
1072 static void
ll_lt_sap_handle_bs_to_wlan_failure(struct bearer_switch_info * bs_ctx,struct wlan_bearer_switch_request * bs_req)1073 ll_lt_sap_handle_bs_to_wlan_failure(
1074 				struct bearer_switch_info *bs_ctx,
1075 				struct wlan_bearer_switch_request *bs_req)
1076 {
1077 	ll_lt_sap_stop_bs_timer(bs_ctx, bs_req->request_id);
1078 
1079 	bs_sm_transition_to(bs_ctx, BEARER_WLAN);
1080 
1081 	bs_ctx->last_status = QDF_STATUS_E_FAILURE;
1082 
1083 	ll_lt_sap_switch_to_non_wlan_from_wlan(bs_ctx);
1084 }
1085 
1086 /**
1087  * bs_state_non_wlan_entry() - Entry API for non wlan state for bearer switch
1088  * state machine
1089  * @ctx: Bearer switch context
1090  *
1091  * API to perform operations on moving to non-wlan state
1092  *
1093  * Return: void
1094  */
bs_state_non_wlan_entry(void * ctx)1095 static void bs_state_non_wlan_entry(void *ctx)
1096 {
1097 	struct bearer_switch_info *bs_ctx = ctx;
1098 
1099 	bs_sm_state_update(bs_ctx, BEARER_NON_WLAN);
1100 }
1101 
1102 /**
1103  * bs_state_non_wlan_exit() - Exit API for non wlan state for bearer switch
1104  * state machine
1105  * @ctx: Bearer switch context
1106  *
1107  * API to perform operations on exiting from non-wlan state
1108  *
1109  * Return: void
1110  */
bs_state_non_wlan_exit(void * ctx)1111 static void bs_state_non_wlan_exit(void *ctx)
1112 {
1113 }
1114 
1115 /**
1116  * bs_state_non_wlan_event() - Non-wlan State event handler for bearer switch
1117  * state machine
1118  * @ctx: Bearer switch context
1119  * @event: event
1120  * @data_len: length of @data
1121  * @data: event data
1122  *
1123  * API to handle events in Non-wlan state
1124  *
1125  * Return: bool
1126  */
bs_state_non_wlan_event(void * ctx,uint16_t event,uint16_t data_len,void * data)1127 static bool bs_state_non_wlan_event(void *ctx, uint16_t event,
1128 				    uint16_t data_len, void *data)
1129 {
1130 	bool event_handled = true;
1131 	struct bearer_switch_info *bs_ctx = ctx;
1132 	struct wlan_bearer_switch_request *bs_req = data;
1133 
1134 	if (event != WLAN_BS_SM_EV_SWITCH_TO_WLAN_COMPLETED &&
1135 	    !ll_lt_sap_is_bs_req_valid(bs_req))
1136 		return false;
1137 	if (!ll_lt_sap_is_bs_ctx_valid(bs_ctx))
1138 		return false;
1139 
1140 	switch (event) {
1141 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN:
1142 		ll_lt_sap_handle_bs_to_wlan_in_non_wlan_state(bs_ctx, bs_req);
1143 		break;
1144 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN:
1145 		ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_state(bs_ctx,
1146 								  bs_req);
1147 		break;
1148 	/*
1149 	 * This event is possible when userspace first time sends the request
1150 	 * to switch the bearer.
1151 	 */
1152 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN_COMPLETED:
1153 		ll_lt_sap_handle_bs_to_wlan_completed_wlan_in_non_wlan_state(
1154 									bs_ctx);
1155 		break;
1156 	default:
1157 		event_handled = false;
1158 		break;
1159 	}
1160 
1161 	return event_handled;
1162 }
1163 
1164 /**
1165  * bs_state_non_wlan_req_entry() - Entry API for non wlan requested state for
1166  * bearer switch state machine
1167  * @ctx: Bearer switch context
1168  *
1169  * API to perform operations on moving to non-wlan requested state
1170  *
1171  * Return: void
1172  */
bs_state_non_wlan_req_entry(void * ctx)1173 static void bs_state_non_wlan_req_entry(void *ctx)
1174 {
1175 	struct bearer_switch_info *bs_ctx = ctx;
1176 
1177 	bs_sm_state_update(bs_ctx, BEARER_NON_WLAN_REQUESTED);
1178 }
1179 
1180 /**
1181  * bs_state_non_wlan_req_exit() - Exit API for non wlan requested state for
1182  * bearer switch state machine
1183  * @ctx: Bearer switch context
1184  *
1185  * API to perform operations on exiting from non-wlan requested state
1186  *
1187  * Return: void
1188  */
bs_state_non_wlan_req_exit(void * ctx)1189 static void bs_state_non_wlan_req_exit(void *ctx)
1190 {
1191 }
1192 
1193 /**
1194  * bs_state_non_wlan_req_event() - Non-wlan requested State event handler for
1195  * bearer switch state machine
1196  * @ctx: Bearer switch context
1197  * @event: event
1198  * @data_len: length of @data
1199  * @data: event data
1200  *
1201  * API to handle events in Non-wlan requested state
1202  *
1203  * Return: bool
1204  */
bs_state_non_wlan_req_event(void * ctx,uint16_t event,uint16_t data_len,void * data)1205 static bool bs_state_non_wlan_req_event(void *ctx, uint16_t event,
1206 					uint16_t data_len, void *data)
1207 {
1208 	bool event_handled = true;
1209 	struct bearer_switch_info *bs_ctx = ctx;
1210 	struct wlan_bearer_switch_request *bs_req = data;
1211 
1212 	if (!ll_lt_sap_is_bs_req_valid(bs_req))
1213 		return false;
1214 	if (!ll_lt_sap_is_bs_ctx_valid(bs_ctx))
1215 		return false;
1216 
1217 	switch (event) {
1218 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN:
1219 		ll_lt_sap_handle_bs_to_wlan_in_non_wlan_requested_state(bs_ctx,
1220 									bs_req);
1221 		break;
1222 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN:
1223 		ll_lt_sap_handle_bs_to_non_wlan_in_non_wlan_requested_state(
1224 									bs_ctx,
1225 									bs_req);
1226 		break;
1227 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_TIMEOUT:
1228 		ll_lt_sap_handle_bs_to_non_wlan_timeout(bs_ctx, bs_req);
1229 		break;
1230 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_COMPLETED:
1231 		ll_lt_sap_handle_bs_to_non_wlan_completed(bs_ctx, bs_req);
1232 		break;
1233 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_FAILURE:
1234 		ll_lt_sap_handle_bs_to_non_wlan_failure(bs_ctx, bs_req);
1235 		break;
1236 	default:
1237 		event_handled = false;
1238 		break;
1239 	}
1240 
1241 	return event_handled;
1242 }
1243 
1244 /**
1245  * bs_state_wlan_entry() - Entry API for wlan state for bearer switch
1246  * state machine
1247  * @ctx: Bearer switch context
1248  *
1249  * API to perform operations on moving to wlan state
1250  *
1251  * Return: void
1252  */
bs_state_wlan_entry(void * ctx)1253 static void bs_state_wlan_entry(void *ctx)
1254 {
1255 	struct bearer_switch_info *bs_ctx = ctx;
1256 
1257 	bs_sm_state_update(bs_ctx, BEARER_WLAN);
1258 }
1259 
1260 /**
1261  * bs_state_wlan_exit() - Exit API for wlan state for bearer switch
1262  * state machine
1263  * @ctx: Bearer switch context
1264  *
1265  * API to perform operations on exiting from wlan state
1266  *
1267  * Return: void
1268  */
bs_state_wlan_exit(void * ctx)1269 static void bs_state_wlan_exit(void *ctx)
1270 {
1271 }
1272 
1273 /**
1274  * bs_state_wlan_event() - Wlan State event handler for bearer switch
1275  * state machine
1276  * @ctx: Bearer switch context
1277  * @event: event
1278  * @data_len: length of @data
1279  * @data: event data
1280  *
1281  * API to handle events in Wlan state
1282  *
1283  * Return: bool
1284  */
bs_state_wlan_event(void * ctx,uint16_t event,uint16_t data_len,void * data)1285 static bool bs_state_wlan_event(void *ctx, uint16_t event,
1286 				uint16_t data_len, void *data)
1287 {
1288 	bool event_handled = true;
1289 	struct bearer_switch_info *bs_ctx = ctx;
1290 	struct wlan_bearer_switch_request *bs_req = data;
1291 
1292 	if (!ll_lt_sap_is_bs_req_valid(bs_req))
1293 		return false;
1294 	if (!ll_lt_sap_is_bs_ctx_valid(bs_ctx))
1295 		return false;
1296 
1297 	switch (event) {
1298 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN:
1299 		ll_lt_sap_handle_bs_to_wlan_in_wlan_state(bs_ctx, bs_req);
1300 		break;
1301 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN:
1302 		ll_lt_sap_handle_bs_to_non_wlan_in_wlan_state(bs_ctx, bs_req);
1303 		break;
1304 	default:
1305 		event_handled = false;
1306 		break;
1307 	}
1308 
1309 	return event_handled;
1310 }
1311 
1312 /**
1313  * bs_state_wlan_req_entry() - Entry API for Wlan requested state for
1314  *bearer switch state machine
1315  * @ctx: Bearer switch context
1316  *
1317  * API to perform operations on moving to Wlan requested state
1318  *
1319  * Return: void
1320  */
bs_state_wlan_req_entry(void * ctx)1321 static void bs_state_wlan_req_entry(void *ctx)
1322 {
1323 }
1324 
1325 /**
1326  * bs_state_wlan_req_exit() - Exit API for Wlan requested state for
1327  * bearer switch state machine
1328  * @ctx: Bearer switch context
1329  *
1330  * API to perform operations on exiting from Wlan requested state
1331  *
1332  * Return: void
1333  */
bs_state_wlan_req_exit(void * ctx)1334 static void bs_state_wlan_req_exit(void *ctx)
1335 {
1336 	struct bearer_switch_info *bs_ctx = ctx;
1337 
1338 	bs_sm_state_update(bs_ctx, BEARER_WLAN_REQUESTED);
1339 }
1340 
1341 /**
1342  * bs_state_wlan_req_event() - Wlan requested State event handler for
1343  * bearer switch state machine
1344  * @ctx: Bearer switch context
1345  * @event: event
1346  * @data_len: length of @data
1347  * @data: event data
1348  *
1349  * API to handle events in Wlan state
1350  *
1351  * Return: bool
1352  */
bs_state_wlan_req_event(void * ctx,uint16_t event,uint16_t data_len,void * data)1353 static bool bs_state_wlan_req_event(void *ctx, uint16_t event,
1354 				    uint16_t data_len, void *data)
1355 {
1356 	bool event_handled = true;
1357 	struct bearer_switch_info *bs_ctx = ctx;
1358 	struct wlan_bearer_switch_request *bs_req = data;
1359 
1360 	if (!ll_lt_sap_is_bs_req_valid(bs_req))
1361 		return false;
1362 	if (!ll_lt_sap_is_bs_ctx_valid(bs_ctx))
1363 		return false;
1364 
1365 	switch (event) {
1366 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN:
1367 		ll_lt_sap_handle_bs_to_wlan_in_wlan_req_state(bs_ctx, bs_req);
1368 		break;
1369 	case WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN:
1370 		ll_lt_sap_handle_bs_to_non_wlan_in_wlan_req_state(bs_ctx,
1371 								  bs_req);
1372 		break;
1373 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN_TIMEOUT:
1374 		ll_lt_sap_handle_bs_to_wlan_timeout(bs_ctx, bs_req);
1375 		break;
1376 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN_FAILURE:
1377 		ll_lt_sap_handle_bs_to_wlan_failure(bs_ctx, bs_req);
1378 		break;
1379 	case WLAN_BS_SM_EV_SWITCH_TO_WLAN_COMPLETED:
1380 		ll_lt_sap_handle_bs_to_wlan_completed(bs_ctx, bs_req);
1381 		break;
1382 	default:
1383 		event_handled = false;
1384 		break;
1385 	}
1386 
1387 	return event_handled;
1388 }
1389 
1390 struct wlan_sm_state_info bs_sm_info[] = {
1391 	{
1392 		(uint8_t)BEARER_NON_WLAN,
1393 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1394 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1395 		false,
1396 		"NON_WLAN",
1397 		bs_state_non_wlan_entry,
1398 		bs_state_non_wlan_exit,
1399 		bs_state_non_wlan_event
1400 	},
1401 	{
1402 		(uint8_t)BEARER_NON_WLAN_REQUESTED,
1403 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1404 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1405 		false,
1406 		"NON_WLAN_REQUESTED",
1407 		bs_state_non_wlan_req_entry,
1408 		bs_state_non_wlan_req_exit,
1409 		bs_state_non_wlan_req_event
1410 	},
1411 	{
1412 		(uint8_t)BEARER_WLAN_REQUESTED,
1413 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1414 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1415 		false,
1416 		"WLAN_REQUESTED",
1417 		bs_state_wlan_req_entry,
1418 		bs_state_wlan_req_exit,
1419 		bs_state_wlan_req_event
1420 	},
1421 	{
1422 		(uint8_t)BEARER_WLAN,
1423 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1424 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1425 		false,
1426 		"WLAN",
1427 		bs_state_wlan_entry,
1428 		bs_state_wlan_exit,
1429 		bs_state_wlan_event
1430 	},
1431 	{
1432 		(uint8_t)BEARER_SWITCH_MAX,
1433 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1434 		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
1435 		false,
1436 		"INVALID",
1437 		NULL,
1438 		NULL,
1439 		NULL
1440 	},
1441 };
1442 
1443 static const char *bs_sm_event_names[] = {
1444 	"EV_SW_TO_WLAN",
1445 	"EV_SW_TO_NON_WLAN",
1446 	"EV_SW_TO_WLAN_TIMEOUT",
1447 	"EV_SW_TO_NON_WLAN_TIMEOUT",
1448 	"EV_SW_TO_WLAN_COMPLETED",
1449 	"EV_SW_TO_NON_WLAN_COMPLETED",
1450 	"EV_SW_TO_WLAN_FAILURE",
1451 	"EV_SW_TO_NON_WLAN_FAILURE",
1452 };
1453 
bs_sm_create(struct bearer_switch_info * bs_ctx)1454 QDF_STATUS bs_sm_create(struct bearer_switch_info *bs_ctx)
1455 {
1456 	struct wlan_sm *sm;
1457 	uint8_t name[WLAN_SM_ENGINE_MAX_NAME];
1458 
1459 	qdf_scnprintf(name, sizeof(name), "BS_%d",
1460 		      wlan_vdev_get_id(bs_ctx->vdev));
1461 	sm = wlan_sm_create(name, bs_ctx,
1462 			    BEARER_NON_WLAN,
1463 			    bs_sm_info,
1464 			    QDF_ARRAY_SIZE(bs_sm_info),
1465 			    bs_sm_event_names,
1466 			    QDF_ARRAY_SIZE(bs_sm_event_names));
1467 	if (!sm) {
1468 		ll_sap_err("Vdev %d BS_SM State Machine creation failed",
1469 			   wlan_vdev_get_id(bs_ctx->vdev));
1470 		return QDF_STATUS_E_NOMEM;
1471 	}
1472 	bs_ctx->sm.sm_hdl = sm;
1473 
1474 	bs_lock_create(bs_ctx);
1475 
1476 	bs_req_timer_init(bs_ctx);
1477 
1478 	return QDF_STATUS_SUCCESS;
1479 }
1480 
bs_sm_destroy(struct bearer_switch_info * bs_ctx)1481 QDF_STATUS bs_sm_destroy(struct bearer_switch_info *bs_ctx)
1482 {
1483 	bs_lock_destroy(bs_ctx);
1484 	bs_req_timer_deinit(bs_ctx);
1485 	wlan_sm_delete(bs_ctx->sm.sm_hdl);
1486 
1487 	return QDF_STATUS_SUCCESS;
1488 }
1489 
1490 /**
1491  * bs_get_state() - Get current state of the bearer switch state machine
1492  * @bearer_switch_ctx: lBearer switch context
1493  *
1494  * Return: Current state of the bearer switch state machine
1495  */
1496 static enum wlan_bearer_switch_sm_state
bs_get_state(struct bearer_switch_info * bearer_switch_ctx)1497 bs_get_state(struct bearer_switch_info *bearer_switch_ctx)
1498 {
1499 	if (!bearer_switch_ctx || !bearer_switch_ctx->vdev)
1500 		return BEARER_SWITCH_MAX;
1501 
1502 	return bearer_switch_ctx->sm.bs_state;
1503 }
1504 
1505 /**
1506  * bs_sm_print_state_event() - Print BS_SM state and event
1507  * @bearer_switch_ctx: lBearer switch context
1508  * @event: Event which needs to be printed
1509  *
1510  * Return: None
1511  */
1512 static void
bs_sm_print_state_event(struct bearer_switch_info * bearer_switch_ctx,enum wlan_bearer_switch_sm_evt event)1513 bs_sm_print_state_event(struct bearer_switch_info *bearer_switch_ctx,
1514 			enum wlan_bearer_switch_sm_evt event)
1515 {
1516 	enum wlan_bearer_switch_sm_state state;
1517 
1518 	state = bs_get_state(bearer_switch_ctx);
1519 
1520 	ll_sap_debug("[%s]%s, %s", bearer_switch_ctx->sm.sm_hdl->name,
1521 		     bs_sm_info[state].name, bs_sm_event_names[event]);
1522 }
1523 
1524 /**
1525  * bs_sm_print_state() - Print BS_SM state
1526  * @bearer_switch_ctx: lBearer switch context
1527  *
1528  * Return: None
1529  */
1530 static void
bs_sm_print_state(struct bearer_switch_info * bearer_switch_ctx)1531 bs_sm_print_state(struct bearer_switch_info *bearer_switch_ctx)
1532 {
1533 	enum wlan_bearer_switch_sm_state state;
1534 
1535 	state = bs_get_state(bearer_switch_ctx);
1536 
1537 	ll_sap_debug("[%s]%s", bearer_switch_ctx->sm.sm_hdl->name,
1538 		     bs_sm_info[state].name);
1539 }
1540 
bs_sm_deliver_event(struct wlan_objmgr_psoc * psoc,enum wlan_bearer_switch_sm_evt event,uint16_t data_len,void * data)1541 QDF_STATUS bs_sm_deliver_event(struct wlan_objmgr_psoc *psoc,
1542 			       enum wlan_bearer_switch_sm_evt event,
1543 			       uint16_t data_len, void *data)
1544 {
1545 	QDF_STATUS status;
1546 	enum wlan_bearer_switch_sm_state state_entry, state_exit;
1547 	struct bearer_switch_info *bearer_switch_ctx;
1548 	struct wlan_objmgr_vdev *vdev;
1549 	struct ll_sap_vdev_priv_obj *ll_sap_obj;
1550 	uint8_t vdev_id;
1551 
1552 	vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
1553 	if (vdev_id == WLAN_INVALID_VDEV_ID)
1554 		return QDF_STATUS_E_INVAL;
1555 
1556 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1557 						    WLAN_LL_SAP_ID);
1558 	if (!vdev)
1559 		return QDF_STATUS_E_INVAL;
1560 
1561 	ll_sap_obj = ll_sap_get_vdev_priv_obj(vdev);
1562 
1563 	if (!ll_sap_obj) {
1564 		ll_sap_err("BS_SM vdev %d ll_sap obj null",
1565 			   wlan_vdev_get_id(vdev));
1566 		status = QDF_STATUS_E_INVAL;
1567 		goto rel_ref;
1568 	}
1569 
1570 	bearer_switch_ctx = ll_sap_obj->bearer_switch_ctx;
1571 	if (!bearer_switch_ctx) {
1572 		status = QDF_STATUS_E_FAILURE;
1573 		goto rel_ref;
1574 	}
1575 
1576 	bs_lock_acquire(bearer_switch_ctx);
1577 
1578 	/* store entry state and sub state for prints */
1579 	state_entry = bs_get_state(bearer_switch_ctx);
1580 	bs_sm_print_state_event(bearer_switch_ctx, event);
1581 
1582 	status = wlan_sm_dispatch(bearer_switch_ctx->sm.sm_hdl,
1583 				  event, data_len, data);
1584 	/* Take exit state, exit substate for prints */
1585 	state_exit = bs_get_state(bearer_switch_ctx);
1586 
1587 	/* If no state change, don't print */
1588 	if (!(state_entry == state_exit))
1589 		bs_sm_print_state(bearer_switch_ctx);
1590 	bs_lock_release(bearer_switch_ctx);
1591 
1592 rel_ref:
1593 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LL_SAP_ID);
1594 
1595 	return status;
1596 }
1597 
1598 QDF_STATUS
ll_lt_sap_switch_bearer_to_ble(struct wlan_objmgr_psoc * psoc,struct wlan_bearer_switch_request * bs_request)1599 ll_lt_sap_switch_bearer_to_ble(struct wlan_objmgr_psoc *psoc,
1600 			       struct wlan_bearer_switch_request *bs_request)
1601 {
1602 	return bs_sm_deliver_event(psoc, WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN,
1603 				   sizeof(*bs_request), bs_request);
1604 }
1605 
1606 QDF_STATUS
ll_lt_sap_switch_bearer_to_wlan(struct wlan_objmgr_psoc * psoc,struct wlan_bearer_switch_request * bs_request)1607 ll_lt_sap_switch_bearer_to_wlan(struct wlan_objmgr_psoc *psoc,
1608 				struct wlan_bearer_switch_request *bs_request)
1609 {
1610 	return bs_sm_deliver_event(psoc, WLAN_BS_SM_EV_SWITCH_TO_WLAN,
1611 				   sizeof(*bs_request), bs_request);
1612 }
1613 
1614 QDF_STATUS
ll_lt_sap_request_for_audio_transport_switch(struct wlan_objmgr_vdev * vdev,enum bearer_switch_req_type req_type)1615 ll_lt_sap_request_for_audio_transport_switch(
1616 					struct wlan_objmgr_vdev *vdev,
1617 					enum bearer_switch_req_type req_type)
1618 {
1619 	struct ll_sap_vdev_priv_obj *ll_sap_obj;
1620 	struct bearer_switch_info *bearer_switch_ctx;
1621 
1622 	ll_sap_obj = ll_sap_get_vdev_priv_obj(vdev);
1623 
1624 	if (!ll_sap_obj) {
1625 		ll_sap_err("BS_SM vdev %d ll_sap obj null",
1626 			   wlan_vdev_get_id(vdev));
1627 		return QDF_STATUS_E_INVAL;
1628 	}
1629 	bearer_switch_ctx = ll_sap_obj->bearer_switch_ctx;
1630 	if (!bearer_switch_ctx)
1631 		return QDF_STATUS_E_INVAL;
1632 
1633 	/*
1634 	 * Request to switch to non-wlan can always be accepted so,
1635 	 * always return success
1636 	 */
1637 	if (req_type == WLAN_BS_REQ_TO_NON_WLAN) {
1638 		ll_sap_debug("BS_SM vdev %d WLAN_BS_REQ_TO_NON_WLAN accepted",
1639 			     wlan_vdev_get_id(vdev));
1640 		return QDF_STATUS_SUCCESS;
1641 	} else if (req_type == WLAN_BS_REQ_TO_WLAN) {
1642 		/*
1643 		 * Total_ref_count zero indicates that no module wants to stay
1644 		 * in non-wlan mode so this request can be accepted
1645 		 */
1646 		if (!qdf_atomic_read(&bearer_switch_ctx->total_ref_count)) {
1647 			ll_sap_debug("BS_SM vdev %d WLAN_BS_REQ_TO_WLAN accepted",
1648 				     wlan_vdev_get_id(vdev));
1649 			return QDF_STATUS_SUCCESS;
1650 		}
1651 		ll_sap_debug("BS_SM vdev %d WLAN_BS_REQ_TO_WLAN rejected",
1652 			     wlan_vdev_get_id(vdev));
1653 
1654 		return QDF_STATUS_E_FAILURE;
1655 	}
1656 	ll_sap_err("BS_SM vdev %d Invalid audio transport type %d",
1657 		   wlan_vdev_get_id(vdev), req_type);
1658 
1659 	return QDF_STATUS_E_INVAL;
1660 }
1661 
1662 /**
1663  * ll_lt_sap_deliver_wlan_audio_transport_switch_resp() - Deliver wlan
1664  * audio transport switch response to BS_SM
1665  * @vdev: ll_lt sap vdev
1666  * @status: Status of the request
1667  *
1668  * Return: None
1669  */
ll_lt_sap_deliver_wlan_audio_transport_switch_resp(struct wlan_objmgr_vdev * vdev,enum bearer_switch_status status)1670 static void ll_lt_sap_deliver_wlan_audio_transport_switch_resp(
1671 					struct wlan_objmgr_vdev *vdev,
1672 					enum bearer_switch_status status)
1673 {
1674 	struct wlan_bearer_switch_request *bs_request;
1675 	struct ll_sap_vdev_priv_obj *ll_sap_obj;
1676 	struct bearer_switch_info *bs_ctx;
1677 
1678 	ll_sap_obj = ll_sap_get_vdev_priv_obj(vdev);
1679 
1680 	if (!ll_sap_obj) {
1681 		ll_sap_err("BS_SM vdev %d ll_sap obj null",
1682 			   wlan_vdev_get_id(vdev));
1683 		return;
1684 	}
1685 
1686 	bs_ctx = ll_sap_obj->bearer_switch_ctx;
1687 	if (!bs_ctx)
1688 		return;
1689 
1690 	bs_request = ll_lt_sap_find_first_valid_bs_wlan_req(bs_ctx);
1691 
1692 	/*
1693 	 * If bs_request is cached in the BS_SM, it means this is a response
1694 	 * to the host driver's request of bearer switch so deliver the event
1695 	 * to the BS_SM
1696 	 * If there is no cached request in BS_SM, it means that some other
1697 	 * module (other than wlan) has performed the bearer switch and it is
1698 	 * not a response of the wlan module's bearer switch request.
1699 	 */
1700 	if (status == WLAN_BS_STATUS_COMPLETED)
1701 		bs_sm_deliver_event(wlan_vdev_get_psoc(vdev),
1702 				    WLAN_BS_SM_EV_SWITCH_TO_WLAN_COMPLETED,
1703 				    sizeof(*bs_request), bs_request);
1704 	else if (status == WLAN_BS_STATUS_REJECTED)
1705 		bs_sm_deliver_event(wlan_vdev_get_psoc(vdev),
1706 				    WLAN_BS_SM_EV_SWITCH_TO_WLAN_FAILURE,
1707 				    sizeof(*bs_request), bs_request);
1708 	else
1709 		ll_sap_err("BS_SM vdev %d Invalid BS status %d",
1710 			   wlan_vdev_get_id(vdev), status);
1711 }
1712 
1713 /**
1714  * ll_lt_sap_deliver_non_wlan_audio_transport_switch_resp() - Deliver non wlan
1715  * audio transport switch response to BS_SM
1716  * @vdev: ll_lt sap vdev
1717  * @status: Status of the request
1718  *
1719  * Return: None
1720  */
ll_lt_sap_deliver_non_wlan_audio_transport_switch_resp(struct wlan_objmgr_vdev * vdev,enum bearer_switch_status status)1721 static void ll_lt_sap_deliver_non_wlan_audio_transport_switch_resp(
1722 					struct wlan_objmgr_vdev *vdev,
1723 					enum bearer_switch_status status)
1724 {
1725 	struct wlan_bearer_switch_request *bs_request;
1726 	struct ll_sap_vdev_priv_obj *ll_sap_obj;
1727 	struct bearer_switch_info *bs_ctx;
1728 
1729 	ll_sap_obj = ll_sap_get_vdev_priv_obj(vdev);
1730 
1731 	if (!ll_sap_obj) {
1732 		ll_sap_err("BS_SM vdev %d ll_sap obj null",
1733 			   wlan_vdev_get_id(vdev));
1734 		return;
1735 	}
1736 
1737 	bs_ctx = ll_sap_obj->bearer_switch_ctx;
1738 	if (!bs_ctx)
1739 		return;
1740 
1741 	bs_request = ll_lt_sap_find_first_valid_bs_non_wlan_req(bs_ctx);
1742 
1743 	/*
1744 	 * If bs_request is cached in the BS_SM, it means this is a response
1745 	 * to the host driver's request of bearer switch so deliver the event
1746 	 * to the BS_SM
1747 	 */
1748 	if (bs_request) {
1749 		if (status == WLAN_BS_STATUS_COMPLETED)
1750 			bs_sm_deliver_event(
1751 				wlan_vdev_get_psoc(vdev),
1752 				WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_COMPLETED,
1753 				sizeof(*bs_request), bs_request);
1754 		else if (status == WLAN_BS_STATUS_REJECTED)
1755 			bs_sm_deliver_event(
1756 				wlan_vdev_get_psoc(vdev),
1757 				WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_FAILURE,
1758 				sizeof(*bs_request), bs_request);
1759 		else
1760 			ll_sap_err(BS_PREFIX_FMT "Invalid BS status %d",
1761 				   BS_PREFIX_REF(wlan_vdev_get_id(vdev),
1762 						 bs_request->request_id),
1763 				   status);
1764 
1765 		return;
1766 	}
1767 
1768 	/*
1769 	 * If there is no cached request in BS_SM, it means that some other
1770 	 * module has performed the bearer switch and it is not a response of
1771 	 * the wlan bearer switch request, so just update the current state of
1772 	 * the state machine
1773 	 */
1774 	bs_sm_state_update(bs_ctx, BEARER_NON_WLAN);
1775 }
1776 
1777 void
ll_lt_sap_deliver_audio_transport_switch_resp(struct wlan_objmgr_vdev * vdev,enum bearer_switch_req_type req_type,enum bearer_switch_status status)1778 ll_lt_sap_deliver_audio_transport_switch_resp(
1779 				struct wlan_objmgr_vdev *vdev,
1780 				enum bearer_switch_req_type req_type,
1781 				enum bearer_switch_status status)
1782 {
1783 	ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(vdev, req_type,
1784 							   status);
1785 
1786 	if (req_type == WLAN_BS_REQ_TO_NON_WLAN)
1787 		ll_lt_sap_deliver_non_wlan_audio_transport_switch_resp(
1788 								vdev,
1789 								status);
1790 
1791 	else if (req_type == WLAN_BS_REQ_TO_WLAN)
1792 		ll_lt_sap_deliver_wlan_audio_transport_switch_resp(
1793 								vdev,
1794 								status);
1795 	else
1796 		ll_sap_err("Vdev %d Invalid req_type %d ",
1797 			   wlan_vdev_get_id(vdev), req_type);
1798 }
1799