1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "qdf_mem.h" 21 #include "qdf_module.h" 22 #include "wlan_lmac_if_def.h" 23 #include "wlan_lmac_if_api.h" 24 #include "wlan_global_lmac_if_api.h" 25 #ifdef WLAN_CONV_SPECTRAL_ENABLE 26 #include <wlan_spectral_utils_api.h> 27 #endif 28 #include <target_if_psoc_wake_lock.h> 29 30 /* Function pointer to call DA/OL specific tx_ops registration function */ 31 QDF_STATUS (*wlan_global_lmac_if_tx_ops_register[MAX_DEV_TYPE]) 32 (struct wlan_lmac_if_tx_ops *tx_ops); 33 34 /* 35 * spectral scan is built as separate .ko for WIN where 36 * MCL it is part of wlan.ko so the registration of 37 .* rx ops to global lmac if layer is different between WIN 38 * and MCL 39 */ 40 #ifdef WLAN_CONV_SPECTRAL_ENABLE 41 #ifdef SPECTRAL_MODULIZED_ENABLE 42 /* Function pointer for spectral rx_ops registration function */ 43 void (*wlan_lmac_if_sptrl_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops); 44 45 QDF_STATUS wlan_lmac_if_sptrl_set_rx_ops_register_cb(void (*handler) 46 (struct wlan_lmac_if_rx_ops *)) 47 { 48 wlan_lmac_if_sptrl_rx_ops = handler; 49 50 return QDF_STATUS_SUCCESS; 51 } 52 53 qdf_export_symbol(wlan_lmac_if_sptrl_set_rx_ops_register_cb); 54 55 /** 56 * wlan_spectral_register_rx_ops() - Register spectral component RX OPS 57 * @rx_ops: lmac if receive ops 58 * 59 * Return: None 60 */ 61 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 62 { 63 wlan_lmac_if_sptrl_rx_ops(rx_ops); 64 } 65 #else 66 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 67 { 68 wlan_lmac_if_sptrl_register_rx_ops(rx_ops); 69 } 70 #endif /* SPECTRAL_MODULIZED_ENABLE */ 71 #else 72 /** 73 * wlan_spectral_register_rx_ops() - Dummy api to register spectral RX OPS 74 * @rx_ops: lmac if receive ops 75 * 76 * Return: None 77 */ 78 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 79 { 80 } 81 #endif /*WLAN_CONV_SPECTRAL_ENABLE*/ 82 83 #ifdef WLAN_IOT_SIM_SUPPORT 84 /* Function pointer for iot_sim rx_ops registration function */ 85 void (*wlan_lmac_if_iot_sim_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops); 86 87 QDF_STATUS wlan_lmac_if_iot_sim_set_rx_ops_register_cb(void (*handler) 88 (struct wlan_lmac_if_rx_ops *)) 89 { 90 wlan_lmac_if_iot_sim_rx_ops = handler; 91 92 return QDF_STATUS_SUCCESS; 93 } 94 95 qdf_export_symbol(wlan_lmac_if_iot_sim_set_rx_ops_register_cb); 96 97 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 98 { 99 if (wlan_lmac_if_iot_sim_rx_ops) 100 wlan_lmac_if_iot_sim_rx_ops(rx_ops); 101 else 102 qdf_print("\n***** IOT SIM MODULE NOT LOADED *****\n"); 103 } 104 105 #else 106 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 107 { 108 } 109 #endif 110 111 #if defined(QCA_SUPPORT_SON) || defined(WLAN_FEATURE_SON) 112 /* Function pointer for son rx_ops registration function */ 113 void (*wlan_lmac_if_son_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops); 114 115 QDF_STATUS wlan_lmac_if_son_set_rx_ops_register_cb(void (*handler) 116 (struct wlan_lmac_if_rx_ops *)) 117 { 118 wlan_lmac_if_son_rx_ops = handler; 119 120 return QDF_STATUS_SUCCESS; 121 } 122 123 qdf_export_symbol(wlan_lmac_if_son_set_rx_ops_register_cb); 124 125 static void wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 126 { 127 if (wlan_lmac_if_son_rx_ops) 128 wlan_lmac_if_son_rx_ops(rx_ops); 129 else 130 qdf_info("\n***** SON MODULE NOT LOADED *****\n"); 131 } 132 133 void wlan_lmac_if_son_mod_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 134 { 135 wlan_son_register_rx_ops(rx_ops); 136 } 137 #else 138 static void wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 139 { 140 } 141 #endif 142 143 /** 144 * wlan_global_lmac_if_rx_ops_register() - Global lmac_if 145 * rx handler register 146 * @rx_ops: Pointer to rx_ops structure to be populated 147 * 148 * Register lmac_if RX callabacks which will be called by DA/OL/WMA/WMI 149 * 150 * Return: QDF_STATUS_SUCCESS - in case of success 151 */ 152 QDF_STATUS 153 wlan_global_lmac_if_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) 154 { 155 /* 156 * Component specific public api's to be called to register 157 * respective callbacks 158 * Ex: rx_ops->fp = function; 159 */ 160 if (!rx_ops) { 161 qdf_err("lmac if rx ops pointer is NULL"); 162 return QDF_STATUS_E_INVAL; 163 } 164 /* Registration for UMAC components */ 165 wlan_lmac_if_umac_rx_ops_register(rx_ops); 166 167 /* spectral rx_ops registration*/ 168 wlan_spectral_register_rx_ops(rx_ops); 169 170 /* iot_sim rx_ops registration*/ 171 wlan_iot_sim_register_rx_ops(rx_ops); 172 173 /* son rx_ops registration*/ 174 wlan_son_register_rx_ops(rx_ops); 175 176 return QDF_STATUS_SUCCESS; 177 } 178 179 /** 180 * wlan_global_lmac_if_open() - global lmac_if open 181 * @psoc: psoc context 182 * 183 * Opens up lmac_if southbound layer. This function calls OL,DA and UMAC 184 * modules to register respective tx and rx callbacks. 185 * 186 * Return: QDF_STATUS 187 */ 188 QDF_STATUS wlan_global_lmac_if_open(struct wlan_objmgr_psoc *psoc) 189 { 190 WLAN_DEV_TYPE dev_type; 191 192 struct wlan_lmac_if_tx_ops *tx_ops; 193 struct wlan_lmac_if_rx_ops *rx_ops; 194 195 if (!psoc) { 196 qdf_err("psoc is NULL"); 197 return QDF_STATUS_E_INVAL; 198 } 199 200 tx_ops = qdf_mem_malloc(sizeof(*tx_ops)); 201 if (!tx_ops) { 202 qdf_err("tx_ops is NULL"); 203 return QDF_STATUS_E_NOMEM; 204 } 205 206 rx_ops = qdf_mem_malloc(sizeof(*rx_ops)); 207 if (!rx_ops) { 208 qdf_err("rx_ops is NULL"); 209 qdf_mem_free(tx_ops); 210 return QDF_STATUS_E_NOMEM; 211 } 212 213 wlan_psoc_set_lmac_if_txops(psoc, tx_ops); 214 wlan_psoc_set_lmac_if_rxops(psoc, rx_ops); 215 216 dev_type = psoc->soc_nif.phy_type; 217 218 if (dev_type == WLAN_DEV_OL) { 219 wlan_global_lmac_if_tx_ops_register[dev_type] 220 (tx_ops); 221 } else { 222 /* Control should ideally not reach here */ 223 qdf_print("Invalid device type"); 224 qdf_mem_free(tx_ops); 225 qdf_mem_free(rx_ops); 226 return QDF_STATUS_E_INVAL; 227 } 228 229 /* Function call to register rx-ops handlers */ 230 wlan_global_lmac_if_rx_ops_register(rx_ops); 231 232 target_if_wake_lock_init(psoc); 233 234 return QDF_STATUS_SUCCESS; 235 } 236 qdf_export_symbol(wlan_global_lmac_if_open); 237 238 /** 239 * wlan_global_lmac_if_close() - Close global lmac_if 240 * @psoc: psoc context 241 * 242 * Deregister lmac_if TX and RX handlers 243 * 244 * Return: QDF_STATUS_SUCCESS - in case of success 245 */ 246 QDF_STATUS wlan_global_lmac_if_close(struct wlan_objmgr_psoc *psoc) 247 { 248 struct wlan_lmac_if_tx_ops *tx_ops; 249 struct wlan_lmac_if_rx_ops *rx_ops; 250 251 if (!psoc) { 252 qdf_err("psoc is NULL"); 253 return QDF_STATUS_E_INVAL; 254 } 255 256 target_if_wake_lock_deinit(psoc); 257 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 258 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 259 260 wlan_psoc_set_lmac_if_txops(psoc, NULL); 261 wlan_psoc_set_lmac_if_rxops(psoc, NULL); 262 263 qdf_mem_free(tx_ops); 264 qdf_mem_free(rx_ops); 265 266 return QDF_STATUS_SUCCESS; 267 } 268 qdf_export_symbol(wlan_global_lmac_if_close); 269 270 /** 271 * wlan_global_lmac_if_set_txops_registration_cb() - tx 272 * registration callback assignment 273 * @dev_type: Dev type can be either Direct attach or Offload 274 * @handler: handler to be called for LMAC tx ops registration 275 * 276 * API to assign appropriate tx registration callback handler based on the 277 * device type(Offload or Direct attach) 278 * 279 * Return: QDF_STATUS_SUCCESS - in case of success 280 */ 281 QDF_STATUS wlan_global_lmac_if_set_txops_registration_cb(WLAN_DEV_TYPE dev_type, 282 QDF_STATUS (*handler)(struct wlan_lmac_if_tx_ops *)) 283 { 284 wlan_global_lmac_if_tx_ops_register[dev_type] = handler; 285 286 return QDF_STATUS_SUCCESS; 287 } 288 qdf_export_symbol(wlan_global_lmac_if_set_txops_registration_cb); 289