1 /* 2 * Copyright (c) 2017-2019 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 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 QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc) 36 { 37 QDF_STATUS status = QDF_STATUS_E_FAILURE; 38 struct wlan_ser_psoc_obj *ser_soc_obj = 39 wlan_serialization_get_psoc_obj(psoc); 40 41 if (!ser_soc_obj) { 42 ser_err("invalid ser_soc_obj"); 43 goto error; 44 } 45 /* clean up all timers before exiting */ 46 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 47 if (status != QDF_STATUS_SUCCESS) 48 ser_err("ser cleanning up all timer failed"); 49 50 qdf_mem_free(ser_soc_obj->timers); 51 ser_soc_obj->timers = NULL; 52 ser_soc_obj->max_active_cmds = 0; 53 54 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 55 error: 56 return status; 57 } 58 59 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) 60 { 61 uint8_t pdev_count; 62 struct wlan_ser_psoc_obj *ser_soc_obj = 63 wlan_serialization_get_psoc_obj(psoc); 64 QDF_STATUS status = QDF_STATUS_E_FAILURE; 65 66 if (!ser_soc_obj) { 67 ser_err("invalid ser_soc_obj"); 68 goto error; 69 } 70 71 pdev_count = wlan_psoc_get_pdev_count(psoc); 72 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 73 (pdev_count * WLAN_SER_MAX_VDEVS); 74 75 ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds); 76 77 ser_soc_obj->timers = 78 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 79 ser_soc_obj->max_active_cmds); 80 if (!ser_soc_obj->timers) { 81 ser_alert("Mem alloc failed for ser timers"); 82 status = QDF_STATUS_E_NOMEM; 83 goto error; 84 } 85 86 wlan_serialization_create_lock(&ser_soc_obj->timer_lock); 87 status = QDF_STATUS_SUCCESS; 88 89 error: 90 return status; 91 } 92 93 /** 94 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 95 * @psoc: PSOC object 96 * @arg_list: Variable argument list 97 * 98 * This callback is registered with object manager during initialization and 99 * when obj manager gets its turn to create the object, it would notify each 100 * component with the corresponding callback registered to inform the 101 * completion of the creation of the respective object. 102 * 103 * Return: QDF Status 104 */ 105 static QDF_STATUS wlan_serialization_psoc_create_handler( 106 struct wlan_objmgr_psoc *psoc, void *arg_list) 107 { 108 struct wlan_ser_psoc_obj *soc_ser_obj; 109 QDF_STATUS status = QDF_STATUS_E_NOMEM; 110 111 soc_ser_obj = 112 qdf_mem_malloc(sizeof(*soc_ser_obj)); 113 if (!soc_ser_obj) { 114 ser_alert("Mem alloc failed for ser psoc priv obj"); 115 goto error; 116 } 117 status = wlan_objmgr_psoc_component_obj_attach( 118 psoc, 119 WLAN_UMAC_COMP_SERIALIZATION, 120 soc_ser_obj, 121 QDF_STATUS_SUCCESS); 122 if (QDF_IS_STATUS_ERROR(status)) { 123 qdf_mem_free(soc_ser_obj); 124 ser_err("Obj attach failed"); 125 goto error; 126 } 127 ser_debug("ser psoc obj created"); 128 status = QDF_STATUS_SUCCESS; 129 130 error: 131 return status; 132 } 133 134 /** 135 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 136 * @ser_pdev_obj: Serialization private pdev object 137 * 138 * Return: None 139 */ 140 static void wlan_serialization_destroy_cmd_pool( 141 struct wlan_serialization_pdev_queue *pdev_queue) 142 { 143 qdf_list_node_t *node = NULL; 144 struct wlan_serialization_command_list *cmd_list; 145 146 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 147 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 148 &node); 149 cmd_list = (struct wlan_serialization_command_list *)node; 150 ser_debug("Node being freed from global pool %pK", 151 cmd_list); 152 qdf_mem_free(cmd_list); 153 } 154 155 qdf_list_destroy(&pdev_queue->cmd_pool_list); 156 157 } 158 159 /** 160 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 161 * @pdev: PDEV Object 162 * @ser_pdev_obj: Serialization private pdev object 163 * 164 * Global command pool of memory is created here. 165 * It is safe to allocate memory individually for each command rather than 166 * requesting for a huge chunk of memory at once. 167 * 168 * The individual command nodes allocated above will keep moving between 169 * the active, pending and global pool lists dynamically, but all the 170 * memory will be freed during driver unload only. 171 * 172 * Return: QDF Status 173 */ 174 static QDF_STATUS 175 wlan_serialization_create_cmd_pool( 176 struct wlan_serialization_pdev_queue *pdev_queue, 177 uint16_t cmd_pool_size) 178 { 179 struct wlan_serialization_command_list *cmd_list_ptr; 180 uint8_t i; 181 QDF_STATUS status = QDF_STATUS_E_NOMEM; 182 183 qdf_list_create(&pdev_queue->cmd_pool_list, cmd_pool_size); 184 185 for (i = 0; i < cmd_pool_size; i++) { 186 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 187 if (!cmd_list_ptr) { 188 ser_alert("Mem alloc failed for cmd node"); 189 wlan_serialization_destroy_cmd_pool(pdev_queue); 190 goto error; 191 } 192 193 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 194 qdf_list_insert_back( 195 &pdev_queue->cmd_pool_list, 196 &cmd_list_ptr->pdev_node); 197 cmd_list_ptr->cmd_in_use = 0; 198 ser_debug("Created node at %pK and inserted to pool", 199 cmd_list_ptr); 200 } 201 202 status = QDF_STATUS_SUCCESS; 203 204 error: 205 return status; 206 } 207 208 /** 209 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 210 * @pdev: PDEV object 211 * @arg_list: Variable argument list 212 * 213 * This callback is registered with object manager during initialization and 214 * when obj manager gets its turn to create the object, it would notify each 215 * component with the corresponding callback registered to inform the 216 * completion of the creation of the respective object. 217 * 218 * Return: QDF Status 219 */ 220 static QDF_STATUS wlan_serialization_pdev_create_handler( 221 struct wlan_objmgr_pdev *pdev, void *arg_list) 222 { 223 struct wlan_ser_pdev_obj *ser_pdev_obj; 224 struct wlan_serialization_pdev_queue *pdev_queue; 225 QDF_STATUS status = QDF_STATUS_E_NOMEM; 226 uint8_t index; 227 uint8_t free_index; 228 uint8_t max_active_cmds; 229 uint8_t max_pending_cmds; 230 uint16_t cmd_pool_size; 231 232 ser_pdev_obj = 233 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 234 if (!ser_pdev_obj) { 235 ser_alert("Mem alloc failed for ser pdev obj"); 236 goto error; 237 } 238 239 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 240 pdev_queue = &ser_pdev_obj->pdev_q[index]; 241 242 wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock); 243 244 switch (index) { 245 case SER_PDEV_QUEUE_COMP_SCAN: 246 max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS; 247 max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS; 248 cmd_pool_size = max_active_cmds + max_pending_cmds; 249 break; 250 251 case SER_PDEV_QUEUE_COMP_NON_SCAN: 252 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS; 253 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS; 254 cmd_pool_size = max_active_cmds + max_pending_cmds; 255 break; 256 } 257 qdf_list_create(&pdev_queue->active_list, 258 max_active_cmds); 259 qdf_list_create(&pdev_queue->pending_list, 260 max_pending_cmds); 261 262 status = wlan_serialization_create_cmd_pool(pdev_queue, 263 cmd_pool_size); 264 if (status != QDF_STATUS_SUCCESS) { 265 ser_err("Create cmd pool failed, status %d", status); 266 goto error_free; 267 } 268 269 pdev_queue->vdev_active_cmd_bitmap = 0; 270 pdev_queue->blocking_cmd_active = 0; 271 pdev_queue->blocking_cmd_waiting = 0; 272 } 273 274 status = wlan_objmgr_pdev_component_obj_attach( 275 pdev, WLAN_UMAC_COMP_SERIALIZATION, 276 ser_pdev_obj, QDF_STATUS_SUCCESS); 277 278 if (status != QDF_STATUS_SUCCESS) { 279 ser_err("Pdev obj attach failed, status %d", status); 280 goto error_free; 281 } 282 283 return QDF_STATUS_SUCCESS; 284 285 error_free: 286 for (free_index = 0; free_index <= index; free_index++) { 287 pdev_queue = &ser_pdev_obj->pdev_q[free_index]; 288 289 wlan_serialization_destroy_cmd_pool(pdev_queue); 290 qdf_list_destroy(&pdev_queue->pending_list); 291 qdf_list_destroy(&pdev_queue->active_list); 292 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 293 } 294 error: 295 return status; 296 } 297 298 /** 299 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 300 * @psoc: PSOC object 301 * @arg_list: Variable argument list 302 * 303 * This callback is registered with object manager during initialization and 304 * when obj manager gets its turn to delete the object, it would notify each 305 * component with the corresponding callback registered to inform the 306 * completion of the deletion of the respective object. 307 * 308 * Return: QDF Status 309 */ 310 static QDF_STATUS 311 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 312 void *arg_list) 313 { 314 QDF_STATUS status = QDF_STATUS_E_FAULT; 315 struct wlan_ser_psoc_obj *ser_soc_obj = 316 wlan_serialization_get_psoc_obj(psoc); 317 318 if (!ser_soc_obj) { 319 ser_err("invalid ser_soc_obj"); 320 goto error; 321 } 322 status = wlan_objmgr_psoc_component_obj_detach( 323 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 324 if (status != QDF_STATUS_SUCCESS) 325 ser_err("ser psoc private obj detach failed"); 326 327 ser_debug("ser psoc obj deleted with status %d", status); 328 qdf_mem_free(ser_soc_obj); 329 330 error: 331 return status; 332 } 333 334 /** 335 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 336 * @pdev: PDEV object 337 * @arg_list: Variable argument list 338 * 339 * This callback is registered with object manager during initialization and 340 * when obj manager gets its turn to delete the object, it would notify each 341 * component with the corresponding callback registered to inform the 342 * completion of the deletion of the respective object. 343 * 344 * Return: QDF Status 345 */ 346 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 347 struct wlan_objmgr_pdev *pdev, void *arg_list) 348 { 349 QDF_STATUS status; 350 struct wlan_serialization_pdev_queue *pdev_queue; 351 struct wlan_ser_pdev_obj *ser_pdev_obj = 352 wlan_serialization_get_pdev_obj(pdev); 353 uint8_t index; 354 355 if (!ser_pdev_obj) { 356 ser_err("ser_pdev_obj NULL"); 357 return QDF_STATUS_E_INVAL; 358 } 359 status = wlan_objmgr_pdev_component_obj_detach( 360 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 361 362 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 363 pdev_queue = &ser_pdev_obj->pdev_q[index]; 364 365 wlan_serialization_destroy_pdev_list(pdev_queue); 366 wlan_serialization_destroy_cmd_pool(pdev_queue); 367 368 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 369 } 370 qdf_mem_free(ser_pdev_obj); 371 372 return status; 373 } 374 375 /** 376 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 377 * @vdev: VDEV object 378 * @arg_list: Variable argument list 379 * 380 * This callback is registered with object manager during initialization and 381 * when obj manager gets its turn to create the object, it would notify each 382 * component with the corresponding callback registered to inform the 383 * completion of the creation of the respective object. 384 * 385 * Return: QDF Status 386 */ 387 static QDF_STATUS 388 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 389 void *arg_list) 390 { 391 struct wlan_ser_vdev_obj *ser_vdev_obj; 392 struct wlan_serialization_vdev_queue *vdev_q; 393 QDF_STATUS status = QDF_STATUS_E_NOMEM; 394 uint8_t index; 395 uint8_t max_active_cmds; 396 uint8_t max_pending_cmds; 397 398 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 399 if (!ser_vdev_obj) { 400 ser_alert("Mem alloc failed for ser vdev obj"); 401 goto error; 402 } 403 404 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 405 vdev_q = &ser_vdev_obj->vdev_q[index]; 406 407 switch (index) { 408 case SER_VDEV_QUEUE_COMP_NON_SCAN: 409 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 410 WLAN_SER_MAX_VDEVS; 411 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS / 412 WLAN_SER_MAX_VDEVS; 413 break; 414 } 415 416 qdf_list_create(&vdev_q->active_list, 417 max_active_cmds); 418 qdf_list_create(&vdev_q->pending_list, 419 max_pending_cmds); 420 } 421 422 status = wlan_objmgr_vdev_component_obj_attach( 423 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 424 QDF_STATUS_SUCCESS); 425 426 if (status != QDF_STATUS_SUCCESS) { 427 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 428 vdev_q = &ser_vdev_obj->vdev_q[index]; 429 qdf_list_destroy(&vdev_q->pending_list); 430 qdf_list_destroy(&vdev_q->active_list); 431 } 432 qdf_mem_free(ser_vdev_obj); 433 ser_err("serialization vdev obj attach failed"); 434 } 435 error: 436 return status; 437 } 438 439 /** 440 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 441 * @vdev: VDEV object 442 * @arg_list: Variable argument list 443 * 444 * This callback is registered with object manager during initialization and 445 * when obj manager gets its turn to delete the object, it would notify each 446 * component with the corresponding callback registered to inform the 447 * completion of the deletion of the respective object. 448 * 449 * Return: QDF Status 450 */ 451 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 452 struct wlan_objmgr_vdev *vdev, void *arg_list) 453 { 454 QDF_STATUS status = QDF_STATUS_SUCCESS; 455 struct wlan_serialization_vdev_queue *vdev_q; 456 struct wlan_ser_vdev_obj *ser_vdev_obj = 457 wlan_serialization_get_vdev_obj(vdev); 458 uint8_t index; 459 460 if (!ser_vdev_obj) { 461 ser_err("ser_vdev_obj NULL"); 462 return QDF_STATUS_E_INVAL; 463 } 464 465 status = wlan_objmgr_vdev_component_obj_detach( 466 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 467 468 /*Clean up serialization timers if any for this vdev*/ 469 wlan_serialization_cleanup_vdev_timers(vdev); 470 471 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 472 vdev_q = &ser_vdev_obj->vdev_q[index]; 473 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 474 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 475 } 476 477 qdf_mem_free(ser_vdev_obj); 478 479 return status; 480 } 481 482 QDF_STATUS wlan_serialization_init(void) 483 { 484 QDF_STATUS status = QDF_STATUS_SUCCESS; 485 486 status = wlan_objmgr_register_psoc_create_handler( 487 WLAN_UMAC_COMP_SERIALIZATION, 488 wlan_serialization_psoc_create_handler, NULL); 489 if (status != QDF_STATUS_SUCCESS) { 490 ser_err("Failed to reg soc ser obj create handler"); 491 goto err_psoc_create; 492 } 493 494 status = wlan_objmgr_register_psoc_destroy_handler( 495 WLAN_UMAC_COMP_SERIALIZATION, 496 wlan_serialization_psoc_destroy_handler, NULL); 497 if (status != QDF_STATUS_SUCCESS) { 498 ser_err("Failed to reg soc ser obj delete handler"); 499 goto err_psoc_delete; 500 } 501 502 status = wlan_objmgr_register_pdev_create_handler( 503 WLAN_UMAC_COMP_SERIALIZATION, 504 wlan_serialization_pdev_create_handler, NULL); 505 if (status != QDF_STATUS_SUCCESS) { 506 ser_err("Failed to reg pdev ser obj create handler"); 507 goto err_pdev_create; 508 } 509 510 status = wlan_objmgr_register_pdev_destroy_handler( 511 WLAN_UMAC_COMP_SERIALIZATION, 512 wlan_serialization_pdev_destroy_handler, NULL); 513 if (status != QDF_STATUS_SUCCESS) { 514 ser_err("Failed to reg pdev ser obj delete handler"); 515 goto err_pdev_delete; 516 } 517 518 status = wlan_objmgr_register_vdev_create_handler( 519 WLAN_UMAC_COMP_SERIALIZATION, 520 wlan_serialization_vdev_create_handler, NULL); 521 if (status != QDF_STATUS_SUCCESS) { 522 ser_err("Failed to reg vdev ser obj create handler"); 523 goto err_vdev_create; 524 } 525 526 status = wlan_objmgr_register_vdev_destroy_handler( 527 WLAN_UMAC_COMP_SERIALIZATION, 528 wlan_serialization_vdev_destroy_handler, NULL); 529 if (status != QDF_STATUS_SUCCESS) { 530 ser_err("Failed to reg vdev ser obj delete handler"); 531 goto err_vdev_delete; 532 } 533 534 status = QDF_STATUS_SUCCESS; 535 goto exit; 536 537 err_vdev_delete: 538 wlan_objmgr_unregister_vdev_create_handler( 539 WLAN_UMAC_COMP_SERIALIZATION, 540 wlan_serialization_vdev_create_handler, 541 NULL); 542 err_vdev_create: 543 wlan_objmgr_unregister_pdev_destroy_handler( 544 WLAN_UMAC_COMP_SERIALIZATION, 545 wlan_serialization_pdev_destroy_handler, 546 NULL); 547 err_pdev_delete: 548 wlan_objmgr_unregister_pdev_create_handler( 549 WLAN_UMAC_COMP_SERIALIZATION, 550 wlan_serialization_pdev_create_handler, 551 NULL); 552 err_pdev_create: 553 wlan_objmgr_unregister_psoc_destroy_handler( 554 WLAN_UMAC_COMP_SERIALIZATION, 555 wlan_serialization_psoc_destroy_handler, 556 NULL); 557 err_psoc_delete: 558 wlan_objmgr_unregister_psoc_create_handler( 559 WLAN_UMAC_COMP_SERIALIZATION, 560 wlan_serialization_psoc_create_handler, 561 NULL); 562 err_psoc_create: 563 exit: 564 return status; 565 } 566 567 QDF_STATUS wlan_serialization_deinit(void) 568 { 569 QDF_STATUS status; 570 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 571 572 status = wlan_objmgr_unregister_psoc_create_handler( 573 WLAN_UMAC_COMP_SERIALIZATION, 574 wlan_serialization_psoc_create_handler, 575 NULL); 576 577 if (status != QDF_STATUS_SUCCESS) { 578 ser_err("unreg fail for psoc ser obj create notf:%d", status); 579 ret_status = QDF_STATUS_E_FAILURE; 580 } 581 status = wlan_objmgr_unregister_psoc_destroy_handler( 582 WLAN_UMAC_COMP_SERIALIZATION, 583 wlan_serialization_psoc_destroy_handler, 584 NULL); 585 586 if (status != QDF_STATUS_SUCCESS) { 587 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 588 ret_status = QDF_STATUS_E_FAILURE; 589 } 590 591 status = wlan_objmgr_unregister_pdev_create_handler( 592 WLAN_UMAC_COMP_SERIALIZATION, 593 wlan_serialization_pdev_create_handler, 594 NULL); 595 if (status != QDF_STATUS_SUCCESS) { 596 ser_err("unreg fail for pdev ser obj create notf:%d", status); 597 ret_status = QDF_STATUS_E_FAILURE; 598 } 599 600 status = wlan_objmgr_unregister_pdev_destroy_handler( 601 WLAN_UMAC_COMP_SERIALIZATION, 602 wlan_serialization_pdev_destroy_handler, 603 NULL); 604 605 if (status != QDF_STATUS_SUCCESS) { 606 ser_err("unreg fail for pdev ser destroy notf:%d", status); 607 ret_status = QDF_STATUS_E_FAILURE; 608 } 609 610 ser_alert("deregistered callbacks with obj mgr successfully"); 611 612 return ret_status; 613 } 614