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