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 serialization_debug("Created node at %pK and inserted to pool", 172 cmd_list_ptr); 173 } 174 175 return QDF_STATUS_SUCCESS; 176 } 177 178 179 /** 180 * wlan_serialization_pdev_obj_create_notification() - PDEV obj create callback 181 * @pdev: PDEV object 182 * @arg_list: Variable argument list 183 * 184 * This callback is registered with object manager during initialization and 185 * when obj manager gets its turn to create the object, it would notify each 186 * component with the corresponding callback registered to inform the 187 * completion of the creation of the respective object. 188 * 189 * Return: QDF Status 190 */ 191 static QDF_STATUS wlan_serialization_pdev_obj_create_notification( 192 struct wlan_objmgr_pdev *pdev, void *arg_list) 193 { 194 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 195 QDF_STATUS status; 196 197 ser_pdev_obj = 198 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 199 if (NULL == ser_pdev_obj) { 200 serialization_alert("Mem alloc failed for ser pdev obj"); 201 return QDF_STATUS_E_NOMEM; 202 } 203 qdf_list_create(&ser_pdev_obj->active_list, 204 WLAN_SERIALIZATION_MAX_ACTIVE_CMDS); 205 qdf_list_create(&ser_pdev_obj->pending_list, 206 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 207 qdf_list_create(&ser_pdev_obj->active_scan_list, 208 WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS); 209 qdf_list_create(&ser_pdev_obj->pending_scan_list, 210 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 211 qdf_list_create(&ser_pdev_obj->global_cmd_pool_list, 212 WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS); 213 status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj); 214 if (status != QDF_STATUS_SUCCESS) { 215 serialization_err("ser_pdev_obj failed status %d", status); 216 return status; 217 } 218 status = wlan_objmgr_pdev_component_obj_attach(pdev, 219 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj, 220 QDF_STATUS_SUCCESS); 221 if (status != QDF_STATUS_SUCCESS) { 222 serialization_err("serialization pdev obj attach failed"); 223 return status; 224 } 225 226 return status; 227 } 228 229 /** 230 * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback 231 * @psoc: PSOC object 232 * @arg_list: Variable argument list 233 * 234 * This callback is registered with object manager during initialization and 235 * when obj manager gets its turn to delete the object, it would notify each 236 * component with the corresponding callback registered to inform the 237 * completion of the deletion of the respective object. 238 * 239 * Return: QDF Status 240 */ 241 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification( 242 struct wlan_objmgr_psoc *psoc, void *arg_list) 243 { 244 QDF_STATUS status; 245 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = 246 wlan_serialization_get_psoc_priv_obj(psoc); 247 248 if (NULL == ser_soc_obj) { 249 serialization_err("invalid ser_soc_obj"); 250 return QDF_STATUS_E_FAULT; 251 } 252 status = wlan_objmgr_psoc_component_obj_detach(psoc, 253 WLAN_UMAC_COMP_SERIALIZATION, 254 ser_soc_obj); 255 if (status != QDF_STATUS_SUCCESS) 256 serialization_err("ser psoc private obj detach failed"); 257 serialization_debug("ser psoc obj deleted with status %d", status); 258 qdf_mem_free(ser_soc_obj); 259 260 return status; 261 } 262 263 /** 264 * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback 265 * @pdev: PDEV object 266 * @arg_list: Variable argument list 267 * 268 * This callback is registered with object manager during initialization and 269 * when obj manager gets its turn to delete the object, it would notify each 270 * component with the corresponding callback registered to inform the 271 * completion of the deletion of the respective object. 272 * 273 * Return: QDF Status 274 */ 275 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification( 276 struct wlan_objmgr_pdev *pdev, void *arg_list) 277 { 278 QDF_STATUS status; 279 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 280 wlan_serialization_get_pdev_priv_obj(pdev); 281 282 status = wlan_objmgr_pdev_component_obj_detach(pdev, 283 WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 284 wlan_serialization_destroy_list(ser_pdev_obj, 285 &ser_pdev_obj->active_list); 286 wlan_serialization_destroy_list(ser_pdev_obj, 287 &ser_pdev_obj->pending_list); 288 wlan_serialization_destroy_list(ser_pdev_obj, 289 &ser_pdev_obj->active_scan_list); 290 wlan_serialization_destroy_list(ser_pdev_obj, 291 &ser_pdev_obj->pending_scan_list); 292 wlan_serialization_destroy_cmd_pool(ser_pdev_obj); 293 serialization_debug("ser pdev obj deleted with status %d", status); 294 qdf_mem_free(ser_pdev_obj); 295 296 return status; 297 } 298 299 /** 300 * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback 301 * @vdev: VDEV object 302 * @arg_list: Variable argument list 303 * 304 * This callback is registered with object manager during initialization and 305 * when obj manager gets its turn to create the object, it would notify each 306 * component with the corresponding callback registered to inform the 307 * completion of the creation of the respective object. 308 * 309 * Return: QDF Status 310 */ 311 static QDF_STATUS wlan_serialization_vdev_obj_create_notification( 312 struct wlan_objmgr_vdev *vdev, void *arg_list) 313 { 314 return QDF_STATUS_SUCCESS; 315 } 316 317 /** 318 * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback 319 * @vdev: VDEV object 320 * @arg_list: Variable argument list 321 * 322 * This callback is registered with object manager during initialization and 323 * when obj manager gets its turn to delete the object, it would notify each 324 * component with the corresponding callback registered to inform the 325 * completion of the deletion of the respective object. 326 * 327 * Return: QDF Status 328 */ 329 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification( 330 struct wlan_objmgr_vdev *vdev, void *arg_list) 331 { 332 uint8_t vdev_id = wlan_vdev_get_id(vdev); 333 334 if (!ser_legacy_cb.serialization_purge_cmd_list) 335 return QDF_STATUS_SUCCESS; 336 337 serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds", 338 vdev_id, vdev); 339 ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev), 340 vdev, false, false, false, false, true); 341 342 return QDF_STATUS_SUCCESS; 343 } 344 345 QDF_STATUS wlan_serialization_init(void) 346 { 347 QDF_STATUS status = QDF_STATUS_SUCCESS; 348 349 status = wlan_objmgr_register_psoc_create_handler( 350 WLAN_UMAC_COMP_SERIALIZATION, 351 wlan_serialization_psoc_obj_create_notification, NULL); 352 if (status != QDF_STATUS_SUCCESS) { 353 serialization_err("Failed to reg soc ser obj create handler"); 354 goto err_psoc_create; 355 } 356 357 status = wlan_objmgr_register_psoc_destroy_handler( 358 WLAN_UMAC_COMP_SERIALIZATION, 359 wlan_serialization_psoc_obj_destroy_notification, NULL); 360 if (status != QDF_STATUS_SUCCESS) { 361 serialization_err("Failed to reg soc ser obj delete handler"); 362 goto err_psoc_delete; 363 } 364 365 status = wlan_objmgr_register_pdev_create_handler( 366 WLAN_UMAC_COMP_SERIALIZATION, 367 wlan_serialization_pdev_obj_create_notification, NULL); 368 if (status != QDF_STATUS_SUCCESS) { 369 serialization_err("Failed to reg pdev ser obj create handler"); 370 goto err_pdev_create; 371 } 372 373 status = wlan_objmgr_register_pdev_destroy_handler( 374 WLAN_UMAC_COMP_SERIALIZATION, 375 wlan_serialization_pdev_obj_destroy_notification, NULL); 376 if (status != QDF_STATUS_SUCCESS) { 377 serialization_err("Failed to reg pdev ser obj delete handler"); 378 goto err_pdev_delete; 379 } 380 381 status = wlan_objmgr_register_vdev_create_handler( 382 WLAN_UMAC_COMP_SERIALIZATION, 383 wlan_serialization_vdev_obj_create_notification, NULL); 384 if (status != QDF_STATUS_SUCCESS) { 385 serialization_err("Failed to reg vdev ser obj create handler"); 386 goto err_vdev_create; 387 } 388 389 status = wlan_objmgr_register_vdev_destroy_handler( 390 WLAN_UMAC_COMP_SERIALIZATION, 391 wlan_serialization_vdev_obj_destroy_notification, NULL); 392 if (status != QDF_STATUS_SUCCESS) { 393 serialization_err("Failed to reg vdev ser obj delete handler"); 394 goto err_vdev_delete; 395 } 396 serialization_debug("serialization handlers registered with obj mgr"); 397 /* 398 * Initialize the structure so all callbacks are registered 399 * initially as NULL. 400 */ 401 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 402 403 return QDF_STATUS_SUCCESS; 404 405 err_vdev_delete: 406 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 407 wlan_serialization_vdev_obj_create_notification, NULL); 408 err_vdev_create: 409 wlan_objmgr_unregister_pdev_destroy_handler( 410 WLAN_UMAC_COMP_SERIALIZATION, 411 wlan_serialization_pdev_obj_destroy_notification, NULL); 412 err_pdev_delete: 413 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 414 wlan_serialization_pdev_obj_create_notification, NULL); 415 err_pdev_create: 416 wlan_objmgr_unregister_psoc_destroy_handler( 417 WLAN_UMAC_COMP_SERIALIZATION, 418 wlan_serialization_psoc_obj_destroy_notification, NULL); 419 err_psoc_delete: 420 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION, 421 wlan_serialization_psoc_obj_create_notification, NULL); 422 err_psoc_create: 423 return status; 424 425 } 426 427 QDF_STATUS wlan_serialization_deinit(void) 428 { 429 QDF_STATUS status; 430 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 431 432 status = wlan_objmgr_unregister_psoc_create_handler( 433 WLAN_UMAC_COMP_SERIALIZATION, 434 wlan_serialization_psoc_obj_create_notification, 435 NULL); 436 if (status != QDF_STATUS_SUCCESS) { 437 serialization_err("unreg fail for psoc ser obj create notf:%d", 438 status); 439 ret_status = QDF_STATUS_E_FAILURE; 440 } 441 status = wlan_objmgr_unregister_psoc_destroy_handler( 442 WLAN_UMAC_COMP_SERIALIZATION, 443 wlan_serialization_psoc_obj_destroy_notification, 444 NULL); 445 if (status != QDF_STATUS_SUCCESS) { 446 serialization_err("unreg fail for psoc ser obj destroy notf:%d", 447 status); 448 ret_status = QDF_STATUS_E_FAILURE; 449 } 450 451 status = wlan_objmgr_unregister_pdev_create_handler( 452 WLAN_UMAC_COMP_SERIALIZATION, 453 wlan_serialization_pdev_obj_create_notification, 454 NULL); 455 if (status != QDF_STATUS_SUCCESS) { 456 serialization_err("unreg fail for pdev ser obj create notf:%d", 457 status); 458 ret_status = QDF_STATUS_E_FAILURE; 459 } 460 461 status = wlan_objmgr_unregister_pdev_destroy_handler( 462 WLAN_UMAC_COMP_SERIALIZATION, 463 wlan_serialization_pdev_obj_destroy_notification, 464 NULL); 465 if (status != QDF_STATUS_SUCCESS) { 466 serialization_err("unreg fail for pdev ser destroy notf:%d", 467 status); 468 ret_status = QDF_STATUS_E_FAILURE; 469 } 470 471 serialization_alert("deregistered callbacks with obj mgr successfully"); 472 /* 473 * Initialize the structure so all callbacks are registered 474 * initially as NULL. 475 */ 476 qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb)); 477 478 return ret_status; 479 } 480