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