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 #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 struct serialization_legacy_callback ser_legacy_cb; 35 36 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc) 37 { 38 QDF_STATUS status; 39 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 40 wlan_serialization_get_psoc_priv_obj(psoc); 41 42 if (!ser_soc_obj) { 43 serialization_err("invalid ser_soc_obj"); 44 return QDF_STATUS_E_FAILURE; 45 } 46 /* clean up all timers before exiting */ 47 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 48 if (status != QDF_STATUS_SUCCESS) 49 serialization_err("ser cleanning up all timer failed"); 50 51 qdf_mem_free(ser_soc_obj->timers); 52 ser_soc_obj->timers = NULL; 53 ser_soc_obj->max_active_cmds = 0; 54 55 return status; 56 } 57 58 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc) 59 { 60 uint8_t pdev_count; 61 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 62 wlan_serialization_get_psoc_priv_obj(psoc); 63 64 if (!ser_soc_obj) { 65 serialization_err("invalid ser_soc_obj"); 66 return QDF_STATUS_E_FAILURE; 67 } 68 /* TODO:Get WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS frm service ready */ 69 pdev_count = wlan_psoc_get_pdev_count(psoc); 70 ser_soc_obj->max_active_cmds = WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS + 71 pdev_count; 72 ser_soc_obj->timers = 73 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 74 ser_soc_obj->max_active_cmds); 75 if (NULL == ser_soc_obj->timers) { 76 serialization_alert("Mem alloc failed for ser timers"); 77 return QDF_STATUS_E_NOMEM; 78 } 79 80 return QDF_STATUS_SUCCESS; 81 } 82 83 /** 84 * wlan_serialization_psoc_obj_create_notification() - PSOC obj create callback 85 * @psoc: PSOC object 86 * @arg_list: Variable argument list 87 * 88 * This callback is registered with object manager during initialization and 89 * when obj manager gets its turn to create the object, it would notify each 90 * component with the corresponding callback registered to inform the 91 * completion of the creation of the respective object. 92 * 93 * Return: QDF Status 94 */ 95 static QDF_STATUS wlan_serialization_psoc_obj_create_notification( 96 struct wlan_objmgr_psoc *psoc, void *arg_list) 97 { 98 struct wlan_serialization_psoc_priv_obj *soc_ser_obj; 99 100 soc_ser_obj = 101 qdf_mem_malloc(sizeof(*soc_ser_obj)); 102 if (NULL == soc_ser_obj) { 103 serialization_alert("Mem alloc failed for ser psoc priv obj"); 104 return QDF_STATUS_E_NOMEM; 105 } 106 wlan_objmgr_psoc_component_obj_attach(psoc, 107 WLAN_UMAC_COMP_SERIALIZATION, soc_ser_obj, 108 QDF_STATUS_SUCCESS); 109 serialization_debug("ser psoc obj created"); 110 111 return QDF_STATUS_SUCCESS; 112 } 113 114 /** 115 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 116 * @ser_pdev_obj: Serialization private pdev object 117 * 118 * Return: None 119 */ 120 static void wlan_serialization_destroy_cmd_pool( 121 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 122 { 123 124 qdf_list_node_t *node = NULL; 125 struct wlan_serialization_command_list *cmd_list; 126 127 while (!qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) { 128 qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list, 129 &node); 130 cmd_list = (struct wlan_serialization_command_list *)node; 131 serialization_debug("Node being freed from global pool %pK", 132 cmd_list); 133 qdf_mem_free(cmd_list); 134 135 } 136 qdf_list_destroy(&ser_pdev_obj->global_cmd_pool_list); 137 } 138 139 /** 140 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 141 * @pdev: PDEV Object 142 * @ser_pdev_obj: Serialization private pdev object 143 * 144 * Global command pool of memory is created here. 145 * It is safe to allocate memory individually for each command rather than 146 * requesting for a huge chunk of memory at once. 147 * 148 * The individual command nodes allocated above will keep moving between 149 * the active, pending and global pool lists dynamically, but all the 150 * memory will be freed during driver unload only. 151 * 152 * Return: QDF Status 153 */ 154 static QDF_STATUS 155 wlan_serialization_create_cmd_pool(struct wlan_objmgr_pdev *pdev, 156 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 157 { 158 struct wlan_serialization_command_list *cmd_list_ptr; 159 uint8_t i; 160 161 for (i = 0; i < WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS; i++) { 162 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 163 if (NULL == cmd_list_ptr) { 164 serialization_alert("Mem alloc failed for cmd node"); 165 wlan_serialization_destroy_cmd_pool(ser_pdev_obj); 166 return QDF_STATUS_E_NOMEM; 167 } 168 qdf_list_insert_back( 169 &ser_pdev_obj->global_cmd_pool_list, 170 &cmd_list_ptr->node); 171 cmd_list_ptr->cmd_in_use = 0; 172 serialization_debug("Created node at %pK and inserted to pool", 173 cmd_list_ptr); 174 } 175 176 return QDF_STATUS_SUCCESS; 177 } 178 179 180 /** 181 * wlan_serialization_pdev_obj_create_notification() - PDEV obj create callback 182 * @pdev: PDEV object 183 * @arg_list: Variable argument list 184 * 185 * This callback is registered with object manager during initialization and 186 * when obj manager gets its turn to create the object, it would notify each 187 * component with the corresponding callback registered to inform the 188 * completion of the creation of the respective object. 189 * 190 * Return: QDF Status 191 */ 192 static QDF_STATUS wlan_serialization_pdev_obj_create_notification( 193 struct wlan_objmgr_pdev *pdev, void *arg_list) 194 { 195 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 196 QDF_STATUS status; 197 198 ser_pdev_obj = 199 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 200 if (NULL == ser_pdev_obj) { 201 serialization_alert("Mem alloc failed for ser pdev obj"); 202 return QDF_STATUS_E_NOMEM; 203 } 204 status = wlan_serialization_create_lock(ser_pdev_obj); 205 if (status != QDF_STATUS_SUCCESS) { 206 serialization_err("Failed to create serialization lock"); 207 return status; 208 } 209 qdf_list_create(&ser_pdev_obj->active_list, 210 WLAN_SERIALIZATION_MAX_ACTIVE_CMDS); 211 qdf_list_create(&ser_pdev_obj->pending_list, 212 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 213 qdf_list_create(&ser_pdev_obj->active_scan_list, 214 WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS); 215 qdf_list_create(&ser_pdev_obj->pending_scan_list, 216 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 217 qdf_list_create(&ser_pdev_obj->global_cmd_pool_list, 218 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 219 status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj); 220 if (status != QDF_STATUS_SUCCESS) { 221 serialization_err("ser_pdev_obj failed status %d", status); 222 return status; 223 } 224 status = wlan_objmgr_pdev_component_obj_attach(pdev, 225 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj, 226 QDF_STATUS_SUCCESS); 227 if (status != QDF_STATUS_SUCCESS) { 228 serialization_err("serialization pdev obj attach failed"); 229 return status; 230 } 231 232 return status; 233 } 234 235 /** 236 * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback 237 * @psoc: PSOC object 238 * @arg_list: Variable argument list 239 * 240 * This callback is registered with object manager during initialization and 241 * when obj manager gets its turn to delete the object, it would notify each 242 * component with the corresponding callback registered to inform the 243 * completion of the deletion of the respective object. 244 * 245 * Return: QDF Status 246 */ 247 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification( 248 struct wlan_objmgr_psoc *psoc, void *arg_list) 249 { 250 QDF_STATUS status; 251 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 252 wlan_serialization_get_psoc_priv_obj(psoc); 253 254 if (NULL == ser_soc_obj) { 255 serialization_err("invalid ser_soc_obj"); 256 return QDF_STATUS_E_FAULT; 257 } 258 status = wlan_objmgr_psoc_component_obj_detach(psoc, 259 WLAN_UMAC_COMP_SERIALIZATION, 260 ser_soc_obj); 261 if (status != QDF_STATUS_SUCCESS) 262 serialization_err("ser psoc private obj detach failed"); 263 serialization_debug("ser psoc obj deleted with status %d", status); 264 qdf_mem_free(ser_soc_obj); 265 266 return status; 267 } 268 269 /** 270 * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback 271 * @pdev: PDEV object 272 * @arg_list: Variable argument list 273 * 274 * This callback is registered with object manager during initialization and 275 * when obj manager gets its turn to delete the object, it would notify each 276 * component with the corresponding callback registered to inform the 277 * completion of the deletion of the respective object. 278 * 279 * Return: QDF Status 280 */ 281 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification( 282 struct wlan_objmgr_pdev *pdev, void *arg_list) 283 { 284 QDF_STATUS status; 285 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 286 wlan_serialization_get_pdev_priv_obj(pdev); 287 288 status = wlan_objmgr_pdev_component_obj_detach(pdev, 289 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 290 wlan_serialization_destroy_list(ser_pdev_obj, 291 &ser_pdev_obj->active_list); 292 wlan_serialization_destroy_list(ser_pdev_obj, 293 &ser_pdev_obj->pending_list); 294 wlan_serialization_destroy_list(ser_pdev_obj, 295 &ser_pdev_obj->active_scan_list); 296 wlan_serialization_destroy_list(ser_pdev_obj, 297 &ser_pdev_obj->pending_scan_list); 298 wlan_serialization_destroy_cmd_pool(ser_pdev_obj); 299 serialization_debug("ser pdev obj detached with status %d", status); 300 status = wlan_serialization_destroy_lock(ser_pdev_obj); 301 if (status != QDF_STATUS_SUCCESS) 302 serialization_err("Failed to destroy serialization lock"); 303 qdf_mem_free(ser_pdev_obj); 304 305 return status; 306 } 307 308 /** 309 * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback 310 * @vdev: VDEV object 311 * @arg_list: Variable argument list 312 * 313 * This callback is registered with object manager during initialization and 314 * when obj manager gets its turn to create the object, it would notify each 315 * component with the corresponding callback registered to inform the 316 * completion of the creation of the respective object. 317 * 318 * Return: QDF Status 319 */ 320 static QDF_STATUS wlan_serialization_vdev_obj_create_notification( 321 struct wlan_objmgr_vdev *vdev, void *arg_list) 322 { 323 return QDF_STATUS_SUCCESS; 324 } 325 326 /** 327 * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback 328 * @vdev: VDEV object 329 * @arg_list: Variable argument list 330 * 331 * This callback is registered with object manager during initialization and 332 * when obj manager gets its turn to delete the object, it would notify each 333 * component with the corresponding callback registered to inform the 334 * completion of the deletion of the respective object. 335 * 336 * Return: QDF Status 337 */ 338 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification( 339 struct wlan_objmgr_vdev *vdev, void *arg_list) 340 { 341 uint8_t vdev_id = wlan_vdev_get_id(vdev); 342 343 if (!ser_legacy_cb.serialization_purge_cmd_list) 344 return QDF_STATUS_SUCCESS; 345 346 serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds", 347 vdev_id, vdev); 348 ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev), 349 vdev, false, false, false, false, true); 350 351 return QDF_STATUS_SUCCESS; 352 } 353 354 QDF_STATUS wlan_serialization_init(void) 355 { 356 QDF_STATUS status = QDF_STATUS_SUCCESS; 357 358 status = wlan_objmgr_register_psoc_create_handler( 359 WLAN_UMAC_COMP_SERIALIZATION, 360 wlan_serialization_psoc_obj_create_notification, NULL); 361 if (status != QDF_STATUS_SUCCESS) { 362 serialization_err("Failed to reg soc ser obj create handler"); 363 goto err_psoc_create; 364 } 365 366 status = wlan_objmgr_register_psoc_destroy_handler( 367 WLAN_UMAC_COMP_SERIALIZATION, 368 wlan_serialization_psoc_obj_destroy_notification, NULL); 369 if (status != QDF_STATUS_SUCCESS) { 370 serialization_err("Failed to reg soc ser obj delete handler"); 371 goto err_psoc_delete; 372 } 373 374 status = wlan_objmgr_register_pdev_create_handler( 375 WLAN_UMAC_COMP_SERIALIZATION, 376 wlan_serialization_pdev_obj_create_notification, NULL); 377 if (status != QDF_STATUS_SUCCESS) { 378 serialization_err("Failed to reg pdev ser obj create handler"); 379 goto err_pdev_create; 380 } 381 382 status = wlan_objmgr_register_pdev_destroy_handler( 383 WLAN_UMAC_COMP_SERIALIZATION, 384 wlan_serialization_pdev_obj_destroy_notification, NULL); 385 if (status != QDF_STATUS_SUCCESS) { 386 serialization_err("Failed to reg pdev ser obj delete handler"); 387 goto err_pdev_delete; 388 } 389 390 status = wlan_objmgr_register_vdev_create_handler( 391 WLAN_UMAC_COMP_SERIALIZATION, 392 wlan_serialization_vdev_obj_create_notification, NULL); 393 if (status != QDF_STATUS_SUCCESS) { 394 serialization_err("Failed to reg vdev ser obj create handler"); 395 goto err_vdev_create; 396 } 397 398 status = wlan_objmgr_register_vdev_destroy_handler( 399 WLAN_UMAC_COMP_SERIALIZATION, 400 wlan_serialization_vdev_obj_destroy_notification, NULL); 401 if (status != QDF_STATUS_SUCCESS) { 402 serialization_err("Failed to reg vdev ser obj delete handler"); 403 goto err_vdev_delete; 404 } 405 serialization_debug("serialization handlers registered with obj mgr"); 406 /* 407 * Initialize the structure so all callbacks are registered 408 * initially as NULL. 409 */ 410 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 411 412 return QDF_STATUS_SUCCESS; 413 414 err_vdev_delete: 415 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 416 wlan_serialization_vdev_obj_create_notification, NULL); 417 err_vdev_create: 418 wlan_objmgr_unregister_pdev_destroy_handler( 419 WLAN_UMAC_COMP_SERIALIZATION, 420 wlan_serialization_pdev_obj_destroy_notification, NULL); 421 err_pdev_delete: 422 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 423 wlan_serialization_pdev_obj_create_notification, NULL); 424 err_pdev_create: 425 wlan_objmgr_unregister_psoc_destroy_handler( 426 WLAN_UMAC_COMP_SERIALIZATION, 427 wlan_serialization_psoc_obj_destroy_notification, NULL); 428 err_psoc_delete: 429 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 430 wlan_serialization_psoc_obj_create_notification, NULL); 431 err_psoc_create: 432 return status; 433 434 } 435 436 QDF_STATUS wlan_serialization_deinit(void) 437 { 438 QDF_STATUS status; 439 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 440 441 status = wlan_objmgr_unregister_psoc_create_handler( 442 WLAN_UMAC_COMP_SERIALIZATION, 443 wlan_serialization_psoc_obj_create_notification, 444 NULL); 445 if (status != QDF_STATUS_SUCCESS) { 446 serialization_err("unreg fail for psoc ser obj create notf:%d", 447 status); 448 ret_status = QDF_STATUS_E_FAILURE; 449 } 450 status = wlan_objmgr_unregister_psoc_destroy_handler( 451 WLAN_UMAC_COMP_SERIALIZATION, 452 wlan_serialization_psoc_obj_destroy_notification, 453 NULL); 454 if (status != QDF_STATUS_SUCCESS) { 455 serialization_err("unreg fail for psoc ser obj destroy notf:%d", 456 status); 457 ret_status = QDF_STATUS_E_FAILURE; 458 } 459 460 status = wlan_objmgr_unregister_pdev_create_handler( 461 WLAN_UMAC_COMP_SERIALIZATION, 462 wlan_serialization_pdev_obj_create_notification, 463 NULL); 464 if (status != QDF_STATUS_SUCCESS) { 465 serialization_err("unreg fail for pdev ser obj create notf:%d", 466 status); 467 ret_status = QDF_STATUS_E_FAILURE; 468 } 469 470 status = wlan_objmgr_unregister_pdev_destroy_handler( 471 WLAN_UMAC_COMP_SERIALIZATION, 472 wlan_serialization_pdev_obj_destroy_notification, 473 NULL); 474 if (status != QDF_STATUS_SUCCESS) { 475 serialization_err("unreg fail for pdev ser destroy notf:%d", 476 status); 477 ret_status = QDF_STATUS_E_FAILURE; 478 } 479 480 serialization_alert("deregistered callbacks with obj mgr successfully"); 481 /* 482 * Initialize the structure so all callbacks are registered 483 * initially as NULL. 484 */ 485 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 486 487 return ret_status; 488 } 489