1 /* 2 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: Implements MLME component object creation/initialization/destroy 19 */ 20 21 #include <wlan_objmgr_cmn.h> 22 #include <wlan_objmgr_global_obj.h> 23 #include <wlan_objmgr_vdev_obj.h> 24 #include <wlan_mlme_dbg.h> 25 #include <include/wlan_mlme_cmn.h> 26 #include <include/wlan_vdev_mlme.h> 27 #include <include/wlan_pdev_mlme.h> 28 #include <vdev_mgr/core/src/vdev_mlme_sm.h> 29 #include <wlan_pdev_mlme_api.h> 30 #include <wlan_vdev_mlme_api.h> 31 #include <wlan_serialization_api.h> 32 #include <wlan_utility.h> 33 #include <cdp_txrx_cmn.h> 34 #include <wlan_lmac_if_def.h> 35 #include <target_if_vdev_mgr_tx_ops.h> 36 #include "connection_mgr/core/src/wlan_cm_main.h" 37 38 static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, 39 void *arg) 40 { 41 struct vdev_mlme_obj *vdev_mlme; 42 struct wlan_objmgr_pdev *pdev; 43 struct wlan_objmgr_psoc *psoc; 44 struct pdev_mlme_obj *pdev_mlme; 45 struct wlan_lmac_if_mlme_tx_ops *txops; 46 QDF_STATUS status; 47 48 if (!vdev) { 49 mlme_err(" VDEV is NULL"); 50 return QDF_STATUS_E_FAILURE; 51 } 52 53 pdev = wlan_vdev_get_pdev(vdev); 54 if (!pdev) { 55 mlme_err(" PDEV is NULL"); 56 return QDF_STATUS_E_FAILURE; 57 } 58 59 /** 60 * 1st check whether for this vdev any vdev commands are pending for 61 * response. 62 */ 63 psoc = wlan_pdev_get_psoc(pdev); 64 if (!psoc) { 65 mlme_err("PSOC is NULL"); 66 return QDF_STATUS_E_FAILURE; 67 } 68 69 txops = wlan_mlme_get_lmac_tx_ops(psoc); 70 if (!txops || !txops->psoc_vdev_rsp_timer_inuse) { 71 mlme_err("Failed to get mlme txrx_ops PSOC_%d", 72 wlan_psoc_get_id(psoc)); 73 return QDF_STATUS_E_FAILURE; 74 } 75 76 status = txops->psoc_vdev_rsp_timer_inuse(psoc, wlan_vdev_get_id(vdev)); 77 if (QDF_IS_STATUS_ERROR(status)) { 78 mlme_err("The vdev response is pending for VDEV_%d status:%d", 79 wlan_vdev_get_id(vdev), status); 80 return QDF_STATUS_E_FAILURE; 81 } 82 83 pdev_mlme = wlan_pdev_mlme_get_cmpt_obj(pdev); 84 if (!pdev_mlme) { 85 mlme_err("PDEV MLME is NULL"); 86 return QDF_STATUS_E_FAILURE; 87 } 88 89 vdev_mlme = qdf_mem_malloc(sizeof(*vdev_mlme)); 90 if (!vdev_mlme) 91 return QDF_STATUS_E_NOMEM; 92 wlan_minidump_log(vdev_mlme, sizeof(*vdev_mlme), psoc, 93 WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme"); 94 95 vdev_mlme->vdev = vdev; 96 97 if (pdev_mlme->mlme_register_ops(vdev_mlme) != QDF_STATUS_SUCCESS) { 98 mlme_err("Callbacks registration is failed"); 99 goto init_failed; 100 } 101 102 if (mlme_vdev_sm_create(vdev_mlme) != QDF_STATUS_SUCCESS) { 103 mlme_err("SME creation failed"); 104 goto init_failed; 105 } 106 107 if (QDF_IS_STATUS_ERROR(wlan_cm_init(vdev_mlme))) { 108 mlme_err("CM SM create failed"); 109 goto cm_sm_create_failed; 110 } 111 112 if (mlme_vdev_ops_ext_hdl_create(vdev_mlme) != 113 QDF_STATUS_SUCCESS) { 114 mlme_err("Legacy vdev object creation failed"); 115 goto ext_hdl_create_failed; 116 } 117 118 wlan_objmgr_vdev_component_obj_attach((struct wlan_objmgr_vdev *)vdev, 119 WLAN_UMAC_COMP_MLME, 120 (void *)vdev_mlme, 121 QDF_STATUS_SUCCESS); 122 123 if (mlme_vdev_ops_ext_hdl_post_create(vdev_mlme) != 124 QDF_STATUS_SUCCESS) { 125 mlme_err("Legacy vdev object post creation failed"); 126 goto ext_hdl_post_create_failed; 127 } 128 129 return QDF_STATUS_SUCCESS; 130 131 ext_hdl_post_create_failed: 132 mlme_vdev_ops_ext_hdl_destroy(vdev_mlme); 133 wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME, 134 vdev_mlme); 135 ext_hdl_create_failed: 136 wlan_cm_deinit(vdev_mlme); 137 cm_sm_create_failed: 138 mlme_vdev_sm_destroy(vdev_mlme); 139 init_failed: 140 wlan_minidump_remove(vdev_mlme, sizeof(*vdev_mlme), psoc, 141 WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme"); 142 143 qdf_mem_free(vdev_mlme); 144 return QDF_STATUS_E_FAILURE; 145 } 146 147 static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, 148 void *arg) 149 { 150 struct vdev_mlme_obj *vdev_mlme; 151 152 if (!vdev) { 153 mlme_err(" VDEV is NULL"); 154 return QDF_STATUS_E_FAILURE; 155 } 156 157 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 158 if (!vdev_mlme) { 159 mlme_info(" VDEV MLME component object is NULL"); 160 return QDF_STATUS_SUCCESS; 161 } 162 163 wlan_cm_deinit(vdev_mlme); 164 mlme_vdev_sm_destroy(vdev_mlme); 165 mlme_vdev_ops_ext_hdl_destroy(vdev_mlme); 166 wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME, 167 vdev_mlme); 168 169 wlan_minidump_remove(vdev_mlme, sizeof(*vdev_mlme), 170 wlan_vdev_get_psoc(vdev), 171 WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme"); 172 173 qdf_mem_free(vdev_mlme); 174 175 return QDF_STATUS_SUCCESS; 176 } 177 178 static void mlme_scan_serialization_comp_info_cb( 179 struct wlan_objmgr_vdev *vdev, 180 union wlan_serialization_rules_info *comp_info, 181 struct wlan_serialization_command *cmd) 182 { 183 struct wlan_objmgr_pdev *pdev; 184 struct scan_start_request *scan_start_req = cmd->umac_cmd; 185 QDF_STATUS status; 186 187 if (!comp_info || !vdev) { 188 mlme_err("comp_info or vdev is NULL"); 189 return; 190 } 191 192 pdev = wlan_vdev_get_pdev(vdev); 193 if (!pdev) { 194 mlme_err("pdev is NULL"); 195 return; 196 } 197 198 if (!scan_start_req) { 199 mlme_err("scan start request is null"); 200 return; 201 } 202 203 comp_info->scan_info.is_scan_for_connect = false; 204 205 if (cmd->cmd_type == WLAN_SER_CMD_SCAN && 206 scan_start_req->scan_req.scan_type == SCAN_TYPE_SCAN_FOR_CONNECT) { 207 comp_info->scan_info.is_scan_for_connect = true; 208 } 209 210 comp_info->scan_info.is_mlme_op_in_progress = false; 211 212 status = wlan_util_is_pdev_scan_allowed(pdev, WLAN_MLME_SER_IF_ID); 213 if (status != QDF_STATUS_SUCCESS) 214 comp_info->scan_info.is_mlme_op_in_progress = true; 215 } 216 217 QDF_STATUS wlan_mlme_psoc_enable(struct wlan_objmgr_psoc *psoc) 218 { 219 QDF_STATUS status; 220 struct wlan_lmac_if_mlme_tx_ops *tx_ops; 221 222 status = wlan_serialization_register_comp_info_cb 223 (psoc, 224 WLAN_UMAC_COMP_MLME, 225 WLAN_SER_CMD_SCAN, 226 mlme_scan_serialization_comp_info_cb); 227 if (status != QDF_STATUS_SUCCESS) { 228 mlme_err("Serialize scan cmd register failed"); 229 return status; 230 } 231 232 /* Register for WMI events into target_if rx */ 233 tx_ops = wlan_mlme_get_lmac_tx_ops(psoc); 234 if (tx_ops && tx_ops->vdev_mlme_attach) 235 tx_ops->vdev_mlme_attach(psoc); 236 237 return QDF_STATUS_SUCCESS; 238 } 239 240 QDF_STATUS wlan_mlme_psoc_disable(struct wlan_objmgr_psoc *psoc) 241 { 242 QDF_STATUS status; 243 struct wlan_lmac_if_mlme_tx_ops *tx_ops; 244 245 status = wlan_serialization_deregister_comp_info_cb 246 (psoc, 247 WLAN_UMAC_COMP_MLME, 248 WLAN_SER_CMD_SCAN); 249 if (status != QDF_STATUS_SUCCESS) { 250 mlme_err("Serialize scan cmd deregister failed"); 251 return status; 252 } 253 254 /* Unregister WMI events */ 255 tx_ops = wlan_mlme_get_lmac_tx_ops(psoc); 256 if (tx_ops && tx_ops->vdev_mlme_detach) 257 tx_ops->vdev_mlme_detach(psoc); 258 259 return QDF_STATUS_SUCCESS; 260 } 261 262 QDF_STATUS wlan_vdev_mlme_init(void) 263 { 264 if (wlan_objmgr_register_vdev_create_handler 265 (WLAN_UMAC_COMP_MLME, 266 mlme_vdev_obj_create_handler, NULL) 267 != QDF_STATUS_SUCCESS) 268 return QDF_STATUS_E_FAILURE; 269 270 if (wlan_objmgr_register_vdev_destroy_handler 271 (WLAN_UMAC_COMP_MLME, 272 mlme_vdev_obj_destroy_handler, NULL) 273 != QDF_STATUS_SUCCESS) { 274 if (wlan_objmgr_unregister_vdev_create_handler 275 (WLAN_UMAC_COMP_MLME, 276 mlme_vdev_obj_create_handler, NULL) 277 != QDF_STATUS_SUCCESS) 278 return QDF_STATUS_E_FAILURE; 279 280 return QDF_STATUS_E_FAILURE; 281 } 282 283 return QDF_STATUS_SUCCESS; 284 } 285 286 QDF_STATUS wlan_vdev_mlme_deinit(void) 287 { 288 if (wlan_objmgr_unregister_vdev_create_handler 289 (WLAN_UMAC_COMP_MLME, 290 mlme_vdev_obj_create_handler, NULL) 291 != QDF_STATUS_SUCCESS) 292 return QDF_STATUS_E_FAILURE; 293 294 if (wlan_objmgr_unregister_vdev_destroy_handler 295 (WLAN_UMAC_COMP_MLME, 296 mlme_vdev_obj_destroy_handler, NULL) 297 != QDF_STATUS_SUCCESS) 298 return QDF_STATUS_E_FAILURE; 299 300 return QDF_STATUS_SUCCESS; 301 } 302