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