1  /*
2   * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2024 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  
18  /*
19   * DOC: contains MLO manager ap related functionality
20   */
21  #include "wlan_mlo_mgr_cmn.h"
22  #include "wlan_mlo_mgr_main.h"
23  #include "wlan_mlo_mgr_sta.h"
24  #ifdef WLAN_MLO_MULTI_CHIP
25  #include "wlan_lmac_if_def.h"
26  #endif
27  #include "wlan_serialization_api.h"
28  #include <target_if_mlo_mgr.h>
29  #include <cdp_txrx_cmn.h>
30  #include <wlan_cfg.h>
31  #include "wlan_utility.h"
32  
mlo_get_link_information(struct qdf_mac_addr * mld_addr,struct mlo_link_info * info)33  void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
34  			      struct mlo_link_info *info)
35  {
36  /* Pass the partner link information*/
37  }
38  
is_mlo_all_links_up(struct wlan_mlo_dev_context * mldev)39  void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev)
40  {
41  /* Loop through all the vdev's part of the ML device*/
42  /* STA: Loop through all the associated vdev status. */
43  }
44  
mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev * vdev,uint8_t link_id,wlan_objmgr_ref_dbgid id)45  struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev *vdev,
46  						 uint8_t link_id,
47  						 wlan_objmgr_ref_dbgid id)
48  {
49  	struct wlan_mlo_dev_context *dev_ctx;
50  	int i;
51  	struct wlan_objmgr_vdev *partner_vdev = NULL;
52  
53  	if (!vdev || !vdev->mlo_dev_ctx) {
54  		mlo_err("Invalid input");
55  		return partner_vdev;
56  	}
57  
58  	dev_ctx = vdev->mlo_dev_ctx;
59  
60  	mlo_dev_lock_acquire(dev_ctx);
61  	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
62  		if (dev_ctx->wlan_vdev_list[i] &&
63  		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
64  		    dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
65  		    link_id) {
66  			if (wlan_objmgr_vdev_try_get_ref(
67  						dev_ctx->wlan_vdev_list[i],
68  						id) == QDF_STATUS_SUCCESS)
69  				partner_vdev = dev_ctx->wlan_vdev_list[i];
70  
71  			break;
72  		}
73  	}
74  	mlo_dev_lock_release(dev_ctx);
75  
76  	return partner_vdev;
77  }
78  
mlo_release_vdev_ref(struct wlan_objmgr_vdev * vdev)79  void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
80  {
81  	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
82  }
83  
mlo_reg_mlme_ext_cb(struct mlo_mgr_context * ctx,struct mlo_mlme_ext_ops * ops)84  QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx,
85  			       struct mlo_mlme_ext_ops *ops)
86  {
87  	if (!ctx)
88  		return QDF_STATUS_E_FAILURE;
89  
90  	ctx->mlme_ops = ops;
91  	return QDF_STATUS_SUCCESS;
92  }
93  
mlo_unreg_mlme_ext_cb(struct mlo_mgr_context * ctx)94  QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx)
95  {
96  	if (!ctx)
97  		return QDF_STATUS_E_FAILURE;
98  
99  	ctx->mlme_ops = NULL;
100  	return QDF_STATUS_SUCCESS;
101  }
102  
103  #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context * mlo_ctx,struct mlo_osif_ext_ops * ops)104  QDF_STATUS wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context *mlo_ctx,
105  					      struct mlo_osif_ext_ops *ops)
106  {
107  	if (!ops || !mlo_ctx)
108  		return QDF_STATUS_E_FAILURE;
109  
110  	mlo_ctx->osif_ops = ops;
111  	return QDF_STATUS_SUCCESS;
112  }
113  
wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context * mlo_ctx)114  QDF_STATUS wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context *mlo_ctx)
115  {
116  	if (!mlo_ctx)
117  		return QDF_STATUS_E_FAILURE;
118  
119  	mlo_ctx->osif_ops = NULL;
120  	return QDF_STATUS_SUCCESS;
121  }
122  #endif
123  
mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)124  QDF_STATUS mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev *vdev,
125  				       struct wlan_cm_connect_req *req)
126  {
127  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
128  	struct vdev_mlme_obj *vdev_mlme;
129  	QDF_STATUS status = QDF_STATUS_SUCCESS;
130  
131  	if (!req || !mlo_ctx || !mlo_ctx->mlme_ops ||
132  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
133  		return QDF_STATUS_E_FAILURE;
134  
135  	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
136  	if (!vdev_mlme)
137  		return QDF_STATUS_E_FAILURE;
138  
139  	if (mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param) {
140  		status =
141  			mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param(
142  				vdev_mlme, req);
143  	}
144  
145  	return status;
146  }
147  
mlo_mlme_sta_op_class(struct wlan_objmgr_vdev * vdev,uint8_t * ml_ie)148  QDF_STATUS mlo_mlme_sta_op_class(struct wlan_objmgr_vdev *vdev,
149  				 uint8_t *ml_ie)
150  {
151  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
152  	struct vdev_mlme_obj *vdev_mlme;
153  	QDF_STATUS status = QDF_STATUS_SUCCESS;
154  
155  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
156  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
157  		return QDF_STATUS_E_FAILURE;
158  
159  	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
160  	if (!vdev_mlme)
161  		return QDF_STATUS_E_FAILURE;
162  
163  	if (mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class)
164  		status =
165  			mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class(
166  				vdev_mlme, ml_ie);
167  
168  	return status;
169  }
170  
mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev * vdev,void * ext_data)171  QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev,
172  				      void *ext_data)
173  {
174  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
175  	struct vdev_mlme_obj *vdev_mlme;
176  	QDF_STATUS status;
177  
178  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
179  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
180  		return QDF_STATUS_E_FAILURE;
181  
182  	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
183  	if (!vdev_mlme)
184  		return QDF_STATUS_E_FAILURE;
185  
186  	status =
187  		mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme,
188  								  ext_data);
189  	return status;
190  }
191  
mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev * vdev,void * ext_data)192  QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
193  				     void *ext_data)
194  {
195  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
196  	struct vdev_mlme_obj *vdev_mlme;
197  	QDF_STATUS status;
198  
199  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
200  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev)
201  		return QDF_STATUS_E_FAILURE;
202  
203  	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
204  	if (!vdev_mlme)
205  		return QDF_STATUS_E_FAILURE;
206  
207  	status =
208  		mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme,
209  								 ext_data);
210  	return status;
211  }
212  
mlo_mlme_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)213  void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
214  			  struct wlan_mlo_peer_context *ml_peer,
215  			  struct qdf_mac_addr *addr,
216  			  qdf_nbuf_t frm_buf)
217  {
218  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
219  
220  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
221  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create)
222  		return;
223  
224  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer,
225  						    addr, frm_buf);
226  }
227  
mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)228  void mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev *vdev,
229  				 struct wlan_mlo_peer_context *ml_peer,
230  				 struct qdf_mac_addr *addr,
231  				 qdf_nbuf_t frm_buf)
232  {
233  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
234  
235  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
236  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create)
237  		return;
238  
239  	mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create(vdev, ml_peer,
240  							   addr, frm_buf);
241  }
242  
mlo_mlme_peer_assoc(struct wlan_objmgr_peer * peer)243  void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
244  {
245  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
246  
247  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
248  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc)
249  		return;
250  
251  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer);
252  }
253  
mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer * peer)254  void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer)
255  {
256  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
257  
258  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
259  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail)
260  		return;
261  
262  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer);
263  }
264  
mlo_mlme_peer_delete(struct wlan_objmgr_peer * peer)265  void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
266  {
267  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
268  
269  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
270  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete)
271  		return;
272  
273  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
274  }
275  
mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer * peer)276  void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
277  {
278  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
279  
280  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
281  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
282  		return;
283  
284  	mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
285  }
286  
mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer * peer,uint8_t link_ix)287  qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
288  				       uint8_t link_ix)
289  {
290  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
291  
292  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
293  	    !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req)
294  		return NULL;
295  
296  	return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix);
297  }
298  
mlo_mlme_peer_deauth(struct wlan_objmgr_peer * peer,uint8_t is_disassoc)299  void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer, uint8_t is_disassoc)
300  {
301  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
302  
303  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
304  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth)
305  		return;
306  
307  	mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer, is_disassoc);
308  }
309  
310  #ifdef UMAC_MLO_AUTH_DEFER
mlo_mlme_peer_process_auth(struct mlpeer_auth_params * auth_param)311  void mlo_mlme_peer_process_auth(struct mlpeer_auth_params *auth_param)
312  {
313  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
314  
315  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
316  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth)
317  		return;
318  
319  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth(auth_param);
320  }
321  #endif
322  
mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)323  void mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev *vdev,
324  			   struct wlan_mlo_peer_context *ml_peer,
325  			   struct qdf_mac_addr *addr,
326  			   qdf_nbuf_t frm_buf)
327  {
328  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
329  
330  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
331  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc)
332  		return;
333  
334  	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc(vdev, ml_peer, addr,
335  						     frm_buf);
336  }
337  
mlo_get_link_vdev_ix(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)338  uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
339  			     struct wlan_objmgr_vdev *vdev)
340  {
341  	uint8_t i;
342  
343  	mlo_dev_lock_acquire(ml_dev);
344  	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
345  		if (vdev == ml_dev->wlan_vdev_list[i]) {
346  			mlo_dev_lock_release(ml_dev);
347  			return i;
348  		}
349  	}
350  	mlo_dev_lock_release(ml_dev);
351  
352  	return (uint8_t)-1;
353  }
354  
355  #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_get_max_num_links(uint8_t grp_id)356  int8_t wlan_mlo_get_max_num_links(uint8_t grp_id)
357  {
358  	struct mlo_mgr_context *mlo_ctx;
359  
360  	mlo_ctx = wlan_objmgr_get_mlo_ctx();
361  	if (!mlo_ctx)
362  		return WLAN_MLO_INVALID_NUM_LINKS;
363  
364  	if (grp_id >= mlo_ctx->total_grp) {
365  		mlo_err("Invalid grp id %d, total no of groups %d",
366  			grp_id, mlo_ctx->total_grp);
367  		return WLAN_MLO_INVALID_NUM_LINKS;
368  	}
369  
370  	return (mlo_ctx->setup_info[grp_id].tot_socs *
371  		WLAN_MAX_MLO_LINKS_PER_SOC);
372  }
373  
wlan_mlo_get_num_active_links(uint8_t grp_id)374  int8_t wlan_mlo_get_num_active_links(uint8_t grp_id)
375  {
376  	struct mlo_mgr_context *mlo_ctx;
377  
378  	mlo_ctx = wlan_objmgr_get_mlo_ctx();
379  
380  	if (!mlo_ctx)
381  		return WLAN_MLO_INVALID_NUM_LINKS;
382  
383  	if (grp_id >= mlo_ctx->total_grp) {
384  		qdf_err("Invalid grp id %d, total no of groups %d",
385  			grp_id, mlo_ctx->total_grp);
386  		return WLAN_MLO_INVALID_NUM_LINKS;
387  	}
388  
389  	return mlo_ctx->setup_info[grp_id].tot_links;
390  }
391  
wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)392  uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)
393  {
394  	struct mlo_mgr_context *mlo_ctx;
395  
396  	mlo_ctx = wlan_objmgr_get_mlo_ctx();
397  	if (!mlo_ctx)
398  		return 0;
399  
400  	if (grp_id >= mlo_ctx->total_grp) {
401  		qdf_err("Invalid grp id %d, total no of groups %d",
402  			grp_id, mlo_ctx->total_grp);
403  		return 0;
404  	}
405  
406  	return mlo_ctx->setup_info[grp_id].valid_link_bitmap;
407  }
408  
wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc * psoc)409  uint8_t wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc *psoc)
410  {
411  	struct wlan_lmac_if_tx_ops *tx_ops;
412  	uint8_t mlo_chip_id = WLAN_MLO_CHIP_ID_INVALID;
413  
414  	if (!psoc) {
415  		qdf_err("PSOC is NULL");
416  		return mlo_chip_id;
417  	}
418  
419  	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
420  	if (tx_ops && tx_ops->mops.get_psoc_mlo_chip_id)
421  		mlo_chip_id = tx_ops->mops.get_psoc_mlo_chip_id(psoc);
422  
423  	return mlo_chip_id;
424  }
425  
426  qdf_export_symbol(wlan_mlo_get_psoc_mlo_chip_id);
427  
wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc * psoc)428  uint8_t wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc *psoc)
429  {
430  	struct wlan_lmac_if_tx_ops *tx_ops;
431  	uint8_t ml_grp_id = WLAN_MLO_GROUP_INVALID;
432  
433  	if (!psoc) {
434  		qdf_err("PSOC is NULL");
435  		return -EINVAL;
436  	}
437  
438  	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
439  	if (tx_ops && tx_ops->mops.get_psoc_mlo_group_id)
440  		ml_grp_id = tx_ops->mops.get_psoc_mlo_group_id(psoc);
441  
442  	return ml_grp_id;
443  }
444  
445  qdf_export_symbol(wlan_mlo_get_psoc_group_id);
446  
wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc * psoc)447  bool wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc *psoc)
448  {
449  	struct target_psoc_info *tgt_hdl;
450  
451  	if (!psoc) {
452  		qdf_err("PSOC is NULL");
453  		return false;
454  	}
455  
456  	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
457  	if (!tgt_hdl) {
458  		target_if_err("target_psoc_info is null");
459  		return false;
460  	}
461  
462  	if ((tgt_hdl->tif_ops) &&
463  	    (tgt_hdl->tif_ops->mlo_capable))
464  		return tgt_hdl->tif_ops->mlo_capable(psoc);
465  
466  	return false;
467  }
468  
wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev * pdev)469  uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
470  {
471  	struct wlan_objmgr_psoc *psoc;
472  	struct wlan_lmac_if_tx_ops *tx_ops;
473  	uint16_t hw_link_id = INVALID_HW_LINK_ID;
474  
475  	psoc = wlan_pdev_get_psoc(pdev);
476  	if (psoc) {
477  		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
478  		if (tx_ops && tx_ops->mops.get_hw_link_id)
479  			hw_link_id = tx_ops->mops.get_hw_link_id(pdev);
480  	}
481  
482  	return hw_link_id;
483  }
484  
485  qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id);
486  
wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)487  static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc,
488  				       void *obj, void *arg)
489  {
490  	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
491  	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
492  	uint16_t hw_link_id;
493  	uint8_t ml_grp_id;
494  
495  	if (itr->pdev)
496  		return;
497  
498  	ml_grp_id = wlan_mlo_get_psoc_group_id(psoc);
499  	if (ml_grp_id > WLAN_MAX_MLO_GROUPS)
500  		return;
501  
502  	if (ml_grp_id != itr->mlo_grp_id)
503  		return;
504  
505  	hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
506  	if (hw_link_id == itr->hw_link_id) {
507  		if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) ==
508  							QDF_STATUS_SUCCESS)
509  			itr->pdev = pdev;
510  	}
511  }
512  
wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)513  static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc,
514  				     void *arg,
515  				     uint8_t index)
516  {
517  	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
518  
519  	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
520  				     wlan_pdev_hw_link_iterator,
521  				     arg, false, itr->dbgid);
522  }
523  
524  struct wlan_objmgr_pdev *
wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,uint8_t ml_grp_id,wlan_objmgr_ref_dbgid refdbgid)525  wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id, uint8_t ml_grp_id,
526  				wlan_objmgr_ref_dbgid refdbgid)
527  {
528  	struct hw_link_id_iterator itr;
529  
530  	itr.hw_link_id = hw_link_id;
531  	itr.pdev = NULL;
532  	itr.mlo_grp_id = ml_grp_id;
533  	itr.dbgid = refdbgid;
534  
535  	wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id,
536  				      &itr, refdbgid);
537  
538  	return itr.pdev;
539  }
540  
541  qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id);
542  #endif /*WLAN_MLO_MULTI_CHIP*/
543  
mlo_get_ml_vdev_list(struct wlan_objmgr_vdev * vdev,uint16_t * vdev_count,struct wlan_objmgr_vdev ** wlan_vdev_list)544  void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev,
545  			  uint16_t *vdev_count,
546  			  struct wlan_objmgr_vdev **wlan_vdev_list)
547  {
548  	struct wlan_mlo_dev_context *dev_ctx;
549  	int i;
550  	QDF_STATUS status;
551  
552  	*vdev_count = 0;
553  
554  	if (!vdev || !vdev->mlo_dev_ctx) {
555  		mlo_err("Invalid input");
556  		return;
557  	}
558  
559  	dev_ctx = vdev->mlo_dev_ctx;
560  
561  	mlo_dev_lock_acquire(dev_ctx);
562  	*vdev_count = 0;
563  	for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
564  		if (dev_ctx->wlan_vdev_list[i] &&
565  		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) {
566  			status = wlan_objmgr_vdev_try_get_ref(
567  						dev_ctx->wlan_vdev_list[i],
568  						WLAN_MLO_MGR_ID);
569  			if (QDF_IS_STATUS_ERROR(status))
570  				break;
571  			wlan_vdev_list[*vdev_count] =
572  				dev_ctx->wlan_vdev_list[i];
573  			(*vdev_count) += 1;
574  		}
575  	}
576  	mlo_dev_lock_release(dev_ctx);
577  }
578  
579  /**
580   * mlo_link_set_active() - send MLO link set active command
581   * @psoc: PSOC object
582   * @req: MLO link set active request
583   *
584   * Return: QDF_STATUS
585   */
586  static QDF_STATUS
mlo_link_set_active(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_req * req)587  mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
588  		    struct mlo_link_set_active_req *req)
589  {
590  	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
591  	struct mlo_link_set_active_param *param = &req->param;
592  	QDF_STATUS status;
593  	struct mlo_link_set_active_resp rsp_evt;
594  
595  	if (!psoc) {
596  		mlo_err("psoc is null");
597  		return QDF_STATUS_E_NULL_VALUE;
598  	}
599  
600  	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
601  	if (!mlo_tx_ops) {
602  		mlo_err("tx_ops is null!");
603  		return QDF_STATUS_E_NULL_VALUE;
604  	}
605  
606  	if (!mlo_tx_ops->link_set_active) {
607  		mlo_err("link_set_active function is null!");
608  		return QDF_STATUS_E_NULL_VALUE;
609  	}
610  
611  	if (req->ctx.validate_set_mlo_link_cb) {
612  		status = req->ctx.validate_set_mlo_link_cb(psoc, param);
613  		if (QDF_IS_STATUS_ERROR(status)) {
614  			qdf_mem_zero(&rsp_evt, sizeof(rsp_evt));
615  			rsp_evt.status = status;
616  			if (req->ctx.set_mlo_link_cb)
617  				req->ctx.set_mlo_link_cb(req->ctx.vdev,
618  							 req->ctx.cb_arg,
619  							 &rsp_evt);
620  			return status;
621  		}
622  	}
623  
624  	return mlo_tx_ops->link_set_active(psoc, param);
625  }
626  
627  /**
628   * mlo_release_ser_link_set_active_cmd() - releases serialization command for
629   *  forcing MLO link active/inactive
630   * @vdev: Object manager vdev
631   *
632   * Return: None
633   */
634  static void
mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev * vdev)635  mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev)
636  {
637  	struct wlan_serialization_queued_cmd_info cmd = {0};
638  
639  	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
640  	cmd.requestor = WLAN_UMAC_COMP_MLO_MGR;
641  	cmd.cmd_id = 0;
642  	cmd.vdev = vdev;
643  
644  	mlo_debug("release serialization command");
645  	wlan_serialization_remove_cmd(&cmd);
646  }
647  
648  /**
649   * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set
650   * active response event.
651   * @psoc: psoc object
652   * @obj: vdev object
653   * @arg: mlo link set active response
654   *
655   * Return: None
656   */
657  static void
mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)658  mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc,
659  				      void *obj, void *arg)
660  {
661  	struct mlo_link_set_active_req *req;
662  	struct wlan_objmgr_vdev *vdev = obj;
663  	struct mlo_link_set_active_resp *event = arg;
664  
665  	if (event->evt_handled)
666  		return;
667  	req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev),
668  						wlan_vdev_get_id(vdev),
669  						WLAN_SER_CMD_SET_MLO_LINK);
670  	if (!req)
671  		return;
672  
673  	if (req->ctx.set_mlo_link_cb)
674  		req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event);
675  
676  	mlo_release_ser_link_set_active_cmd(vdev);
677  	event->evt_handled = true;
678  }
679  
680  QDF_STATUS
mlo_process_link_set_active_resp(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_resp * event)681  mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc,
682  				 struct mlo_link_set_active_resp *event)
683  {
684  	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
685  				     mlo_link_set_active_resp_vdev_handler,
686  				     event, true, WLAN_MLO_MGR_ID);
687  	if (!event->evt_handled)
688  		mlo_debug("link set resp evt not handled");
689  
690  	return QDF_STATUS_SUCCESS;
691  }
692  
693  /**
694   * mlo_ser_set_link_cb() - Serialization callback function
695   * @cmd: Serialization command info
696   * @reason: Serialization reason for callback execution
697   *
698   * Return: Status of callback execution
699   */
700  static QDF_STATUS
mlo_ser_set_link_cb(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)701  mlo_ser_set_link_cb(struct wlan_serialization_command *cmd,
702  		    enum wlan_serialization_cb_reason reason)
703  {
704  	QDF_STATUS status = QDF_STATUS_SUCCESS;
705  	struct wlan_objmgr_vdev *vdev;
706  	struct wlan_objmgr_psoc *psoc;
707  	struct mlo_link_set_active_req *req;
708  	struct mlo_mgr_context *mlo_ctx;
709  
710  	if (!cmd || !cmd->vdev)
711  		return QDF_STATUS_E_FAILURE;
712  
713  	mlo_ctx = wlan_objmgr_get_mlo_ctx();
714  	if (!mlo_ctx)
715  		return QDF_STATUS_E_FAILURE;
716  
717  	psoc = wlan_vdev_get_psoc(cmd->vdev);
718  	if (!psoc) {
719  		mlo_err("psoc is NULL, reason: %d", reason);
720  		return QDF_STATUS_E_NULL_VALUE;
721  	}
722  
723  	req = cmd->umac_cmd;
724  	if (!req)
725  		return QDF_STATUS_E_INVAL;
726  
727  	vdev = cmd->vdev;
728  	switch (reason) {
729  	case WLAN_SER_CB_ACTIVATE_CMD:
730  		status = mlo_link_set_active(psoc, req);
731  		break;
732  	case WLAN_SER_CB_CANCEL_CMD:
733  	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
734  		mlo_err("vdev %d command not execute: %d",
735  			wlan_vdev_get_id(vdev), reason);
736  		if (req->ctx.set_mlo_link_cb)
737  			req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL);
738  		break;
739  	case WLAN_SER_CB_RELEASE_MEM_CMD:
740  		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
741  		qdf_mem_free(req);
742  		break;
743  	default:
744  		QDF_ASSERT(0);
745  		status = QDF_STATUS_E_INVAL;
746  		break;
747  	}
748  
749  	return status;
750  }
751  
752  #define MLO_SER_CMD_TIMEOUT_MS 5000
mlo_ser_set_link_req(struct mlo_link_set_active_req * req)753  QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req)
754  {
755  	struct wlan_serialization_command cmd = {0, };
756  	enum wlan_serialization_status ser_cmd_status;
757  	QDF_STATUS status;
758  	struct wlan_objmgr_vdev *vdev;
759  
760  	if (!req)
761  		return QDF_STATUS_E_INVAL;
762  
763  	vdev = req->ctx.vdev;
764  	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID);
765  	if (QDF_IS_STATUS_ERROR(status)) {
766  		mlo_err("vdev %d unable to get reference",
767  			wlan_vdev_get_id(vdev));
768  		return status;
769  	}
770  
771  	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
772  	cmd.cmd_id = 0;
773  	cmd.cmd_cb = mlo_ser_set_link_cb;
774  	cmd.source = WLAN_UMAC_COMP_MLO_MGR;
775  	cmd.is_high_priority = false;
776  	cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS;
777  	cmd.vdev = vdev;
778  	cmd.is_blocking = true;
779  	cmd.umac_cmd = (void *)req;
780  
781  	ser_cmd_status = wlan_serialization_request(&cmd);
782  	switch (ser_cmd_status) {
783  	case WLAN_SER_CMD_PENDING:
784  		/* command moved to pending list.Do nothing */
785  		break;
786  	case WLAN_SER_CMD_ACTIVE:
787  		/* command moved to active list. Do nothing */
788  		break;
789  	default:
790  		mlo_err("vdev %d ser cmd status %d",
791  			wlan_vdev_get_id(vdev), ser_cmd_status);
792  		status = QDF_STATUS_E_FAILURE;
793  	}
794  
795  	if (QDF_IS_STATUS_SUCCESS(status))
796  		return status;
797  
798  	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
799  
800  	return status;
801  }
802  
mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev * vdev,struct csa_offload_params * csa_param)803  void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev,
804  				   struct csa_offload_params *csa_param)
805  {
806  	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
807  
808  	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
809  	    !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param)
810  		return;
811  
812  	mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param);
813  }
814  
815  QDF_STATUS
mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc * psoc,struct mlo_stats_vdev_params * info,uint8_t vdev_id)816  mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc,
817  			    struct mlo_stats_vdev_params *info,
818  			    uint8_t vdev_id)
819  {
820  	struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
821  	struct wlan_objmgr_vdev *vdev;
822  	int i;
823  	uint16_t ml_vdev_cnt = 0;
824  
825  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
826  						    WLAN_MLO_MGR_ID);
827  	if (!vdev) {
828  		mlo_err("vdev object is NULL for vdev %d", vdev_id);
829  		return QDF_STATUS_E_INVAL;
830  	}
831  
832  	mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list);
833  	for (i = 0; i < ml_vdev_cnt; i++) {
834  		info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]);
835  		mlo_release_vdev_ref(ml_vdev_list[i]);
836  	}
837  	info->ml_vdev_count = ml_vdev_cnt;
838  	mlo_release_vdev_ref(vdev);
839  
840  	return QDF_STATUS_SUCCESS;
841  }
842  
ml_extract_link_state(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)843  static void ml_extract_link_state(struct wlan_objmgr_psoc *psoc,
844  				  struct ml_link_state_info_event *event)
845  {
846  	QDF_STATUS status;
847  	get_ml_link_state_cb resp_cb = NULL;
848  	void *context = NULL;
849  	uint8_t vdev_id;
850  
851  	vdev_id = event->vdev_id;
852  
853  	status = mlo_get_link_state_context(psoc,
854  					    &resp_cb, &context, vdev_id);
855  
856  	if (QDF_IS_STATUS_ERROR(status))
857  		return;
858  
859  	if (resp_cb)
860  		resp_cb(event, context);
861  }
862  
863  QDF_STATUS
wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)864  wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc *psoc,
865  				     struct ml_link_state_info_event *event)
866  {
867  	if (!event)
868  		return QDF_STATUS_E_NULL_VALUE;
869  
870  	ml_extract_link_state(psoc, event);
871  
872  	return QDF_STATUS_SUCCESS;
873  }
874  
ml_get_link_state_req_cb(struct scheduler_msg * msg)875  static QDF_STATUS ml_get_link_state_req_cb(struct scheduler_msg *msg)
876  {
877  	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
878  	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
879  	struct mlo_link_state_cmd_params cmd = {0};
880  	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
881  	struct wlan_objmgr_psoc *psoc;
882  	int status = 0;
883  
884  	if (!vdev) {
885  		mlo_err("null input vdev");
886  		return QDF_STATUS_E_INVAL;
887  	}
888  
889  	psoc = wlan_vdev_get_psoc(vdev);
890  
891  	if (!psoc) {
892  		mlo_err("null psoc");
893  		return QDF_STATUS_E_NULL_VALUE;
894  	}
895  
896  	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
897  
898  	if (!mlo_tx_ops) {
899  		mlo_err("tx_ops is null!");
900  		return QDF_STATUS_E_NULL_VALUE;
901  	}
902  
903  	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
904  		mlo_err("vdev is not MLO vdev");
905  		return status;
906  	}
907  
908  	mlo_dev_ctx = vdev->mlo_dev_ctx;
909  	cmd.vdev_id = vdev->vdev_objmgr.vdev_id;
910  	qdf_mem_copy(&cmd.mld_mac[0], &mlo_dev_ctx->mld_addr,
911  		     QDF_MAC_ADDR_SIZE);
912  
913  	if (!mlo_tx_ops->request_link_state_info_cmd) {
914  		mlo_err("handler is not registered");
915  		return QDF_STATUS_E_NULL_VALUE;
916  	}
917  
918  	status = mlo_tx_ops->request_link_state_info_cmd(psoc, &cmd);
919  
920  	if (QDF_IS_STATUS_ERROR(status))
921  		mlo_err("failed to send ml link info command to FW");
922  
923  	return QDF_STATUS_SUCCESS;
924  }
925  
926  QDF_STATUS
mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev * vdev,struct ml_link_state_cmd_info * req)927  mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev *vdev,
928  				    struct ml_link_state_cmd_info *req)
929  {
930  	struct wlan_mlo_dev_context *mlo_ctx;
931  	struct wlan_mlo_sta *sta_ctx = NULL;
932  
933  	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
934  		return QDF_STATUS_E_NULL_VALUE;
935  	mlo_ctx = vdev->mlo_dev_ctx;
936  
937  	if (!mlo_ctx) {
938  		mlo_err("null mlo_dev_ctx");
939  		return QDF_STATUS_E_NULL_VALUE;
940  	}
941  
942  	sta_ctx = mlo_ctx->sta_ctx;
943  
944  	if (!sta_ctx)
945  		return QDF_STATUS_E_INVAL;
946  
947  	mlo_dev_lock_acquire(mlo_ctx);
948  
949  	sta_ctx->ml_link_state.ml_link_state_resp_cb =
950  		req->ml_link_state_resp_cb;
951  	sta_ctx->ml_link_state.ml_link_state_req_context =
952  		req->request_cookie;
953  	mlo_dev_lock_release(mlo_ctx);
954  
955  	return QDF_STATUS_SUCCESS;
956  }
957  
ml_get_link_state_req_flush_cb(struct scheduler_msg * msg)958  static QDF_STATUS ml_get_link_state_req_flush_cb(struct scheduler_msg *msg)
959  {
960  	mlo_debug("ml_get_link_state_req flush callback");
961  	return QDF_STATUS_SUCCESS;
962  }
963  
ml_post_get_link_state_msg(struct wlan_objmgr_vdev * vdev)964  QDF_STATUS ml_post_get_link_state_msg(struct wlan_objmgr_vdev *vdev)
965  {
966  	struct scheduler_msg msg = {0};
967  	QDF_STATUS qdf_status = 0;
968  
969  	msg.bodyptr = vdev;
970  	msg.callback = ml_get_link_state_req_cb;
971  	msg.flush_callback = ml_get_link_state_req_flush_cb;
972  
973  	qdf_status = scheduler_post_message(
974  				QDF_MODULE_ID_OS_IF,
975  				QDF_MODULE_ID_MLME,
976  				QDF_MODULE_ID_OS_IF,
977  				&msg);
978  	return qdf_status;
979  }
980  
981  bool
wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev * vdev,uint16_t csa_freq)982  wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq)
983  {
984  	struct wlan_channel *chan;
985  	struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
986  	uint16_t ml_vdev_cnt = 0;
987  	struct wlan_objmgr_vdev *t_vdev;
988  	int i;
989  	bool is_allow = true;
990  
991  	if (!vdev) {
992  		mlo_err("vdev is NULL");
993  		return false;
994  	}
995  
996  	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
997  		return true;
998  
999  	mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list);
1000  	for (i = 0; i < ml_vdev_cnt; i++) {
1001  		t_vdev = ml_vdev_list[i];
1002  		if (t_vdev == vdev)
1003  			goto next;
1004  		chan = wlan_vdev_get_active_channel(t_vdev);
1005  		if (!chan)
1006  			goto next;
1007  
1008  		if (csa_freq == chan->ch_freq) {
1009  			mlo_err("vdev %d will SCC with vdev %d on freq %d",
1010  				wlan_vdev_get_id(vdev),
1011  				wlan_vdev_get_id(t_vdev), csa_freq);
1012  			is_allow = false;
1013  		}
1014  next:
1015  		mlo_release_vdev_ref(t_vdev);
1016  	}
1017  
1018  	return is_allow;
1019  }
1020  
1021