xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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
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_PEER_ASSOC:
50 		peer_assoc = (struct peer_assoc_notify_s *)payload;
51 		mlo_mlme_peer_assoc(peer_assoc->peer);
52 		wlan_objmgr_peer_release_ref(peer_assoc->peer,
53 					     WLAN_MLO_MGR_ID);
54 		break;
55 
56 	case MLO_PEER_ASSOC_FAIL:
57 		peer_assoc_fail = (struct peer_assoc_fail_notify_s *)payload;
58 		mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
59 		wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
60 					     WLAN_MLO_MGR_ID);
61 		break;
62 
63 	case MLO_PEER_DISCONNECT:
64 		peer_disconn = (struct peer_discon_notify_s *)payload;
65 		mlo_mlme_peer_delete(peer_disconn->peer);
66 		wlan_objmgr_peer_release_ref(peer_disconn->peer,
67 					     WLAN_MLO_MGR_ID);
68 		break;
69 
70 	case MLO_PEER_DEAUTH:
71 		peer_deauth = (struct peer_deauth_notify_s *)payload;
72 		mlo_mlme_peer_deauth(peer_deauth->peer,
73 				     peer_deauth->is_disassoc);
74 		wlan_objmgr_peer_release_ref(peer_deauth->peer,
75 					     WLAN_MLO_MGR_ID);
76 		break;
77 
78 	case MLO_PEER_PENDING_AUTH:
79 		peer_auth = (struct peer_auth_process_notif_s *)payload;
80 		mlo_mlme_peer_process_auth(peer_auth->auth_params);
81 		break;
82 
83 	default:
84 		break;
85 	}
86 
87 	return QDF_STATUS_SUCCESS;
88 }
89 
90 void mlo_msgq_init(void)
91 {
92 }
93 
94 void mlo_msgq_free(void)
95 {
96 }
97 #else
98 static void mlo_msgq_timer_start(void)
99 {
100 	struct ctxt_switch_mgr *msgq_ctx;
101 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
102 	bool start_timer = true;
103 
104 	if (!mlo_ctx)
105 		return;
106 
107 	msgq_ctx = mlo_ctx->msgq_ctx;
108 
109 	qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
110 	if (!msgq_ctx->timer_started)
111 		msgq_ctx->timer_started = true;
112 	else
113 		start_timer = false;
114 	qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
115 
116 	if (start_timer)
117 		qdf_timer_start(&msgq_ctx->ctxt_mgr_timer, 0);
118 }
119 
120 static void mlo_msgq_timer_stop(void)
121 {
122 	struct ctxt_switch_mgr *msgq_ctx;
123 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
124 
125 	if (!mlo_ctx)
126 		return;
127 
128 	msgq_ctx = mlo_ctx->msgq_ctx;
129 
130 	qdf_timer_stop(&msgq_ctx->ctxt_mgr_timer);
131 
132 	qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
133 	msgq_ctx->timer_started = false;
134 	qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
135 }
136 
137 QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
138 			 struct wlan_mlo_dev_context *ml_dev,
139 			 void *payload)
140 {
141 	struct mlo_ctxt_switch_msg_s *msg;
142 	struct peer_create_notif_s *peer_create, *peer_create_l;
143 	struct peer_assoc_notify_s *peer_assoc, *peer_assoc_l;
144 	struct peer_assoc_fail_notify_s *peer_assoc_fail, *peer_assoc_fail_l;
145 	struct peer_discon_notify_s *peer_disconn, *peer_disconn_l;
146 	struct peer_deauth_notify_s *peer_deauth, *peer_deauth_l;
147 	struct peer_auth_process_notif_s *peer_auth, *peer_auth_l;
148 	struct ctxt_switch_mgr *msgq_ctx;
149 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
150 
151 	if (!mlo_ctx)
152 		return QDF_STATUS_E_FAILURE;
153 
154 	msgq_ctx = mlo_ctx->msgq_ctx;
155 
156 	if (!msgq_ctx->allow_msg)
157 		return QDF_STATUS_E_FAILURE;
158 
159 	msg = qdf_mem_malloc(sizeof(*msg));
160 	if (!msg)
161 		return QDF_STATUS_E_NOMEM;
162 
163 	msg->type = type;
164 	msg->ml_dev = ml_dev;
165 
166 	switch (type) {
167 	case MLO_PEER_CREATE:
168 		peer_create = &msg->m.peer_create;
169 		peer_create_l = (struct peer_create_notif_s *)payload;
170 		peer_create->frm_buf = peer_create_l->frm_buf;
171 		peer_create->ml_peer = peer_create_l->ml_peer;
172 		peer_create->vdev_link = peer_create_l->vdev_link;
173 		qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
174 		break;
175 
176 	case MLO_PEER_ASSOC:
177 		peer_assoc = &msg->m.peer_assoc;
178 		peer_assoc_l = (struct peer_assoc_notify_s *)payload;
179 		peer_assoc->peer = peer_assoc_l->peer;
180 		break;
181 
182 	case MLO_PEER_ASSOC_FAIL:
183 		peer_assoc_fail = &msg->m.peer_assoc_fail;
184 		peer_assoc_fail_l = (struct peer_assoc_fail_notify_s *)payload;
185 		peer_assoc_fail->peer = peer_assoc_fail_l->peer;
186 		break;
187 
188 	case MLO_PEER_DISCONNECT:
189 		peer_disconn = &msg->m.peer_disconn;
190 		peer_disconn_l = (struct peer_discon_notify_s *)payload;
191 		peer_disconn->peer = peer_disconn_l->peer;
192 		break;
193 
194 	case MLO_PEER_DEAUTH:
195 		peer_deauth = &msg->m.peer_deauth;
196 		peer_deauth_l = (struct peer_deauth_notify_s *)payload;
197 		peer_deauth->peer = peer_deauth_l->peer;
198 		peer_deauth->is_disassoc = peer_deauth_l->is_disassoc;
199 		break;
200 
201 	case MLO_PEER_PENDING_AUTH:
202 		peer_auth = &msg->m.peer_auth;
203 		peer_auth_l = (struct peer_auth_process_notif_s *)payload;
204 		peer_auth->auth_params = peer_auth_l->auth_params;
205 		break;
206 
207 	default:
208 		break;
209 	}
210 
211 	qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
212 	qdf_list_insert_back(&msgq_ctx->msgq_list, &msg->node);
213 	qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
214 	mlo_msgq_timer_start();
215 
216 	return QDF_STATUS_SUCCESS;
217 }
218 
219 static void mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s *msg)
220 {
221 	enum mlo_msg_type type;
222 	struct peer_create_notif_s *peer_create;
223 	struct peer_assoc_notify_s *peer_assoc;
224 	struct peer_assoc_fail_notify_s *peer_assoc_fail;
225 	struct peer_discon_notify_s *peer_disconn;
226 	struct peer_deauth_notify_s *peer_deauth;
227 	struct peer_auth_process_notif_s *peer_auth;
228 
229 	type = msg->type;
230 	switch (type) {
231 	case MLO_PEER_CREATE:
232 		peer_create = &msg->m.peer_create;
233 		mlo_mlme_peer_create(peer_create->vdev_link,
234 				     peer_create->ml_peer,
235 				     &peer_create->addr, peer_create->frm_buf);
236 		qdf_nbuf_free(peer_create->frm_buf);
237 		wlan_mlo_peer_release_ref(peer_create->ml_peer);
238 		wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
239 					     WLAN_MLO_MGR_ID);
240 		break;
241 
242 	case MLO_PEER_ASSOC:
243 		peer_assoc = &msg->m.peer_assoc;
244 		mlo_mlme_peer_assoc(peer_assoc->peer);
245 		wlan_objmgr_peer_release_ref(peer_assoc->peer,
246 					     WLAN_MLO_MGR_ID);
247 		break;
248 
249 	case MLO_PEER_ASSOC_FAIL:
250 		peer_assoc_fail = &msg->m.peer_assoc_fail;
251 		mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
252 		wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
253 					     WLAN_MLO_MGR_ID);
254 		break;
255 
256 	case MLO_PEER_DISCONNECT:
257 		peer_disconn = &msg->m.peer_disconn;
258 		mlo_mlme_peer_delete(peer_disconn->peer);
259 		wlan_objmgr_peer_release_ref(peer_disconn->peer,
260 					     WLAN_MLO_MGR_ID);
261 		break;
262 
263 	case MLO_PEER_DEAUTH:
264 		peer_deauth = &msg->m.peer_deauth;
265 		mlo_mlme_peer_deauth(peer_deauth->peer);
266 		wlan_objmgr_peer_release_ref(peer_deauth->peer,
267 					     WLAN_MLO_MGR_ID);
268 		break;
269 
270 	case MLO_PEER_PENDING_AUTH:
271 		peer_auth = &msg->m.peer_auth;
272 		mlo_mlme_peer_process_auth(peer_auth->auth_params);
273 		break;
274 
275 	default:
276 		break;
277 	}
278 	qdf_mem_free(msg);
279 }
280 
281 static void mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s *msg)
282 {
283 	enum mlo_msg_type type;
284 	struct peer_create_notif_s *peer_create;
285 	struct peer_assoc_notify_s *peer_assoc;
286 	struct peer_assoc_fail_notify_s *peer_assoc_fail;
287 	struct peer_discon_notify_s *peer_disconn;
288 	struct peer_deauth_notify_s *peer_deauth;
289 
290 	type = msg->type;
291 	switch (type) {
292 	case MLO_PEER_CREATE:
293 		peer_create = &msg->m.peer_create;
294 		qdf_nbuf_free(peer_create->frm_buf);
295 		wlan_mlo_peer_release_ref(peer_create->ml_peer);
296 		wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
297 					     WLAN_MLO_MGR_ID);
298 		break;
299 
300 	case MLO_PEER_ASSOC:
301 		peer_assoc = &msg->m.peer_assoc;
302 		wlan_objmgr_peer_release_ref(peer_assoc->peer,
303 					     WLAN_MLO_MGR_ID);
304 		break;
305 
306 	case MLO_PEER_ASSOC_FAIL:
307 		peer_assoc_fail = &msg->m.peer_assoc_fail;
308 		wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
309 					     WLAN_MLO_MGR_ID);
310 		break;
311 
312 	case MLO_PEER_DISCONNECT:
313 		peer_disconn = &msg->m.peer_disconn;
314 		wlan_objmgr_peer_release_ref(peer_disconn->peer,
315 					     WLAN_MLO_MGR_ID);
316 		break;
317 
318 	case MLO_PEER_DEAUTH:
319 		peer_deauth = &msg->m.peer_deauth;
320 		wlan_objmgr_peer_release_ref(peer_deauth->peer,
321 					     WLAN_MLO_MGR_ID);
322 		break;
323 
324 	case MLO_PEER_PENDING_AUTH:
325 		peer_auth = &msg->m.peer_auth;
326 		mlo_peer_free_auth_param(peer_auth->auth_params);
327 		break;
328 
329 	default:
330 		break;
331 	}
332 	qdf_mem_free(msg);
333 }
334 
335 static void mlo_msgq_msg_flush(void)
336 {
337 	struct ctxt_switch_mgr *msgq_ctx;
338 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
339 	qdf_list_node_t *msgbuf_node = NULL;
340 	struct mlo_ctxt_switch_msg_s *msg;
341 	QDF_STATUS status;
342 
343 	if (!mlo_ctx)
344 		return;
345 
346 	msgq_ctx = mlo_ctx->msgq_ctx;
347 	do {
348 		msg = NULL;
349 		qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
350 		status = qdf_list_peek_front(&msgq_ctx->msgq_list,
351 					     &msgbuf_node);
352 		if (status != QDF_STATUS_E_EMPTY) {
353 			qdf_list_remove_node(&msgq_ctx->msgq_list,
354 					     msgbuf_node);
355 			msg = qdf_container_of(msgbuf_node,
356 					       struct mlo_ctxt_switch_msg_s,
357 					       node);
358 		}
359 		qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
360 
361 		if (!msg)
362 			break;
363 
364 		mlo_msgq_msg_flush_hdlr(msg);
365 
366 	} while (true);
367 }
368 
369 static void mlo_msgq_msg_handler(void *arg)
370 {
371 	struct ctxt_switch_mgr *msgq_ctx;
372 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
373 	qdf_list_node_t *msgbuf_node = NULL;
374 	struct mlo_ctxt_switch_msg_s *msg;
375 	QDF_STATUS status;
376 
377 	if (!mlo_ctx)
378 		return;
379 
380 	msgq_ctx = mlo_ctx->msgq_ctx;
381 	do {
382 		msg = NULL;
383 		qdf_spin_lock_bh(&msgq_ctx->ctxt_lock);
384 		status = qdf_list_peek_front(&msgq_ctx->msgq_list,
385 					     &msgbuf_node);
386 		if (status != QDF_STATUS_E_EMPTY) {
387 			qdf_list_remove_node(&msgq_ctx->msgq_list,
388 					     msgbuf_node);
389 			msg = qdf_container_of(msgbuf_node,
390 					       struct mlo_ctxt_switch_msg_s,
391 					       node);
392 		} else {
393 			msgq_ctx->timer_started = false;
394 		}
395 		qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock);
396 
397 		if (!msg)
398 			break;
399 
400 		mlo_msgq_msg_process_hdlr(msg);
401 
402 	} while (true);
403 }
404 
405 void mlo_msgq_init(void)
406 {
407 	struct ctxt_switch_mgr *msgq_ctx;
408 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
409 
410 	msgq_ctx = qdf_mem_malloc(sizeof(*msgq_ctx));
411 	if (!msgq_ctx) {
412 		mlo_err(" message queue context allocation failed");
413 		return;
414 	}
415 
416 	qdf_spinlock_create(&msgq_ctx->ctxt_lock);
417 	/* Initialize timer with timeout handler */
418 	qdf_timer_init(NULL, &msgq_ctx->ctxt_mgr_timer,
419 		       mlo_msgq_msg_handler,
420 		       NULL, QDF_TIMER_TYPE_WAKE_APPS);
421 
422 	msgq_ctx->timer_started = false;
423 	msgq_ctx->allow_msg = true;
424 	qdf_list_create(&msgq_ctx->msgq_list, MLO_MAX_MSGQ_SIZE);
425 
426 	mlo_ctx->msgq_ctx = msgq_ctx;
427 }
428 
429 void mlo_msgq_free(void)
430 {
431 	struct ctxt_switch_mgr *msgq_ctx;
432 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
433 
434 	if (!mlo_ctx)
435 		return;
436 
437 	msgq_ctx = mlo_ctx->msgq_ctx;
438 
439 	msgq_ctx->timer_started = false;
440 	msgq_ctx->allow_msg = false;
441 	mlo_msgq_msg_flush();
442 	qdf_list_destroy(&msgq_ctx->msgq_list);
443 	qdf_timer_free(&msgq_ctx->ctxt_mgr_timer);
444 	qdf_spinlock_destroy(&msgq_ctx->ctxt_lock);
445 	qdf_mem_free(msgq_ctx);
446 }
447 #endif
448