xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c (revision bd23cf7dccea2c964087a8e7bb3abed720075ec8)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021 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 #ifdef WLAN_MLO_MULTI_CHIP
24 #include "wlan_lmac_if_def.h"
25 #endif
26 
27 void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
28 			      struct mlo_link_info *info)
29 {
30 /* Pass the partner link information*/
31 }
32 
33 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev)
34 {
35 /* Loop through all the vdev's part of the ML device*/
36 /* STA: Loop through all the associated vdev status. */
37 }
38 
39 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(
40 			struct wlan_objmgr_vdev *vdev,
41 			uint8_t link_id)
42 {
43 	struct wlan_mlo_dev_context *dev_ctx;
44 	int i;
45 	struct wlan_objmgr_vdev *partner_vdev = NULL;
46 
47 	if (!vdev || !vdev->mlo_dev_ctx) {
48 		mlo_err("Invalid input");
49 		return partner_vdev;
50 	}
51 
52 	dev_ctx = vdev->mlo_dev_ctx;
53 
54 	mlo_dev_lock_acquire(dev_ctx);
55 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
56 		if (dev_ctx->wlan_vdev_list[i] &&
57 		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
58 		    dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
59 		    link_id) {
60 			if (wlan_objmgr_vdev_try_get_ref(
61 						dev_ctx->wlan_vdev_list[i],
62 						WLAN_MLO_MGR_ID) ==
63 							QDF_STATUS_SUCCESS)
64 				partner_vdev = dev_ctx->wlan_vdev_list[i];
65 
66 			break;
67 		}
68 	}
69 	mlo_dev_lock_release(dev_ctx);
70 
71 	return partner_vdev;
72 }
73 
74 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
75 {
76 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
77 }
78 
79 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx,
80 			       struct mlo_mlme_ext_ops *ops)
81 {
82 	if (!ctx)
83 		return QDF_STATUS_E_FAILURE;
84 
85 	ctx->mlme_ops = ops;
86 	return QDF_STATUS_SUCCESS;
87 }
88 
89 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx)
90 {
91 	if (!ctx)
92 		return QDF_STATUS_E_FAILURE;
93 
94 	ctx->mlme_ops = NULL;
95 	return QDF_STATUS_SUCCESS;
96 }
97 
98 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev,
99 				      void *ext_data)
100 {
101 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
102 	struct vdev_mlme_obj *vdev_mlme;
103 	QDF_STATUS status;
104 
105 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
106 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
107 		return QDF_STATUS_E_FAILURE;
108 
109 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
110 	if (!vdev_mlme)
111 		return QDF_STATUS_E_FAILURE;
112 
113 	status =
114 		mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme,
115 								  ext_data);
116 	return status;
117 }
118 
119 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
120 				     void *ext_data)
121 {
122 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
123 	struct vdev_mlme_obj *vdev_mlme;
124 	QDF_STATUS status;
125 
126 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
127 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev)
128 		return QDF_STATUS_E_FAILURE;
129 
130 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
131 	if (!vdev_mlme)
132 		return QDF_STATUS_E_FAILURE;
133 
134 	status =
135 		mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme,
136 								 ext_data);
137 	return status;
138 }
139 
140 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
141 			  struct wlan_mlo_peer_context *ml_peer,
142 			  struct qdf_mac_addr *addr,
143 			  qdf_nbuf_t frm_buf)
144 {
145 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
146 
147 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
148 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create)
149 		return;
150 
151 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer,
152 						    addr, frm_buf);
153 }
154 
155 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
156 {
157 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
158 
159 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
160 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc)
161 		return;
162 
163 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer);
164 }
165 
166 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer)
167 {
168 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
169 
170 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
171 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail)
172 		return;
173 
174 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer);
175 }
176 
177 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
178 {
179 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
180 
181 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
182 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete)
183 		return;
184 
185 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
186 }
187 
188 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
189 {
190 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
191 
192 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
193 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
194 		return;
195 
196 	mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
197 }
198 
199 qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
200 				       uint8_t link_ix)
201 {
202 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
203 
204 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
205 	    !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req)
206 		return NULL;
207 
208 	return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix);
209 }
210 
211 void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer)
212 {
213 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
214 
215 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
216 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth)
217 		return;
218 
219 	mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer);
220 }
221 
222 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
223 			     struct wlan_objmgr_vdev *vdev)
224 {
225 	uint8_t i;
226 
227 	mlo_dev_lock_acquire(ml_dev);
228 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
229 		if (vdev == ml_dev->wlan_vdev_list[i]) {
230 			mlo_dev_lock_release(ml_dev);
231 			return i;
232 		}
233 	}
234 	mlo_dev_lock_release(ml_dev);
235 
236 	return (uint8_t)-1;
237 }
238 
239 #ifdef WLAN_MLO_MULTI_CHIP
240 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
241 {
242 	struct wlan_objmgr_psoc *psoc;
243 	struct wlan_lmac_if_tx_ops *tx_ops;
244 	uint16_t hw_link_id = INVALID_HW_LINK_ID;
245 
246 	psoc = wlan_pdev_get_psoc(pdev);
247 	if (psoc) {
248 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
249 		if (tx_ops && tx_ops->mops.get_hw_link_id)
250 			hw_link_id = tx_ops->mops.get_hw_link_id(pdev);
251 	}
252 
253 	return hw_link_id;
254 }
255 
256 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc,
257 				       void *obj, void *arg)
258 {
259 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
260 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
261 	uint16_t hw_link_id;
262 
263 	if (itr->pdev)
264 		return;
265 
266 	hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
267 	if (hw_link_id == itr->hw_link_id) {
268 		if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) ==
269 							QDF_STATUS_SUCCESS)
270 			itr->pdev = pdev;
271 	}
272 }
273 
274 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc,
275 				     void *arg,
276 				     uint8_t index)
277 {
278 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
279 
280 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
281 				     wlan_pdev_hw_link_iterator,
282 				     arg, false, itr->dbgid);
283 }
284 
285 struct wlan_objmgr_pdev *
286 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,
287 				wlan_objmgr_ref_dbgid refdbgid)
288 {
289 	struct hw_link_id_iterator itr;
290 
291 	itr.hw_link_id = hw_link_id;
292 	itr.pdev = NULL;
293 	itr.dbgid = refdbgid;
294 
295 	wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id,
296 				      &itr, refdbgid);
297 
298 	return itr.pdev;
299 }
300 #endif /*WLAN_MLO_MULTI_CHIP*/
301 
302 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev,
303 			  uint16_t *vdev_count,
304 			  struct wlan_objmgr_vdev **wlan_vdev_list)
305 {
306 	struct wlan_mlo_dev_context *dev_ctx;
307 	int i;
308 	QDF_STATUS status;
309 
310 	*vdev_count = 0;
311 
312 	if (!vdev || !vdev->mlo_dev_ctx) {
313 		mlo_err("Invalid input");
314 		return;
315 	}
316 
317 	dev_ctx = vdev->mlo_dev_ctx;
318 
319 	mlo_dev_lock_acquire(dev_ctx);
320 	*vdev_count = 0;
321 	for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
322 		if (dev_ctx->wlan_vdev_list[i] &&
323 		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) {
324 			status = wlan_objmgr_vdev_try_get_ref(
325 						dev_ctx->wlan_vdev_list[i],
326 						WLAN_MLO_MGR_ID);
327 			if (QDF_IS_STATUS_ERROR(status))
328 				break;
329 			wlan_vdev_list[*vdev_count] =
330 				dev_ctx->wlan_vdev_list[i];
331 			(*vdev_count) += 1;
332 		}
333 	}
334 	mlo_dev_lock_release(dev_ctx);
335 }
336