1 /* 2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: defines driver functions interfacing with linux kernel 21 */ 22 23 #include <qdf_list.h> 24 #include <qdf_status.h> 25 #include <linux/wireless.h> 26 #include <linux/netdevice.h> 27 #include <net/cfg80211.h> 28 #include <wlan_cfg80211.h> 29 #include <wlan_osif_priv.h> 30 #include <qdf_mem.h> 31 #include <wlan_spectral_ucfg_api.h> 32 #include <wlan_cfg80211_spectral.h> 33 #include <spectral_ioctl.h> 34 35 static const struct nla_policy spectral_scan_policy[ 36 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = { 37 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = { 38 .type = NLA_U32}, 39 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = { 40 .type = NLA_U32}, 41 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = { 42 .type = NLA_U32}, 43 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = { 44 .type = NLA_U32}, 45 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = { 46 .type = NLA_U32}, 47 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = { 48 .type = NLA_U32}, 49 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = { 50 .type = NLA_U32}, 51 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = { 52 .type = NLA_U32}, 53 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = { 54 .type = NLA_U32}, 55 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = { 56 .type = NLA_U32}, 57 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = { 58 .type = NLA_U32}, 59 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = { 60 .type = NLA_U32}, 61 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = { 62 .type = NLA_U32}, 63 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = { 64 .type = NLA_U32}, 65 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = { 66 .type = NLA_U32}, 67 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = { 68 .type = NLA_U32}, 69 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = { 70 .type = NLA_U32}, 71 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = { 72 .type = NLA_U32}, 73 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = { 74 .type = NLA_U32}, 75 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = { 76 .type = NLA_U64}, 77 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = { 78 .type = NLA_U32}, 79 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = { 80 .type = NLA_U32}, 81 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = { 82 .type = NLA_U32}, 83 }; 84 85 static void wlan_spectral_intit_config(struct spectral_config *config_req) 86 { 87 config_req->ss_period = SPECTRAL_PHYERR_PARAM_NOVAL; 88 config_req->ss_count = SPECTRAL_PHYERR_PARAM_NOVAL; 89 config_req->ss_fft_period = SPECTRAL_PHYERR_PARAM_NOVAL; 90 config_req->ss_short_report = SPECTRAL_PHYERR_PARAM_NOVAL; 91 config_req->ss_spectral_pri = SPECTRAL_PHYERR_PARAM_NOVAL; 92 config_req->ss_fft_size = SPECTRAL_PHYERR_PARAM_NOVAL; 93 config_req->ss_gc_ena = SPECTRAL_PHYERR_PARAM_NOVAL; 94 config_req->ss_restart_ena = SPECTRAL_PHYERR_PARAM_NOVAL; 95 config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL; 96 config_req->ss_init_delay = SPECTRAL_PHYERR_PARAM_NOVAL; 97 config_req->ss_nb_tone_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 98 config_req->ss_str_bin_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 99 config_req->ss_wb_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 100 config_req->ss_rssi_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 101 config_req->ss_rssi_thr = SPECTRAL_PHYERR_PARAM_NOVAL; 102 config_req->ss_pwr_format = SPECTRAL_PHYERR_PARAM_NOVAL; 103 config_req->ss_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; 104 config_req->ss_bin_scale = SPECTRAL_PHYERR_PARAM_NOVAL; 105 config_req->ss_dbm_adj = SPECTRAL_PHYERR_PARAM_NOVAL; 106 config_req->ss_chn_mask = SPECTRAL_PHYERR_PARAM_NOVAL; 107 } 108 109 static int wlan_spectral_set_config(struct wlan_objmgr_pdev *pdev, 110 struct spectral_config *config_req) 111 { 112 int status; 113 114 status = ucfg_spectral_control(pdev, 115 SPECTRAL_SET_CONFIG, 116 config_req, 117 sizeof(struct spectral_config), 118 NULL, 119 NULL); 120 if (status < 0) 121 return -EINVAL; 122 123 return 0; 124 } 125 126 static int wlan_spectral_set_debug_level(struct wlan_objmgr_pdev *pdev, 127 uint32_t spectral_dbg_level) 128 { 129 int status; 130 131 status = ucfg_spectral_control(pdev, 132 SPECTRAL_SET_DEBUG_LEVEL, 133 &spectral_dbg_level, 134 sizeof(uint32_t), 135 NULL, 136 NULL); 137 if (status < 0) 138 return -EINVAL; 139 140 return 0; 141 } 142 143 static int wlan_spectral_get_debug_level(struct wlan_objmgr_pdev *pdev, 144 uint32_t *spectral_dbg_level) 145 { 146 int status; 147 uint32_t outsize; 148 149 outsize = sizeof(uint32_t); 150 status = ucfg_spectral_control(pdev, 151 SPECTRAL_GET_DEBUG_LEVEL, 152 NULL, 153 0, 154 spectral_dbg_level, 155 &outsize); 156 if (status < 0) 157 return -EINVAL; 158 159 return 0; 160 } 161 162 static int wlan_spectral_get_config(struct wlan_objmgr_pdev *pdev, 163 struct spectral_config *config_req) 164 { 165 int status; 166 uint32_t outsize; 167 168 outsize = sizeof(struct spectral_config); 169 status = ucfg_spectral_control(pdev, 170 SPECTRAL_GET_CONFIG, 171 NULL, 172 0, 173 config_req, 174 &outsize); 175 if (status < 0) 176 return -EINVAL; 177 178 return 0; 179 } 180 181 static int wlan_spectral_get_cap(struct wlan_objmgr_pdev *pdev, 182 struct spectral_caps *spectral_cap) 183 { 184 int status; 185 uint32_t outsize; 186 187 outsize = sizeof(struct spectral_caps); 188 status = ucfg_spectral_control(pdev, 189 SPECTRAL_GET_CAPABILITY_INFO, 190 NULL, 191 0, 192 spectral_cap, 193 &outsize); 194 if (status < 0) 195 return -EINVAL; 196 197 return 0; 198 } 199 200 static int wlan_spectral_get_diag_stats( 201 struct wlan_objmgr_pdev *pdev, 202 struct spectral_diag_stats *spectral_diag) 203 { 204 int status; 205 uint32_t outsize; 206 207 outsize = sizeof(struct spectral_diag_stats); 208 status = ucfg_spectral_control(pdev, 209 SPECTRAL_GET_DIAG_STATS, 210 NULL, 211 0, 212 spectral_diag, 213 &outsize); 214 if (status < 0) 215 return -EINVAL; 216 217 return 0; 218 } 219 220 static int wlan_spectral_scan_get_status( 221 struct wlan_objmgr_pdev *pdev, 222 struct spectral_scan_state *sscan_state) 223 { 224 uint32_t is_active; 225 uint32_t is_enabled; 226 int status; 227 uint32_t outsize; 228 229 outsize = sizeof(uint32_t); 230 status = ucfg_spectral_control(pdev, 231 SPECTRAL_IS_ACTIVE, 232 NULL, 233 0, 234 &is_active, 235 &outsize); 236 if (status < 0) 237 return -EINVAL; 238 239 sscan_state->is_active = is_active; 240 241 outsize = sizeof(uint32_t); 242 status = ucfg_spectral_control(pdev, 243 SPECTRAL_IS_ENABLED, 244 NULL, 245 0, 246 &is_enabled, 247 &outsize); 248 if (status < 0) 249 return -EINVAL; 250 251 sscan_state->is_enabled = is_enabled; 252 253 return 0; 254 } 255 256 static int wlan_start_spectral_scan(struct wlan_objmgr_pdev *pdev) 257 { 258 int status; 259 260 status = ucfg_spectral_control(pdev, 261 SPECTRAL_ACTIVATE_SCAN, 262 NULL, 263 0, 264 NULL, 265 NULL); 266 if (status < 0) 267 return -EINVAL; 268 269 return 0; 270 } 271 272 static int wlan_stop_spectral_scan(struct wlan_objmgr_pdev *pdev) 273 { 274 int status; 275 276 status = ucfg_spectral_control(pdev, 277 SPECTRAL_STOP_SCAN, 278 NULL, 279 0, 280 NULL, 281 NULL); 282 if (status < 0) 283 return -EINVAL; 284 285 return 0; 286 } 287 288 int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, 289 struct wlan_objmgr_pdev *pdev, 290 const void *data, 291 int data_len) 292 { 293 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1]; 294 struct spectral_config config_req; 295 QDF_STATUS status; 296 uint64_t cookie; 297 struct sk_buff *skb; 298 uint32_t spectral_dbg_level; 299 uint32_t scan_req_type = 0; 300 301 if (wlan_cfg80211_nla_parse( 302 tb, 303 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX, 304 data, 305 data_len, 306 spectral_scan_policy)) { 307 qdf_print("Invalid Spectral Scan config ATTR"); 308 return -EINVAL; 309 } 310 311 wlan_spectral_intit_config(&config_req); 312 313 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]) 314 config_req.ss_count = nla_get_u32(tb 315 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]); 316 317 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]) 318 config_req.ss_period = nla_get_u32(tb 319 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]); 320 321 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]) 322 config_req.ss_spectral_pri = nla_get_u32(tb 323 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]); 324 325 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]) 326 config_req.ss_fft_size = nla_get_u32(tb 327 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]); 328 329 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]) 330 config_req.ss_gc_ena = nla_get_u32(tb 331 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]); 332 333 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]) 334 config_req.ss_restart_ena = nla_get_u32(tb 335 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]); 336 337 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]) 338 config_req.ss_noise_floor_ref = nla_get_u32(tb 339 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]); 340 341 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]) 342 config_req.ss_init_delay = nla_get_u32(tb 343 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]); 344 345 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]) 346 config_req.ss_nb_tone_thr = nla_get_u32(tb 347 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]); 348 349 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]) 350 config_req.ss_str_bin_thr = nla_get_u32(tb 351 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]); 352 353 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]) 354 config_req.ss_wb_rpt_mode = nla_get_u32(tb 355 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]); 356 357 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]) 358 config_req.ss_rssi_rpt_mode = nla_get_u32(tb 359 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]); 360 361 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]) 362 config_req.ss_rssi_thr = nla_get_u32(tb 363 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]); 364 365 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]) 366 config_req.ss_pwr_format = nla_get_u32(tb 367 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]); 368 369 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]) 370 config_req.ss_rpt_mode = nla_get_u32(tb 371 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]); 372 373 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]) 374 config_req.ss_bin_scale = nla_get_u32(tb 375 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]); 376 377 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]) 378 config_req.ss_dbm_adj = nla_get_u32(tb 379 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]); 380 381 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]) 382 config_req.ss_chn_mask = nla_get_u32(tb 383 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]); 384 385 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]) 386 config_req.ss_fft_period = nla_get_u32(tb 387 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]); 388 389 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]) 390 config_req.ss_short_report = nla_get_u32(tb 391 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]); 392 393 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) { 394 spectral_dbg_level = nla_get_u32(tb 395 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]); 396 status = wlan_spectral_set_debug_level(pdev, 397 spectral_dbg_level); 398 if (QDF_STATUS_SUCCESS != status) 399 return -EINVAL; 400 } 401 402 if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]) 403 scan_req_type = nla_get_u32(tb 404 [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]); 405 406 if (CONFIG_REQUESTED(scan_req_type)) { 407 status = wlan_spectral_set_config(pdev, &config_req); 408 if (QDF_STATUS_SUCCESS != status) 409 return -EINVAL; 410 } 411 412 if (SCAN_REQUESTED(scan_req_type)) { 413 status = wlan_start_spectral_scan(pdev); 414 if (QDF_STATUS_SUCCESS != status) 415 return -EINVAL; 416 } 417 418 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) + 419 NLA_HDRLEN + NLMSG_HDRLEN); 420 if (!skb) { 421 qdf_print(" reply skb alloc failed"); 422 return -ENOMEM; 423 } 424 425 cookie = 0; 426 if (wlan_cfg80211_nla_put_u64(skb, 427 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE, 428 cookie)) { 429 kfree_skb(skb); 430 return -EINVAL; 431 } 432 433 cfg80211_vendor_cmd_reply(skb); 434 435 return 0; 436 } 437 438 int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, 439 struct wlan_objmgr_pdev *pdev, 440 const void *data, 441 int data_len) 442 { 443 QDF_STATUS status; 444 445 status = wlan_stop_spectral_scan(pdev); 446 if (QDF_STATUS_SUCCESS != status) 447 return -EINVAL; 448 return 0; 449 } 450 451 int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, 452 struct wlan_objmgr_pdev *pdev, 453 const void *data, 454 int data_len) 455 { 456 struct spectral_config config_buf; 457 uint32_t spectral_dbg_level; 458 struct sk_buff *skb; 459 460 wlan_spectral_get_config(pdev, &config_buf); 461 wlan_spectral_get_debug_level(pdev, &spectral_dbg_level); 462 463 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (21 * sizeof(u32)) + 464 NLA_HDRLEN + NLMSG_HDRLEN); 465 if (!skb) { 466 qdf_print(" reply skb alloc failed"); 467 return -ENOMEM; 468 } 469 470 if (nla_put_u32(skb, 471 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT, 472 config_buf.ss_count) || 473 nla_put_u32(skb, 474 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD, 475 config_buf.ss_period) || 476 nla_put_u32(skb, 477 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY, 478 config_buf.ss_spectral_pri) || 479 nla_put_u32(skb, 480 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE, 481 config_buf.ss_fft_size) || 482 nla_put_u32(skb, 483 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA, 484 config_buf.ss_gc_ena) || 485 nla_put_u32(skb, 486 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA, 487 config_buf.ss_restart_ena) || 488 nla_put_u32( 489 skb, 490 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF, 491 config_buf.ss_noise_floor_ref) || 492 nla_put_u32(skb, 493 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY, 494 config_buf.ss_init_delay) || 495 nla_put_u32(skb, 496 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR, 497 config_buf.ss_nb_tone_thr) || 498 nla_put_u32(skb, 499 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR, 500 config_buf.ss_str_bin_thr) || 501 nla_put_u32(skb, 502 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE, 503 config_buf.ss_wb_rpt_mode) || 504 nla_put_u32(skb, 505 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE, 506 config_buf.ss_rssi_rpt_mode) || 507 nla_put_u32(skb, 508 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR, 509 config_buf.ss_rssi_thr) || 510 nla_put_u32(skb, 511 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT, 512 config_buf.ss_pwr_format) || 513 nla_put_u32(skb, 514 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE, 515 config_buf.ss_rpt_mode) || 516 nla_put_u32(skb, 517 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE, 518 config_buf.ss_bin_scale) || 519 nla_put_u32(skb, 520 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ, 521 config_buf.ss_dbm_adj) || 522 nla_put_u32(skb, 523 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK, 524 config_buf.ss_chn_mask) || 525 nla_put_u32(skb, 526 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD, 527 config_buf.ss_fft_period) || 528 nla_put_u32(skb, 529 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT, 530 config_buf.ss_short_report) || 531 nla_put_u32(skb, 532 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL, 533 spectral_dbg_level)) { 534 kfree_skb(skb); 535 return -EINVAL; 536 } 537 cfg80211_vendor_cmd_reply(skb); 538 539 return 0; 540 } 541 542 int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, 543 struct wlan_objmgr_pdev *pdev, 544 const void *data, 545 int data_len) 546 { 547 struct spectral_caps spectral_cap; 548 struct sk_buff *skb; 549 550 wlan_spectral_get_cap(pdev, &spectral_cap); 551 552 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u32) + 553 NLA_HDRLEN + NLMSG_HDRLEN); 554 if (!skb) { 555 qdf_print(" reply skb alloc failed"); 556 return -ENOMEM; 557 } 558 559 if (spectral_cap.phydiag_cap) 560 if (nla_put_flag( 561 skb, 562 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG)) 563 goto fail; 564 565 if (spectral_cap.radar_cap) 566 if (nla_put_flag(skb, 567 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR)) 568 goto fail; 569 570 if (spectral_cap.spectral_cap) 571 if (nla_put_flag( 572 skb, 573 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL)) 574 goto fail; 575 576 if (spectral_cap.advncd_spectral_cap) 577 if (nla_put_flag( 578 skb, 579 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL)) 580 goto fail; 581 582 if (nla_put_u32(skb, 583 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN, 584 spectral_cap.hw_gen)) 585 goto fail; 586 587 cfg80211_vendor_cmd_reply(skb); 588 589 return 0; 590 591 fail: 592 kfree_skb(skb); 593 return -EINVAL; 594 } 595 596 int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, 597 struct wlan_objmgr_pdev *pdev, 598 const void *data, 599 int data_len) 600 { 601 struct spectral_diag_stats spetcral_diag; 602 struct sk_buff *skb; 603 604 wlan_spectral_get_diag_stats(pdev, &spetcral_diag); 605 606 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u64) + 607 NLA_HDRLEN + NLMSG_HDRLEN); 608 if (!skb) { 609 qdf_print(" reply skb alloc failed"); 610 return -ENOMEM; 611 } 612 613 if (wlan_cfg80211_nla_put_u64( 614 skb, 615 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH, 616 spetcral_diag.spectral_mismatch) || 617 wlan_cfg80211_nla_put_u64( 618 skb, 619 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN, 620 spetcral_diag.spectral_sec80_sfft_insufflen) || 621 wlan_cfg80211_nla_put_u64( 622 skb, 623 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT, 624 spetcral_diag.spectral_no_sec80_sfft) || 625 wlan_cfg80211_nla_put_u64( 626 skb, 627 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH, 628 spetcral_diag.spectral_vhtseg1id_mismatch) || 629 wlan_cfg80211_nla_put_u64( 630 skb, 631 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH, 632 spetcral_diag.spectral_vhtseg2id_mismatch)) { 633 kfree_skb(skb); 634 return -EINVAL; 635 } 636 cfg80211_vendor_cmd_reply(skb); 637 638 return 0; 639 } 640 641 int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, 642 struct wlan_objmgr_pdev *pdev, 643 const void *data, 644 int data_len) 645 { 646 struct spectral_scan_state sscan_state = { 0 }; 647 struct sk_buff *skb; 648 649 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * sizeof(u32) + 650 NLA_HDRLEN + NLMSG_HDRLEN); 651 if (!skb) { 652 qdf_print(" reply skb alloc failed"); 653 return -ENOMEM; 654 } 655 656 wlan_spectral_scan_get_status(pdev, &sscan_state); 657 658 if (sscan_state.is_enabled) 659 if (nla_put_flag( 660 skb, 661 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED)) 662 goto fail; 663 664 if (sscan_state.is_active) 665 if (nla_put_flag( 666 skb, 667 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE)) 668 goto fail; 669 cfg80211_vendor_cmd_reply(skb); 670 return 0; 671 672 fail: 673 kfree_skb(skb); 674 return -EINVAL; 675 } 676