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