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 error: 524 ser_exit(); 525 return status; 526 } 527 528 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc) 529 { 530 uint8_t pdev_count; 531 struct wlan_ser_psoc_obj *ser_soc_obj = 532 wlan_serialization_get_psoc_obj(psoc); 533 QDF_STATUS status = QDF_STATUS_E_FAILURE; 534 535 if (!ser_soc_obj) { 536 ser_err("invalid ser_soc_obj"); 537 goto error; 538 } 539 540 pdev_count = wlan_psoc_get_pdev_count(psoc); 541 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 542 (pdev_count * WLAN_SER_MAX_VDEVS); 543 544 ser_soc_obj->timers = 545 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 546 ser_soc_obj->max_active_cmds); 547 if (!ser_soc_obj->timers) { 548 ser_alert("Mem alloc failed for ser timers"); 549 status = QDF_STATUS_E_NOMEM; 550 goto error; 551 } 552 553 status = QDF_STATUS_SUCCESS; 554 555 error: 556 ser_exit(); 557 return status; 558 } 559 560 /** 561 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 562 * @psoc: PSOC object 563 * @arg_list: Variable argument list 564 * 565 * This callback is registered with object manager during initialization and 566 * when obj manager gets its turn to create the object, it would notify each 567 * component with the corresponding callback registered to inform the 568 * completion of the creation of the respective object. 569 * 570 * Return: QDF Status 571 */ 572 static QDF_STATUS wlan_serialization_psoc_create_handler( 573 struct wlan_objmgr_psoc *psoc, void *arg_list) 574 { 575 struct wlan_ser_psoc_obj *soc_ser_obj; 576 QDF_STATUS status = QDF_STATUS_E_NOMEM; 577 578 ser_enter(); 579 580 soc_ser_obj = 581 qdf_mem_malloc(sizeof(*soc_ser_obj)); 582 if (!soc_ser_obj) { 583 ser_alert("Mem alloc failed for ser psoc priv obj"); 584 goto error; 585 } 586 wlan_objmgr_psoc_component_obj_attach(psoc, 587 WLAN_UMAC_COMP_SERIALIZATION, 588 soc_ser_obj, 589 QDF_STATUS_SUCCESS); 590 ser_debug("ser psoc obj created"); 591 592 status = QDF_STATUS_SUCCESS; 593 594 error: 595 ser_exit(); 596 return status; 597 } 598 599 /** 600 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 601 * @ser_pdev_obj: Serialization private pdev object 602 * 603 * Return: None 604 */ 605 static void wlan_serialization_destroy_cmd_pool( 606 struct wlan_serialization_pdev_queue *pdev_queue) 607 { 608 qdf_list_node_t *node = NULL; 609 struct wlan_serialization_command_list *cmd_list; 610 611 ser_enter(); 612 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 613 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 614 &node); 615 cmd_list = (struct wlan_serialization_command_list *)node; 616 ser_debug("Node being freed from global pool %pK", 617 cmd_list); 618 qdf_mem_free(cmd_list); 619 } 620 621 qdf_list_destroy(&pdev_queue->cmd_pool_list); 622 623 ser_exit(); 624 } 625 626 /** 627 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 628 * @pdev: PDEV Object 629 * @ser_pdev_obj: Serialization private pdev object 630 * 631 * Global command pool of memory is created here. 632 * It is safe to allocate memory individually for each command rather than 633 * requesting for a huge chunk of memory at once. 634 * 635 * The individual command nodes allocated above will keep moving between 636 * the active, pending and global pool lists dynamically, but all the 637 * memory will be freed during driver unload only. 638 * 639 * Return: QDF Status 640 */ 641 static QDF_STATUS 642 wlan_serialization_create_cmd_pool( 643 struct wlan_serialization_pdev_queue *pdev_queue, 644 uint16_t cmd_pool_size) 645 { 646 struct wlan_serialization_command_list *cmd_list_ptr; 647 uint8_t i; 648 QDF_STATUS status = QDF_STATUS_E_NOMEM; 649 650 ser_enter(); 651 652 for (i = 0; i < cmd_pool_size; i++) { 653 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 654 if (!cmd_list_ptr) { 655 ser_alert("Mem alloc failed for cmd node"); 656 wlan_serialization_destroy_cmd_pool(pdev_queue); 657 goto error; 658 } 659 660 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 661 qdf_list_insert_back( 662 &pdev_queue->cmd_pool_list, 663 &cmd_list_ptr->pdev_node); 664 cmd_list_ptr->cmd_in_use = 0; 665 ser_debug("Created node at %pK and inserted to pool", 666 cmd_list_ptr); 667 } 668 669 status = QDF_STATUS_SUCCESS; 670 671 error: 672 ser_exit(); 673 return status; 674 } 675 676 /** 677 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 678 * @pdev: PDEV object 679 * @arg_list: Variable argument list 680 * 681 * This callback is registered with object manager during initialization and 682 * when obj manager gets its turn to create the object, it would notify each 683 * component with the corresponding callback registered to inform the 684 * completion of the creation of the respective object. 685 * 686 * Return: QDF Status 687 */ 688 static QDF_STATUS wlan_serialization_pdev_create_handler( 689 struct wlan_objmgr_pdev *pdev, void *arg_list) 690 { 691 struct wlan_ser_pdev_obj *ser_pdev_obj; 692 struct wlan_serialization_pdev_queue *pdev_queue; 693 QDF_STATUS status = QDF_STATUS_E_NOMEM; 694 uint8_t index; 695 uint8_t max_active_cmds; 696 uint8_t max_pending_cmds; 697 uint16_t cmd_pool_size; 698 699 ser_enter(); 700 701 ser_pdev_obj = 702 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 703 if (!ser_pdev_obj) { 704 ser_alert("Mem alloc failed for ser pdev obj"); 705 goto error; 706 } 707 708 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 709 pdev_queue = &ser_pdev_obj->pdev_q[index]; 710 711 qdf_spinlock_create(&pdev_queue->pdev_queue_lock); 712 713 switch (index) { 714 case SER_PDEV_QUEUE_COMP_SCAN: 715 max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS; 716 max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS; 717 cmd_pool_size = max_active_cmds + max_pending_cmds; 718 break; 719 720 case SER_PDEV_QUEUE_COMP_NON_SCAN: 721 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS; 722 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS; 723 cmd_pool_size = max_active_cmds + max_pending_cmds; 724 break; 725 } 726 qdf_list_create(&pdev_queue->active_list, 727 max_active_cmds); 728 qdf_list_create(&pdev_queue->pending_list, 729 max_pending_cmds); 730 qdf_list_create(&pdev_queue->cmd_pool_list, 731 cmd_pool_size); 732 733 status = wlan_serialization_create_cmd_pool(pdev_queue, 734 cmd_pool_size); 735 if (status != QDF_STATUS_SUCCESS) { 736 ser_err("ser_pdev_obj failed status %d", status); 737 goto error; 738 } 739 740 pdev_queue->vdev_active_cmd_bitmap = 0; 741 pdev_queue->blocking_cmd_active = 0; 742 pdev_queue->blocking_cmd_waiting = 0; 743 } 744 745 status = wlan_objmgr_pdev_component_obj_attach( 746 pdev, WLAN_UMAC_COMP_SERIALIZATION, 747 ser_pdev_obj, QDF_STATUS_SUCCESS); 748 749 if (status != QDF_STATUS_SUCCESS) 750 ser_err("serialization pdev obj attach failed"); 751 752 error: 753 ser_exit(); 754 return status; 755 } 756 757 /** 758 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 759 * @psoc: PSOC object 760 * @arg_list: Variable argument list 761 * 762 * This callback is registered with object manager during initialization and 763 * when obj manager gets its turn to delete the object, it would notify each 764 * component with the corresponding callback registered to inform the 765 * completion of the deletion of the respective object. 766 * 767 * Return: QDF Status 768 */ 769 static QDF_STATUS 770 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 771 void *arg_list) 772 { 773 QDF_STATUS status = QDF_STATUS_E_FAULT; 774 struct wlan_ser_psoc_obj *ser_soc_obj = 775 wlan_serialization_get_psoc_obj(psoc); 776 777 ser_enter(); 778 779 if (!ser_soc_obj) { 780 ser_err("invalid ser_soc_obj"); 781 goto error; 782 } 783 status = wlan_objmgr_psoc_component_obj_detach( 784 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 785 if (status != QDF_STATUS_SUCCESS) 786 ser_err("ser psoc private obj detach failed"); 787 788 ser_debug("ser psoc obj deleted with status %d", status); 789 qdf_mem_free(ser_soc_obj); 790 791 error: 792 ser_exit(); 793 return status; 794 } 795 796 /** 797 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 798 * @pdev: PDEV object 799 * @arg_list: Variable argument list 800 * 801 * This callback is registered with object manager during initialization and 802 * when obj manager gets its turn to delete the object, it would notify each 803 * component with the corresponding callback registered to inform the 804 * completion of the deletion of the respective object. 805 * 806 * Return: QDF Status 807 */ 808 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 809 struct wlan_objmgr_pdev *pdev, void *arg_list) 810 { 811 QDF_STATUS status; 812 struct wlan_serialization_pdev_queue *pdev_queue; 813 struct wlan_ser_pdev_obj *ser_pdev_obj = 814 wlan_serialization_get_pdev_obj(pdev); 815 uint8_t index; 816 817 ser_enter(); 818 819 status = wlan_objmgr_pdev_component_obj_detach( 820 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 821 822 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 823 pdev_queue = &ser_pdev_obj->pdev_q[index]; 824 825 wlan_serialization_destroy_pdev_list(pdev_queue); 826 wlan_serialization_destroy_cmd_pool(pdev_queue); 827 828 qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock); 829 } 830 831 qdf_mem_free(ser_pdev_obj); 832 833 ser_exit(); 834 return status; 835 } 836 837 /** 838 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 839 * @vdev: VDEV object 840 * @arg_list: Variable argument list 841 * 842 * This callback is registered with object manager during initialization and 843 * when obj manager gets its turn to create the object, it would notify each 844 * component with the corresponding callback registered to inform the 845 * completion of the creation of the respective object. 846 * 847 * Return: QDF Status 848 */ 849 static QDF_STATUS 850 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 851 void *arg_list) 852 { 853 struct wlan_ser_vdev_obj *ser_vdev_obj; 854 struct wlan_serialization_vdev_queue *vdev_q; 855 QDF_STATUS status = QDF_STATUS_E_NOMEM; 856 uint8_t index; 857 uint8_t max_active_cmds; 858 uint8_t max_pending_cmds; 859 860 ser_enter(); 861 862 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 863 if (!ser_vdev_obj) { 864 ser_alert("Mem alloc failed for ser vdev obj"); 865 goto error; 866 } 867 868 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 869 vdev_q = &ser_vdev_obj->vdev_q[index]; 870 871 switch (index) { 872 case SER_VDEV_QUEUE_COMP_NON_SCAN: 873 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 874 WLAN_SER_MAX_VDEVS; 875 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS / 876 WLAN_SER_MAX_VDEVS; 877 break; 878 } 879 880 qdf_list_create(&vdev_q->active_list, 881 max_active_cmds); 882 qdf_list_create(&vdev_q->pending_list, 883 max_pending_cmds); 884 } 885 886 status = wlan_objmgr_vdev_component_obj_attach( 887 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 888 QDF_STATUS_SUCCESS); 889 890 if (status != QDF_STATUS_SUCCESS) 891 ser_err("serialization vdev obj attach failed"); 892 893 error: 894 ser_exit(); 895 return status; 896 } 897 898 /** 899 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 900 * @vdev: VDEV object 901 * @arg_list: Variable argument list 902 * 903 * This callback is registered with object manager during initialization and 904 * when obj manager gets its turn to delete the object, it would notify each 905 * component with the corresponding callback registered to inform the 906 * completion of the deletion of the respective object. 907 * 908 * Return: QDF Status 909 */ 910 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 911 struct wlan_objmgr_vdev *vdev, void *arg_list) 912 { 913 QDF_STATUS status = QDF_STATUS_SUCCESS; 914 struct wlan_serialization_vdev_queue *vdev_q; 915 struct wlan_ser_vdev_obj *ser_vdev_obj = 916 wlan_serialization_get_vdev_obj(vdev); 917 uint8_t vdev_id = wlan_vdev_get_id(vdev); 918 uint8_t index; 919 920 ser_enter(); 921 922 status = wlan_objmgr_vdev_component_obj_detach( 923 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 924 925 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 926 vdev_q = &ser_vdev_obj->vdev_q[index]; 927 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 928 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 929 } 930 931 qdf_mem_free(ser_vdev_obj); 932 if (!ser_legacy_cb.serialization_purge_cmd_list) 933 goto error; 934 935 ser_debug("for vdev_id[%d] vdev[%pK] flush all cmds", 936 vdev_id, vdev); 937 ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev), 938 vdev, false, false, 939 false, false, true); 940 941 error: 942 ser_exit(); 943 return status; 944 } 945 946 QDF_STATUS wlan_serialization_init(void) 947 { 948 QDF_STATUS status = QDF_STATUS_SUCCESS; 949 950 ser_enter(); 951 952 status = wlan_objmgr_register_psoc_create_handler( 953 WLAN_UMAC_COMP_SERIALIZATION, 954 wlan_serialization_psoc_create_handler, NULL); 955 if (status != QDF_STATUS_SUCCESS) { 956 ser_err("Failed to reg soc ser obj create handler"); 957 goto err_psoc_create; 958 } 959 960 status = wlan_objmgr_register_psoc_destroy_handler( 961 WLAN_UMAC_COMP_SERIALIZATION, 962 wlan_serialization_psoc_destroy_handler, NULL); 963 if (status != QDF_STATUS_SUCCESS) { 964 ser_err("Failed to reg soc ser obj delete handler"); 965 goto err_psoc_delete; 966 } 967 968 status = wlan_objmgr_register_pdev_create_handler( 969 WLAN_UMAC_COMP_SERIALIZATION, 970 wlan_serialization_pdev_create_handler, NULL); 971 if (status != QDF_STATUS_SUCCESS) { 972 ser_err("Failed to reg pdev ser obj create handler"); 973 goto err_pdev_create; 974 } 975 976 status = wlan_objmgr_register_pdev_destroy_handler( 977 WLAN_UMAC_COMP_SERIALIZATION, 978 wlan_serialization_pdev_destroy_handler, NULL); 979 if (status != QDF_STATUS_SUCCESS) { 980 ser_err("Failed to reg pdev ser obj delete handler"); 981 goto err_pdev_delete; 982 } 983 984 status = wlan_objmgr_register_vdev_create_handler( 985 WLAN_UMAC_COMP_SERIALIZATION, 986 wlan_serialization_vdev_create_handler, NULL); 987 if (status != QDF_STATUS_SUCCESS) { 988 ser_err("Failed to reg vdev ser obj create handler"); 989 goto err_vdev_create; 990 } 991 992 status = wlan_objmgr_register_vdev_destroy_handler( 993 WLAN_UMAC_COMP_SERIALIZATION, 994 wlan_serialization_vdev_destroy_handler, NULL); 995 if (status != QDF_STATUS_SUCCESS) { 996 ser_err("Failed to reg vdev ser obj delete handler"); 997 goto err_vdev_delete; 998 } 999 ser_debug("serialization handlers registered with obj mgr"); 1000 /* 1001 * Initialize the structure so all callbacks are registered 1002 * initially as NULL. 1003 */ 1004 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 1005 1006 status = QDF_STATUS_SUCCESS; 1007 goto exit; 1008 1009 err_vdev_delete: 1010 wlan_objmgr_unregister_vdev_create_handler( 1011 WLAN_UMAC_COMP_SERIALIZATION, 1012 wlan_serialization_vdev_create_handler, 1013 NULL); 1014 err_vdev_create: 1015 wlan_objmgr_unregister_pdev_destroy_handler( 1016 WLAN_UMAC_COMP_SERIALIZATION, 1017 wlan_serialization_pdev_destroy_handler, 1018 NULL); 1019 err_pdev_delete: 1020 wlan_objmgr_unregister_pdev_create_handler( 1021 WLAN_UMAC_COMP_SERIALIZATION, 1022 wlan_serialization_pdev_create_handler, 1023 NULL); 1024 err_pdev_create: 1025 wlan_objmgr_unregister_psoc_destroy_handler( 1026 WLAN_UMAC_COMP_SERIALIZATION, 1027 wlan_serialization_psoc_destroy_handler, 1028 NULL); 1029 err_psoc_delete: 1030 wlan_objmgr_unregister_psoc_create_handler( 1031 WLAN_UMAC_COMP_SERIALIZATION, 1032 wlan_serialization_psoc_create_handler, 1033 NULL); 1034 err_psoc_create: 1035 exit: 1036 ser_exit(); 1037 return status; 1038 } 1039 1040 QDF_STATUS wlan_serialization_deinit(void) 1041 { 1042 QDF_STATUS status; 1043 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 1044 1045 ser_enter(); 1046 1047 status = wlan_objmgr_unregister_psoc_create_handler( 1048 WLAN_UMAC_COMP_SERIALIZATION, 1049 wlan_serialization_psoc_create_handler, 1050 NULL); 1051 1052 if (status != QDF_STATUS_SUCCESS) { 1053 ser_err("unreg fail for psoc ser obj create notf:%d", status); 1054 ret_status = QDF_STATUS_E_FAILURE; 1055 } 1056 status = wlan_objmgr_unregister_psoc_destroy_handler( 1057 WLAN_UMAC_COMP_SERIALIZATION, 1058 wlan_serialization_psoc_destroy_handler, 1059 NULL); 1060 1061 if (status != QDF_STATUS_SUCCESS) { 1062 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 1063 ret_status = QDF_STATUS_E_FAILURE; 1064 } 1065 1066 status = wlan_objmgr_unregister_pdev_create_handler( 1067 WLAN_UMAC_COMP_SERIALIZATION, 1068 wlan_serialization_pdev_create_handler, 1069 NULL); 1070 if (status != QDF_STATUS_SUCCESS) { 1071 ser_err("unreg fail for pdev ser obj create notf:%d", status); 1072 ret_status = QDF_STATUS_E_FAILURE; 1073 } 1074 1075 status = wlan_objmgr_unregister_pdev_destroy_handler( 1076 WLAN_UMAC_COMP_SERIALIZATION, 1077 wlan_serialization_pdev_destroy_handler, 1078 NULL); 1079 1080 if (status != QDF_STATUS_SUCCESS) { 1081 ser_err("unreg fail for pdev ser destroy notf:%d", status); 1082 ret_status = QDF_STATUS_E_FAILURE; 1083 } 1084 1085 ser_alert("deregistered callbacks with obj mgr successfully"); 1086 /* 1087 * Initialize the structure so all callbacks are registered 1088 * initially as NULL. 1089 */ 1090 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 1091 1092 ser_exit(); 1093 return ret_status; 1094 } 1095 #endif 1096