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