1 /* 2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: wlan_serialization_main.c 21 * This file defines the important functions pertinent to 22 * serialization to initialize and de-initialize the 23 * component. 24 */ 25 #ifdef CONFIG_SERIALIZATION_V1 26 #include "qdf_status.h" 27 #include "qdf_list.h" 28 #include "wlan_objmgr_cmn.h" 29 #include "wlan_objmgr_global_obj.h" 30 #include "wlan_objmgr_psoc_obj.h" 31 #include "wlan_serialization_main_i.h" 32 #include "wlan_serialization_rules_i.h" 33 #include "wlan_serialization_utils_i.h" 34 35 struct serialization_legacy_callback ser_legacy_cb; 36 37 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc) 38 { 39 QDF_STATUS status; 40 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 41 wlan_serialization_get_psoc_priv_obj(psoc); 42 43 if (!ser_soc_obj) { 44 serialization_err("invalid ser_soc_obj"); 45 return QDF_STATUS_E_FAILURE; 46 } 47 /* clean up all timers before exiting */ 48 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 49 if (status != QDF_STATUS_SUCCESS) 50 serialization_err("ser cleanning up all timer failed"); 51 52 qdf_mem_free(ser_soc_obj->timers); 53 ser_soc_obj->timers = NULL; 54 ser_soc_obj->max_active_cmds = 0; 55 56 return status; 57 } 58 59 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc) 60 { 61 uint8_t pdev_count; 62 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 63 wlan_serialization_get_psoc_priv_obj(psoc); 64 65 if (!ser_soc_obj) { 66 serialization_err("invalid ser_soc_obj"); 67 return QDF_STATUS_E_FAILURE; 68 } 69 /* TODO:Get WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS frm service ready */ 70 pdev_count = wlan_psoc_get_pdev_count(psoc); 71 ser_soc_obj->max_active_cmds = WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS + 72 pdev_count; 73 ser_soc_obj->timers = 74 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 75 ser_soc_obj->max_active_cmds); 76 if (NULL == ser_soc_obj->timers) { 77 serialization_alert("Mem alloc failed for ser timers"); 78 return QDF_STATUS_E_NOMEM; 79 } 80 81 return QDF_STATUS_SUCCESS; 82 } 83 84 /** 85 * wlan_serialization_psoc_obj_create_notification() - PSOC obj create callback 86 * @psoc: PSOC object 87 * @arg_list: Variable argument list 88 * 89 * This callback is registered with object manager during initialization and 90 * when obj manager gets its turn to create the object, it would notify each 91 * component with the corresponding callback registered to inform the 92 * completion of the creation of the respective object. 93 * 94 * Return: QDF Status 95 */ 96 static QDF_STATUS wlan_serialization_psoc_obj_create_notification( 97 struct wlan_objmgr_psoc *psoc, void *arg_list) 98 { 99 struct wlan_serialization_psoc_priv_obj *soc_ser_obj; 100 101 soc_ser_obj = 102 qdf_mem_malloc(sizeof(*soc_ser_obj)); 103 if (NULL == soc_ser_obj) { 104 serialization_alert("Mem alloc failed for ser psoc priv obj"); 105 return QDF_STATUS_E_NOMEM; 106 } 107 wlan_objmgr_psoc_component_obj_attach(psoc, 108 WLAN_UMAC_COMP_SERIALIZATION, soc_ser_obj, 109 QDF_STATUS_SUCCESS); 110 serialization_debug("ser psoc obj created"); 111 112 return QDF_STATUS_SUCCESS; 113 } 114 115 /** 116 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 117 * @ser_pdev_obj: Serialization private pdev object 118 * 119 * Return: None 120 */ 121 static void wlan_serialization_destroy_cmd_pool( 122 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 123 { 124 125 qdf_list_node_t *node = NULL; 126 struct wlan_serialization_command_list *cmd_list; 127 128 while (!qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) { 129 qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list, 130 &node); 131 cmd_list = (struct wlan_serialization_command_list *)node; 132 serialization_debug("Node being freed from global pool %pK", 133 cmd_list); 134 qdf_mem_free(cmd_list); 135 136 } 137 qdf_list_destroy(&ser_pdev_obj->global_cmd_pool_list); 138 } 139 140 /** 141 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 142 * @pdev: PDEV Object 143 * @ser_pdev_obj: Serialization private pdev object 144 * 145 * Global command pool of memory is created here. 146 * It is safe to allocate memory individually for each command rather than 147 * requesting for a huge chunk of memory at once. 148 * 149 * The individual command nodes allocated above will keep moving between 150 * the active, pending and global pool lists dynamically, but all the 151 * memory will be freed during driver unload only. 152 * 153 * Return: QDF Status 154 */ 155 static QDF_STATUS 156 wlan_serialization_create_cmd_pool(struct wlan_objmgr_pdev *pdev, 157 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 158 { 159 struct wlan_serialization_command_list *cmd_list_ptr; 160 uint8_t i; 161 162 for (i = 0; i < WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS; i++) { 163 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 164 if (NULL == cmd_list_ptr) { 165 serialization_alert("Mem alloc failed for cmd node"); 166 wlan_serialization_destroy_cmd_pool(ser_pdev_obj); 167 return QDF_STATUS_E_NOMEM; 168 } 169 qdf_list_insert_back( 170 &ser_pdev_obj->global_cmd_pool_list, 171 &cmd_list_ptr->node); 172 cmd_list_ptr->cmd_in_use = 0; 173 serialization_debug("Created node at %pK and inserted to pool", 174 cmd_list_ptr); 175 } 176 177 return QDF_STATUS_SUCCESS; 178 } 179 180 181 /** 182 * wlan_serialization_pdev_obj_create_notification() - PDEV obj create callback 183 * @pdev: PDEV object 184 * @arg_list: Variable argument list 185 * 186 * This callback is registered with object manager during initialization and 187 * when obj manager gets its turn to create the object, it would notify each 188 * component with the corresponding callback registered to inform the 189 * completion of the creation of the respective object. 190 * 191 * Return: QDF Status 192 */ 193 static QDF_STATUS wlan_serialization_pdev_obj_create_notification( 194 struct wlan_objmgr_pdev *pdev, void *arg_list) 195 { 196 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 197 QDF_STATUS status; 198 199 ser_pdev_obj = 200 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 201 if (NULL == ser_pdev_obj) { 202 serialization_alert("Mem alloc failed for ser pdev obj"); 203 return QDF_STATUS_E_NOMEM; 204 } 205 status = wlan_serialization_create_lock(ser_pdev_obj); 206 if (status != QDF_STATUS_SUCCESS) { 207 serialization_err("Failed to create serialization lock"); 208 return status; 209 } 210 qdf_list_create(&ser_pdev_obj->active_list, 211 WLAN_SERIALIZATION_MAX_ACTIVE_CMDS); 212 qdf_list_create(&ser_pdev_obj->pending_list, 213 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 214 qdf_list_create(&ser_pdev_obj->active_scan_list, 215 WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS); 216 qdf_list_create(&ser_pdev_obj->pending_scan_list, 217 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 218 qdf_list_create(&ser_pdev_obj->global_cmd_pool_list, 219 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 220 status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj); 221 if (status != QDF_STATUS_SUCCESS) { 222 serialization_err("ser_pdev_obj failed status %d", status); 223 return status; 224 } 225 status = wlan_objmgr_pdev_component_obj_attach(pdev, 226 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj, 227 QDF_STATUS_SUCCESS); 228 if (status != QDF_STATUS_SUCCESS) { 229 serialization_err("serialization pdev obj attach failed"); 230 return status; 231 } 232 233 return status; 234 } 235 236 /** 237 * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback 238 * @psoc: PSOC object 239 * @arg_list: Variable argument list 240 * 241 * This callback is registered with object manager during initialization and 242 * when obj manager gets its turn to delete the object, it would notify each 243 * component with the corresponding callback registered to inform the 244 * completion of the deletion of the respective object. 245 * 246 * Return: QDF Status 247 */ 248 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification( 249 struct wlan_objmgr_psoc *psoc, void *arg_list) 250 { 251 QDF_STATUS status; 252 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 253 wlan_serialization_get_psoc_priv_obj(psoc); 254 255 if (NULL == ser_soc_obj) { 256 serialization_err("invalid ser_soc_obj"); 257 return QDF_STATUS_E_FAULT; 258 } 259 status = wlan_objmgr_psoc_component_obj_detach(psoc, 260 WLAN_UMAC_COMP_SERIALIZATION, 261 ser_soc_obj); 262 if (status != QDF_STATUS_SUCCESS) 263 serialization_err("ser psoc private obj detach failed"); 264 serialization_debug("ser psoc obj deleted with status %d", status); 265 qdf_mem_free(ser_soc_obj); 266 267 return status; 268 } 269 270 /** 271 * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback 272 * @pdev: PDEV object 273 * @arg_list: Variable argument list 274 * 275 * This callback is registered with object manager during initialization and 276 * when obj manager gets its turn to delete the object, it would notify each 277 * component with the corresponding callback registered to inform the 278 * completion of the deletion of the respective object. 279 * 280 * Return: QDF Status 281 */ 282 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification( 283 struct wlan_objmgr_pdev *pdev, void *arg_list) 284 { 285 QDF_STATUS status; 286 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 287 wlan_serialization_get_pdev_priv_obj(pdev); 288 289 status = wlan_objmgr_pdev_component_obj_detach(pdev, 290 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 291 wlan_serialization_destroy_list(ser_pdev_obj, 292 &ser_pdev_obj->active_list); 293 wlan_serialization_destroy_list(ser_pdev_obj, 294 &ser_pdev_obj->pending_list); 295 wlan_serialization_destroy_list(ser_pdev_obj, 296 &ser_pdev_obj->active_scan_list); 297 wlan_serialization_destroy_list(ser_pdev_obj, 298 &ser_pdev_obj->pending_scan_list); 299 wlan_serialization_destroy_cmd_pool(ser_pdev_obj); 300 serialization_debug("ser pdev obj detached with status %d", status); 301 status = wlan_serialization_destroy_lock(ser_pdev_obj); 302 if (status != QDF_STATUS_SUCCESS) 303 serialization_err("Failed to destroy serialization lock"); 304 qdf_mem_free(ser_pdev_obj); 305 306 return status; 307 } 308 309 /** 310 * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback 311 * @vdev: VDEV object 312 * @arg_list: Variable argument list 313 * 314 * This callback is registered with object manager during initialization and 315 * when obj manager gets its turn to create the object, it would notify each 316 * component with the corresponding callback registered to inform the 317 * completion of the creation of the respective object. 318 * 319 * Return: QDF Status 320 */ 321 static QDF_STATUS wlan_serialization_vdev_obj_create_notification( 322 struct wlan_objmgr_vdev *vdev, void *arg_list) 323 { 324 return QDF_STATUS_SUCCESS; 325 } 326 327 /** 328 * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback 329 * @vdev: VDEV object 330 * @arg_list: Variable argument list 331 * 332 * This callback is registered with object manager during initialization and 333 * when obj manager gets its turn to delete the object, it would notify each 334 * component with the corresponding callback registered to inform the 335 * completion of the deletion of the respective object. 336 * 337 * Return: QDF Status 338 */ 339 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification( 340 struct wlan_objmgr_vdev *vdev, void *arg_list) 341 { 342 uint8_t vdev_id = wlan_vdev_get_id(vdev); 343 344 if (!ser_legacy_cb.serialization_purge_cmd_list) 345 return QDF_STATUS_SUCCESS; 346 347 serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds", 348 vdev_id, vdev); 349 ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev), 350 vdev, false, false, false, false, true); 351 352 return QDF_STATUS_SUCCESS; 353 } 354 355 QDF_STATUS wlan_serialization_init(void) 356 { 357 QDF_STATUS status = QDF_STATUS_SUCCESS; 358 359 status = wlan_objmgr_register_psoc_create_handler( 360 WLAN_UMAC_COMP_SERIALIZATION, 361 wlan_serialization_psoc_obj_create_notification, NULL); 362 if (status != QDF_STATUS_SUCCESS) { 363 serialization_err("Failed to reg soc ser obj create handler"); 364 goto err_psoc_create; 365 } 366 367 status = wlan_objmgr_register_psoc_destroy_handler( 368 WLAN_UMAC_COMP_SERIALIZATION, 369 wlan_serialization_psoc_obj_destroy_notification, NULL); 370 if (status != QDF_STATUS_SUCCESS) { 371 serialization_err("Failed to reg soc ser obj delete handler"); 372 goto err_psoc_delete; 373 } 374 375 status = wlan_objmgr_register_pdev_create_handler( 376 WLAN_UMAC_COMP_SERIALIZATION, 377 wlan_serialization_pdev_obj_create_notification, NULL); 378 if (status != QDF_STATUS_SUCCESS) { 379 serialization_err("Failed to reg pdev ser obj create handler"); 380 goto err_pdev_create; 381 } 382 383 status = wlan_objmgr_register_pdev_destroy_handler( 384 WLAN_UMAC_COMP_SERIALIZATION, 385 wlan_serialization_pdev_obj_destroy_notification, NULL); 386 if (status != QDF_STATUS_SUCCESS) { 387 serialization_err("Failed to reg pdev ser obj delete handler"); 388 goto err_pdev_delete; 389 } 390 391 status = wlan_objmgr_register_vdev_create_handler( 392 WLAN_UMAC_COMP_SERIALIZATION, 393 wlan_serialization_vdev_obj_create_notification, NULL); 394 if (status != QDF_STATUS_SUCCESS) { 395 serialization_err("Failed to reg vdev ser obj create handler"); 396 goto err_vdev_create; 397 } 398 399 status = wlan_objmgr_register_vdev_destroy_handler( 400 WLAN_UMAC_COMP_SERIALIZATION, 401 wlan_serialization_vdev_obj_destroy_notification, NULL); 402 if (status != QDF_STATUS_SUCCESS) { 403 serialization_err("Failed to reg vdev ser obj delete handler"); 404 goto err_vdev_delete; 405 } 406 serialization_debug("serialization handlers registered with obj mgr"); 407 /* 408 * Initialize the structure so all callbacks are registered 409 * initially as NULL. 410 */ 411 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 412 413 return QDF_STATUS_SUCCESS; 414 415 err_vdev_delete: 416 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 417 wlan_serialization_vdev_obj_create_notification, NULL); 418 err_vdev_create: 419 wlan_objmgr_unregister_pdev_destroy_handler( 420 WLAN_UMAC_COMP_SERIALIZATION, 421 wlan_serialization_pdev_obj_destroy_notification, NULL); 422 err_pdev_delete: 423 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 424 wlan_serialization_pdev_obj_create_notification, NULL); 425 err_pdev_create: 426 wlan_objmgr_unregister_psoc_destroy_handler( 427 WLAN_UMAC_COMP_SERIALIZATION, 428 wlan_serialization_psoc_obj_destroy_notification, NULL); 429 err_psoc_delete: 430 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 431 wlan_serialization_psoc_obj_create_notification, NULL); 432 err_psoc_create: 433 return status; 434 435 } 436 437 QDF_STATUS wlan_serialization_deinit(void) 438 { 439 QDF_STATUS status; 440 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 441 442 status = wlan_objmgr_unregister_psoc_create_handler( 443 WLAN_UMAC_COMP_SERIALIZATION, 444 wlan_serialization_psoc_obj_create_notification, 445 NULL); 446 if (status != QDF_STATUS_SUCCESS) { 447 serialization_err("unreg fail for psoc ser obj create notf:%d", 448 status); 449 ret_status = QDF_STATUS_E_FAILURE; 450 } 451 status = wlan_objmgr_unregister_psoc_destroy_handler( 452 WLAN_UMAC_COMP_SERIALIZATION, 453 wlan_serialization_psoc_obj_destroy_notification, 454 NULL); 455 if (status != QDF_STATUS_SUCCESS) { 456 serialization_err("unreg fail for psoc ser obj destroy notf:%d", 457 status); 458 ret_status = QDF_STATUS_E_FAILURE; 459 } 460 461 status = wlan_objmgr_unregister_pdev_create_handler( 462 WLAN_UMAC_COMP_SERIALIZATION, 463 wlan_serialization_pdev_obj_create_notification, 464 NULL); 465 if (status != QDF_STATUS_SUCCESS) { 466 serialization_err("unreg fail for pdev ser obj create notf:%d", 467 status); 468 ret_status = QDF_STATUS_E_FAILURE; 469 } 470 471 status = wlan_objmgr_unregister_pdev_destroy_handler( 472 WLAN_UMAC_COMP_SERIALIZATION, 473 wlan_serialization_pdev_obj_destroy_notification, 474 NULL); 475 if (status != QDF_STATUS_SUCCESS) { 476 serialization_err("unreg fail for pdev ser destroy notf:%d", 477 status); 478 ret_status = QDF_STATUS_E_FAILURE; 479 } 480 481 serialization_alert("deregistered callbacks with obj mgr successfully"); 482 /* 483 * Initialize the structure so all callbacks are registered 484 * initially as NULL. 485 */ 486 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 487 488 return ret_status; 489 } 490 #else /* New serialition code*/ 491 #include <qdf_status.h> 492 #include <qdf_list.h> 493 #include <wlan_objmgr_cmn.h> 494 #include <wlan_objmgr_global_obj.h> 495 #include <wlan_objmgr_psoc_obj.h> 496 #include "wlan_serialization_main_i.h" 497 #include "wlan_serialization_rules_i.h" 498 #include "wlan_serialization_utils_i.h" 499 500 struct serialization_legacy_callback ser_legacy_cb; 501 502 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc) 503 { 504 QDF_STATUS status = QDF_STATUS_E_FAILURE; 505 struct wlan_ser_psoc_obj *ser_soc_obj = 506 wlan_serialization_get_psoc_obj(psoc); 507 508 ser_enter(); 509 510 if (!ser_soc_obj) { 511 ser_err("invalid ser_soc_obj"); 512 goto error; 513 } 514 /* clean up all timers before exiting */ 515 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 516 if (status != QDF_STATUS_SUCCESS) 517 ser_err("ser cleanning up all timer failed"); 518 519 qdf_mem_free(ser_soc_obj->timers); 520 ser_soc_obj->timers = NULL; 521 ser_soc_obj->max_active_cmds = 0; 522 523 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 524 error: 525 ser_exit(); 526 return status; 527 } 528 529 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc) 530 { 531 uint8_t pdev_count; 532 struct wlan_ser_psoc_obj *ser_soc_obj = 533 wlan_serialization_get_psoc_obj(psoc); 534 QDF_STATUS status = QDF_STATUS_E_FAILURE; 535 536 if (!ser_soc_obj) { 537 ser_err("invalid ser_soc_obj"); 538 goto error; 539 } 540 541 pdev_count = wlan_psoc_get_pdev_count(psoc); 542 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 543 (pdev_count * WLAN_SER_MAX_VDEVS); 544 545 ser_soc_obj->timers = 546 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 547 ser_soc_obj->max_active_cmds); 548 if (!ser_soc_obj->timers) { 549 ser_alert("Mem alloc failed for ser timers"); 550 status = QDF_STATUS_E_NOMEM; 551 goto error; 552 } 553 554 wlan_serialization_create_lock(&ser_soc_obj->timer_lock); 555 status = QDF_STATUS_SUCCESS; 556 557 error: 558 ser_exit(); 559 return status; 560 } 561 562 /** 563 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 564 * @psoc: PSOC object 565 * @arg_list: Variable argument list 566 * 567 * This callback is registered with object manager during initialization and 568 * when obj manager gets its turn to create the object, it would notify each 569 * component with the corresponding callback registered to inform the 570 * completion of the creation of the respective object. 571 * 572 * Return: QDF Status 573 */ 574 static QDF_STATUS wlan_serialization_psoc_create_handler( 575 struct wlan_objmgr_psoc *psoc, void *arg_list) 576 { 577 struct wlan_ser_psoc_obj *soc_ser_obj; 578 QDF_STATUS status = QDF_STATUS_E_NOMEM; 579 580 ser_enter(); 581 582 soc_ser_obj = 583 qdf_mem_malloc(sizeof(*soc_ser_obj)); 584 if (!soc_ser_obj) { 585 ser_alert("Mem alloc failed for ser psoc priv obj"); 586 goto error; 587 } 588 wlan_objmgr_psoc_component_obj_attach(psoc, 589 WLAN_UMAC_COMP_SERIALIZATION, 590 soc_ser_obj, 591 QDF_STATUS_SUCCESS); 592 ser_debug("ser psoc obj created"); 593 594 status = QDF_STATUS_SUCCESS; 595 596 error: 597 ser_exit(); 598 return status; 599 } 600 601 /** 602 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 603 * @ser_pdev_obj: Serialization private pdev object 604 * 605 * Return: None 606 */ 607 static void wlan_serialization_destroy_cmd_pool( 608 struct wlan_serialization_pdev_queue *pdev_queue) 609 { 610 qdf_list_node_t *node = NULL; 611 struct wlan_serialization_command_list *cmd_list; 612 613 ser_enter(); 614 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 615 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 616 &node); 617 cmd_list = (struct wlan_serialization_command_list *)node; 618 ser_debug("Node being freed from global pool %pK", 619 cmd_list); 620 qdf_mem_free(cmd_list); 621 } 622 623 qdf_list_destroy(&pdev_queue->cmd_pool_list); 624 625 ser_exit(); 626 } 627 628 /** 629 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 630 * @pdev: PDEV Object 631 * @ser_pdev_obj: Serialization private pdev object 632 * 633 * Global command pool of memory is created here. 634 * It is safe to allocate memory individually for each command rather than 635 * requesting for a huge chunk of memory at once. 636 * 637 * The individual command nodes allocated above will keep moving between 638 * the active, pending and global pool lists dynamically, but all the 639 * memory will be freed during driver unload only. 640 * 641 * Return: QDF Status 642 */ 643 static QDF_STATUS 644 wlan_serialization_create_cmd_pool( 645 struct wlan_serialization_pdev_queue *pdev_queue, 646 uint16_t cmd_pool_size) 647 { 648 struct wlan_serialization_command_list *cmd_list_ptr; 649 uint8_t i; 650 QDF_STATUS status = QDF_STATUS_E_NOMEM; 651 652 ser_enter(); 653 654 for (i = 0; i < cmd_pool_size; i++) { 655 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 656 if (!cmd_list_ptr) { 657 ser_alert("Mem alloc failed for cmd node"); 658 wlan_serialization_destroy_cmd_pool(pdev_queue); 659 goto error; 660 } 661 662 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 663 qdf_list_insert_back( 664 &pdev_queue->cmd_pool_list, 665 &cmd_list_ptr->pdev_node); 666 cmd_list_ptr->cmd_in_use = 0; 667 ser_debug("Created node at %pK and inserted to pool", 668 cmd_list_ptr); 669 } 670 671 status = QDF_STATUS_SUCCESS; 672 673 error: 674 ser_exit(); 675 return status; 676 } 677 678 /** 679 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 680 * @pdev: PDEV object 681 * @arg_list: Variable argument list 682 * 683 * This callback is registered with object manager during initialization and 684 * when obj manager gets its turn to create the object, it would notify each 685 * component with the corresponding callback registered to inform the 686 * completion of the creation of the respective object. 687 * 688 * Return: QDF Status 689 */ 690 static QDF_STATUS wlan_serialization_pdev_create_handler( 691 struct wlan_objmgr_pdev *pdev, void *arg_list) 692 { 693 struct wlan_ser_pdev_obj *ser_pdev_obj; 694 struct wlan_serialization_pdev_queue *pdev_queue; 695 QDF_STATUS status = QDF_STATUS_E_NOMEM; 696 uint8_t index; 697 uint8_t max_active_cmds; 698 uint8_t max_pending_cmds; 699 uint16_t cmd_pool_size; 700 701 ser_enter(); 702 703 ser_pdev_obj = 704 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 705 if (!ser_pdev_obj) { 706 ser_alert("Mem alloc failed for ser pdev obj"); 707 goto error; 708 } 709 710 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 711 pdev_queue = &ser_pdev_obj->pdev_q[index]; 712 713 wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock); 714 715 switch (index) { 716 case SER_PDEV_QUEUE_COMP_SCAN: 717 max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS; 718 max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS; 719 cmd_pool_size = max_active_cmds + max_pending_cmds; 720 break; 721 722 case SER_PDEV_QUEUE_COMP_NON_SCAN: 723 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS; 724 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS; 725 cmd_pool_size = max_active_cmds + max_pending_cmds; 726 break; 727 } 728 qdf_list_create(&pdev_queue->active_list, 729 max_active_cmds); 730 qdf_list_create(&pdev_queue->pending_list, 731 max_pending_cmds); 732 qdf_list_create(&pdev_queue->cmd_pool_list, 733 cmd_pool_size); 734 735 status = wlan_serialization_create_cmd_pool(pdev_queue, 736 cmd_pool_size); 737 if (status != QDF_STATUS_SUCCESS) { 738 ser_err("ser_pdev_obj failed status %d", status); 739 goto error; 740 } 741 742 pdev_queue->vdev_active_cmd_bitmap = 0; 743 pdev_queue->blocking_cmd_active = 0; 744 pdev_queue->blocking_cmd_waiting = 0; 745 } 746 747 status = wlan_objmgr_pdev_component_obj_attach( 748 pdev, WLAN_UMAC_COMP_SERIALIZATION, 749 ser_pdev_obj, QDF_STATUS_SUCCESS); 750 751 if (status != QDF_STATUS_SUCCESS) 752 ser_err("serialization pdev obj attach failed"); 753 754 error: 755 ser_exit(); 756 return status; 757 } 758 759 /** 760 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 761 * @psoc: PSOC object 762 * @arg_list: Variable argument list 763 * 764 * This callback is registered with object manager during initialization and 765 * when obj manager gets its turn to delete the object, it would notify each 766 * component with the corresponding callback registered to inform the 767 * completion of the deletion of the respective object. 768 * 769 * Return: QDF Status 770 */ 771 static QDF_STATUS 772 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 773 void *arg_list) 774 { 775 QDF_STATUS status = QDF_STATUS_E_FAULT; 776 struct wlan_ser_psoc_obj *ser_soc_obj = 777 wlan_serialization_get_psoc_obj(psoc); 778 779 ser_enter(); 780 781 if (!ser_soc_obj) { 782 ser_err("invalid ser_soc_obj"); 783 goto error; 784 } 785 status = wlan_objmgr_psoc_component_obj_detach( 786 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 787 if (status != QDF_STATUS_SUCCESS) 788 ser_err("ser psoc private obj detach failed"); 789 790 ser_debug("ser psoc obj deleted with status %d", status); 791 qdf_mem_free(ser_soc_obj); 792 793 error: 794 ser_exit(); 795 return status; 796 } 797 798 /** 799 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 800 * @pdev: PDEV object 801 * @arg_list: Variable argument list 802 * 803 * This callback is registered with object manager during initialization and 804 * when obj manager gets its turn to delete the object, it would notify each 805 * component with the corresponding callback registered to inform the 806 * completion of the deletion of the respective object. 807 * 808 * Return: QDF Status 809 */ 810 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 811 struct wlan_objmgr_pdev *pdev, void *arg_list) 812 { 813 QDF_STATUS status; 814 struct wlan_serialization_pdev_queue *pdev_queue; 815 struct wlan_ser_pdev_obj *ser_pdev_obj = 816 wlan_serialization_get_pdev_obj(pdev); 817 uint8_t index; 818 819 ser_enter(); 820 821 status = wlan_objmgr_pdev_component_obj_detach( 822 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 823 824 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 825 pdev_queue = &ser_pdev_obj->pdev_q[index]; 826 827 wlan_serialization_destroy_pdev_list(pdev_queue); 828 wlan_serialization_destroy_cmd_pool(pdev_queue); 829 830 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 831 } 832 833 qdf_mem_free(ser_pdev_obj); 834 835 ser_exit(); 836 return status; 837 } 838 839 /** 840 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 841 * @vdev: VDEV object 842 * @arg_list: Variable argument list 843 * 844 * This callback is registered with object manager during initialization and 845 * when obj manager gets its turn to create the object, it would notify each 846 * component with the corresponding callback registered to inform the 847 * completion of the creation of the respective object. 848 * 849 * Return: QDF Status 850 */ 851 static QDF_STATUS 852 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 853 void *arg_list) 854 { 855 struct wlan_ser_vdev_obj *ser_vdev_obj; 856 struct wlan_serialization_vdev_queue *vdev_q; 857 QDF_STATUS status = QDF_STATUS_E_NOMEM; 858 uint8_t index; 859 uint8_t max_active_cmds; 860 uint8_t max_pending_cmds; 861 862 ser_enter(); 863 864 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 865 if (!ser_vdev_obj) { 866 ser_alert("Mem alloc failed for ser vdev obj"); 867 goto error; 868 } 869 870 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 871 vdev_q = &ser_vdev_obj->vdev_q[index]; 872 873 switch (index) { 874 case SER_VDEV_QUEUE_COMP_NON_SCAN: 875 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 876 WLAN_SER_MAX_VDEVS; 877 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS / 878 WLAN_SER_MAX_VDEVS; 879 break; 880 } 881 882 qdf_list_create(&vdev_q->active_list, 883 max_active_cmds); 884 qdf_list_create(&vdev_q->pending_list, 885 max_pending_cmds); 886 } 887 888 status = wlan_objmgr_vdev_component_obj_attach( 889 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 890 QDF_STATUS_SUCCESS); 891 892 if (status != QDF_STATUS_SUCCESS) 893 ser_err("serialization vdev obj attach failed"); 894 895 error: 896 ser_exit(); 897 return status; 898 } 899 900 /** 901 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 902 * @vdev: VDEV object 903 * @arg_list: Variable argument list 904 * 905 * This callback is registered with object manager during initialization and 906 * when obj manager gets its turn to delete the object, it would notify each 907 * component with the corresponding callback registered to inform the 908 * completion of the deletion of the respective object. 909 * 910 * Return: QDF Status 911 */ 912 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 913 struct wlan_objmgr_vdev *vdev, void *arg_list) 914 { 915 QDF_STATUS status = QDF_STATUS_SUCCESS; 916 struct wlan_serialization_vdev_queue *vdev_q; 917 struct wlan_ser_vdev_obj *ser_vdev_obj = 918 wlan_serialization_get_vdev_obj(vdev); 919 uint8_t vdev_id = wlan_vdev_get_id(vdev); 920 uint8_t index; 921 922 ser_enter(); 923 924 status = wlan_objmgr_vdev_component_obj_detach( 925 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 926 927 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 928 vdev_q = &ser_vdev_obj->vdev_q[index]; 929 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 930 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 931 } 932 933 qdf_mem_free(ser_vdev_obj); 934 if (!ser_legacy_cb.serialization_purge_cmd_list) 935 goto error; 936 937 ser_debug("for vdev_id[%d] vdev[%pK] flush all cmds", 938 vdev_id, vdev); 939 ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev), 940 vdev, false, false, 941 false, false, true); 942 943 error: 944 ser_exit(); 945 return status; 946 } 947 948 QDF_STATUS wlan_serialization_init(void) 949 { 950 QDF_STATUS status = QDF_STATUS_SUCCESS; 951 952 ser_enter(); 953 954 status = wlan_objmgr_register_psoc_create_handler( 955 WLAN_UMAC_COMP_SERIALIZATION, 956 wlan_serialization_psoc_create_handler, NULL); 957 if (status != QDF_STATUS_SUCCESS) { 958 ser_err("Failed to reg soc ser obj create handler"); 959 goto err_psoc_create; 960 } 961 962 status = wlan_objmgr_register_psoc_destroy_handler( 963 WLAN_UMAC_COMP_SERIALIZATION, 964 wlan_serialization_psoc_destroy_handler, NULL); 965 if (status != QDF_STATUS_SUCCESS) { 966 ser_err("Failed to reg soc ser obj delete handler"); 967 goto err_psoc_delete; 968 } 969 970 status = wlan_objmgr_register_pdev_create_handler( 971 WLAN_UMAC_COMP_SERIALIZATION, 972 wlan_serialization_pdev_create_handler, NULL); 973 if (status != QDF_STATUS_SUCCESS) { 974 ser_err("Failed to reg pdev ser obj create handler"); 975 goto err_pdev_create; 976 } 977 978 status = wlan_objmgr_register_pdev_destroy_handler( 979 WLAN_UMAC_COMP_SERIALIZATION, 980 wlan_serialization_pdev_destroy_handler, NULL); 981 if (status != QDF_STATUS_SUCCESS) { 982 ser_err("Failed to reg pdev ser obj delete handler"); 983 goto err_pdev_delete; 984 } 985 986 status = wlan_objmgr_register_vdev_create_handler( 987 WLAN_UMAC_COMP_SERIALIZATION, 988 wlan_serialization_vdev_create_handler, NULL); 989 if (status != QDF_STATUS_SUCCESS) { 990 ser_err("Failed to reg vdev ser obj create handler"); 991 goto err_vdev_create; 992 } 993 994 status = wlan_objmgr_register_vdev_destroy_handler( 995 WLAN_UMAC_COMP_SERIALIZATION, 996 wlan_serialization_vdev_destroy_handler, NULL); 997 if (status != QDF_STATUS_SUCCESS) { 998 ser_err("Failed to reg vdev ser obj delete handler"); 999 goto err_vdev_delete; 1000 } 1001 ser_debug("serialization handlers registered with obj mgr"); 1002 /* 1003 * Initialize the structure so all callbacks are registered 1004 * initially as NULL. 1005 */ 1006 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 1007 1008 status = QDF_STATUS_SUCCESS; 1009 goto exit; 1010 1011 err_vdev_delete: 1012 wlan_objmgr_unregister_vdev_create_handler( 1013 WLAN_UMAC_COMP_SERIALIZATION, 1014 wlan_serialization_vdev_create_handler, 1015 NULL); 1016 err_vdev_create: 1017 wlan_objmgr_unregister_pdev_destroy_handler( 1018 WLAN_UMAC_COMP_SERIALIZATION, 1019 wlan_serialization_pdev_destroy_handler, 1020 NULL); 1021 err_pdev_delete: 1022 wlan_objmgr_unregister_pdev_create_handler( 1023 WLAN_UMAC_COMP_SERIALIZATION, 1024 wlan_serialization_pdev_create_handler, 1025 NULL); 1026 err_pdev_create: 1027 wlan_objmgr_unregister_psoc_destroy_handler( 1028 WLAN_UMAC_COMP_SERIALIZATION, 1029 wlan_serialization_psoc_destroy_handler, 1030 NULL); 1031 err_psoc_delete: 1032 wlan_objmgr_unregister_psoc_create_handler( 1033 WLAN_UMAC_COMP_SERIALIZATION, 1034 wlan_serialization_psoc_create_handler, 1035 NULL); 1036 err_psoc_create: 1037 exit: 1038 ser_exit(); 1039 return status; 1040 } 1041 1042 QDF_STATUS wlan_serialization_deinit(void) 1043 { 1044 QDF_STATUS status; 1045 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 1046 1047 ser_enter(); 1048 1049 status = wlan_objmgr_unregister_psoc_create_handler( 1050 WLAN_UMAC_COMP_SERIALIZATION, 1051 wlan_serialization_psoc_create_handler, 1052 NULL); 1053 1054 if (status != QDF_STATUS_SUCCESS) { 1055 ser_err("unreg fail for psoc ser obj create notf:%d", status); 1056 ret_status = QDF_STATUS_E_FAILURE; 1057 } 1058 status = wlan_objmgr_unregister_psoc_destroy_handler( 1059 WLAN_UMAC_COMP_SERIALIZATION, 1060 wlan_serialization_psoc_destroy_handler, 1061 NULL); 1062 1063 if (status != QDF_STATUS_SUCCESS) { 1064 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 1065 ret_status = QDF_STATUS_E_FAILURE; 1066 } 1067 1068 status = wlan_objmgr_unregister_pdev_create_handler( 1069 WLAN_UMAC_COMP_SERIALIZATION, 1070 wlan_serialization_pdev_create_handler, 1071 NULL); 1072 if (status != QDF_STATUS_SUCCESS) { 1073 ser_err("unreg fail for pdev ser obj create notf:%d", status); 1074 ret_status = QDF_STATUS_E_FAILURE; 1075 } 1076 1077 status = wlan_objmgr_unregister_pdev_destroy_handler( 1078 WLAN_UMAC_COMP_SERIALIZATION, 1079 wlan_serialization_pdev_destroy_handler, 1080 NULL); 1081 1082 if (status != QDF_STATUS_SUCCESS) { 1083 ser_err("unreg fail for pdev ser destroy notf:%d", status); 1084 ret_status = QDF_STATUS_E_FAILURE; 1085 } 1086 1087 ser_alert("deregistered callbacks with obj mgr successfully"); 1088 /* 1089 * Initialize the structure so all callbacks are registered 1090 * initially as NULL. 1091 */ 1092 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 1093 1094 ser_exit(); 1095 return ret_status; 1096 } 1097 #endif 1098