1 /* 2 * Copyright (c) 2017-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 <wlan_spectral_ucfg_api.h> 21 #include "../../core/spectral_cmn_api_i.h" 22 #include <wlan_spectral_utils_api.h> 23 #include <qdf_module.h> 24 #include <cfg_ucfg_api.h> 25 26 static bool 27 ucfg_spectral_is_mode_specific_request(uint8_t spectral_cp_request_id) 28 { 29 bool mode_specific_request; 30 31 switch (spectral_cp_request_id) { 32 case SPECTRAL_SET_CONFIG: 33 case SPECTRAL_GET_CONFIG: 34 case SPECTRAL_IS_ACTIVE: 35 case SPECTRAL_IS_ENABLED: 36 case SPECTRAL_ACTIVATE_SCAN: 37 case SPECTRAL_STOP_SCAN: 38 mode_specific_request = true; 39 break; 40 case SPECTRAL_SET_DEBUG_LEVEL: 41 case SPECTRAL_GET_DEBUG_LEVEL: 42 case SPECTRAL_GET_CAPABILITY_INFO: 43 case SPECTRAL_GET_DIAG_STATS: 44 case SPECTRAL_GET_CHAN_WIDTH: 45 case SPECTRAL_SET_DMA_DEBUG: 46 mode_specific_request = false; 47 break; 48 default: 49 spectral_err("Invalid spectral cp request id %u", 50 spectral_cp_request_id); 51 mode_specific_request = false; 52 } 53 54 return mode_specific_request; 55 } 56 57 QDF_STATUS 58 ucfg_spectral_control(struct wlan_objmgr_pdev *pdev, 59 struct spectral_cp_request *sscan_req) 60 { 61 struct spectral_context *sc; 62 63 if (!pdev) { 64 spectral_err("PDEV is NULL!"); 65 return QDF_STATUS_E_INVAL; 66 } 67 68 if (wlan_spectral_is_feature_disabled_pdev(pdev)) { 69 spectral_info("Spectral feature is disabled"); 70 return QDF_STATUS_COMP_DISABLED; 71 } 72 73 /* For mode specific requests, check whether 74 * Spectral mode in the cp request is disabaled 75 */ 76 if (ucfg_spectral_is_mode_specific_request(sscan_req->req_id) && 77 wlan_spectral_is_mode_disabled_pdev(pdev, sscan_req->ss_mode)) { 78 spectral_info("Spectral mode %d is disabled", 79 sscan_req->ss_mode); 80 return QDF_STATUS_E_NOSUPPORT; 81 } 82 83 sc = spectral_get_spectral_ctx_from_pdev(pdev); 84 if (!sc) { 85 spectral_err("spectral context is NULL!"); 86 return QDF_STATUS_E_INVAL; 87 } 88 89 return sc->sptrlc_spectral_control(pdev, sscan_req); 90 } 91 qdf_export_symbol(ucfg_spectral_control); 92 93 void ucfg_spectral_scan_set_ppid(struct wlan_objmgr_pdev *pdev, uint32_t ppid) 94 { 95 struct pdev_spectral *ps = NULL; 96 97 if (!pdev) { 98 spectral_err("PDEV is NULL!"); 99 return; 100 } 101 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, 102 WLAN_UMAC_COMP_SPECTRAL); 103 if (!ps) { 104 spectral_err("spectral context is NULL!"); 105 return; 106 } 107 ps->spectral_pid = ppid; 108 spectral_debug("spectral ppid: %d", ppid); 109 110 return; 111 } 112 113 QDF_STATUS ucfg_spectral_create_cp_req(struct spectral_cp_request *sscan_req, 114 void *indata, u_int32_t insize) 115 { 116 QDF_STATUS status = QDF_STATUS_SUCCESS; 117 118 switch (sscan_req->req_id) { 119 case SPECTRAL_SET_CONFIG: 120 { 121 if (insize < sizeof(struct spectral_config) || 122 !indata) { 123 status = QDF_STATUS_E_FAILURE; 124 goto bad; 125 } 126 qdf_mem_copy(&sscan_req->config_req.sscan_config, 127 indata, 128 sizeof(struct spectral_config)); 129 } 130 break; 131 132 case SPECTRAL_SET_DEBUG_LEVEL: 133 { 134 if (insize < sizeof(uint32_t) || !indata) { 135 status = QDF_STATUS_E_FAILURE; 136 goto bad; 137 } 138 sscan_req->debug_req.spectral_dbg_level = 139 *(uint32_t *)indata; 140 } 141 break; 142 143 default: 144 break; 145 } 146 147 bad: 148 return status; 149 } 150 151 qdf_export_symbol(ucfg_spectral_create_cp_req); 152 153 QDF_STATUS ucfg_spectral_extract_response(struct spectral_cp_request *sscan_req, 154 void *outdata, u_int32_t *outsize) 155 { 156 QDF_STATUS status = QDF_STATUS_SUCCESS; 157 158 switch (sscan_req->req_id) { 159 case SPECTRAL_GET_CONFIG: 160 { 161 if (!outdata || !outsize || 162 (*outsize < sizeof(struct spectral_config))) { 163 status = QDF_STATUS_E_FAILURE; 164 goto bad; 165 } 166 *outsize = sizeof(struct spectral_config); 167 qdf_mem_copy(outdata, 168 &sscan_req->config_req.sscan_config, 169 sizeof(struct spectral_config)); 170 } 171 break; 172 173 case SPECTRAL_IS_ACTIVE: 174 { 175 if (!outdata || !outsize || 176 *outsize < sizeof(uint32_t)) { 177 status = QDF_STATUS_E_FAILURE; 178 goto bad; 179 } 180 *outsize = sizeof(uint32_t); 181 *((uint32_t *)outdata) = 182 sscan_req->status_req.is_active; 183 } 184 break; 185 186 case SPECTRAL_IS_ENABLED: 187 { 188 if (!outdata || !outsize || 189 *outsize < sizeof(uint32_t)) { 190 status = QDF_STATUS_E_FAILURE; 191 goto bad; 192 } 193 *outsize = sizeof(uint32_t); 194 *((uint32_t *)outdata) = 195 sscan_req->status_req.is_enabled; 196 } 197 break; 198 199 case SPECTRAL_GET_DEBUG_LEVEL: 200 { 201 if (!outdata || !outsize || 202 *outsize < sizeof(uint32_t)) { 203 status = QDF_STATUS_E_FAILURE; 204 goto bad; 205 } 206 *outsize = sizeof(uint32_t); 207 *((uint32_t *)outdata) = 208 sscan_req->debug_req.spectral_dbg_level; 209 } 210 break; 211 212 case SPECTRAL_GET_CAPABILITY_INFO: 213 { 214 if (!outdata || !outsize || 215 *outsize < sizeof(struct spectral_caps)) { 216 status = QDF_STATUS_E_FAILURE; 217 goto bad; 218 } 219 *outsize = sizeof(struct spectral_caps); 220 qdf_mem_copy(outdata, &sscan_req->caps_req.sscan_caps, 221 sizeof(struct spectral_caps)); 222 } 223 break; 224 225 case SPECTRAL_GET_DIAG_STATS: 226 { 227 if (!outdata || !outsize || 228 (*outsize < sizeof(struct spectral_diag_stats))) { 229 status = QDF_STATUS_E_FAILURE; 230 goto bad; 231 } 232 *outsize = sizeof(struct spectral_diag_stats); 233 qdf_mem_copy(outdata, &sscan_req->diag_req.sscan_diag, 234 sizeof(struct spectral_diag_stats)); 235 } 236 break; 237 238 case SPECTRAL_GET_CHAN_WIDTH: 239 { 240 if (!outdata || !outsize || 241 *outsize < sizeof(uint32_t)) { 242 status = QDF_STATUS_E_FAILURE; 243 goto bad; 244 } 245 *outsize = sizeof(uint32_t); 246 *((uint32_t *)outdata) = 247 sscan_req->chan_width_req.chan_width; 248 } 249 break; 250 251 default: 252 break; 253 } 254 255 bad: 256 return status; 257 } 258 259 qdf_export_symbol(ucfg_spectral_extract_response); 260 261 QDF_STATUS ucfg_spectral_register_to_dbr(struct wlan_objmgr_pdev *pdev) 262 { 263 return spectral_pdev_open(pdev); 264 } 265 266 QDF_STATUS ucfg_spectral_get_version(struct wlan_objmgr_pdev *pdev, 267 uint32_t *version, uint32_t *sub_version) 268 { 269 if (!pdev || !version || !sub_version) { 270 spectral_err("invalid param"); 271 return QDF_STATUS_E_INVAL; 272 } 273 274 *version = SPECTRAL_VERSION; 275 *sub_version = SPECTRAL_SUB_VERSION; 276 spectral_debug("Spectral get version %d:%d", *version, *sub_version); 277 278 return QDF_STATUS_SUCCESS; 279 } 280