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 * 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) 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_pending_list_count( 81 struct wlan_objmgr_psoc *psoc, 82 uint8_t is_cmd_from_pending_scan_queue) 83 { 84 struct wlan_ser_pdev_obj *ser_pdev_obj; 85 qdf_list_t *queue; 86 uint32_t count = 0; 87 struct wlan_serialization_pdev_queue *pdev_queue; 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_pending_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 queue = &pdev_queue->pending_list; 101 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 102 count = qdf_list_size(queue); 103 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 104 105 return count; 106 } 107 108 struct wlan_serialization_command* 109 wlan_serialization_peek_head_active_cmd_using_psoc( 110 struct wlan_objmgr_psoc *psoc, 111 uint8_t is_cmd_from_active_scan_queue) 112 { 113 struct wlan_ser_pdev_obj *ser_pdev_obj; 114 struct wlan_serialization_command_list *cmd_list = NULL; 115 struct wlan_serialization_command *cmd = NULL; 116 qdf_list_node_t *nnode = NULL; 117 qdf_list_t *queue; 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 NULL; 124 } 125 126 if (is_cmd_from_active_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->active_list; 132 if (wlan_serialization_list_empty(queue)) { 133 ser_debug_rl("Empty Queue"); 134 goto end; 135 } 136 137 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue, 138 &nnode)) { 139 ser_err("Can't get command from queue"); 140 goto end; 141 } 142 143 cmd_list = qdf_container_of(nnode, 144 struct wlan_serialization_command_list, pdev_node); 145 cmd = &cmd_list->cmd; 146 ser_debug("cmd_type[%d], cmd_id[%d]", 147 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 148 149 end: 150 return cmd; 151 } 152 153 struct wlan_serialization_command* 154 wlan_serialization_peek_head_pending_cmd_using_psoc( 155 struct wlan_objmgr_psoc *psoc, 156 uint8_t is_cmd_from_pending_scan_queue) 157 { 158 struct wlan_ser_pdev_obj *ser_pdev_obj; 159 struct wlan_serialization_command_list *cmd_list = NULL; 160 struct wlan_serialization_command *cmd = NULL; 161 qdf_list_node_t *nnode = NULL; 162 qdf_list_t *queue; 163 struct wlan_serialization_pdev_queue *pdev_queue; 164 165 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 166 if (!ser_pdev_obj) { 167 ser_err("invalid ser_pdev_obj"); 168 return NULL; 169 } 170 if (is_cmd_from_pending_scan_queue) 171 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 172 else 173 pdev_queue = 174 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 175 queue = &pdev_queue->pending_list; 176 if (wlan_serialization_list_empty(queue)) { 177 ser_err("Empty Queue"); 178 goto end; 179 } 180 181 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 182 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( 183 queue, 184 &nnode)) { 185 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 186 ser_err("Can't get command from queue"); 187 goto end; 188 } 189 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 190 cmd_list = qdf_container_of(nnode, 191 struct wlan_serialization_command_list, pdev_node); 192 cmd = &cmd_list->cmd; 193 ser_debug("cmd_type[%d] cmd_id[%d]matched", 194 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 195 196 end: 197 return cmd; 198 } 199 200 static struct wlan_serialization_command* 201 wlan_serialization_get_list_next_node(qdf_list_t *queue, 202 struct wlan_serialization_command *cmd, 203 struct wlan_ser_pdev_obj *ser_pdev_obj) 204 { 205 struct wlan_serialization_command_list *cmd_list = NULL; 206 qdf_list_node_t *pnode = NULL, *nnode = NULL; 207 bool found = false; 208 uint32_t i = 0; 209 QDF_STATUS status; 210 struct wlan_serialization_command *ret_cmd = NULL; 211 212 i = wlan_serialization_list_size(queue); 213 if (i == 0) { 214 ser_err("Empty Queue"); 215 return NULL; 216 } 217 while (i--) { 218 if (!cmd_list) 219 status = wlan_serialization_peek_front(queue, &nnode); 220 else 221 status = wlan_serialization_peek_next(queue, pnode, 222 &nnode); 223 224 if ((status != QDF_STATUS_SUCCESS) || found) 225 break; 226 227 pnode = nnode; 228 cmd_list = qdf_container_of( 229 nnode, 230 struct wlan_serialization_command_list, 231 pdev_node); 232 if (wlan_serialization_match_cmd_id_type( 233 nnode, cmd, WLAN_SER_PDEV_NODE) && 234 wlan_serialization_match_cmd_vdev(nnode, 235 cmd->vdev, 236 WLAN_SER_PDEV_NODE)) { 237 found = true; 238 } 239 nnode = NULL; 240 } 241 if (nnode && found) { 242 cmd_list = qdf_container_of( 243 nnode, 244 struct wlan_serialization_command_list, 245 pdev_node); 246 ret_cmd = &cmd_list->cmd; 247 } 248 if (!found) { 249 ser_err("Can't locate next command"); 250 return NULL; 251 } 252 if (!nnode) { 253 ser_debug("next node is empty, so fine"); 254 return NULL; 255 } 256 257 return ret_cmd; 258 } 259 260 struct wlan_serialization_command* 261 wlan_serialization_get_pending_list_next_node_using_psoc( 262 struct wlan_objmgr_psoc *psoc, 263 struct wlan_serialization_command *prev_cmd, 264 uint8_t is_cmd_for_pending_scan_queue) 265 { 266 struct wlan_ser_pdev_obj *ser_pdev_obj; 267 qdf_list_t *queue; 268 struct wlan_serialization_pdev_queue *pdev_queue; 269 struct wlan_serialization_command *cmd; 270 271 if (!prev_cmd) { 272 ser_err("invalid prev_cmd"); 273 return NULL; 274 } 275 276 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); 277 if (!ser_pdev_obj) { 278 ser_err("invalid ser_pdev_obj"); 279 return NULL; 280 } 281 if (is_cmd_for_pending_scan_queue) 282 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 283 else 284 pdev_queue = 285 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 286 queue = &pdev_queue->pending_list; 287 288 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 289 cmd = wlan_serialization_get_list_next_node(queue, prev_cmd, 290 ser_pdev_obj); 291 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 292 293 return cmd; 294 } 295