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 #include <qdf_status.h> 26 #include <qdf_list.h> 27 #include <wlan_objmgr_cmn.h> 28 #include <wlan_objmgr_global_obj.h> 29 #include <wlan_objmgr_psoc_obj.h> 30 #include "wlan_serialization_main_i.h" 31 #include "wlan_serialization_rules_i.h" 32 #include "wlan_serialization_utils_i.h" 33 34 QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc) 35 { 36 QDF_STATUS status = QDF_STATUS_E_FAILURE; 37 struct wlan_ser_psoc_obj *ser_soc_obj = 38 wlan_serialization_get_psoc_obj(psoc); 39 40 if (!ser_soc_obj) { 41 ser_err("invalid ser_soc_obj"); 42 goto error; 43 } 44 45 /* 46 * purge all serialization command if there are any pending to make 47 * sure memory and vdev ref are freed. 48 */ 49 wlan_serialization_purge_all_cmd(psoc); 50 /* clean up all timers before exiting */ 51 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 52 if (status != QDF_STATUS_SUCCESS) 53 ser_err("ser cleanning up all timer failed"); 54 55 qdf_mem_free(ser_soc_obj->timers); 56 ser_soc_obj->timers = NULL; 57 ser_soc_obj->max_active_cmds = 0; 58 59 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 60 error: 61 return status; 62 } 63 64 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) 65 { 66 uint8_t pdev_count; 67 struct wlan_ser_psoc_obj *ser_soc_obj = 68 wlan_serialization_get_psoc_obj(psoc); 69 QDF_STATUS status = QDF_STATUS_E_FAILURE; 70 71 if (!ser_soc_obj) { 72 ser_err("invalid ser_soc_obj"); 73 goto error; 74 } 75 76 pdev_count = wlan_psoc_get_pdev_count(psoc); 77 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 78 (pdev_count * WLAN_SER_MAX_VDEVS); 79 80 ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds); 81 82 ser_soc_obj->timers = 83 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 84 ser_soc_obj->max_active_cmds); 85 if (!ser_soc_obj->timers) { 86 status = QDF_STATUS_E_NOMEM; 87 goto error; 88 } 89 90 wlan_serialization_create_lock(&ser_soc_obj->timer_lock); 91 status = QDF_STATUS_SUCCESS; 92 93 error: 94 return status; 95 } 96 97 /** 98 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 99 * @psoc: PSOC object 100 * @arg_list: Variable argument list 101 * 102 * This callback is registered with object manager during initialization and 103 * when obj manager gets its turn to create the object, it would notify each 104 * component with the corresponding callback registered to inform the 105 * completion of the creation of the respective object. 106 * 107 * Return: QDF Status 108 */ 109 static QDF_STATUS wlan_serialization_psoc_create_handler( 110 struct wlan_objmgr_psoc *psoc, void *arg_list) 111 { 112 struct wlan_ser_psoc_obj *soc_ser_obj; 113 QDF_STATUS status = QDF_STATUS_E_NOMEM; 114 115 soc_ser_obj = 116 qdf_mem_malloc(sizeof(*soc_ser_obj)); 117 if (!soc_ser_obj) 118 goto error; 119 120 status = wlan_objmgr_psoc_component_obj_attach( 121 psoc, 122 WLAN_UMAC_COMP_SERIALIZATION, 123 soc_ser_obj, 124 QDF_STATUS_SUCCESS); 125 if (QDF_IS_STATUS_ERROR(status)) { 126 qdf_mem_free(soc_ser_obj); 127 ser_err("Obj attach failed"); 128 goto error; 129 } 130 ser_debug("ser psoc obj created"); 131 status = QDF_STATUS_SUCCESS; 132 133 error: 134 return status; 135 } 136 137 /** 138 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 139 * @ser_pdev_obj: Serialization private pdev object 140 * 141 * Return: None 142 */ 143 static void wlan_serialization_destroy_cmd_pool( 144 struct wlan_serialization_pdev_queue *pdev_queue) 145 { 146 qdf_list_node_t *node = NULL; 147 struct wlan_serialization_command_list *cmd_list; 148 149 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 150 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 151 &node); 152 cmd_list = (struct wlan_serialization_command_list *)node; 153 ser_debug("Node being freed from global pool %pK", 154 cmd_list); 155 qdf_mem_free(cmd_list); 156 } 157 158 qdf_list_destroy(&pdev_queue->cmd_pool_list); 159 160 } 161 162 /** 163 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 164 * @pdev: PDEV Object 165 * @ser_pdev_obj: Serialization private pdev object 166 * 167 * Global command pool of memory is created here. 168 * It is safe to allocate memory individually for each command rather than 169 * requesting for a huge chunk of memory at once. 170 * 171 * The individual command nodes allocated above will keep moving between 172 * the active, pending and global pool lists dynamically, but all the 173 * memory will be freed during driver unload only. 174 * 175 * Return: QDF Status 176 */ 177 static QDF_STATUS 178 wlan_serialization_create_cmd_pool( 179 struct wlan_serialization_pdev_queue *pdev_queue, 180 uint16_t cmd_pool_size) 181 { 182 struct wlan_serialization_command_list *cmd_list_ptr; 183 uint8_t i; 184 QDF_STATUS status = QDF_STATUS_E_NOMEM; 185 186 qdf_list_create(&pdev_queue->cmd_pool_list, cmd_pool_size); 187 188 for (i = 0; i < cmd_pool_size; i++) { 189 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 190 if (!cmd_list_ptr) { 191 wlan_serialization_destroy_cmd_pool(pdev_queue); 192 goto error; 193 } 194 195 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 196 qdf_list_insert_back( 197 &pdev_queue->cmd_pool_list, 198 &cmd_list_ptr->pdev_node); 199 cmd_list_ptr->cmd_in_use = 0; 200 ser_debug("Created node at %pK and inserted to pool", 201 cmd_list_ptr); 202 } 203 204 status = QDF_STATUS_SUCCESS; 205 206 error: 207 return status; 208 } 209 210 /** 211 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 212 * @pdev: PDEV object 213 * @arg_list: Variable argument list 214 * 215 * This callback is registered with object manager during initialization and 216 * when obj manager gets its turn to create the object, it would notify each 217 * component with the corresponding callback registered to inform the 218 * completion of the creation of the respective object. 219 * 220 * Return: QDF Status 221 */ 222 static QDF_STATUS wlan_serialization_pdev_create_handler( 223 struct wlan_objmgr_pdev *pdev, void *arg_list) 224 { 225 struct wlan_ser_pdev_obj *ser_pdev_obj; 226 struct wlan_serialization_pdev_queue *pdev_queue; 227 QDF_STATUS status = QDF_STATUS_E_NOMEM; 228 uint8_t index; 229 uint8_t free_index; 230 uint8_t max_active_cmds; 231 uint8_t max_pending_cmds; 232 uint16_t cmd_pool_size; 233 234 ser_pdev_obj = 235 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 236 if (!ser_pdev_obj) 237 goto error; 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 goto error; 401 402 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 403 vdev_q = &ser_vdev_obj->vdev_q[index]; 404 405 switch (index) { 406 case SER_VDEV_QUEUE_COMP_NON_SCAN: 407 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 408 WLAN_SER_MAX_VDEVS; 409 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS / 410 WLAN_SER_MAX_VDEVS; 411 break; 412 } 413 414 qdf_list_create(&vdev_q->active_list, 415 max_active_cmds); 416 qdf_list_create(&vdev_q->pending_list, 417 max_pending_cmds); 418 } 419 420 status = wlan_objmgr_vdev_component_obj_attach( 421 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 422 QDF_STATUS_SUCCESS); 423 424 if (status != QDF_STATUS_SUCCESS) { 425 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 426 vdev_q = &ser_vdev_obj->vdev_q[index]; 427 qdf_list_destroy(&vdev_q->pending_list); 428 qdf_list_destroy(&vdev_q->active_list); 429 } 430 qdf_mem_free(ser_vdev_obj); 431 ser_err("serialization vdev obj attach failed"); 432 } 433 error: 434 return status; 435 } 436 437 /** 438 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 439 * @vdev: VDEV object 440 * @arg_list: Variable argument list 441 * 442 * This callback is registered with object manager during initialization and 443 * when obj manager gets its turn to delete the object, it would notify each 444 * component with the corresponding callback registered to inform the 445 * completion of the deletion of the respective object. 446 * 447 * Return: QDF Status 448 */ 449 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 450 struct wlan_objmgr_vdev *vdev, void *arg_list) 451 { 452 QDF_STATUS status = QDF_STATUS_SUCCESS; 453 struct wlan_serialization_vdev_queue *vdev_q; 454 struct wlan_ser_vdev_obj *ser_vdev_obj = 455 wlan_serialization_get_vdev_obj(vdev); 456 uint8_t index; 457 458 if (!ser_vdev_obj) { 459 ser_err("ser_vdev_obj NULL"); 460 return QDF_STATUS_E_INVAL; 461 } 462 463 status = wlan_objmgr_vdev_component_obj_detach( 464 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 465 466 /*Clean up serialization timers if any for this vdev*/ 467 wlan_serialization_cleanup_vdev_timers(vdev); 468 469 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 470 vdev_q = &ser_vdev_obj->vdev_q[index]; 471 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 472 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 473 } 474 475 qdf_mem_free(ser_vdev_obj); 476 477 return status; 478 } 479 480 QDF_STATUS wlan_serialization_init(void) 481 { 482 QDF_STATUS status = QDF_STATUS_SUCCESS; 483 484 status = wlan_objmgr_register_psoc_create_handler( 485 WLAN_UMAC_COMP_SERIALIZATION, 486 wlan_serialization_psoc_create_handler, NULL); 487 if (status != QDF_STATUS_SUCCESS) { 488 ser_err("Failed to reg soc ser obj create handler"); 489 goto err_psoc_create; 490 } 491 492 status = wlan_objmgr_register_psoc_destroy_handler( 493 WLAN_UMAC_COMP_SERIALIZATION, 494 wlan_serialization_psoc_destroy_handler, NULL); 495 if (status != QDF_STATUS_SUCCESS) { 496 ser_err("Failed to reg soc ser obj delete handler"); 497 goto err_psoc_delete; 498 } 499 500 status = wlan_objmgr_register_pdev_create_handler( 501 WLAN_UMAC_COMP_SERIALIZATION, 502 wlan_serialization_pdev_create_handler, NULL); 503 if (status != QDF_STATUS_SUCCESS) { 504 ser_err("Failed to reg pdev ser obj create handler"); 505 goto err_pdev_create; 506 } 507 508 status = wlan_objmgr_register_pdev_destroy_handler( 509 WLAN_UMAC_COMP_SERIALIZATION, 510 wlan_serialization_pdev_destroy_handler, NULL); 511 if (status != QDF_STATUS_SUCCESS) { 512 ser_err("Failed to reg pdev ser obj delete handler"); 513 goto err_pdev_delete; 514 } 515 516 status = wlan_objmgr_register_vdev_create_handler( 517 WLAN_UMAC_COMP_SERIALIZATION, 518 wlan_serialization_vdev_create_handler, NULL); 519 if (status != QDF_STATUS_SUCCESS) { 520 ser_err("Failed to reg vdev ser obj create handler"); 521 goto err_vdev_create; 522 } 523 524 status = wlan_objmgr_register_vdev_destroy_handler( 525 WLAN_UMAC_COMP_SERIALIZATION, 526 wlan_serialization_vdev_destroy_handler, NULL); 527 if (status != QDF_STATUS_SUCCESS) { 528 ser_err("Failed to reg vdev ser obj delete handler"); 529 goto err_vdev_delete; 530 } 531 532 status = QDF_STATUS_SUCCESS; 533 goto exit; 534 535 err_vdev_delete: 536 wlan_objmgr_unregister_vdev_create_handler( 537 WLAN_UMAC_COMP_SERIALIZATION, 538 wlan_serialization_vdev_create_handler, 539 NULL); 540 err_vdev_create: 541 wlan_objmgr_unregister_pdev_destroy_handler( 542 WLAN_UMAC_COMP_SERIALIZATION, 543 wlan_serialization_pdev_destroy_handler, 544 NULL); 545 err_pdev_delete: 546 wlan_objmgr_unregister_pdev_create_handler( 547 WLAN_UMAC_COMP_SERIALIZATION, 548 wlan_serialization_pdev_create_handler, 549 NULL); 550 err_pdev_create: 551 wlan_objmgr_unregister_psoc_destroy_handler( 552 WLAN_UMAC_COMP_SERIALIZATION, 553 wlan_serialization_psoc_destroy_handler, 554 NULL); 555 err_psoc_delete: 556 wlan_objmgr_unregister_psoc_create_handler( 557 WLAN_UMAC_COMP_SERIALIZATION, 558 wlan_serialization_psoc_create_handler, 559 NULL); 560 err_psoc_create: 561 exit: 562 return status; 563 } 564 565 QDF_STATUS wlan_serialization_deinit(void) 566 { 567 QDF_STATUS status; 568 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 569 570 status = wlan_objmgr_unregister_psoc_create_handler( 571 WLAN_UMAC_COMP_SERIALIZATION, 572 wlan_serialization_psoc_create_handler, 573 NULL); 574 575 if (status != QDF_STATUS_SUCCESS) { 576 ser_err("unreg fail for psoc ser obj create notf:%d", status); 577 ret_status = QDF_STATUS_E_FAILURE; 578 } 579 status = wlan_objmgr_unregister_psoc_destroy_handler( 580 WLAN_UMAC_COMP_SERIALIZATION, 581 wlan_serialization_psoc_destroy_handler, 582 NULL); 583 584 if (status != QDF_STATUS_SUCCESS) { 585 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 586 ret_status = QDF_STATUS_E_FAILURE; 587 } 588 589 status = wlan_objmgr_unregister_pdev_create_handler( 590 WLAN_UMAC_COMP_SERIALIZATION, 591 wlan_serialization_pdev_create_handler, 592 NULL); 593 if (status != QDF_STATUS_SUCCESS) { 594 ser_err("unreg fail for pdev ser obj create notf:%d", status); 595 ret_status = QDF_STATUS_E_FAILURE; 596 } 597 598 status = wlan_objmgr_unregister_pdev_destroy_handler( 599 WLAN_UMAC_COMP_SERIALIZATION, 600 wlan_serialization_pdev_destroy_handler, 601 NULL); 602 603 if (status != QDF_STATUS_SUCCESS) { 604 ser_err("unreg fail for pdev ser destroy notf:%d", status); 605 ret_status = QDF_STATUS_E_FAILURE; 606 } 607 608 ser_alert("deregistered callbacks with obj mgr successfully"); 609 610 return ret_status; 611 } 612