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