xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c (revision 2c413289151e361000b8a608edfab592080b7911)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /*
18  * DOC: contains MLO manager ap related functionality
19  */
20 #include "wlan_mlo_mgr_cmn.h"
21 #include "wlan_mlo_mgr_main.h"
22 #ifdef WLAN_MLO_MULTI_CHIP
23 #include "wlan_lmac_if_def.h"
24 #endif
25 
26 void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
27 			      struct mlo_link_info *info)
28 {
29 /* Pass the partner link information*/
30 }
31 
32 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev)
33 {
34 /* Loop through all the vdev's part of the ML device*/
35 /* STA: Loop through all the associated vdev status. */
36 }
37 
38 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(
39 			struct wlan_objmgr_vdev *vdev,
40 			uint8_t link_id)
41 {
42 	struct wlan_mlo_dev_context *dev_ctx;
43 	int i;
44 	struct wlan_objmgr_vdev *partner_vdev = NULL;
45 
46 	if (!vdev || !vdev->mlo_dev_ctx) {
47 		mlo_err("Invalid input");
48 		return partner_vdev;
49 	}
50 
51 	dev_ctx = vdev->mlo_dev_ctx;
52 
53 	mlo_dev_lock_acquire(dev_ctx);
54 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
55 		if (dev_ctx->wlan_vdev_list[i] &&
56 		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
57 		    dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
58 		    link_id) {
59 			if (wlan_objmgr_vdev_try_get_ref(
60 						dev_ctx->wlan_vdev_list[i],
61 						WLAN_MLO_MGR_ID) ==
62 							QDF_STATUS_SUCCESS)
63 				partner_vdev = dev_ctx->wlan_vdev_list[i];
64 
65 			break;
66 		}
67 	}
68 	mlo_dev_lock_release(dev_ctx);
69 
70 	return partner_vdev;
71 }
72 
73 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
74 {
75 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
76 }
77 
78 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx,
79 			       struct mlo_mlme_ext_ops *ops)
80 {
81 	if (!ctx)
82 		return QDF_STATUS_E_FAILURE;
83 
84 	ctx->mlme_ops = ops;
85 	return QDF_STATUS_SUCCESS;
86 }
87 
88 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx)
89 {
90 	if (!ctx)
91 		return QDF_STATUS_E_FAILURE;
92 
93 	ctx->mlme_ops = NULL;
94 	return QDF_STATUS_SUCCESS;
95 }
96 
97 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev,
98 				      void *ext_data)
99 {
100 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
101 	struct vdev_mlme_obj *vdev_mlme;
102 	QDF_STATUS status;
103 
104 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
105 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
106 		return QDF_STATUS_E_FAILURE;
107 
108 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
109 	if (!vdev_mlme)
110 		return QDF_STATUS_E_FAILURE;
111 
112 	status =
113 		mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme,
114 								  ext_data);
115 	return status;
116 }
117 
118 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
119 				     void *ext_data)
120 {
121 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
122 	struct vdev_mlme_obj *vdev_mlme;
123 	QDF_STATUS status;
124 
125 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
126 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev)
127 		return QDF_STATUS_E_FAILURE;
128 
129 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
130 	if (!vdev_mlme)
131 		return QDF_STATUS_E_FAILURE;
132 
133 	status =
134 		mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme,
135 								 ext_data);
136 	return status;
137 }
138 
139 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
140 			  struct wlan_mlo_peer_context *ml_peer,
141 			  struct qdf_mac_addr *addr,
142 			  qdf_nbuf_t frm_buf)
143 {
144 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
145 
146 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
147 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create)
148 		return;
149 
150 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer,
151 						    addr, frm_buf);
152 }
153 
154 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
155 {
156 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
157 
158 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
159 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc)
160 		return;
161 
162 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer);
163 }
164 
165 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer)
166 {
167 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
168 
169 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
170 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail)
171 		return;
172 
173 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer);
174 }
175 
176 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
177 {
178 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
179 
180 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
181 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete)
182 		return;
183 
184 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
185 }
186 
187 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
188 {
189 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
190 
191 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
192 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
193 		return;
194 
195 	mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
196 }
197 
198 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
199 			     struct wlan_objmgr_vdev *vdev)
200 {
201 	uint8_t i;
202 
203 	mlo_dev_lock_acquire(ml_dev);
204 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
205 		if (vdev == ml_dev->wlan_vdev_list[i]) {
206 			mlo_dev_lock_release(ml_dev);
207 			return i;
208 		}
209 	}
210 	mlo_dev_lock_release(ml_dev);
211 
212 	return (uint8_t)-1;
213 }
214 
215 #ifdef WLAN_MLO_MULTI_CHIP
216 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
217 {
218 	struct wlan_objmgr_psoc *psoc;
219 	struct wlan_lmac_if_tx_ops *tx_ops;
220 	uint16_t hw_link_id = INVALID_HW_LINK_ID;
221 
222 	psoc = wlan_pdev_get_psoc(pdev);
223 	if (psoc) {
224 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
225 		if (tx_ops && tx_ops->mops.get_hw_link_id)
226 			hw_link_id = tx_ops->mops.get_hw_link_id(pdev);
227 	}
228 
229 	return hw_link_id;
230 }
231 
232 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc,
233 				       void *obj, void *arg)
234 {
235 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
236 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
237 	uint16_t hw_link_id;
238 
239 	if (itr->pdev)
240 		return;
241 
242 	hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
243 	if (hw_link_id == itr->hw_link_id) {
244 		if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) ==
245 							QDF_STATUS_SUCCESS)
246 			itr->pdev = pdev;
247 	}
248 }
249 
250 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc,
251 				     void *arg,
252 				     uint8_t index)
253 {
254 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
255 
256 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
257 				     wlan_pdev_hw_link_iterator,
258 				     arg, false, itr->dbgid);
259 }
260 
261 struct wlan_objmgr_pdev *
262 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,
263 				wlan_objmgr_ref_dbgid refdbgid)
264 {
265 	struct hw_link_id_iterator itr;
266 
267 	itr.hw_link_id = hw_link_id;
268 	itr.pdev = NULL;
269 	itr.dbgid = refdbgid;
270 
271 	wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id,
272 				      &itr, refdbgid);
273 
274 	return itr.pdev;
275 }
276 #endif /*WLAN_MLO_MULTI_CHIP*/
277