1 /* 2 * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. 3 * 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 29 /* Function pointer to call DA/OL specific tx_ops registration function */ 30 QDF_STATUS (*wlan_global_lmac_if_tx_ops_register[MAX_DEV_TYPE]) 31 (struct wlan_lmac_if_tx_ops *tx_ops); 32 33 /* 34 * spectral scan is built as separate .ko for WIN where 35 * MCL it is part of wlan.ko so the registration of 36 .* rx ops to global lmac if layer is different between WIN 37 * and MCL 38 */ 39 #ifdef WLAN_CONV_SPECTRAL_ENABLE 40 /** 41 * wlan_spectral_register_rx_ops() - Register spectral component RX OPS 42 * @rx_ops: lmac if receive ops 43 * 44 * Return: None 45 */ 46 #ifdef SPECTRAL_MODULIZED_ENABLE 47 /* Function pointer for spectral rx_ops registration function */ 48 void (*wlan_lmac_if_sptrl_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops); 49 50 QDF_STATUS wlan_lmac_if_sptrl_set_rx_ops_register_cb(void (*handler) 51 (struct wlan_lmac_if_rx_ops *)) 52 { 53 wlan_lmac_if_sptrl_rx_ops = handler; 54 55 return QDF_STATUS_SUCCESS; 56 } 57 58 qdf_export_symbol(wlan_lmac_if_sptrl_set_rx_ops_register_cb); 59 60 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 61 { 62 wlan_lmac_if_sptrl_rx_ops(rx_ops); 63 } 64 #else 65 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 66 { 67 wlan_lmac_if_sptrl_register_rx_ops(rx_ops); 68 } 69 #endif /* SPECTRAL_MODULIZED_ENABLE */ 70 #else 71 /** 72 * wlan_spectral_register_rx_ops() - Dummy api to register spectral RX OPS 73 * @rx_ops: lmac if receive ops 74 * 75 * Return: None 76 */ 77 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 78 { 79 } 80 #endif /*WLAN_CONV_SPECTRAL_ENABLE*/ 81 82 #ifdef WLAN_IOT_SIM_SUPPORT 83 /* Function pointer for iot_sim rx_ops registration function */ 84 void (*wlan_lmac_if_iot_sim_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops); 85 86 QDF_STATUS wlan_lmac_if_iot_sim_set_rx_ops_register_cb(void (*handler) 87 (struct wlan_lmac_if_rx_ops *)) 88 { 89 wlan_lmac_if_iot_sim_rx_ops = handler; 90 91 return QDF_STATUS_SUCCESS; 92 } 93 94 qdf_export_symbol(wlan_lmac_if_iot_sim_set_rx_ops_register_cb); 95 96 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 97 { 98 if (wlan_lmac_if_iot_sim_rx_ops) 99 wlan_lmac_if_iot_sim_rx_ops(rx_ops); 100 else 101 qdf_print("\n***** IOT SIM MODULE NOT LOADED *****\n"); 102 } 103 104 #else 105 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 106 { 107 } 108 #endif 109 110 /** 111 * wlan_global_lmac_if_rx_ops_register() - Global lmac_if 112 * rx handler register 113 * @rx_ops: Pointer to rx_ops structure to be populated 114 * 115 * Register lmac_if RX callabacks which will be called by DA/OL/WMA/WMI 116 * 117 * Return: QDF_STATUS_SUCCESS - in case of success 118 */ 119 QDF_STATUS 120 wlan_global_lmac_if_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) 121 { 122 /* 123 * Component specific public api's to be called to register 124 * respective callbacks 125 * Ex: rx_ops->fp = function; 126 */ 127 if (!rx_ops) { 128 qdf_err("lmac if rx ops pointer is NULL"); 129 return QDF_STATUS_E_INVAL; 130 } 131 /* Registeration for UMAC componets */ 132 wlan_lmac_if_umac_rx_ops_register(rx_ops); 133 134 /* spectral rx_ops registration*/ 135 wlan_spectral_register_rx_ops(rx_ops); 136 137 /* iot_sim rx_ops registration*/ 138 wlan_iot_sim_register_rx_ops(rx_ops); 139 140 return QDF_STATUS_SUCCESS; 141 } 142 143 /** 144 * wlan_global_lmac_if_open() - global lmac_if open 145 * @psoc: psoc context 146 * 147 * Opens up lmac_if southbound layer. This function calls OL,DA and UMAC 148 * modules to register respective tx and rx callbacks. 149 * 150 * Return: QDF_STATUS 151 */ 152 QDF_STATUS wlan_global_lmac_if_open(struct wlan_objmgr_psoc *psoc) 153 { 154 WLAN_DEV_TYPE dev_type; 155 156 struct wlan_lmac_if_tx_ops *tx_ops; 157 struct wlan_lmac_if_rx_ops *rx_ops; 158 159 if (!psoc) { 160 qdf_err("psoc is NULL"); 161 return QDF_STATUS_E_INVAL; 162 } 163 164 tx_ops = qdf_mem_malloc(sizeof(*tx_ops)); 165 if (!tx_ops) { 166 qdf_err("tx_ops is NULL"); 167 return QDF_STATUS_E_NOMEM; 168 } 169 170 rx_ops = qdf_mem_malloc(sizeof(*rx_ops)); 171 if (!rx_ops) { 172 qdf_err("rx_ops is NULL"); 173 qdf_mem_free(tx_ops); 174 return QDF_STATUS_E_NOMEM; 175 } 176 177 wlan_psoc_set_lmac_if_txops(psoc, tx_ops); 178 wlan_psoc_set_lmac_if_rxops(psoc, rx_ops); 179 180 dev_type = psoc->soc_nif.phy_type; 181 182 if (dev_type == WLAN_DEV_DA || dev_type == WLAN_DEV_OL) { 183 wlan_global_lmac_if_tx_ops_register[dev_type] 184 (tx_ops); 185 } else { 186 /* Control should ideally not reach here */ 187 qdf_print("Invalid device type"); 188 qdf_mem_free(tx_ops); 189 qdf_mem_free(rx_ops); 190 return QDF_STATUS_E_INVAL; 191 } 192 193 /* Function call to register rx-ops handlers */ 194 wlan_global_lmac_if_rx_ops_register(rx_ops); 195 196 return QDF_STATUS_SUCCESS; 197 } 198 qdf_export_symbol(wlan_global_lmac_if_open); 199 200 /** 201 * wlan_global_lmac_if_close() - Close global lmac_if 202 * @psoc: psoc context 203 * 204 * Deregister lmac_if TX and RX handlers 205 * 206 * Return: QDF_STATUS_SUCCESS - in case of success 207 */ 208 QDF_STATUS wlan_global_lmac_if_close(struct wlan_objmgr_psoc *psoc) 209 { 210 struct wlan_lmac_if_tx_ops *tx_ops; 211 struct wlan_lmac_if_rx_ops *rx_ops; 212 213 if (!psoc) { 214 qdf_err("psoc is NULL"); 215 return QDF_STATUS_E_INVAL; 216 } 217 218 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 219 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 220 221 wlan_psoc_set_lmac_if_txops(psoc, NULL); 222 wlan_psoc_set_lmac_if_rxops(psoc, NULL); 223 224 qdf_mem_free(tx_ops); 225 qdf_mem_free(rx_ops); 226 227 return QDF_STATUS_SUCCESS; 228 } 229 qdf_export_symbol(wlan_global_lmac_if_close); 230 231 /** 232 * wlan_global_lmac_if_set_txops_registration_cb() - tx 233 * registration callback assignment 234 * @dev_type: Dev type can be either Direct attach or Offload 235 * @handler: handler to be called for LMAC tx ops registration 236 * 237 * API to assign appropriate tx registration callback handler based on the 238 * device type(Offload or Direct attach) 239 * 240 * Return: QDF_STATUS_SUCCESS - in case of success 241 */ 242 QDF_STATUS wlan_global_lmac_if_set_txops_registration_cb(WLAN_DEV_TYPE dev_type, 243 QDF_STATUS (*handler)(struct wlan_lmac_if_tx_ops *)) 244 { 245 wlan_global_lmac_if_tx_ops_register[dev_type] = handler; 246 247 return QDF_STATUS_SUCCESS; 248 } 249 qdf_export_symbol(wlan_global_lmac_if_set_txops_registration_cb); 250