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 * DOC: wlan_serialization_legacy_api.c 20 * This file provides prototypes of the routines needed for the 21 * legacy mcl serialization to utilize the services provided by the 22 * serialization component. 23 */ 24 25 #include "wlan_serialization_legacy_api.h" 26 #include "wlan_serialization_main_i.h" 27 #include "wlan_serialization_utils_i.h" 28 #include "wlan_objmgr_vdev_obj.h" 29 #include "wlan_serialization_internal_i.h" 30 #include "wlan_serialization_scan_i.h" 31 #include "wlan_serialization_non_scan_i.h" 32 33 extern struct serialization_legacy_callback ser_legacy_cb; 34 35 static struct wlan_objmgr_pdev *wlan_serialization_get_first_pdev( 36 struct wlan_objmgr_psoc *psoc) 37 { 38 struct wlan_objmgr_pdev *pdev; 39 uint8_t i = 0; 40 41 if (!psoc) { 42 ser_err("invalid psoc"); 43 return NULL; 44 } 45 for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { 46 pdev = wlan_objmgr_get_pdev_by_id(psoc, i, 47 WLAN_SERIALIZATION_ID); 48 if (pdev != NULL) 49 break; 50 } 51 52 return pdev; 53 } 54 55 static struct wlan_ser_pdev_obj * 56 wlan_serialization_get_pdev_priv_obj_using_psoc(struct wlan_objmgr_psoc *psoc) 57 { 58 struct wlan_objmgr_pdev *pdev = NULL; 59 struct wlan_ser_pdev_obj *ser_pdev_obj; 60 61 if (!psoc) { 62 ser_err("invalid psoc"); 63 return NULL; 64 } 65 66 pdev = wlan_serialization_get_first_pdev(psoc); 67 if (!pdev) { 68 ser_err("invalid pdev"); 69 return NULL; 70 } 71 72 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 73 wlan_objmgr_pdev_release_ref(pdev, WLAN_SERIALIZATION_ID); 74 if (!ser_pdev_obj) { 75 ser_err("invalid ser_pdev_obj"); 76 return NULL; 77 } 78 79 return ser_pdev_obj; 80 } 81 82 uint32_t wlan_serialization_get_active_list_count( 83 struct wlan_objmgr_psoc *psoc, 84 uint8_t is_cmd_from_active_scan_queue) 85 { 86 struct wlan_ser_pdev_obj *ser_pdev_obj; 87 qdf_list_t *queue; 88 struct wlan_serialization_pdev_queue *pdev_queue; 89 uint32_t count; 90 91 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 92 if (!ser_pdev_obj) { 93 ser_err("invalid ser_pdev_obj"); 94 return 0; 95 } 96 97 if (is_cmd_from_active_scan_queue) 98 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 99 else 100 pdev_queue = 101 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 102 103 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 104 queue = &pdev_queue->active_list; 105 count = qdf_list_size(queue); 106 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 107 108 return count; 109 } 110 111 uint32_t wlan_serialization_get_pending_list_count( 112 struct wlan_objmgr_psoc *psoc, 113 uint8_t is_cmd_from_pending_scan_queue) 114 { 115 struct wlan_ser_pdev_obj *ser_pdev_obj; 116 qdf_list_t *queue; 117 uint32_t count = 0; 118 struct wlan_serialization_pdev_queue *pdev_queue; 119 120 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 121 if (!ser_pdev_obj) { 122 ser_err("invalid ser_pdev_obj"); 123 return 0; 124 } 125 126 if (is_cmd_from_pending_scan_queue) 127 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 128 else 129 pdev_queue = 130 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 131 queue = &pdev_queue->pending_list; 132 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 133 count = qdf_list_size(queue); 134 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 135 136 return count; 137 } 138 139 struct wlan_serialization_command* 140 wlan_serialization_peek_head_active_cmd_using_psoc( 141 struct wlan_objmgr_psoc *psoc, 142 uint8_t is_cmd_from_active_scan_queue) 143 { 144 struct wlan_ser_pdev_obj *ser_pdev_obj; 145 struct wlan_serialization_command_list *cmd_list = NULL; 146 struct wlan_serialization_command *cmd = NULL; 147 qdf_list_node_t *nnode = NULL; 148 qdf_list_t *queue; 149 struct wlan_serialization_pdev_queue *pdev_queue; 150 151 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 152 if (!ser_pdev_obj) { 153 ser_err("invalid ser_pdev_obj"); 154 return NULL; 155 } 156 157 if (is_cmd_from_active_scan_queue) 158 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 159 else 160 pdev_queue = 161 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 162 queue = &pdev_queue->active_list; 163 if (wlan_serialization_list_empty(queue)) { 164 ser_err("Empty Queue"); 165 goto end; 166 } 167 168 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue, 169 &nnode)) { 170 ser_err("Can't get command from queue"); 171 goto end; 172 } 173 174 cmd_list = qdf_container_of(nnode, 175 struct wlan_serialization_command_list, pdev_node); 176 cmd = &cmd_list->cmd; 177 ser_debug("cmd_type[%d], cmd_id[%d]", 178 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 179 180 end: 181 return cmd; 182 } 183 184 struct wlan_serialization_command* 185 wlan_serialization_peek_head_pending_cmd_using_psoc( 186 struct wlan_objmgr_psoc *psoc, 187 uint8_t is_cmd_from_pending_scan_queue) 188 { 189 struct wlan_ser_pdev_obj *ser_pdev_obj; 190 struct wlan_serialization_command_list *cmd_list = NULL; 191 struct wlan_serialization_command *cmd = NULL; 192 qdf_list_node_t *nnode = NULL; 193 qdf_list_t *queue; 194 struct wlan_serialization_pdev_queue *pdev_queue; 195 196 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 197 if (!ser_pdev_obj) { 198 ser_err("invalid ser_pdev_obj"); 199 return NULL; 200 } 201 if (is_cmd_from_pending_scan_queue) 202 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 203 else 204 pdev_queue = 205 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 206 queue = &pdev_queue->pending_list; 207 if (wlan_serialization_list_empty(queue)) { 208 ser_err("Empty Queue"); 209 goto end; 210 } 211 212 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( 213 queue, 214 &nnode)) { 215 ser_err("Can't get command from queue"); 216 goto end; 217 } 218 cmd_list = qdf_container_of(nnode, 219 struct wlan_serialization_command_list, pdev_node); 220 cmd = &cmd_list->cmd; 221 ser_debug("cmd_type[%d] cmd_id[%d]matched", 222 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 223 224 end: 225 return cmd; 226 } 227 228 static struct wlan_serialization_command* 229 wlan_serialization_get_list_next_node(qdf_list_t *queue, 230 struct wlan_serialization_command *cmd, 231 struct wlan_ser_pdev_obj *ser_pdev_obj) 232 { 233 struct wlan_serialization_command_list *cmd_list = NULL; 234 qdf_list_node_t *pnode = NULL, *nnode = NULL; 235 bool found = false; 236 uint32_t i = 0; 237 QDF_STATUS status; 238 struct wlan_serialization_command *ret_cmd = NULL; 239 240 i = wlan_serialization_list_size(queue); 241 if (i == 0) { 242 ser_err("Empty Queue"); 243 return NULL; 244 } 245 while (i--) { 246 if (!cmd_list) 247 status = wlan_serialization_peek_front(queue, &nnode); 248 else 249 status = wlan_serialization_peek_next(queue, pnode, 250 &nnode); 251 252 if ((status != QDF_STATUS_SUCCESS) || found) 253 break; 254 255 pnode = nnode; 256 cmd_list = qdf_container_of( 257 nnode, 258 struct wlan_serialization_command_list, 259 pdev_node); 260 if (wlan_serialization_match_cmd_id_type( 261 nnode, cmd, WLAN_SER_PDEV_NODE) && 262 wlan_serialization_match_cmd_vdev(nnode, 263 cmd->vdev, 264 WLAN_SER_PDEV_NODE)) { 265 found = true; 266 } 267 nnode = NULL; 268 } 269 if (nnode && found) { 270 cmd_list = qdf_container_of( 271 nnode, 272 struct wlan_serialization_command_list, 273 pdev_node); 274 ret_cmd = &cmd_list->cmd; 275 } 276 if (!found) { 277 ser_err("Can't locate next command"); 278 return NULL; 279 } 280 if (!nnode) { 281 ser_debug("next node is empty, so fine"); 282 return NULL; 283 } 284 285 return ret_cmd; 286 } 287 288 struct wlan_serialization_command* 289 wlan_serialization_get_active_list_next_node_using_psoc( 290 struct wlan_objmgr_psoc *psoc, 291 struct wlan_serialization_command *prev_cmd, 292 uint8_t is_cmd_for_active_scan_queue) 293 { 294 struct wlan_ser_pdev_obj *ser_pdev_obj; 295 qdf_list_t *queue; 296 struct wlan_serialization_pdev_queue *pdev_queue; 297 298 if (!prev_cmd) { 299 ser_err("invalid prev_cmd"); 300 return NULL; 301 } 302 303 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 304 if (!ser_pdev_obj) { 305 ser_err("invalid ser_pdev_obj"); 306 return NULL; 307 } 308 309 if (is_cmd_for_active_scan_queue) 310 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 311 else 312 pdev_queue = 313 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 314 queue = &pdev_queue->active_list; 315 return wlan_serialization_get_list_next_node(queue, prev_cmd, 316 ser_pdev_obj); 317 } 318 319 struct wlan_serialization_command* 320 wlan_serialization_get_pending_list_next_node_using_psoc( 321 struct wlan_objmgr_psoc *psoc, 322 struct wlan_serialization_command *prev_cmd, 323 uint8_t is_cmd_for_pending_scan_queue) 324 { 325 struct wlan_ser_pdev_obj *ser_pdev_obj; 326 qdf_list_t *queue; 327 struct wlan_serialization_pdev_queue *pdev_queue; 328 329 if (!prev_cmd) { 330 ser_err("invalid prev_cmd"); 331 return NULL; 332 } 333 334 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 335 if (!ser_pdev_obj) { 336 ser_err("invalid ser_pdev_obj"); 337 return NULL; 338 } 339 if (is_cmd_for_pending_scan_queue) 340 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 341 else 342 pdev_queue = 343 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 344 queue = &pdev_queue->pending_list; 345 return wlan_serialization_get_list_next_node(queue, prev_cmd, 346 ser_pdev_obj); 347 } 348 349 void wlan_serialization_legacy_init_callback(void) 350 { 351 ser_legacy_cb.serialization_purge_cmd_list = 352 wlan_serialization_purge_cmd_list; 353 } 354 355 void wlan_serialization_purge_cmd_list_by_vdev_id( 356 struct wlan_objmgr_psoc *psoc, 357 uint8_t vdev_id, bool purge_scan_active_queue, 358 bool purge_scan_pending_queue, 359 bool purge_nonscan_active_queue, 360 bool purge_nonscan_pending_queue, 361 bool purge_all_queues) 362 { 363 struct wlan_objmgr_vdev *vdev; 364 365 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 366 WLAN_SERIALIZATION_ID); 367 if (!vdev) { 368 ser_err("Invalid vdev"); 369 return; 370 } 371 wlan_serialization_purge_cmd_list( 372 psoc, vdev, purge_scan_active_queue, 373 purge_scan_pending_queue, 374 purge_nonscan_active_queue, 375 purge_nonscan_pending_queue, 376 purge_all_queues); 377 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 378 } 379 380 void wlan_serialization_purge_cmd_list( 381 struct wlan_objmgr_psoc *psoc, 382 struct wlan_objmgr_vdev *vdev, 383 bool purge_scan_active_queue, 384 bool purge_scan_pending_queue, 385 bool purge_nonscan_active_queue, 386 bool purge_nonscan_pending_queue, 387 bool purge_all_queues) 388 { 389 struct wlan_ser_pdev_obj *ser_pdev_obj; 390 struct wlan_objmgr_pdev *pdev = NULL; 391 392 if (!psoc) { 393 ser_err("Invalid psoc"); 394 return; 395 } 396 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 397 if (!ser_pdev_obj) { 398 ser_err("Invalid ser_pdev_obj"); 399 return; 400 } 401 402 pdev = wlan_serialization_get_first_pdev(psoc); 403 if (!pdev) { 404 ser_err("Invalid pdev"); 405 return; 406 } 407 408 if (purge_all_queues || purge_scan_active_queue) { 409 wlan_ser_cancel_scan_cmd(ser_pdev_obj, 410 pdev, 411 vdev, 412 NULL, 413 WLAN_SER_CMD_SCAN, 414 true); 415 } 416 if (purge_all_queues || purge_scan_pending_queue) { 417 wlan_ser_cancel_scan_cmd(ser_pdev_obj, 418 pdev, 419 vdev, 420 NULL, 421 WLAN_SER_CMD_SCAN, 422 false); 423 } 424 if (purge_all_queues || purge_nonscan_active_queue) { 425 wlan_ser_cancel_non_scan_cmd( 426 ser_pdev_obj, 427 pdev, vdev, 428 NULL, 429 WLAN_SER_CMD_NONSCAN, 430 true); 431 } 432 if (purge_all_queues || purge_nonscan_pending_queue) { 433 wlan_ser_cancel_non_scan_cmd( 434 ser_pdev_obj, 435 pdev, vdev, 436 NULL, 437 WLAN_SER_CMD_NONSCAN, 438 false); 439 } 440 wlan_objmgr_pdev_release_ref(pdev, WLAN_SERIALIZATION_ID); 441 442 return; 443 } 444 445