1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include "wlan_mlo_mgr_main.h"
18 #include "qdf_types.h"
19 #include "wlan_cmn.h"
20 #include "wlan_mlo_mgr_cmn.h"
21 #include "wlan_mlo_mgr_msgq.h"
22 #include "wlan_mlo_mgr_peer.h"
23
24 #ifndef MLO_MSGQ_SUPPORT
mlo_msgq_post(enum mlo_msg_type type,struct wlan_mlo_dev_context * ml_dev,void * payload)25 QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
26 struct wlan_mlo_dev_context *ml_dev,
27 void *payload)
28 {
29 struct peer_create_notif_s *peer_create;
30 struct peer_assoc_notify_s *peer_assoc;
31 struct peer_assoc_fail_notify_s *peer_assoc_fail;
32 struct peer_discon_notify_s *peer_disconn;
33 struct peer_deauth_notify_s *peer_deauth;
34 struct peer_auth_process_notif_s *peer_auth;
35
36 switch (type) {
37 case MLO_PEER_CREATE:
38 peer_create = (struct peer_create_notif_s *)payload;
39
40 mlo_mlme_peer_create(peer_create->vdev_link,
41 peer_create->ml_peer,
42 &peer_create->addr, peer_create->frm_buf);
43 qdf_nbuf_free(peer_create->frm_buf);
44 wlan_mlo_peer_release_ref(peer_create->ml_peer);
45 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
46 WLAN_MLO_MGR_ID);
47 break;
48
49 case MLO_BRIDGE_PEER_CREATE:
50 peer_create = (struct peer_create_notif_s *)payload;
51
52 mlo_mlme_bridge_peer_create(peer_create->vdev_link,
53 peer_create->ml_peer,
54 &peer_create->addr,
55 peer_create->frm_buf);
56 wlan_mlo_peer_release_ref(peer_create->ml_peer);
57 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
58 WLAN_MLO_MGR_ID);
59 break;
60
61 case MLO_PEER_ASSOC:
62 peer_assoc = (struct peer_assoc_notify_s *)payload;
63 mlo_mlme_peer_assoc(peer_assoc->peer);
64 wlan_objmgr_peer_release_ref(peer_assoc->peer,
65 WLAN_MLO_MGR_ID);
66 break;
67
68 case MLO_PEER_ASSOC_FAIL:
69 peer_assoc_fail = (struct peer_assoc_fail_notify_s *)payload;
70 mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
71 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
72 WLAN_MLO_MGR_ID);
73 break;
74
75 case MLO_PEER_DISCONNECT:
76 peer_disconn = (struct peer_discon_notify_s *)payload;
77 mlo_mlme_peer_delete(peer_disconn->peer);
78 wlan_objmgr_peer_release_ref(peer_disconn->peer,
79 WLAN_MLO_MGR_ID);
80 break;
81
82 case MLO_PEER_DEAUTH:
83 peer_deauth = (struct peer_deauth_notify_s *)payload;
84 mlo_mlme_peer_deauth(peer_deauth->peer,
85 peer_deauth->is_disassoc);
86 wlan_objmgr_peer_release_ref(peer_deauth->peer,
87 WLAN_MLO_MGR_ID);
88 break;
89
90 case MLO_PEER_PENDING_AUTH:
91 peer_auth = (struct peer_auth_process_notif_s *)payload;
92 mlo_mlme_peer_process_auth(peer_auth->auth_params);
93 break;
94
95 case MLO_PEER_REASSOC:
96 peer_create = (struct peer_create_notif_s *)payload;
97 mlo_mlme_peer_reassoc(peer_create->vdev_link,
98 peer_create->ml_peer, &peer_create->addr,
99 peer_create->frm_buf);
100 qdf_nbuf_free(peer_create->frm_buf);
101 wlan_mlo_peer_release_ref(peer_create->ml_peer);
102 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
103 WLAN_MLO_MGR_ID);
104 break;
105
106 default:
107 break;
108 }
109
110 return QDF_STATUS_SUCCESS;
111 }
112
mlo_msgq_init(void)113 void mlo_msgq_init(void)
114 {
115 }
116
mlo_msgq_free(void)117 void mlo_msgq_free(void)
118 {
119 }
120 #else
mlo_msgq_timer_start(void)121 static void mlo_msgq_timer_start(void)
122 {
123 struct ctxt_switch_mgr *msgq_ctx;
124 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
125 bool start_timer = true;
126
127 if (!mlo_ctx)
128 return;
129
130 msgq_ctx = mlo_ctx->msgq_ctx;
131
132 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
133 if (!msgq_ctx->timer_started)
134 msgq_ctx->timer_started = true;
135 else
136 start_timer = false;
137 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
138
139 if (start_timer)
140 qdf_timer_start(&msgq_ctx->ctxt_mgr_timer, 0);
141 }
142
mlo_msgq_timer_stop(void)143 static void mlo_msgq_timer_stop(void)
144 {
145 struct ctxt_switch_mgr *msgq_ctx;
146 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
147
148 if (!mlo_ctx)
149 return;
150
151 msgq_ctx = mlo_ctx->msgq_ctx;
152
153 qdf_timer_stop(&msgq_ctx->ctxt_mgr_timer);
154
155 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
156 msgq_ctx->timer_started = false;
157 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
158 }
159
mlo_msgq_post(enum mlo_msg_type type,struct wlan_mlo_dev_context * ml_dev,void * payload)160 QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
161 struct wlan_mlo_dev_context *ml_dev,
162 void *payload)
163 {
164 struct mlo_ctxt_switch_msg_s *msg;
165 struct peer_create_notif_s *peer_create, *peer_create_l;
166 struct peer_assoc_notify_s *peer_assoc, *peer_assoc_l;
167 struct peer_assoc_fail_notify_s *peer_assoc_fail, *peer_assoc_fail_l;
168 struct peer_discon_notify_s *peer_disconn, *peer_disconn_l;
169 struct peer_deauth_notify_s *peer_deauth, *peer_deauth_l;
170 struct peer_auth_process_notif_s *peer_auth, *peer_auth_l;
171 struct ctxt_switch_mgr *msgq_ctx;
172 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
173
174 if (!mlo_ctx)
175 return QDF_STATUS_E_FAILURE;
176
177 msgq_ctx = mlo_ctx->msgq_ctx;
178
179 if (!msgq_ctx->allow_msg)
180 return QDF_STATUS_E_FAILURE;
181
182 msg = qdf_mem_malloc(sizeof(*msg));
183 if (!msg)
184 return QDF_STATUS_E_NOMEM;
185
186 msg->type = type;
187 msg->ml_dev = ml_dev;
188
189 switch (type) {
190 case MLO_PEER_CREATE:
191 peer_create = &msg->m.peer_create;
192 peer_create_l = (struct peer_create_notif_s *)payload;
193 peer_create->frm_buf = peer_create_l->frm_buf;
194 peer_create->ml_peer = peer_create_l->ml_peer;
195 peer_create->vdev_link = peer_create_l->vdev_link;
196 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
197 break;
198
199 case MLO_BRIDGE_PEER_CREATE:
200 peer_create = &msg->m.peer_create;
201 peer_create_l = (struct peer_create_notif_s *)payload;
202 peer_create->frm_buf = peer_create_l->frm_buf;
203 peer_create->ml_peer = peer_create_l->ml_peer;
204 peer_create->vdev_link = peer_create_l->vdev_link;
205 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
206 break;
207
208 case MLO_PEER_ASSOC:
209 peer_assoc = &msg->m.peer_assoc;
210 peer_assoc_l = (struct peer_assoc_notify_s *)payload;
211 peer_assoc->peer = peer_assoc_l->peer;
212 break;
213
214 case MLO_PEER_ASSOC_FAIL:
215 peer_assoc_fail = &msg->m.peer_assoc_fail;
216 peer_assoc_fail_l = (struct peer_assoc_fail_notify_s *)payload;
217 peer_assoc_fail->peer = peer_assoc_fail_l->peer;
218 break;
219
220 case MLO_PEER_DISCONNECT:
221 peer_disconn = &msg->m.peer_disconn;
222 peer_disconn_l = (struct peer_discon_notify_s *)payload;
223 peer_disconn->peer = peer_disconn_l->peer;
224 break;
225
226 case MLO_PEER_DEAUTH:
227 peer_deauth = &msg->m.peer_deauth;
228 peer_deauth_l = (struct peer_deauth_notify_s *)payload;
229 peer_deauth->peer = peer_deauth_l->peer;
230 peer_deauth->is_disassoc = peer_deauth_l->is_disassoc;
231 break;
232
233 case MLO_PEER_PENDING_AUTH:
234 peer_auth = &msg->m.peer_auth;
235 peer_auth_l = (struct peer_auth_process_notif_s *)payload;
236 peer_auth->auth_params = peer_auth_l->auth_params;
237 break;
238
239 case MLO_PEER_REASSOC:
240 peer_create = &msg->m.peer_create;
241 peer_create_l = (struct peer_create_notif_s *)payload;
242 peer_create->frm_buf = peer_create_l->frm_buf;
243 peer_create->ml_peer = peer_create_l->ml_peer;
244 peer_create->vdev_link = peer_create_l->vdev_link;
245 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
246 break;
247
248 default:
249 break;
250 }
251
252 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
253 qdf_list_insert_back(&msgq_ctx->msgq_list, &msg->node);
254 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
255 mlo_msgq_timer_start();
256
257 return QDF_STATUS_SUCCESS;
258 }
259
mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s * msg)260 static void mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s *msg)
261 {
262 enum mlo_msg_type type;
263 struct peer_create_notif_s *peer_create;
264 struct peer_assoc_notify_s *peer_assoc;
265 struct peer_assoc_fail_notify_s *peer_assoc_fail;
266 struct peer_discon_notify_s *peer_disconn;
267 struct peer_deauth_notify_s *peer_deauth;
268 struct peer_auth_process_notif_s *peer_auth;
269
270 type = msg->type;
271 switch (type) {
272 case MLO_PEER_CREATE:
273 peer_create = &msg->m.peer_create;
274 mlo_mlme_peer_create(peer_create->vdev_link,
275 peer_create->ml_peer,
276 &peer_create->addr, peer_create->frm_buf);
277 qdf_nbuf_free(peer_create->frm_buf);
278 wlan_mlo_peer_release_ref(peer_create->ml_peer);
279 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
280 WLAN_MLO_MGR_ID);
281 break;
282
283 case MLO_BRIDGE_PEER_CREATE:
284 peer_create = &msg->m.peer_create;
285 mlo_mlme_bridge_peer_create(peer_create->vdev_link,
286 peer_create->ml_peer,
287 &peer_create->addr,
288 peer_create->frm_buf);
289 wlan_mlo_peer_release_ref(peer_create->ml_peer);
290 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
291 WLAN_MLO_MGR_ID);
292 break;
293
294 case MLO_PEER_ASSOC:
295 peer_assoc = &msg->m.peer_assoc;
296 mlo_mlme_peer_assoc(peer_assoc->peer);
297 wlan_objmgr_peer_release_ref(peer_assoc->peer,
298 WLAN_MLO_MGR_ID);
299 break;
300
301 case MLO_PEER_ASSOC_FAIL:
302 peer_assoc_fail = &msg->m.peer_assoc_fail;
303 mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
304 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
305 WLAN_MLO_MGR_ID);
306 break;
307
308 case MLO_PEER_DISCONNECT:
309 peer_disconn = &msg->m.peer_disconn;
310 mlo_mlme_peer_delete(peer_disconn->peer);
311 wlan_objmgr_peer_release_ref(peer_disconn->peer,
312 WLAN_MLO_MGR_ID);
313 break;
314
315 case MLO_PEER_DEAUTH:
316 peer_deauth = &msg->m.peer_deauth;
317 mlo_mlme_peer_deauth(peer_deauth->peer);
318 wlan_objmgr_peer_release_ref(peer_deauth->peer,
319 WLAN_MLO_MGR_ID);
320 break;
321
322 case MLO_PEER_PENDING_AUTH:
323 peer_auth = &msg->m.peer_auth;
324 mlo_mlme_peer_process_auth(peer_auth->auth_params);
325 break;
326
327 case MLO_PEER_REASSOC:
328 peer_create = &msg->m.peer_create;
329 mlo_mlme_peer_reassoc(peer_create->vdev_link,
330 peer_create->ml_peer, &peer_create->addr,
331 peer_create->frm_buf);
332 qdf_nbuf_free(peer_create->frm_buf);
333 wlan_mlo_peer_release_ref(peer_create->ml_peer);
334 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
335 WLAN_MLO_MGR_ID);
336 break;
337
338 default:
339 break;
340 }
341 qdf_mem_free(msg);
342 }
343
mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s * msg)344 static void mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s *msg)
345 {
346 enum mlo_msg_type type;
347 struct peer_create_notif_s *peer_create;
348 struct peer_assoc_notify_s *peer_assoc;
349 struct peer_assoc_fail_notify_s *peer_assoc_fail;
350 struct peer_discon_notify_s *peer_disconn;
351 struct peer_deauth_notify_s *peer_deauth;
352
353 type = msg->type;
354 switch (type) {
355 case MLO_PEER_CREATE:
356 peer_create = &msg->m.peer_create;
357 qdf_nbuf_free(peer_create->frm_buf);
358 wlan_mlo_peer_release_ref(peer_create->ml_peer);
359 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
360 WLAN_MLO_MGR_ID);
361 break;
362
363 case MLO_BRIDGE_PEER_CREATE:
364 peer_create = &msg->m.peer_create;
365 wlan_mlo_peer_release_ref(peer_create->ml_peer);
366 wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
367 WLAN_MLO_MGR_ID);
368 break;
369
370 case MLO_PEER_ASSOC:
371 peer_assoc = &msg->m.peer_assoc;
372 wlan_objmgr_peer_release_ref(peer_assoc->peer,
373 WLAN_MLO_MGR_ID);
374 break;
375
376 case MLO_PEER_ASSOC_FAIL:
377 peer_assoc_fail = &msg->m.peer_assoc_fail;
378 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
379 WLAN_MLO_MGR_ID);
380 break;
381
382 case MLO_PEER_DISCONNECT:
383 peer_disconn = &msg->m.peer_disconn;
384 wlan_objmgr_peer_release_ref(peer_disconn->peer,
385 WLAN_MLO_MGR_ID);
386 break;
387
388 case MLO_PEER_DEAUTH:
389 peer_deauth = &msg->m.peer_deauth;
390 wlan_objmgr_peer_release_ref(peer_deauth->peer,
391 WLAN_MLO_MGR_ID);
392 break;
393
394 case MLO_PEER_PENDING_AUTH:
395 peer_auth = &msg->m.peer_auth;
396 mlo_peer_free_auth_param(peer_auth->auth_params);
397 break;
398
399 default:
400 break;
401 }
402 qdf_mem_free(msg);
403 }
404
mlo_msgq_msg_flush(void)405 static void mlo_msgq_msg_flush(void)
406 {
407 struct ctxt_switch_mgr *msgq_ctx;
408 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
409 qdf_list_node_t *msgbuf_node = NULL;
410 struct mlo_ctxt_switch_msg_s *msg;
411 QDF_STATUS status;
412
413 if (!mlo_ctx)
414 return;
415
416 msgq_ctx = mlo_ctx->msgq_ctx;
417 do {
418 msg = NULL;
419 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
420 status = qdf_list_peek_front(&msgq_ctx->msgq_list,
421 &msgbuf_node);
422 if (status != QDF_STATUS_E_EMPTY) {
423 qdf_list_remove_node(&msgq_ctx->msgq_list,
424 msgbuf_node);
425 msg = qdf_container_of(msgbuf_node,
426 struct mlo_ctxt_switch_msg_s,
427 node);
428 }
429 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
430
431 if (!msg)
432 break;
433
434 mlo_msgq_msg_flush_hdlr(msg);
435
436 } while (true);
437 }
438
mlo_msgq_msg_handler(void * arg)439 static void mlo_msgq_msg_handler(void *arg)
440 {
441 struct ctxt_switch_mgr *msgq_ctx;
442 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
443 qdf_list_node_t *msgbuf_node = NULL;
444 struct mlo_ctxt_switch_msg_s *msg;
445 QDF_STATUS status;
446
447 if (!mlo_ctx)
448 return;
449
450 msgq_ctx = mlo_ctx->msgq_ctx;
451 do {
452 msg = NULL;
453 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
454 status = qdf_list_peek_front(&msgq_ctx->msgq_list,
455 &msgbuf_node);
456 if (status != QDF_STATUS_E_EMPTY) {
457 qdf_list_remove_node(&msgq_ctx->msgq_list,
458 msgbuf_node);
459 msg = qdf_container_of(msgbuf_node,
460 struct mlo_ctxt_switch_msg_s,
461 node);
462 } else {
463 msgq_ctx->timer_started = false;
464 }
465 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
466
467 if (!msg)
468 break;
469
470 mlo_msgq_msg_process_hdlr(msg);
471
472 } while (true);
473 }
474
mlo_msgq_init(void)475 void mlo_msgq_init(void)
476 {
477 struct ctxt_switch_mgr *msgq_ctx;
478 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
479
480 msgq_ctx = qdf_mem_malloc(sizeof(*msgq_ctx));
481 if (!msgq_ctx) {
482 mlo_err(" message queue context allocation failed");
483 return;
484 }
485
486 qdf_spinlock_create(&msgq_ctx->ctxt_lock);
487 /* Initialize timer with timeout handler */
488 qdf_timer_init(NULL, &msgq_ctx->ctxt_mgr_timer,
489 mlo_msgq_msg_handler,
490 NULL, QDF_TIMER_TYPE_WAKE_APPS);
491
492 msgq_ctx->timer_started = false;
493 msgq_ctx->allow_msg = true;
494 qdf_list_create(&msgq_ctx->msgq_list, MLO_MAX_MSGQ_SIZE);
495
496 mlo_ctx->msgq_ctx = msgq_ctx;
497 }
498
mlo_msgq_free(void)499 void mlo_msgq_free(void)
500 {
501 struct ctxt_switch_mgr *msgq_ctx;
502 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
503
504 if (!mlo_ctx)
505 return;
506
507 msgq_ctx = mlo_ctx->msgq_ctx;
508
509 msgq_ctx->timer_started = false;
510 msgq_ctx->allow_msg = false;
511 mlo_msgq_msg_flush();
512 qdf_list_destroy(&msgq_ctx->msgq_list);
513 qdf_timer_free(&msgq_ctx->ctxt_mgr_timer);
514 qdf_spinlock_destroy(&msgq_ctx->ctxt_lock);
515 qdf_mem_free(msgq_ctx);
516 }
517 #endif
518