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