1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 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 #include "wlan_mlo_mgr_main.h" 18 #include "qdf_types.h" 19 #include "wlan_cmn.h" 20 #include "wlan_mlo_mgr_cmn.h" 21 #include "wlan_mlo_mgr_msgq.h" 22 #include "wlan_mlo_mgr_peer.h" 23 24 #ifndef MLO_MSGQ_SUPPORT mlo_msgq_post(enum mlo_msg_type type,struct wlan_mlo_dev_context * ml_dev,void * payload)25 QDF_STATUS mlo_msgq_post(enum mlo_msg_type type, 26 struct wlan_mlo_dev_context *ml_dev, 27 void *payload) 28 { 29 struct peer_create_notif_s *peer_create; 30 struct peer_assoc_notify_s *peer_assoc; 31 struct peer_assoc_fail_notify_s *peer_assoc_fail; 32 struct peer_discon_notify_s *peer_disconn; 33 struct peer_deauth_notify_s *peer_deauth; 34 struct peer_auth_process_notif_s *peer_auth; 35 36 switch (type) { 37 case MLO_PEER_CREATE: 38 peer_create = (struct peer_create_notif_s *)payload; 39 40 mlo_mlme_peer_create(peer_create->vdev_link, 41 peer_create->ml_peer, 42 &peer_create->addr, peer_create->frm_buf); 43 qdf_nbuf_free(peer_create->frm_buf); 44 wlan_mlo_peer_release_ref(peer_create->ml_peer); 45 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 46 WLAN_MLO_MGR_ID); 47 break; 48 49 case MLO_BRIDGE_PEER_CREATE: 50 peer_create = (struct peer_create_notif_s *)payload; 51 52 mlo_mlme_bridge_peer_create(peer_create->vdev_link, 53 peer_create->ml_peer, 54 &peer_create->addr, 55 peer_create->frm_buf); 56 wlan_mlo_peer_release_ref(peer_create->ml_peer); 57 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 58 WLAN_MLO_MGR_ID); 59 break; 60 61 case MLO_PEER_ASSOC: 62 peer_assoc = (struct peer_assoc_notify_s *)payload; 63 mlo_mlme_peer_assoc(peer_assoc->peer); 64 wlan_objmgr_peer_release_ref(peer_assoc->peer, 65 WLAN_MLO_MGR_ID); 66 break; 67 68 case MLO_PEER_ASSOC_FAIL: 69 peer_assoc_fail = (struct peer_assoc_fail_notify_s *)payload; 70 mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer); 71 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer, 72 WLAN_MLO_MGR_ID); 73 break; 74 75 case MLO_PEER_DISCONNECT: 76 peer_disconn = (struct peer_discon_notify_s *)payload; 77 mlo_mlme_peer_delete(peer_disconn->peer); 78 wlan_objmgr_peer_release_ref(peer_disconn->peer, 79 WLAN_MLO_MGR_ID); 80 break; 81 82 case MLO_PEER_DEAUTH: 83 peer_deauth = (struct peer_deauth_notify_s *)payload; 84 mlo_mlme_peer_deauth(peer_deauth->peer, 85 peer_deauth->is_disassoc); 86 wlan_objmgr_peer_release_ref(peer_deauth->peer, 87 WLAN_MLO_MGR_ID); 88 break; 89 90 case MLO_PEER_PENDING_AUTH: 91 peer_auth = (struct peer_auth_process_notif_s *)payload; 92 mlo_mlme_peer_process_auth(peer_auth->auth_params); 93 break; 94 95 case MLO_PEER_REASSOC: 96 peer_create = (struct peer_create_notif_s *)payload; 97 mlo_mlme_peer_reassoc(peer_create->vdev_link, 98 peer_create->ml_peer, &peer_create->addr, 99 peer_create->frm_buf); 100 qdf_nbuf_free(peer_create->frm_buf); 101 wlan_mlo_peer_release_ref(peer_create->ml_peer); 102 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 103 WLAN_MLO_MGR_ID); 104 break; 105 106 default: 107 break; 108 } 109 110 return QDF_STATUS_SUCCESS; 111 } 112 mlo_msgq_init(void)113 void mlo_msgq_init(void) 114 { 115 } 116 mlo_msgq_free(void)117 void mlo_msgq_free(void) 118 { 119 } 120 #else mlo_msgq_timer_start(void)121 static void mlo_msgq_timer_start(void) 122 { 123 struct ctxt_switch_mgr *msgq_ctx; 124 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 125 bool start_timer = true; 126 127 if (!mlo_ctx) 128 return; 129 130 msgq_ctx = mlo_ctx->msgq_ctx; 131 132 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock); 133 if (!msgq_ctx->timer_started) 134 msgq_ctx->timer_started = true; 135 else 136 start_timer = false; 137 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock); 138 139 if (start_timer) 140 qdf_timer_start(&msgq_ctx->ctxt_mgr_timer, 0); 141 } 142 mlo_msgq_timer_stop(void)143 static void mlo_msgq_timer_stop(void) 144 { 145 struct ctxt_switch_mgr *msgq_ctx; 146 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 147 148 if (!mlo_ctx) 149 return; 150 151 msgq_ctx = mlo_ctx->msgq_ctx; 152 153 qdf_timer_stop(&msgq_ctx->ctxt_mgr_timer); 154 155 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock); 156 msgq_ctx->timer_started = false; 157 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock); 158 } 159 mlo_msgq_post(enum mlo_msg_type type,struct wlan_mlo_dev_context * ml_dev,void * payload)160 QDF_STATUS mlo_msgq_post(enum mlo_msg_type type, 161 struct wlan_mlo_dev_context *ml_dev, 162 void *payload) 163 { 164 struct mlo_ctxt_switch_msg_s *msg; 165 struct peer_create_notif_s *peer_create, *peer_create_l; 166 struct peer_assoc_notify_s *peer_assoc, *peer_assoc_l; 167 struct peer_assoc_fail_notify_s *peer_assoc_fail, *peer_assoc_fail_l; 168 struct peer_discon_notify_s *peer_disconn, *peer_disconn_l; 169 struct peer_deauth_notify_s *peer_deauth, *peer_deauth_l; 170 struct peer_auth_process_notif_s *peer_auth, *peer_auth_l; 171 struct ctxt_switch_mgr *msgq_ctx; 172 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 173 174 if (!mlo_ctx) 175 return QDF_STATUS_E_FAILURE; 176 177 msgq_ctx = mlo_ctx->msgq_ctx; 178 179 if (!msgq_ctx->allow_msg) 180 return QDF_STATUS_E_FAILURE; 181 182 msg = qdf_mem_malloc(sizeof(*msg)); 183 if (!msg) 184 return QDF_STATUS_E_NOMEM; 185 186 msg->type = type; 187 msg->ml_dev = ml_dev; 188 189 switch (type) { 190 case MLO_PEER_CREATE: 191 peer_create = &msg->m.peer_create; 192 peer_create_l = (struct peer_create_notif_s *)payload; 193 peer_create->frm_buf = peer_create_l->frm_buf; 194 peer_create->ml_peer = peer_create_l->ml_peer; 195 peer_create->vdev_link = peer_create_l->vdev_link; 196 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr); 197 break; 198 199 case MLO_BRIDGE_PEER_CREATE: 200 peer_create = &msg->m.peer_create; 201 peer_create_l = (struct peer_create_notif_s *)payload; 202 peer_create->frm_buf = peer_create_l->frm_buf; 203 peer_create->ml_peer = peer_create_l->ml_peer; 204 peer_create->vdev_link = peer_create_l->vdev_link; 205 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr); 206 break; 207 208 case MLO_PEER_ASSOC: 209 peer_assoc = &msg->m.peer_assoc; 210 peer_assoc_l = (struct peer_assoc_notify_s *)payload; 211 peer_assoc->peer = peer_assoc_l->peer; 212 break; 213 214 case MLO_PEER_ASSOC_FAIL: 215 peer_assoc_fail = &msg->m.peer_assoc_fail; 216 peer_assoc_fail_l = (struct peer_assoc_fail_notify_s *)payload; 217 peer_assoc_fail->peer = peer_assoc_fail_l->peer; 218 break; 219 220 case MLO_PEER_DISCONNECT: 221 peer_disconn = &msg->m.peer_disconn; 222 peer_disconn_l = (struct peer_discon_notify_s *)payload; 223 peer_disconn->peer = peer_disconn_l->peer; 224 break; 225 226 case MLO_PEER_DEAUTH: 227 peer_deauth = &msg->m.peer_deauth; 228 peer_deauth_l = (struct peer_deauth_notify_s *)payload; 229 peer_deauth->peer = peer_deauth_l->peer; 230 peer_deauth->is_disassoc = peer_deauth_l->is_disassoc; 231 break; 232 233 case MLO_PEER_PENDING_AUTH: 234 peer_auth = &msg->m.peer_auth; 235 peer_auth_l = (struct peer_auth_process_notif_s *)payload; 236 peer_auth->auth_params = peer_auth_l->auth_params; 237 break; 238 239 case MLO_PEER_REASSOC: 240 peer_create = &msg->m.peer_create; 241 peer_create_l = (struct peer_create_notif_s *)payload; 242 peer_create->frm_buf = peer_create_l->frm_buf; 243 peer_create->ml_peer = peer_create_l->ml_peer; 244 peer_create->vdev_link = peer_create_l->vdev_link; 245 qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr); 246 break; 247 248 default: 249 break; 250 } 251 252 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock); 253 qdf_list_insert_back(&msgq_ctx->msgq_list, &msg->node); 254 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock); 255 mlo_msgq_timer_start(); 256 257 return QDF_STATUS_SUCCESS; 258 } 259 mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s * msg)260 static void mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s *msg) 261 { 262 enum mlo_msg_type type; 263 struct peer_create_notif_s *peer_create; 264 struct peer_assoc_notify_s *peer_assoc; 265 struct peer_assoc_fail_notify_s *peer_assoc_fail; 266 struct peer_discon_notify_s *peer_disconn; 267 struct peer_deauth_notify_s *peer_deauth; 268 struct peer_auth_process_notif_s *peer_auth; 269 270 type = msg->type; 271 switch (type) { 272 case MLO_PEER_CREATE: 273 peer_create = &msg->m.peer_create; 274 mlo_mlme_peer_create(peer_create->vdev_link, 275 peer_create->ml_peer, 276 &peer_create->addr, peer_create->frm_buf); 277 qdf_nbuf_free(peer_create->frm_buf); 278 wlan_mlo_peer_release_ref(peer_create->ml_peer); 279 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 280 WLAN_MLO_MGR_ID); 281 break; 282 283 case MLO_BRIDGE_PEER_CREATE: 284 peer_create = &msg->m.peer_create; 285 mlo_mlme_bridge_peer_create(peer_create->vdev_link, 286 peer_create->ml_peer, 287 &peer_create->addr, 288 peer_create->frm_buf); 289 wlan_mlo_peer_release_ref(peer_create->ml_peer); 290 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 291 WLAN_MLO_MGR_ID); 292 break; 293 294 case MLO_PEER_ASSOC: 295 peer_assoc = &msg->m.peer_assoc; 296 mlo_mlme_peer_assoc(peer_assoc->peer); 297 wlan_objmgr_peer_release_ref(peer_assoc->peer, 298 WLAN_MLO_MGR_ID); 299 break; 300 301 case MLO_PEER_ASSOC_FAIL: 302 peer_assoc_fail = &msg->m.peer_assoc_fail; 303 mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer); 304 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer, 305 WLAN_MLO_MGR_ID); 306 break; 307 308 case MLO_PEER_DISCONNECT: 309 peer_disconn = &msg->m.peer_disconn; 310 mlo_mlme_peer_delete(peer_disconn->peer); 311 wlan_objmgr_peer_release_ref(peer_disconn->peer, 312 WLAN_MLO_MGR_ID); 313 break; 314 315 case MLO_PEER_DEAUTH: 316 peer_deauth = &msg->m.peer_deauth; 317 mlo_mlme_peer_deauth(peer_deauth->peer); 318 wlan_objmgr_peer_release_ref(peer_deauth->peer, 319 WLAN_MLO_MGR_ID); 320 break; 321 322 case MLO_PEER_PENDING_AUTH: 323 peer_auth = &msg->m.peer_auth; 324 mlo_mlme_peer_process_auth(peer_auth->auth_params); 325 break; 326 327 case MLO_PEER_REASSOC: 328 peer_create = &msg->m.peer_create; 329 mlo_mlme_peer_reassoc(peer_create->vdev_link, 330 peer_create->ml_peer, &peer_create->addr, 331 peer_create->frm_buf); 332 qdf_nbuf_free(peer_create->frm_buf); 333 wlan_mlo_peer_release_ref(peer_create->ml_peer); 334 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 335 WLAN_MLO_MGR_ID); 336 break; 337 338 default: 339 break; 340 } 341 qdf_mem_free(msg); 342 } 343 mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s * msg)344 static void mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s *msg) 345 { 346 enum mlo_msg_type type; 347 struct peer_create_notif_s *peer_create; 348 struct peer_assoc_notify_s *peer_assoc; 349 struct peer_assoc_fail_notify_s *peer_assoc_fail; 350 struct peer_discon_notify_s *peer_disconn; 351 struct peer_deauth_notify_s *peer_deauth; 352 353 type = msg->type; 354 switch (type) { 355 case MLO_PEER_CREATE: 356 peer_create = &msg->m.peer_create; 357 qdf_nbuf_free(peer_create->frm_buf); 358 wlan_mlo_peer_release_ref(peer_create->ml_peer); 359 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 360 WLAN_MLO_MGR_ID); 361 break; 362 363 case MLO_BRIDGE_PEER_CREATE: 364 peer_create = &msg->m.peer_create; 365 wlan_mlo_peer_release_ref(peer_create->ml_peer); 366 wlan_objmgr_vdev_release_ref(peer_create->vdev_link, 367 WLAN_MLO_MGR_ID); 368 break; 369 370 case MLO_PEER_ASSOC: 371 peer_assoc = &msg->m.peer_assoc; 372 wlan_objmgr_peer_release_ref(peer_assoc->peer, 373 WLAN_MLO_MGR_ID); 374 break; 375 376 case MLO_PEER_ASSOC_FAIL: 377 peer_assoc_fail = &msg->m.peer_assoc_fail; 378 wlan_objmgr_peer_release_ref(peer_assoc_fail->peer, 379 WLAN_MLO_MGR_ID); 380 break; 381 382 case MLO_PEER_DISCONNECT: 383 peer_disconn = &msg->m.peer_disconn; 384 wlan_objmgr_peer_release_ref(peer_disconn->peer, 385 WLAN_MLO_MGR_ID); 386 break; 387 388 case MLO_PEER_DEAUTH: 389 peer_deauth = &msg->m.peer_deauth; 390 wlan_objmgr_peer_release_ref(peer_deauth->peer, 391 WLAN_MLO_MGR_ID); 392 break; 393 394 case MLO_PEER_PENDING_AUTH: 395 peer_auth = &msg->m.peer_auth; 396 mlo_peer_free_auth_param(peer_auth->auth_params); 397 break; 398 399 default: 400 break; 401 } 402 qdf_mem_free(msg); 403 } 404 mlo_msgq_msg_flush(void)405 static void mlo_msgq_msg_flush(void) 406 { 407 struct ctxt_switch_mgr *msgq_ctx; 408 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 409 qdf_list_node_t *msgbuf_node = NULL; 410 struct mlo_ctxt_switch_msg_s *msg; 411 QDF_STATUS status; 412 413 if (!mlo_ctx) 414 return; 415 416 msgq_ctx = mlo_ctx->msgq_ctx; 417 do { 418 msg = NULL; 419 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock); 420 status = qdf_list_peek_front(&msgq_ctx->msgq_list, 421 &msgbuf_node); 422 if (status != QDF_STATUS_E_EMPTY) { 423 qdf_list_remove_node(&msgq_ctx->msgq_list, 424 msgbuf_node); 425 msg = qdf_container_of(msgbuf_node, 426 struct mlo_ctxt_switch_msg_s, 427 node); 428 } 429 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock); 430 431 if (!msg) 432 break; 433 434 mlo_msgq_msg_flush_hdlr(msg); 435 436 } while (true); 437 } 438 mlo_msgq_msg_handler(void * arg)439 static void mlo_msgq_msg_handler(void *arg) 440 { 441 struct ctxt_switch_mgr *msgq_ctx; 442 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 443 qdf_list_node_t *msgbuf_node = NULL; 444 struct mlo_ctxt_switch_msg_s *msg; 445 QDF_STATUS status; 446 447 if (!mlo_ctx) 448 return; 449 450 msgq_ctx = mlo_ctx->msgq_ctx; 451 do { 452 msg = NULL; 453 qdf_spin_lock_bh(&msgq_ctx->ctxt_lock); 454 status = qdf_list_peek_front(&msgq_ctx->msgq_list, 455 &msgbuf_node); 456 if (status != QDF_STATUS_E_EMPTY) { 457 qdf_list_remove_node(&msgq_ctx->msgq_list, 458 msgbuf_node); 459 msg = qdf_container_of(msgbuf_node, 460 struct mlo_ctxt_switch_msg_s, 461 node); 462 } else { 463 msgq_ctx->timer_started = false; 464 } 465 qdf_spin_unlock_bh(&msgq_ctx->ctxt_lock); 466 467 if (!msg) 468 break; 469 470 mlo_msgq_msg_process_hdlr(msg); 471 472 } while (true); 473 } 474 mlo_msgq_init(void)475 void mlo_msgq_init(void) 476 { 477 struct ctxt_switch_mgr *msgq_ctx; 478 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 479 480 msgq_ctx = qdf_mem_malloc(sizeof(*msgq_ctx)); 481 if (!msgq_ctx) { 482 mlo_err(" message queue context allocation failed"); 483 return; 484 } 485 486 qdf_spinlock_create(&msgq_ctx->ctxt_lock); 487 /* Initialize timer with timeout handler */ 488 qdf_timer_init(NULL, &msgq_ctx->ctxt_mgr_timer, 489 mlo_msgq_msg_handler, 490 NULL, QDF_TIMER_TYPE_WAKE_APPS); 491 492 msgq_ctx->timer_started = false; 493 msgq_ctx->allow_msg = true; 494 qdf_list_create(&msgq_ctx->msgq_list, MLO_MAX_MSGQ_SIZE); 495 496 mlo_ctx->msgq_ctx = msgq_ctx; 497 } 498 mlo_msgq_free(void)499 void mlo_msgq_free(void) 500 { 501 struct ctxt_switch_mgr *msgq_ctx; 502 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 503 504 if (!mlo_ctx) 505 return; 506 507 msgq_ctx = mlo_ctx->msgq_ctx; 508 509 msgq_ctx->timer_started = false; 510 msgq_ctx->allow_msg = false; 511 mlo_msgq_msg_flush(); 512 qdf_list_destroy(&msgq_ctx->msgq_list); 513 qdf_timer_free(&msgq_ctx->ctxt_mgr_timer); 514 qdf_spinlock_destroy(&msgq_ctx->ctxt_lock); 515 qdf_mem_free(msgq_ctx); 516 } 517 #endif 518