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