1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 #include <wlan_mlo_mgr_cmn.h> 19 #include <wlan_mlo_mgr_public_structs.h> 20 #include "wlan_mlo_mgr_main.h" 21 #include "qdf_types.h" 22 #include "wlan_cmn.h" 23 #include "wlan_mlo_mgr_peer.h" 24 25 struct aid_search { 26 struct wlan_mlo_peer_context *ml_peer; 27 uint16_t aid; 28 }; 29 30 struct mlpeerid_search { 31 struct wlan_mlo_peer_context *ml_peer; 32 uint16_t ml_peerid; 33 }; 34 35 struct mac_addr_search { 36 struct wlan_mlo_peer_context *ml_peer; 37 struct qdf_mac_addr mac_addr; 38 }; 39 40 static inline struct wlan_mlo_peer_context *wlan_mlo_peer_list_peek_head( 41 qdf_list_t *peer_list) 42 { 43 struct wlan_mlo_peer_context *ml_peer; 44 qdf_list_node_t *peer_node = NULL; 45 46 /* This API is invoked with lock acquired, do not add log prints */ 47 if (qdf_list_peek_front(peer_list, &peer_node) != QDF_STATUS_SUCCESS) 48 return NULL; 49 50 ml_peer = qdf_container_of(peer_node, 51 struct wlan_mlo_peer_context, peer_node); 52 return ml_peer; 53 } 54 55 static inline struct wlan_mlo_peer_context *wlan_mlo_peer_get_next_mlpeer( 56 qdf_list_t *peer_list, 57 struct wlan_mlo_peer_context *ml_peer) 58 { 59 struct wlan_mlo_peer_context *next_peer; 60 qdf_list_node_t *node = &ml_peer->peer_node; 61 qdf_list_node_t *next_node = NULL; 62 63 /* This API is invoked with lock acquired, do not add log prints */ 64 if (!node) 65 return NULL; 66 67 if (qdf_list_peek_next(peer_list, node, &next_node) != 68 QDF_STATUS_SUCCESS) 69 return NULL; 70 71 next_peer = qdf_container_of(next_node, 72 struct wlan_mlo_peer_context, peer_node); 73 74 return next_peer; 75 } 76 77 struct wlan_mlo_peer_context *mlo_get_mlpeer( 78 struct wlan_mlo_dev_context *ml_dev, 79 const struct qdf_mac_addr *ml_addr) 80 { 81 uint8_t hash_index; 82 struct wlan_mlo_peer_list *mlo_peer_list; 83 struct wlan_mlo_peer_context *ml_peer; 84 struct wlan_mlo_peer_context *next_ml_peer; 85 qdf_list_t *peer_hash_list; 86 87 mlo_peer_list = &ml_dev->mlo_peer_list; 88 hash_index = WLAN_PEER_HASH(ml_addr->bytes); 89 90 peer_hash_list = &mlo_peer_list->peer_hash[hash_index]; 91 /* Get first vdev */ 92 ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list); 93 /** 94 * Iterate through pdev's vdev list, till vdev id matches with 95 * entry of vdev list 96 */ 97 while (ml_peer) { 98 if (qdf_is_macaddr_equal(&ml_peer->peer_mld_addr, ml_addr)) 99 return ml_peer; 100 101 /* get next vdev */ 102 next_ml_peer = wlan_mlo_peer_get_next_mlpeer(peer_hash_list, 103 ml_peer); 104 ml_peer = next_ml_peer; 105 } 106 107 return NULL; 108 } 109 110 QDF_STATUS wlan_mlo_iterate_ml_peerlist(struct wlan_mlo_dev_context *ml_dev, 111 wlan_mlo_op_handler handler, 112 void *arg) 113 { 114 uint8_t hash_index; 115 struct wlan_mlo_peer_list *peerlist; 116 struct wlan_mlo_peer_context *ml_peer; 117 struct wlan_mlo_peer_context *next; 118 qdf_list_t *peer_hash_list; 119 QDF_STATUS status; 120 121 peerlist = &ml_dev->mlo_peer_list; 122 ml_peerlist_lock_acquire(peerlist); 123 124 for (hash_index = 0; hash_index < WLAN_PEER_HASHSIZE; hash_index++) { 125 peer_hash_list = &peerlist->peer_hash[hash_index]; 126 /* Get first vdev */ 127 ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list); 128 /** 129 * Iterate through pdev's vdev list, till vdev id matches with 130 * entry of vdev list 131 */ 132 while (ml_peer) { 133 status = handler(ml_dev, ml_peer, arg); 134 if (status == QDF_STATUS_SUCCESS) { 135 ml_peerlist_lock_release(peerlist); 136 return QDF_STATUS_SUCCESS; 137 } 138 /* get next ml peer */ 139 next = wlan_mlo_peer_get_next_mlpeer(peer_hash_list, 140 ml_peer); 141 ml_peer = next; 142 } 143 } 144 ml_peerlist_lock_release(peerlist); 145 146 return QDF_STATUS_E_NOENT; 147 } 148 149 static QDF_STATUS 150 wlan_find_mlpeer_link_mac_addr(struct wlan_mlo_dev_context *ml_dev, 151 void *iter_ml_peer, 152 void *arg) 153 { 154 struct mac_addr_search *link_mac_arg = (struct mac_addr_search *)arg; 155 struct wlan_mlo_link_peer_entry *link_peer; 156 struct wlan_mlo_peer_context *ml_peer; 157 uint8_t i; 158 159 ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer; 160 mlo_debug("MLD ID %d ML Peer mac " QDF_MAC_ADDR_FMT, 161 ml_dev->mld_id, 162 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 163 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 164 link_peer = &ml_peer->peer_list[i]; 165 166 mlo_debug("MLD ID %d, index %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 167 i, ml_dev->mld_id, 168 QDF_MAC_ADDR_REF(link_peer->link_addr.bytes)); 169 if (qdf_is_macaddr_equal(&link_mac_arg->mac_addr, 170 &link_peer->link_addr)) { 171 link_mac_arg->ml_peer = ml_peer; 172 return QDF_STATUS_SUCCESS; 173 } 174 } 175 176 return QDF_STATUS_E_NOENT; 177 } 178 179 static QDF_STATUS 180 wlan_find_mlpeer_mld_mac_addr(struct wlan_mlo_dev_context *ml_dev, 181 void *iter_ml_peer, 182 void *arg) 183 { 184 struct mac_addr_search *mld_mac_arg = (struct mac_addr_search *)arg; 185 struct wlan_mlo_peer_context *ml_peer; 186 187 ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer; 188 mlo_debug("MLD ID %d ML Peer mac " QDF_MAC_ADDR_FMT, 189 ml_dev->mld_id, 190 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 191 192 if (qdf_is_macaddr_equal(&mld_mac_arg->mac_addr, 193 &ml_peer->peer_mld_addr)) { 194 mld_mac_arg->ml_peer = ml_peer; 195 return QDF_STATUS_SUCCESS; 196 } 197 198 return QDF_STATUS_E_NOENT; 199 } 200 201 static QDF_STATUS wlan_find_mlpeer_aid(struct wlan_mlo_dev_context *ml_dev, 202 void *iter_ml_peer, 203 void *arg) 204 { 205 struct aid_search *aid_arg = (struct aid_search *)arg; 206 struct wlan_mlo_peer_context *ml_peer; 207 208 ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer; 209 210 if (aid_arg->aid == ml_peer->assoc_id) { 211 aid_arg->ml_peer = ml_peer; 212 return QDF_STATUS_SUCCESS; 213 } 214 215 return QDF_STATUS_E_NOENT; 216 } 217 218 static QDF_STATUS 219 wlan_find_mlpeer_ml_peerid(struct wlan_mlo_dev_context *ml_dev, 220 void *iter_ml_peer, 221 void *arg) 222 { 223 struct mlpeerid_search *mlpeer_id_arg = (struct mlpeerid_search *)arg; 224 struct wlan_mlo_peer_context *ml_peer; 225 226 ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer; 227 228 if (mlpeer_id_arg->ml_peerid == ml_peer->mlo_peer_id) { 229 mlpeer_id_arg->ml_peer = ml_peer; 230 return QDF_STATUS_SUCCESS; 231 } 232 233 return QDF_STATUS_E_NOENT; 234 } 235 236 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_linkmac( 237 struct wlan_mlo_dev_context *ml_dev, 238 struct qdf_mac_addr *link_mac) 239 { 240 struct mac_addr_search link_mac_arg; 241 QDF_STATUS status; 242 243 mlo_debug("MLD ID %d ML Peer search with link mac " QDF_MAC_ADDR_FMT, 244 ml_dev->mld_id, QDF_MAC_ADDR_REF(link_mac->bytes)); 245 qdf_copy_macaddr(&link_mac_arg.mac_addr, link_mac); 246 status = wlan_mlo_iterate_ml_peerlist(ml_dev, 247 wlan_find_mlpeer_link_mac_addr, 248 &link_mac_arg); 249 if (status == QDF_STATUS_SUCCESS) 250 return link_mac_arg.ml_peer; 251 252 /* TODO: Take ref */ 253 254 return NULL; 255 } 256 257 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_aid( 258 struct wlan_mlo_dev_context *ml_dev, 259 uint16_t assoc_id) 260 { 261 struct aid_search aid_arg; 262 QDF_STATUS status; 263 264 aid_arg.aid = assoc_id; 265 status = wlan_mlo_iterate_ml_peerlist(ml_dev, 266 wlan_find_mlpeer_aid, 267 &aid_arg); 268 if (status == QDF_STATUS_SUCCESS) 269 return aid_arg.ml_peer; 270 271 /* TODO: Take ref */ 272 273 return NULL; 274 } 275 276 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_mld_mac( 277 struct wlan_mlo_dev_context *ml_dev, 278 struct qdf_mac_addr *mld_mac) 279 { 280 struct mac_addr_search mld_mac_arg; 281 QDF_STATUS status; 282 283 mlo_debug("MLD ID %d ML Peer search with mld mac " QDF_MAC_ADDR_FMT, 284 ml_dev->mld_id, QDF_MAC_ADDR_REF(mld_mac->bytes)); 285 qdf_copy_macaddr(&mld_mac_arg.mac_addr, mld_mac); 286 status = wlan_mlo_iterate_ml_peerlist(ml_dev, 287 wlan_find_mlpeer_mld_mac_addr, 288 &mld_mac_arg); 289 if (QDF_IS_STATUS_SUCCESS(status)) 290 return mld_mac_arg.ml_peer; 291 292 /* TODO: Take ref */ 293 294 return NULL; 295 } 296 297 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid( 298 struct wlan_mlo_dev_context *ml_dev, 299 uint16_t ml_peerid) 300 { 301 struct mlpeerid_search peerid_arg; 302 QDF_STATUS status; 303 304 peerid_arg.ml_peerid = ml_peerid; 305 status = wlan_mlo_iterate_ml_peerlist(ml_dev, 306 wlan_find_mlpeer_ml_peerid, 307 &peerid_arg); 308 if (status == QDF_STATUS_SUCCESS) 309 return peerid_arg.ml_peer; 310 311 /* TODO: Take ref */ 312 313 return NULL; 314 } 315 316 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer( 317 struct wlan_mlo_dev_context *ml_dev, 318 struct qdf_mac_addr *ml_addr) 319 { 320 struct wlan_mlo_peer_context *ml_peer; 321 struct wlan_mlo_peer_list *mlo_peer_list; 322 323 mlo_debug("MLD ID %d ML Peer search mac " QDF_MAC_ADDR_FMT, 324 ml_dev->mld_id, QDF_MAC_ADDR_REF(ml_addr->bytes)); 325 mlo_peer_list = &ml_dev->mlo_peer_list; 326 ml_peerlist_lock_acquire(mlo_peer_list); 327 ml_peer = mlo_get_mlpeer(ml_dev, ml_addr); 328 if (!ml_peer) { 329 ml_peerlist_lock_release(mlo_peer_list); 330 return NULL; 331 } 332 /* TODO: Take ref */ 333 334 ml_peerlist_lock_release(mlo_peer_list); 335 return ml_peer; 336 } 337 338 static void wlan_mlo_peerlist_add_tail(qdf_list_t *obj_list, 339 struct wlan_mlo_peer_context *obj) 340 { 341 qdf_list_insert_back(obj_list, &obj->peer_node); 342 } 343 344 static QDF_STATUS wlan_mlo_peerlist_remove_mlpeer( 345 qdf_list_t *obj_list, 346 struct wlan_mlo_peer_context *ml_peer) 347 { 348 qdf_list_node_t *peer_node = NULL; 349 350 if (!ml_peer) 351 return QDF_STATUS_E_FAILURE; 352 /* get vdev list node element */ 353 peer_node = &ml_peer->peer_node; 354 /* list is empty, return failure */ 355 if (qdf_list_remove_node(obj_list, peer_node) != QDF_STATUS_SUCCESS) 356 return QDF_STATUS_E_FAILURE; 357 358 return QDF_STATUS_SUCCESS; 359 } 360 361 QDF_STATUS mlo_dev_mlpeer_attach(struct wlan_mlo_dev_context *ml_dev, 362 struct wlan_mlo_peer_context *ml_peer) 363 { 364 uint8_t hash_index; 365 struct wlan_mlo_peer_list *mlo_peer_list; 366 367 mlo_peer_list = &ml_dev->mlo_peer_list; 368 ml_peerlist_lock_acquire(mlo_peer_list); 369 if (mlo_get_mlpeer(ml_dev, &ml_peer->peer_mld_addr)) { 370 ml_peerlist_lock_release(mlo_peer_list); 371 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 372 ml_dev->mld_id, 373 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 374 return QDF_STATUS_E_EXISTS; 375 } 376 377 hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes); 378 wlan_mlo_peerlist_add_tail(&mlo_peer_list->peer_hash[hash_index], 379 ml_peer); 380 ml_peerlist_lock_release(mlo_peer_list); 381 382 mlo_debug("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is attached", 383 ml_dev->mld_id, 384 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 385 386 return QDF_STATUS_SUCCESS; 387 } 388 389 QDF_STATUS mlo_dev_mlpeer_detach(struct wlan_mlo_dev_context *ml_dev, 390 struct wlan_mlo_peer_context *ml_peer) 391 { 392 uint8_t hash_index; 393 QDF_STATUS status; 394 struct wlan_mlo_peer_list *mlo_peer_list; 395 396 mlo_peer_list = &ml_dev->mlo_peer_list; 397 ml_peerlist_lock_acquire(mlo_peer_list); 398 hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes); 399 status = wlan_mlo_peerlist_remove_mlpeer( 400 &mlo_peer_list->peer_hash[hash_index], 401 ml_peer); 402 ml_peerlist_lock_release(mlo_peer_list); 403 404 mlo_debug("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is detached", 405 ml_dev->mld_id, 406 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 407 408 return status; 409 } 410 411 QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev) 412 { 413 struct wlan_mlo_peer_list *mlo_peer_list; 414 uint16_t i; 415 416 mlo_peer_list = &ml_dev->mlo_peer_list; 417 ml_peerlist_lock_create(mlo_peer_list); 418 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 419 qdf_list_create(&mlo_peer_list->peer_hash[i], 420 WLAN_UMAC_PSOC_MAX_PEERS + 421 WLAN_MAX_PSOC_TEMP_PEERS); 422 423 return QDF_STATUS_SUCCESS; 424 } 425 426 QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev) 427 { 428 uint16_t i; 429 struct wlan_mlo_peer_list *mlo_peer_list; 430 431 /* deinit the lock */ 432 mlo_peer_list = &ml_dev->mlo_peer_list; 433 ml_peerlist_lock_destroy(mlo_peer_list); 434 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 435 qdf_list_destroy(&mlo_peer_list->peer_hash[i]); 436 437 return QDF_STATUS_SUCCESS; 438 } 439