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