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