1 /* 2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: defines driver functions interfacing with linux kernel 21 */ 22 23 #include <qdf_list.h> 24 #include <qdf_status.h> 25 #include <linux/wireless.h> 26 #include <linux/netdevice.h> 27 #include <net/cfg80211.h> 28 #include <wlan_cfg80211.h> 29 #include <wlan_osif_priv.h> 30 #include <qdf_mem.h> 31 #include <wlan_spectral_ucfg_api.h> 32 #include <wlan_cfg80211_spectral.h> 33 #include <spectral_ioctl.h> 34 35 static const struct nla_policy spectral_scan_policy[ 36 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = { 37 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = { 38 .type = NLA_U32}, 39 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = { 40 .type = NLA_U32}, 41 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = { 42 .type = NLA_U32}, 43 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = { 44 .type = NLA_U32}, 45 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = { 46 .type = NLA_U32}, 47 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = { 48 .type = NLA_U32}, 49 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = { 50 .type = NLA_U32}, 51 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = { 52 .type = NLA_U32}, 53 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = { 54 .type = NLA_U32}, 55 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = { 56 .type = NLA_U32}, 57 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = { 58 .type = NLA_U32}, 59 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = { 60 .type = NLA_U32}, 61 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = { 62 .type = NLA_U32}, 63 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = { 64 .type = NLA_U32}, 65 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = { 66 .type = NLA_U32}, 67 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = { 68 .type = NLA_U32}, 69 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = { 70 .type = NLA_U32}, 71 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = { 72 .type = NLA_U32}, 73 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = { 74 .type = NLA_U32}, 75 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = { 76 .type = NLA_U64}, 77 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = { 78 .type = NLA_U32}, 79 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = { 80 .type = NLA_U32}, 81 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = { 82 .type = NLA_U32}, 83 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY] = { 84 .type = NLA_U32}, 85 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE] = { 86 .type = NLA_U32}, 87 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG] = { 88 .type = NLA_U8}, 89 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG] = { 90 .type = NLA_U8}, 91 }; 92 93 static void wlan_spectral_intit_config(struct spectral_config *config_req) 94 { 95 config_req->ss_period = SPECTRAL_PHYERR_PARAM_NOVAL; 96 config_req->ss_count = SPECTRAL_PHYERR_PARAM_NOVAL; 97 config_req->ss_fft_period = SPECTRAL_PHYERR_PARAM_NOVAL; 98 config_req->ss_short_report = SPECTRAL_PHYERR_PARAM_NOVAL; 99 config_req->ss_spectral_pri = SPECTRAL_PHYERR_PARAM_NOVAL; 100 config_req->ss_fft_size = SPECTRAL_PHYERR_PARAM_NOVAL; 101 config_req->ss_gc_ena = SPECTRAL_PHYERR_PARAM_NOVAL; 102 config_req->ss_restart_ena = SPECTRAL_PHYERR_PARAM_NOVAL; 103 config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL; 104 config_req->ss_init_delay = SPECTRAL_PHYERR_PARAM_NOVAL; 105 config_req->ss_nb_tone_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 106 config_req->ss_str_bin_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 107 config_req->ss_wb_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 108 config_req->ss_rssi_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 109 config_req->ss_rssi_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 110 config_req->ss_pwr_format = SPECTRAL_PHYERR_PARAM_NOVAL; 111 config_req->ss_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 112 config_req->ss_bin_scale = SPECTRAL_PHYERR_PARAM_NOVAL; 113 config_req->ss_dbm_adj = SPECTRAL_PHYERR_PARAM_NOVAL; 114 config_req->ss_chn_mask = SPECTRAL_PHYERR_PARAM_NOVAL; 115 config_req->ss_frequency = SPECTRAL_PHYERR_PARAM_NOVAL; 116 } 117 118 /** 119 * convert_spectral_mode_nl_to_internal() - Get Spectral mode 120 * @nl_spectral_mode: Spectral mode in vendor attribute 121 * @mode: Converted Spectral mode 122 * 123 * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE 124 */ 125 static QDF_STATUS 126 convert_spectral_mode_nl_to_internal 127 (enum qca_wlan_vendor_spectral_scan_mode nl_spectral_mode, 128 enum spectral_scan_mode *mode) 129 { 130 switch (nl_spectral_mode) { 131 case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL: 132 *mode = SPECTRAL_SCAN_MODE_NORMAL; 133 break; 134 135 case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE: 136 *mode = SPECTRAL_SCAN_MODE_AGILE; 137 break; 138 139 default: 140 osif_err("Invalid spectral mode %u", nl_spectral_mode); 141 return QDF_STATUS_E_FAILURE; 142 } 143 144 return QDF_STATUS_SUCCESS; 145 } 146 147 /** 148 * convert_spectral_err_code_internal_to_nl() - Get Spectral error code 149 * @spectral_err_code: Spectral error code used internally 150 * @nl_err_code: Spectral error code for cfg80211 151 * 152 * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE 153 */ 154 static QDF_STATUS 155 convert_spectral_err_code_internal_to_nl 156 (enum spectral_cp_error_code spectral_err_code, 157 enum qca_wlan_vendor_spectral_scan_error_code *nl_err_code) 158 { 159 switch (spectral_err_code) { 160 case SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED: 161 *nl_err_code = 162 QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 163 break; 164 165 case SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED: 166 *nl_err_code = 167 QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 168 break; 169 170 case SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE: 171 *nl_err_code = 172 QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 173 break; 174 175 case SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED: 176 *nl_err_code = 177 QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 178 break; 179 180 default: 181 osif_err("Invalid spectral error code %u", spectral_err_code); 182 return QDF_STATUS_E_FAILURE; 183 } 184 185 return QDF_STATUS_SUCCESS; 186 } 187 188 #ifdef DIRECT_BUF_RX_DEBUG 189 QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config( 190 struct wlan_objmgr_pdev *pdev, 191 struct nlattr **tb, 192 enum spectral_scan_mode sscan_mode) 193 { 194 struct spectral_cp_request sscan_req; 195 uint8_t dma_debug_enable; 196 QDF_STATUS status; 197 198 if (!tb || !pdev) 199 return QDF_STATUS_E_FAILURE; 200 201 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]) { 202 dma_debug_enable = nla_get_u8(tb[ 203 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]); 204 sscan_req.ss_mode = sscan_mode; 205 sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable; 206 sscan_req.dma_debug_req.dma_debug_type = 207 SPECTRAL_DMA_RING_DEBUG; 208 sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG; 209 status = ucfg_spectral_control(pdev, &sscan_req); 210 if (status != QDF_STATUS_SUCCESS) { 211 osif_err("Could not configure dma ring debug"); 212 return QDF_STATUS_E_FAILURE; 213 } 214 } 215 216 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]) { 217 dma_debug_enable = nla_get_u8(tb[ 218 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]); 219 sscan_req.ss_mode = sscan_mode; 220 sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable; 221 sscan_req.dma_debug_req.dma_debug_type = 222 SPECTRAL_DMA_BUFFER_DEBUG; 223 sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG; 224 return ucfg_spectral_control(pdev, &sscan_req); 225 } 226 227 return QDF_STATUS_SUCCESS; 228 } 229 #else 230 QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config( 231 struct wlan_objmgr_pdev *pdev, 232 struct nlattr **tb, 233 enum spectral_scan_mode sscan_mode) 234 { 235 return QDF_STATUS_SUCCESS; 236 } 237 #endif /* DIRECT_BUF_RX_DEBUG */ 238 239 int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, 240 struct wlan_objmgr_pdev *pdev, 241 const void *data, 242 int data_len) 243 { 244 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1]; 245 struct spectral_config config_req; 246 QDF_STATUS status; 247 uint64_t cookie; 248 struct sk_buff *skb; 249 uint32_t spectral_dbg_level; 250 uint32_t scan_req_type = 0; 251 struct spectral_cp_request sscan_req; 252 enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; 253 uint16_t skb_len; 254 255 if (wlan_cfg80211_nla_parse( 256 tb, 257 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX, 258 data, 259 data_len, 260 spectral_scan_policy)) { 261 osif_err("Invalid Spectral Scan config ATTR"); 262 return -EINVAL; 263 } 264 265 wlan_spectral_intit_config(&config_req); 266 267 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]) 268 config_req.ss_count = nla_get_u32(tb 269 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]); 270 271 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]) 272 config_req.ss_period = nla_get_u32(tb 273 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]); 274 275 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]) 276 config_req.ss_spectral_pri = nla_get_u32(tb 277 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]); 278 279 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]) 280 config_req.ss_fft_size = nla_get_u32(tb 281 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]); 282 283 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]) 284 config_req.ss_gc_ena = nla_get_u32(tb 285 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]); 286 287 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]) 288 config_req.ss_restart_ena = nla_get_u32(tb 289 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]); 290 291 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]) 292 config_req.ss_noise_floor_ref = nla_get_u32(tb 293 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]); 294 295 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]) 296 config_req.ss_init_delay = nla_get_u32(tb 297 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]); 298 299 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]) 300 config_req.ss_nb_tone_thr = nla_get_u32(tb 301 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]); 302 303 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]) 304 config_req.ss_str_bin_thr = nla_get_u32(tb 305 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]); 306 307 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]) 308 config_req.ss_wb_rpt_mode = nla_get_u32(tb 309 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]); 310 311 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]) 312 config_req.ss_rssi_rpt_mode = nla_get_u32(tb 313 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]); 314 315 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]) 316 config_req.ss_rssi_thr = nla_get_u32(tb 317 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]); 318 319 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]) 320 config_req.ss_pwr_format = nla_get_u32(tb 321 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]); 322 323 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]) 324 config_req.ss_rpt_mode = nla_get_u32(tb 325 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]); 326 327 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]) 328 config_req.ss_bin_scale = nla_get_u32(tb 329 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]); 330 331 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]) 332 config_req.ss_dbm_adj = nla_get_u32(tb 333 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]); 334 335 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]) 336 config_req.ss_chn_mask = nla_get_u32(tb 337 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]); 338 339 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]) 340 config_req.ss_fft_period = nla_get_u32(tb 341 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]); 342 343 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]) 344 config_req.ss_short_report = nla_get_u32(tb 345 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]); 346 347 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY]) 348 config_req.ss_frequency = nla_get_u32(tb 349 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY]); 350 351 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) { 352 status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb 353 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode); 354 355 if (QDF_IS_STATUS_ERROR(status)) 356 return -EINVAL; 357 } 358 359 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) { 360 spectral_dbg_level = nla_get_u32(tb 361 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]); 362 sscan_req.ss_mode = sscan_mode; 363 sscan_req.debug_req.spectral_dbg_level = spectral_dbg_level; 364 sscan_req.req_id = SPECTRAL_SET_DEBUG_LEVEL; 365 status = ucfg_spectral_control(pdev, &sscan_req); 366 if (QDF_IS_STATUS_ERROR(status)) 367 return -EINVAL; 368 } 369 370 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]) 371 scan_req_type = nla_get_u32(tb 372 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]); 373 374 skb_len = NLMSG_HDRLEN; 375 /* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE */ 376 skb_len += NLA_HDRLEN + sizeof(u32); 377 /* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE */ 378 skb_len += NLA_HDRLEN + sizeof(u64); 379 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len); 380 381 if (!skb) { 382 osif_err(" reply skb alloc failed"); 383 return -ENOMEM; 384 } 385 386 status = wlan_cfg80211_spectral_scan_dma_debug_config( 387 pdev, tb, sscan_mode); 388 if (QDF_IS_STATUS_ERROR(status)) { 389 status = QDF_STATUS_E_INVAL; 390 goto free_skb_return_os_status; 391 } 392 393 if (CONFIG_REQUESTED(scan_req_type)) { 394 sscan_req.ss_mode = sscan_mode; 395 sscan_req.req_id = SPECTRAL_SET_CONFIG; 396 qdf_mem_copy(&sscan_req.config_req.sscan_config, &config_req, 397 qdf_min(sizeof(sscan_req.config_req.sscan_config), 398 sizeof(config_req))); 399 status = ucfg_spectral_control(pdev, &sscan_req); 400 if (QDF_IS_STATUS_ERROR(status)) { 401 enum qca_wlan_vendor_spectral_scan_error_code 402 spectral_nl_err_code; 403 404 /* No error reasons populated, just return error */ 405 if (sscan_req.config_req.sscan_err_code == 406 SPECTRAL_SCAN_ERR_INVALID) 407 goto free_skb_return_os_status; 408 409 status = convert_spectral_err_code_internal_to_nl 410 (sscan_req.config_req.sscan_err_code, 411 &spectral_nl_err_code); 412 if (QDF_IS_STATUS_ERROR(status)) { 413 status = QDF_STATUS_E_INVAL; 414 goto free_skb_return_os_status; 415 } 416 417 if (nla_put_u32 418 (skb, 419 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, 420 spectral_nl_err_code)) { 421 status = QDF_STATUS_E_INVAL; 422 goto free_skb_return_os_status; 423 } 424 } 425 } 426 427 if (SCAN_REQUESTED(scan_req_type)) { 428 sscan_req.ss_mode = sscan_mode; 429 sscan_req.req_id = SPECTRAL_ACTIVATE_SCAN; 430 status = ucfg_spectral_control(pdev, &sscan_req); 431 if (QDF_IS_STATUS_ERROR(status)) { 432 enum qca_wlan_vendor_spectral_scan_error_code 433 spectral_nl_err_code; 434 435 /* No error reasons populated, just return error */ 436 if (sscan_req.action_req.sscan_err_code == 437 SPECTRAL_SCAN_ERR_INVALID) 438 goto free_skb_return_os_status; 439 440 status = convert_spectral_err_code_internal_to_nl 441 (sscan_req.action_req.sscan_err_code, 442 &spectral_nl_err_code); 443 if (QDF_IS_STATUS_ERROR(status)) { 444 status = QDF_STATUS_E_INVAL; 445 goto free_skb_return_os_status; 446 } 447 448 if (nla_put_u32 449 (skb, 450 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, 451 spectral_nl_err_code)) { 452 status = QDF_STATUS_E_INVAL; 453 goto free_skb_return_os_status; 454 } 455 } 456 } 457 458 cookie = 0; 459 if (wlan_cfg80211_nla_put_u64(skb, 460 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE, 461 cookie)) { 462 status = QDF_STATUS_E_INVAL; 463 goto free_skb_return_os_status; 464 } 465 466 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 467 return 0; 468 free_skb_return_os_status: 469 wlan_cfg80211_vendor_free_skb(skb); 470 return qdf_status_to_os_return(status); 471 } 472 473 int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, 474 struct wlan_objmgr_pdev *pdev, 475 const void *data, 476 int data_len) 477 { 478 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1]; 479 QDF_STATUS status; 480 struct spectral_cp_request sscan_req; 481 enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; 482 struct sk_buff *skb; 483 484 if (wlan_cfg80211_nla_parse( 485 tb, 486 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX, 487 data, 488 data_len, 489 spectral_scan_policy)) { 490 osif_err("Invalid Spectral Scan stop ATTR"); 491 return -EINVAL; 492 } 493 494 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) { 495 status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb 496 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode); 497 498 if (QDF_IS_STATUS_ERROR(status)) 499 return -EINVAL; 500 } 501 502 sscan_req.ss_mode = sscan_mode; 503 sscan_req.req_id = SPECTRAL_STOP_SCAN; 504 status = ucfg_spectral_control(pdev, &sscan_req); 505 if (QDF_IS_STATUS_ERROR(status)) { 506 enum qca_wlan_vendor_spectral_scan_error_code 507 spectral_nl_err_code; 508 509 /* No error reasons populated, just return error */ 510 if (sscan_req.action_req.sscan_err_code == 511 SPECTRAL_SCAN_ERR_INVALID) 512 return qdf_status_to_os_return(status); 513 514 status = convert_spectral_err_code_internal_to_nl 515 (sscan_req.action_req.sscan_err_code, 516 &spectral_nl_err_code); 517 if (QDF_IS_STATUS_ERROR(status)) 518 return -EINVAL; 519 520 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 521 NLMSG_HDRLEN + sizeof(u32) + NLA_HDRLEN); 522 523 if (!skb) { 524 osif_err(" reply skb alloc failed"); 525 return -ENOMEM; 526 } 527 528 if (nla_put_u32 529 (skb, 530 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, 531 spectral_nl_err_code)) { 532 wlan_cfg80211_vendor_free_skb(skb); 533 return -EINVAL; 534 } 535 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 536 } 537 538 return 0; 539 } 540 541 int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, 542 struct wlan_objmgr_pdev *pdev, 543 const void *data, 544 int data_len) 545 { 546 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1]; 547 struct spectral_config *sconfig; 548 uint32_t spectral_dbg_level; 549 struct sk_buff *skb; 550 struct spectral_cp_request sscan_req; 551 enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; 552 QDF_STATUS status; 553 554 if (wlan_cfg80211_nla_parse( 555 tb, 556 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX, 557 data, 558 data_len, 559 spectral_scan_policy)) { 560 osif_err("Invalid Spectral Scan config ATTR"); 561 return -EINVAL; 562 } 563 564 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) { 565 status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb 566 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode); 567 568 if (QDF_IS_STATUS_ERROR(status)) 569 return -EINVAL; 570 } 571 572 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 573 (sizeof(u32) + 574 NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 575 NLMSG_HDRLEN); 576 if (!skb) { 577 osif_err(" reply skb alloc failed"); 578 return -ENOMEM; 579 } 580 581 sscan_req.ss_mode = sscan_mode; 582 sscan_req.req_id = SPECTRAL_GET_CONFIG; 583 status = ucfg_spectral_control(pdev, &sscan_req); 584 sconfig = &sscan_req.config_req.sscan_config; 585 if (nla_put_u32(skb, 586 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT, 587 sconfig->ss_count) || 588 nla_put_u32(skb, 589 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD, 590 sconfig->ss_period) || 591 nla_put_u32(skb, 592 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY, 593 sconfig->ss_spectral_pri) || 594 nla_put_u32(skb, 595 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE, 596 sconfig->ss_fft_size) || 597 nla_put_u32(skb, 598 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA, 599 sconfig->ss_gc_ena) || 600 nla_put_u32(skb, 601 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA, 602 sconfig->ss_restart_ena) || 603 nla_put_u32( 604 skb, 605 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF, 606 sconfig->ss_noise_floor_ref) || 607 nla_put_u32(skb, 608 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY, 609 sconfig->ss_init_delay) || 610 nla_put_u32(skb, 611 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR, 612 sconfig->ss_nb_tone_thr) || 613 nla_put_u32(skb, 614 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR, 615 sconfig->ss_str_bin_thr) || 616 nla_put_u32(skb, 617 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE, 618 sconfig->ss_wb_rpt_mode) || 619 nla_put_u32(skb, 620 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE, 621 sconfig->ss_rssi_rpt_mode) || 622 nla_put_u32(skb, 623 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR, 624 sconfig->ss_rssi_thr) || 625 nla_put_u32(skb, 626 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT, 627 sconfig->ss_pwr_format) || 628 nla_put_u32(skb, 629 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE, 630 sconfig->ss_rpt_mode) || 631 nla_put_u32(skb, 632 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE, 633 sconfig->ss_bin_scale) || 634 nla_put_u32(skb, 635 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ, 636 sconfig->ss_dbm_adj) || 637 nla_put_u32(skb, 638 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK, 639 sconfig->ss_chn_mask) || 640 nla_put_u32(skb, 641 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD, 642 sconfig->ss_fft_period) || 643 nla_put_u32(skb, 644 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT, 645 sconfig->ss_short_report) || 646 nla_put_u32(skb, 647 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY, 648 sconfig->ss_frequency)) 649 goto fail; 650 651 sscan_req.ss_mode = sscan_mode; 652 sscan_req.req_id = SPECTRAL_GET_DEBUG_LEVEL; 653 status = ucfg_spectral_control(pdev, &sscan_req); 654 spectral_dbg_level = sscan_req.debug_req.spectral_dbg_level; 655 if (nla_put_u32(skb, 656 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL, 657 spectral_dbg_level)) 658 goto fail; 659 660 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 661 return 0; 662 fail: 663 wlan_cfg80211_vendor_free_skb(skb); 664 return -EINVAL; 665 } 666 667 int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, 668 struct wlan_objmgr_pdev *pdev, 669 const void *data, 670 int data_len) 671 { 672 struct spectral_caps *scaps; 673 struct sk_buff *skb; 674 struct spectral_cp_request sscan_req; 675 QDF_STATUS status; 676 677 sscan_req.req_id = SPECTRAL_GET_CAPABILITY_INFO; 678 status = ucfg_spectral_control(pdev, &sscan_req); 679 scaps = &sscan_req.caps_req.sscan_caps; 680 681 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 682 (sizeof(u32) + 683 NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX + 684 NLMSG_HDRLEN); 685 if (!skb) { 686 osif_err(" reply skb alloc failed"); 687 return -ENOMEM; 688 } 689 690 if (scaps->phydiag_cap) 691 if (nla_put_flag( 692 skb, 693 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG)) 694 goto fail; 695 696 if (scaps->radar_cap) 697 if (nla_put_flag(skb, 698 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR)) 699 goto fail; 700 701 if (scaps->spectral_cap) 702 if (nla_put_flag( 703 skb, 704 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL)) 705 goto fail; 706 707 if (scaps->advncd_spectral_cap) 708 if (nla_put_flag( 709 skb, 710 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL)) 711 goto fail; 712 713 if (nla_put_u32(skb, 714 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN, 715 scaps->hw_gen)) 716 goto fail; 717 718 if (scaps->is_scaling_params_populated) { 719 if (nla_put_u16( 720 skb, 721 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID, 722 scaps->formula_id)) 723 goto fail; 724 725 if (nla_put_u16( 726 skb, 727 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET, 728 scaps->low_level_offset)) 729 goto fail; 730 731 if (nla_put_u16( 732 skb, 733 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET, 734 scaps->high_level_offset)) 735 goto fail; 736 737 if (nla_put_u16( 738 skb, 739 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR, 740 scaps->rssi_thr)) 741 goto fail; 742 743 if (nla_put_u8( 744 skb, 745 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN, 746 scaps->default_agc_max_gain)) 747 goto fail; 748 } 749 750 if (scaps->agile_spectral_cap) { 751 int ret; 752 753 ret = nla_put_flag 754 (skb, 755 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL); 756 if (ret) 757 goto fail; 758 } 759 760 if (scaps->agile_spectral_cap_160) { 761 int ret; 762 763 ret = nla_put_flag 764 (skb, 765 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160); 766 if (ret) 767 goto fail; 768 } 769 if (scaps->agile_spectral_cap_80p80) { 770 int ret; 771 772 ret = nla_put_flag 773 (skb, 774 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80); 775 if (ret) 776 goto fail; 777 } 778 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 779 780 return 0; 781 782 fail: 783 wlan_cfg80211_vendor_free_skb(skb); 784 return -EINVAL; 785 } 786 787 int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, 788 struct wlan_objmgr_pdev *pdev, 789 const void *data, 790 int data_len) 791 { 792 struct spectral_diag_stats *spetcral_diag; 793 struct sk_buff *skb; 794 struct spectral_cp_request sscan_req; 795 QDF_STATUS status; 796 797 sscan_req.req_id = SPECTRAL_GET_DIAG_STATS; 798 status = ucfg_spectral_control(pdev, &sscan_req); 799 spetcral_diag = &sscan_req.diag_req.sscan_diag; 800 801 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 802 (sizeof(u64) + NLA_HDRLEN) * 803 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX + 804 NLMSG_HDRLEN); 805 if (!skb) { 806 osif_err(" reply skb alloc failed"); 807 return -ENOMEM; 808 } 809 810 if (wlan_cfg80211_nla_put_u64( 811 skb, 812 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH, 813 spetcral_diag->spectral_mismatch) || 814 wlan_cfg80211_nla_put_u64( 815 skb, 816 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN, 817 spetcral_diag->spectral_sec80_sfft_insufflen) || 818 wlan_cfg80211_nla_put_u64( 819 skb, 820 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT, 821 spetcral_diag->spectral_no_sec80_sfft) || 822 wlan_cfg80211_nla_put_u64( 823 skb, 824 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH, 825 spetcral_diag->spectral_vhtseg1id_mismatch) || 826 wlan_cfg80211_nla_put_u64( 827 skb, 828 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH, 829 spetcral_diag->spectral_vhtseg2id_mismatch)) { 830 wlan_cfg80211_vendor_free_skb(skb); 831 return -EINVAL; 832 } 833 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 834 835 return 0; 836 } 837 838 int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, 839 struct wlan_objmgr_pdev *pdev, 840 const void *data, 841 int data_len) 842 { 843 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX + 1]; 844 struct spectral_scan_state sscan_state = { 0 }; 845 struct sk_buff *skb; 846 struct spectral_cp_request sscan_req; 847 enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; 848 QDF_STATUS status; 849 850 if (wlan_cfg80211_nla_parse( 851 tb, 852 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX, 853 data, 854 data_len, 855 NULL)) { 856 osif_err("Invalid Spectral Scan config ATTR"); 857 return -EINVAL; 858 } 859 860 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]) { 861 status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb 862 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]), &sscan_mode); 863 864 if (QDF_IS_STATUS_ERROR(status)) 865 return -EINVAL; 866 } 867 868 /* Sending a request and extracting response from it has to be atomic */ 869 sscan_req.ss_mode = sscan_mode; 870 sscan_req.req_id = SPECTRAL_IS_ACTIVE; 871 status = ucfg_spectral_control(pdev, &sscan_req); 872 sscan_state.is_active = sscan_req.status_req.is_active; 873 874 sscan_req.ss_mode = sscan_mode; 875 sscan_req.req_id = SPECTRAL_IS_ENABLED; 876 status = ucfg_spectral_control(pdev, &sscan_req); 877 sscan_state.is_enabled = sscan_req.status_req.is_enabled; 878 879 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 880 2 * (sizeof(u32) + NLA_HDRLEN) + NLMSG_HDRLEN); 881 if (!skb) { 882 osif_err(" reply skb alloc failed"); 883 return -ENOMEM; 884 } 885 886 if (sscan_state.is_enabled) 887 if (nla_put_flag( 888 skb, 889 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED)) 890 goto fail; 891 892 if (sscan_state.is_active) 893 if (nla_put_flag( 894 skb, 895 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE)) 896 goto fail; 897 wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); 898 899 return 0; 900 fail: 901 wlan_cfg80211_vendor_free_skb(skb); 902 return -EINVAL; 903 } 904