1 /* 2 * Copyright (c) 2018-2019 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 37 static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, 38 void *arg) 39 { 40 struct vdev_mlme_obj *vdev_mlme; 41 struct wlan_objmgr_pdev *pdev; 42 struct wlan_objmgr_psoc *psoc; 43 struct pdev_mlme_obj *pdev_mlme; 44 struct wlan_lmac_if_mlme_tx_ops *txops; 45 QDF_STATUS status; 46 47 if (!vdev) { 48 mlme_err(" VDEV is NULL"); 49 return QDF_STATUS_E_FAILURE; 50 } 51 52 pdev = wlan_vdev_get_pdev(vdev); 53 if (!pdev) { 54 mlme_err(" PDEV is NULL"); 55 return QDF_STATUS_E_FAILURE; 56 } 57 58 /** 59 * 1st check whether for this vdev any vdev commands are pending for 60 * response. 61 */ 62 psoc = wlan_pdev_get_psoc(pdev); 63 if (!psoc) { 64 mlme_err("PSOC is NULL"); 65 return QDF_STATUS_E_FAILURE; 66 } 67 68 txops = wlan_mlme_get_lmac_tx_ops(psoc); 69 if (!txops || !txops->psoc_vdev_rsp_timer_inuse) { 70 mlme_err("Failed to get mlme txrx_ops PSOC_%d", 71 wlan_psoc_get_id(psoc)); 72 return QDF_STATUS_E_FAILURE; 73 } 74 75 status = txops->psoc_vdev_rsp_timer_inuse(psoc, wlan_vdev_get_id(vdev)); 76 if (QDF_IS_STATUS_ERROR(status)) { 77 mlme_err("The vdev response is pending for VDEV_%d status:%d", 78 wlan_vdev_get_id(vdev), status); 79 return QDF_STATUS_E_FAILURE; 80 } 81 82 pdev_mlme = wlan_pdev_mlme_get_cmpt_obj(pdev); 83 if (!pdev_mlme) { 84 mlme_err("PDEV MLME is NULL"); 85 return QDF_STATUS_E_FAILURE; 86 } 87 88 vdev_mlme = qdf_mem_malloc(sizeof(*vdev_mlme)); 89 if (!vdev_mlme) 90 return QDF_STATUS_E_NOMEM; 91 92 vdev_mlme->vdev = vdev; 93 94 if (pdev_mlme->mlme_register_ops(vdev_mlme) != QDF_STATUS_SUCCESS) { 95 mlme_err("Callbacks registration is failed"); 96 goto init_failed; 97 } 98 99 if (mlme_vdev_sm_create(vdev_mlme) != QDF_STATUS_SUCCESS) { 100 mlme_err("SME creation failed"); 101 goto init_failed; 102 } 103 104 if (mlme_vdev_ops_ext_hdl_create(vdev_mlme) != 105 QDF_STATUS_SUCCESS) { 106 mlme_err("Legacy vdev object creation failed"); 107 goto ext_hdl_create_failed; 108 } 109 110 wlan_objmgr_vdev_component_obj_attach((struct wlan_objmgr_vdev *)vdev, 111 WLAN_UMAC_COMP_MLME, 112 (void *)vdev_mlme, 113 QDF_STATUS_SUCCESS); 114 115 if (mlme_vdev_ops_ext_hdl_post_create(vdev_mlme) != 116 QDF_STATUS_SUCCESS) { 117 mlme_err("Legacy vdev object post creation failed"); 118 goto ext_hdl_post_create_failed; 119 } 120 121 return QDF_STATUS_SUCCESS; 122 123 ext_hdl_post_create_failed: 124 mlme_vdev_ops_ext_hdl_destroy(vdev_mlme); 125 wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME, 126 vdev_mlme); 127 ext_hdl_create_failed: 128 mlme_vdev_sm_destroy(vdev_mlme); 129 init_failed: 130 qdf_mem_free(vdev_mlme); 131 132 return QDF_STATUS_E_FAILURE; 133 } 134 135 static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, 136 void *arg) 137 { 138 struct vdev_mlme_obj *vdev_mlme; 139 struct wlan_objmgr_psoc *psoc; 140 struct cdp_soc_t *soc_txrx_handle; 141 142 if (!vdev) { 143 mlme_err(" VDEV is NULL"); 144 return QDF_STATUS_E_FAILURE; 145 } 146 147 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 148 if (!vdev_mlme) { 149 mlme_info(" VDEV MLME component object is NULL"); 150 return QDF_STATUS_SUCCESS; 151 } 152 153 psoc = wlan_vdev_get_psoc(vdev); 154 soc_txrx_handle = (struct cdp_soc_t *)wlan_psoc_get_dp_handle(psoc); 155 if (soc_txrx_handle) { 156 wlan_vdev_set_dp_handle(vdev, NULL); 157 cdp_vdev_detach(soc_txrx_handle, wlan_vdev_get_id(vdev), 158 NULL, NULL); 159 } 160 161 mlme_vdev_sm_destroy(vdev_mlme); 162 163 mlme_vdev_ops_ext_hdl_destroy(vdev_mlme); 164 165 wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME, 166 vdev_mlme); 167 qdf_mem_free(vdev_mlme); 168 169 return QDF_STATUS_SUCCESS; 170 } 171 172 static void mlme_scan_serialization_comp_info_cb( 173 struct wlan_objmgr_vdev *vdev, 174 union wlan_serialization_rules_info *comp_info) 175 { 176 struct wlan_objmgr_pdev *pdev; 177 QDF_STATUS status; 178 179 if (!comp_info || !vdev) { 180 mlme_err("comp_info or vdev is NULL"); 181 return; 182 } 183 184 pdev = wlan_vdev_get_pdev(vdev); 185 if (!pdev) { 186 mlme_err("pdev is NULL"); 187 return; 188 } 189 190 comp_info->scan_info.is_mlme_op_in_progress = false; 191 192 status = wlan_util_is_pdev_scan_allowed(pdev, WLAN_MLME_SER_IF_ID); 193 if (status != QDF_STATUS_SUCCESS) 194 comp_info->scan_info.is_mlme_op_in_progress = true; 195 } 196 197 QDF_STATUS wlan_mlme_psoc_enable(struct wlan_objmgr_psoc *psoc) 198 { 199 QDF_STATUS status; 200 struct wlan_lmac_if_mlme_tx_ops *tx_ops; 201 202 status = wlan_serialization_register_comp_info_cb 203 (psoc, 204 WLAN_UMAC_COMP_MLME, 205 WLAN_SER_CMD_SCAN, 206 mlme_scan_serialization_comp_info_cb); 207 if (status != QDF_STATUS_SUCCESS) { 208 mlme_err("Serialize scan cmd register failed"); 209 return status; 210 } 211 212 /* Register for WMI events into target_if rx */ 213 tx_ops = wlan_mlme_get_lmac_tx_ops(psoc); 214 if (tx_ops && tx_ops->vdev_mlme_attach) 215 tx_ops->vdev_mlme_attach(psoc); 216 217 return QDF_STATUS_SUCCESS; 218 } 219 220 QDF_STATUS wlan_mlme_psoc_disable(struct wlan_objmgr_psoc *psoc) 221 { 222 QDF_STATUS status; 223 struct wlan_lmac_if_mlme_tx_ops *tx_ops; 224 225 status = wlan_serialization_deregister_comp_info_cb 226 (psoc, 227 WLAN_UMAC_COMP_MLME, 228 WLAN_SER_CMD_SCAN); 229 if (status != QDF_STATUS_SUCCESS) { 230 mlme_err("Serialize scan cmd deregister failed"); 231 return status; 232 } 233 234 /* Unregister WMI events */ 235 tx_ops = wlan_mlme_get_lmac_tx_ops(psoc); 236 if (tx_ops && tx_ops->vdev_mlme_detach) 237 tx_ops->vdev_mlme_detach(psoc); 238 239 return QDF_STATUS_SUCCESS; 240 } 241 242 QDF_STATUS wlan_vdev_mlme_init(void) 243 { 244 if (wlan_objmgr_register_vdev_create_handler 245 (WLAN_UMAC_COMP_MLME, 246 mlme_vdev_obj_create_handler, NULL) 247 != QDF_STATUS_SUCCESS) 248 return QDF_STATUS_E_FAILURE; 249 250 if (wlan_objmgr_register_vdev_destroy_handler 251 (WLAN_UMAC_COMP_MLME, 252 mlme_vdev_obj_destroy_handler, NULL) 253 != QDF_STATUS_SUCCESS) { 254 if (wlan_objmgr_unregister_vdev_create_handler 255 (WLAN_UMAC_COMP_MLME, 256 mlme_vdev_obj_create_handler, NULL) 257 != QDF_STATUS_SUCCESS) 258 return QDF_STATUS_E_FAILURE; 259 260 return QDF_STATUS_E_FAILURE; 261 } 262 263 return QDF_STATUS_SUCCESS; 264 } 265 266 QDF_STATUS wlan_vdev_mlme_deinit(void) 267 { 268 if (wlan_objmgr_unregister_vdev_create_handler 269 (WLAN_UMAC_COMP_MLME, 270 mlme_vdev_obj_create_handler, NULL) 271 != QDF_STATUS_SUCCESS) 272 return QDF_STATUS_E_FAILURE; 273 274 if (wlan_objmgr_unregister_vdev_destroy_handler 275 (WLAN_UMAC_COMP_MLME, 276 mlme_vdev_obj_destroy_handler, NULL) 277 != QDF_STATUS_SUCCESS) 278 return QDF_STATUS_E_FAILURE; 279 280 return QDF_STATUS_SUCCESS; 281 } 282