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_api.c 20 * This file provides an interface for the external components 21 * to utilize the services provided by the serialization 22 * component. 23 */ 24 25 /* Include files */ 26 #include "wlan_objmgr_psoc_obj.h" 27 #include "wlan_objmgr_pdev_obj.h" 28 #include "wlan_objmgr_vdev_obj.h" 29 #include "wlan_serialization_main_i.h" 30 #include "wlan_serialization_utils_i.h" 31 32 bool wlan_serialization_is_cmd_present_in_pending_queue( 33 struct wlan_objmgr_psoc *psoc, 34 struct wlan_serialization_command *cmd) 35 { 36 if (!cmd) { 37 serialization_err("invalid cmd"); 38 return false; 39 } 40 return wlan_serialization_is_cmd_present_queue(cmd, false); 41 } 42 43 bool wlan_serialization_is_cmd_present_in_active_queue( 44 struct wlan_objmgr_psoc *psoc, 45 struct wlan_serialization_command *cmd) 46 { 47 if (!cmd) { 48 serialization_err("invalid cmd"); 49 return false; 50 } 51 return wlan_serialization_is_cmd_present_queue(cmd, true); 52 } 53 54 QDF_STATUS 55 wlan_serialization_register_apply_rules_cb(struct wlan_objmgr_psoc *psoc, 56 enum wlan_serialization_cmd_type cmd_type, 57 wlan_serialization_apply_rules_cb cb) 58 { 59 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 60 QDF_STATUS status; 61 62 status = wlan_serialization_validate_cmdtype(cmd_type); 63 if (status != QDF_STATUS_SUCCESS) { 64 serialization_err("invalid cmd_type %d", 65 cmd_type); 66 return status; 67 } 68 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 69 if (!ser_soc_obj) { 70 serialization_err("invalid ser_soc_obj"); 71 return QDF_STATUS_E_FAILURE; 72 } 73 ser_soc_obj->apply_rules_cb[cmd_type] = cb; 74 75 return QDF_STATUS_SUCCESS; 76 } 77 78 QDF_STATUS 79 wlan_serialization_deregister_apply_rules_cb(struct wlan_objmgr_psoc *psoc, 80 enum wlan_serialization_cmd_type cmd_type) 81 { 82 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 83 QDF_STATUS status; 84 85 status = wlan_serialization_validate_cmdtype(cmd_type); 86 if (status != QDF_STATUS_SUCCESS) { 87 serialization_err("invalid cmd_type %d", 88 cmd_type); 89 return status; 90 } 91 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 92 if (!ser_soc_obj) { 93 serialization_err("invalid ser_soc_obj"); 94 return QDF_STATUS_E_FAILURE; 95 } 96 ser_soc_obj->apply_rules_cb[cmd_type] = NULL; 97 98 return QDF_STATUS_SUCCESS; 99 } 100 101 QDF_STATUS 102 wlan_serialization_register_comp_info_cb(struct wlan_objmgr_psoc *psoc, 103 enum wlan_umac_comp_id comp_id, 104 enum wlan_serialization_cmd_type cmd_type, 105 wlan_serialization_comp_info_cb cb) 106 { 107 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 108 QDF_STATUS status; 109 110 status = wlan_serialization_validate_cmd(comp_id, cmd_type); 111 if (status != QDF_STATUS_SUCCESS) { 112 serialization_err("invalid comp_id %d or cmd_type %d", 113 comp_id, cmd_type); 114 return status; 115 } 116 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 117 if (!ser_soc_obj) { 118 serialization_err("invalid ser_soc_obj"); 119 return QDF_STATUS_E_FAILURE; 120 } 121 ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb; 122 123 return QDF_STATUS_SUCCESS; 124 } 125 126 QDF_STATUS 127 wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc, 128 enum wlan_umac_comp_id comp_id, 129 enum wlan_serialization_cmd_type cmd_type) 130 { 131 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 132 QDF_STATUS status; 133 134 status = wlan_serialization_validate_cmd(comp_id, cmd_type); 135 if (status != QDF_STATUS_SUCCESS) { 136 serialization_err("invalid comp_id %d or cmd_type %d", 137 comp_id, cmd_type); 138 return status; 139 } 140 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 141 if (!ser_soc_obj) { 142 serialization_err("invalid ser_soc_obj"); 143 return QDF_STATUS_E_FAILURE; 144 } 145 ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL; 146 147 return QDF_STATUS_SUCCESS; 148 } 149 150 enum wlan_serialization_cmd_status 151 wlan_serialization_non_scan_cmd_status(struct wlan_objmgr_pdev *pdev, 152 enum wlan_serialization_cmd_type cmd_id) 153 { 154 serialization_enter(); 155 156 return WLAN_SER_CMD_NOT_FOUND; 157 } 158 159 enum wlan_serialization_cmd_status 160 wlan_serialization_cancel_request( 161 struct wlan_serialization_queued_cmd_info *req) 162 { 163 QDF_STATUS status; 164 165 serialization_enter(); 166 if (!req) { 167 serialization_err("given request is empty"); 168 return WLAN_SER_CMD_NOT_FOUND; 169 } 170 status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type); 171 if (status != QDF_STATUS_SUCCESS) { 172 serialization_err("req is not valid"); 173 return WLAN_SER_CMD_NOT_FOUND; 174 } 175 176 return wlan_serialization_find_and_cancel_cmd(req); 177 } 178 179 void wlan_serialization_remove_cmd( 180 struct wlan_serialization_queued_cmd_info *cmd) 181 { 182 QDF_STATUS status; 183 184 serialization_enter(); 185 if (!cmd) { 186 serialization_err("given request is empty"); 187 QDF_ASSERT(0); 188 return; 189 } 190 status = wlan_serialization_validate_cmd(cmd->requestor, cmd->cmd_type); 191 if (status != QDF_STATUS_SUCCESS) { 192 serialization_err("cmd is not valid"); 193 QDF_ASSERT(0); 194 return; 195 } 196 wlan_serialization_find_and_remove_cmd(cmd); 197 198 return; 199 } 200 201 enum wlan_serialization_status 202 wlan_serialization_request(struct wlan_serialization_command *cmd) 203 { 204 bool is_active_cmd_allowed; 205 QDF_STATUS status; 206 enum wlan_serialization_status serialization_status; 207 uint8_t comp_id; 208 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 209 union wlan_serialization_rules_info info; 210 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = NULL; 211 struct wlan_objmgr_pdev *pdev = NULL; 212 struct wlan_serialization_command_list *cmd_list = NULL; 213 214 serialization_enter(); 215 if (!cmd) { 216 serialization_err("serialization cmd is null"); 217 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 218 } 219 status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type); 220 if (status != QDF_STATUS_SUCCESS) { 221 serialization_err("cmd is not valid"); 222 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 223 } 224 225 ser_soc_obj = wlan_serialization_get_obj(cmd); 226 if (!ser_soc_obj) { 227 serialization_err("ser_soc_obj is invalid"); 228 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 229 } 230 231 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 232 if (!pdev) { 233 serialization_err("pdev is invalid"); 234 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 235 } 236 237 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 238 WLAN_UMAC_COMP_SERIALIZATION); 239 if (!ser_pdev_obj) { 240 serialization_err("Invalid ser_pdev_obj"); 241 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 242 } 243 /* 244 * Get Component Info callback by calling 245 * each registered module 246 */ 247 for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) { 248 if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id]) 249 continue; 250 (ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])(cmd->vdev, 251 &info); 252 if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type]) 253 continue; 254 if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id)) 255 return WLAN_SER_CMD_DENIED_RULES_FAILED; 256 } 257 258 is_active_cmd_allowed = wlan_serialization_is_active_cmd_allowed(cmd); 259 serialization_status = wlan_serialization_enqueue_cmd( 260 cmd, is_active_cmd_allowed, &cmd_list); 261 if (WLAN_SER_CMD_ACTIVE == serialization_status) 262 wlan_serialization_activate_cmd(cmd_list, ser_pdev_obj); 263 return serialization_status; 264 } 265 266 enum wlan_serialization_cmd_status 267 wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev) 268 { 269 bool cmd_in_active, cmd_in_pending; 270 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 271 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 272 wlan_serialization_get_pdev_priv_obj(pdev); 273 274 cmd_in_active = 275 wlan_serialization_is_cmd_in_vdev_list( 276 vdev, &ser_pdev_obj->active_scan_list); 277 278 cmd_in_pending = 279 wlan_serialization_is_cmd_in_vdev_list( 280 vdev, &ser_pdev_obj->pending_scan_list); 281 282 return wlan_serialization_is_cmd_in_active_pending( 283 cmd_in_active, cmd_in_pending); 284 } 285 286 void wlan_serialization_flush_cmd( 287 struct wlan_serialization_queued_cmd_info *cmd) 288 { 289 serialization_enter(); 290 if (!cmd) { 291 serialization_err("cmd is null, can't flush"); 292 return; 293 } 294 /* TODO: discuss and fill this API later */ 295 296 return; 297 } 298 299 enum wlan_serialization_cmd_status 300 wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev) 301 { 302 bool cmd_in_active, cmd_in_pending; 303 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 304 wlan_serialization_get_pdev_priv_obj(pdev); 305 306 cmd_in_active = 307 wlan_serialization_is_cmd_in_pdev_list( 308 pdev, &ser_pdev_obj->active_scan_list); 309 310 cmd_in_pending = 311 wlan_serialization_is_cmd_in_pdev_list( 312 pdev, &ser_pdev_obj->pending_scan_list); 313 314 return wlan_serialization_is_cmd_in_active_pending( 315 cmd_in_active, cmd_in_pending); 316 } 317 318 struct wlan_serialization_command* 319 wlan_serialization_get_scan_cmd_using_scan_id( 320 struct wlan_objmgr_psoc *psoc, 321 uint8_t vdev_id, uint16_t scan_id, 322 uint8_t is_scan_cmd_from_active_queue) 323 { 324 uint32_t qlen; 325 struct wlan_objmgr_vdev *vdev; 326 struct wlan_objmgr_pdev *pdev; 327 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 328 struct wlan_serialization_command_list *cmd_list = NULL; 329 struct wlan_serialization_command *cmd = NULL; 330 qdf_list_node_t *nnode = NULL; 331 qdf_list_t *queue; 332 333 if (!psoc) { 334 serialization_err("invalid psoc"); 335 return cmd; 336 } 337 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 338 WLAN_SERIALIZATION_ID); 339 if (!vdev) { 340 serialization_err("invalid vdev"); 341 return cmd; 342 } 343 344 pdev = wlan_vdev_get_pdev(vdev); 345 if (!pdev) { 346 serialization_err("invalid pdev"); 347 goto release_vdev_ref; 348 } 349 350 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj(pdev); 351 if (!ser_pdev_obj) { 352 serialization_err("invalid ser_pdev_obj"); 353 goto release_vdev_ref; 354 } 355 if (is_scan_cmd_from_active_queue) 356 queue = &ser_pdev_obj->active_scan_list; 357 else 358 queue = &ser_pdev_obj->pending_scan_list; 359 qlen = qdf_list_size(queue); 360 if (!qlen) { 361 serialization_err("Empty Queue"); 362 goto release_vdev_ref; 363 } 364 while (qlen--) { 365 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( 366 queue, &nnode)) { 367 serialization_err("unsuccessful attempt"); 368 break; 369 } 370 cmd_list = qdf_container_of(nnode, 371 struct wlan_serialization_command_list, node); 372 if ((cmd_list->cmd.cmd_id == scan_id) && 373 (cmd_list->cmd.vdev == vdev)) { 374 serialization_debug("cmd_id[%d] matched", scan_id); 375 cmd = &cmd_list->cmd; 376 break; 377 } 378 } 379 release_vdev_ref: 380 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 381 return cmd; 382 } 383