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