| /* |
| * Copyright (c) 2017 The Linux Foundation. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /** |
| * DOC: defines driver functions interfacing with linux kernel |
| */ |
| |
| #include <qdf_list.h> |
| #include <qdf_status.h> |
| #include <linux/wireless.h> |
| #include <linux/netdevice.h> |
| #include <net/cfg80211.h> |
| #include <wlan_cfg80211.h> |
| #include <wlan_osif_priv.h> |
| #include <qdf_mem.h> |
| #include <wlan_spectral_ucfg_api.h> |
| #include <wlan_cfg80211_spectral.h> |
| #include <spectral_ioctl.h> |
| |
| static const struct nla_policy spectral_scan_policy[ |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = { |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = { |
| .type = NLA_U64}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = { |
| .type = NLA_U32}, |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = { |
| .type = NLA_U32}, |
| }; |
| |
| static void wlan_spectral_intit_config(struct spectral_config *config_req) |
| { |
| config_req->ss_period = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_count = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_fft_period = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_short_report = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_spectral_pri = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_fft_size = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_gc_ena = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_restart_ena = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_init_delay = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_nb_tone_thr = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_str_bin_thr = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_wb_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_rssi_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_rssi_thr = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_pwr_format = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_rpt_mode = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_bin_scale = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_dbm_adj = SPECTRAL_PHYERR_PARAM_NOVAL; |
| config_req->ss_chn_mask = SPECTRAL_PHYERR_PARAM_NOVAL; |
| } |
| |
| static int wlan_spectral_set_config(struct wlan_objmgr_pdev *pdev, |
| struct spectral_config *config_req) |
| { |
| int status; |
| |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_SET_CONFIG, |
| config_req, |
| sizeof(struct spectral_config), |
| NULL, |
| NULL); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_set_debug_level(struct wlan_objmgr_pdev *pdev, |
| uint32_t spectral_dbg_level) |
| { |
| int status; |
| |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_SET_DEBUG_LEVEL, |
| &spectral_dbg_level, |
| sizeof(uint32_t), |
| NULL, |
| NULL); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_get_debug_level(struct wlan_objmgr_pdev *pdev, |
| uint32_t *spectral_dbg_level) |
| { |
| int status; |
| uint32_t outsize; |
| |
| outsize = sizeof(uint32_t); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_GET_DEBUG_LEVEL, |
| NULL, |
| 0, |
| spectral_dbg_level, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_get_config(struct wlan_objmgr_pdev *pdev, |
| struct spectral_config *config_req) |
| { |
| int status; |
| uint32_t outsize; |
| |
| outsize = sizeof(struct spectral_config); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_GET_CONFIG, |
| NULL, |
| 0, |
| config_req, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_get_cap(struct wlan_objmgr_pdev *pdev, |
| struct spectral_caps *spectral_cap) |
| { |
| int status; |
| uint32_t outsize; |
| |
| outsize = sizeof(struct spectral_caps); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_GET_CAPABILITY_INFO, |
| NULL, |
| 0, |
| spectral_cap, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_get_diag_stats( |
| struct wlan_objmgr_pdev *pdev, |
| struct spectral_diag_stats *spectral_diag) |
| { |
| int status; |
| uint32_t outsize; |
| |
| outsize = sizeof(struct spectral_diag_stats); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_GET_DIAG_STATS, |
| NULL, |
| 0, |
| spectral_diag, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_spectral_scan_get_status( |
| struct wlan_objmgr_pdev *pdev, |
| struct spectral_scan_state *sscan_state) |
| { |
| uint32_t is_active; |
| uint32_t is_enabled; |
| int status; |
| uint32_t outsize; |
| |
| outsize = sizeof(uint32_t); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_IS_ACTIVE, |
| NULL, |
| 0, |
| &is_active, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| sscan_state->is_active = is_active; |
| |
| outsize = sizeof(uint32_t); |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_IS_ENABLED, |
| NULL, |
| 0, |
| &is_enabled, |
| &outsize); |
| if (status < 0) |
| return -EINVAL; |
| |
| sscan_state->is_enabled = is_enabled; |
| |
| return 0; |
| } |
| |
| static int wlan_start_spectral_scan(struct wlan_objmgr_pdev *pdev) |
| { |
| int status; |
| |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_ACTIVATE_SCAN, |
| NULL, |
| 0, |
| NULL, |
| NULL); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| static int wlan_stop_spectral_scan(struct wlan_objmgr_pdev *pdev) |
| { |
| int status; |
| |
| status = ucfg_spectral_control(pdev, |
| SPECTRAL_STOP_SCAN, |
| NULL, |
| 0, |
| NULL, |
| NULL); |
| if (status < 0) |
| return -EINVAL; |
| |
| return 0; |
| } |
| |
| int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1]; |
| struct spectral_config config_req; |
| QDF_STATUS status; |
| uint64_t cookie; |
| struct sk_buff *skb; |
| uint32_t spectral_dbg_level; |
| uint32_t scan_req_type; |
| |
| if (wlan_cfg80211_nla_parse( |
| tb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX, |
| data, |
| data_len, |
| spectral_scan_policy)) { |
| qdf_print("Invalid Spectral Scan config ATTR"); |
| return -EINVAL; |
| } |
| |
| wlan_spectral_intit_config(&config_req); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]) |
| config_req.ss_count = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]) |
| config_req.ss_period = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]) |
| config_req.ss_spectral_pri = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]) |
| config_req.ss_fft_size = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]) |
| config_req.ss_gc_ena = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]) |
| config_req.ss_restart_ena = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]) |
| config_req.ss_noise_floor_ref = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]) |
| config_req.ss_init_delay = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]) |
| config_req.ss_nb_tone_thr = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]) |
| config_req.ss_str_bin_thr = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]) |
| config_req.ss_wb_rpt_mode = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]) |
| config_req.ss_rssi_rpt_mode = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]) |
| config_req.ss_rssi_thr = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]) |
| config_req.ss_pwr_format = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]) |
| config_req.ss_rpt_mode = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]) |
| config_req.ss_bin_scale = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]) |
| config_req.ss_dbm_adj = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]) |
| config_req.ss_chn_mask = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]) |
| config_req.ss_fft_period = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]) |
| config_req.ss_short_report = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]); |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) { |
| spectral_dbg_level = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]); |
| status = wlan_spectral_set_debug_level(pdev, |
| spectral_dbg_level); |
| if (QDF_STATUS_SUCCESS != status) |
| return -EINVAL; |
| } |
| |
| if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]) |
| scan_req_type = nla_get_u32(tb |
| [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]); |
| |
| if (CONFIG_REQUESTED(scan_req_type)) { |
| status = wlan_spectral_set_config(pdev, &config_req); |
| if (QDF_STATUS_SUCCESS != status) |
| return -EINVAL; |
| } |
| |
| if (SCAN_REQUESTED(scan_req_type)) { |
| status = wlan_start_spectral_scan(pdev); |
| if (QDF_STATUS_SUCCESS != status) |
| return -EINVAL; |
| } |
| |
| skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) + |
| NLA_HDRLEN + NLMSG_HDRLEN); |
| if (!skb) { |
| qdf_print(" reply skb alloc failed"); |
| return -ENOMEM; |
| } |
| |
| cookie = 0; |
| if (wlan_cfg80211_nla_put_u64(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE, |
| cookie)) { |
| kfree_skb(skb); |
| return -EINVAL; |
| } |
| |
| cfg80211_vendor_cmd_reply(skb); |
| |
| return 0; |
| } |
| |
| int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| QDF_STATUS status; |
| |
| status = wlan_stop_spectral_scan(pdev); |
| if (QDF_STATUS_SUCCESS != status) |
| return -EINVAL; |
| return 0; |
| } |
| |
| int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| struct spectral_config config_buf; |
| uint32_t spectral_dbg_level; |
| struct sk_buff *skb; |
| |
| wlan_spectral_get_config(pdev, &config_buf); |
| wlan_spectral_get_debug_level(pdev, &spectral_dbg_level); |
| |
| skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (21 * sizeof(u32)) + |
| NLA_HDRLEN + NLMSG_HDRLEN); |
| if (!skb) { |
| qdf_print(" reply skb alloc failed"); |
| return -ENOMEM; |
| } |
| |
| if (nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT, |
| config_buf.ss_count) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD, |
| config_buf.ss_period) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY, |
| config_buf.ss_spectral_pri) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE, |
| config_buf.ss_fft_size) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA, |
| config_buf.ss_gc_ena) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA, |
| config_buf.ss_restart_ena) || |
| nla_put_u32( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF, |
| config_buf.ss_noise_floor_ref) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY, |
| config_buf.ss_init_delay) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR, |
| config_buf.ss_nb_tone_thr) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR, |
| config_buf.ss_str_bin_thr) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE, |
| config_buf.ss_wb_rpt_mode) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE, |
| config_buf.ss_rssi_rpt_mode) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR, |
| config_buf.ss_rssi_thr) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT, |
| config_buf.ss_pwr_format) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE, |
| config_buf.ss_rpt_mode) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE, |
| config_buf.ss_bin_scale) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ, |
| config_buf.ss_dbm_adj) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK, |
| config_buf.ss_chn_mask) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD, |
| config_buf.ss_fft_period) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT, |
| config_buf.ss_short_report) || |
| nla_put_u32(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL, |
| spectral_dbg_level)) { |
| kfree_skb(skb); |
| return -EINVAL; |
| } |
| cfg80211_vendor_cmd_reply(skb); |
| |
| return 0; |
| } |
| |
| int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| struct spectral_caps spectral_cap; |
| struct sk_buff *skb; |
| |
| wlan_spectral_get_cap(pdev, &spectral_cap); |
| |
| skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 4 * sizeof(u32) + |
| NLA_HDRLEN + NLMSG_HDRLEN); |
| if (!skb) { |
| qdf_print(" reply skb alloc failed"); |
| return -ENOMEM; |
| } |
| |
| if (spectral_cap.phydiag_cap) |
| if (nla_put_flag( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG)) |
| goto fail; |
| |
| if (spectral_cap.radar_cap) |
| if (nla_put_flag(skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR)) |
| goto fail; |
| |
| if (spectral_cap.spectral_cap) |
| if (nla_put_flag( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL)) |
| goto fail; |
| |
| if (spectral_cap.advncd_spectral_cap) |
| if (nla_put_flag( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL)) |
| goto fail; |
| cfg80211_vendor_cmd_reply(skb); |
| return 0; |
| |
| fail: |
| kfree_skb(skb); |
| return -EINVAL; |
| } |
| |
| int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| struct spectral_diag_stats spetcral_diag; |
| struct sk_buff *skb; |
| |
| wlan_spectral_get_diag_stats(pdev, &spetcral_diag); |
| |
| skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u64) + |
| NLA_HDRLEN + NLMSG_HDRLEN); |
| if (!skb) { |
| qdf_print(" reply skb alloc failed"); |
| return -ENOMEM; |
| } |
| |
| if (wlan_cfg80211_nla_put_u64( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH, |
| spetcral_diag.spectral_mismatch) || |
| wlan_cfg80211_nla_put_u64( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN, |
| spetcral_diag.spectral_sec80_sfft_insufflen) || |
| wlan_cfg80211_nla_put_u64( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT, |
| spetcral_diag.spectral_no_sec80_sfft) || |
| wlan_cfg80211_nla_put_u64( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH, |
| spetcral_diag.spectral_vhtseg1id_mismatch) || |
| wlan_cfg80211_nla_put_u64( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH, |
| spetcral_diag.spectral_vhtseg2id_mismatch)) { |
| kfree_skb(skb); |
| return -EINVAL; |
| } |
| cfg80211_vendor_cmd_reply(skb); |
| |
| return 0; |
| } |
| |
| int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, |
| struct wlan_objmgr_pdev *pdev, |
| const void *data, |
| int data_len) |
| { |
| struct spectral_scan_state sscan_state; |
| struct sk_buff *skb; |
| |
| skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * sizeof(u32) + |
| NLA_HDRLEN + NLMSG_HDRLEN); |
| if (!skb) { |
| qdf_print(" reply skb alloc failed"); |
| return -ENOMEM; |
| } |
| |
| wlan_spectral_scan_get_status(pdev, &sscan_state); |
| |
| if (sscan_state.is_enabled) |
| if (nla_put_flag( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED)) |
| goto fail; |
| |
| if (sscan_state.is_active) |
| if (nla_put_flag( |
| skb, |
| QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE)) |
| goto fail; |
| cfg80211_vendor_cmd_reply(skb); |
| return 0; |
| |
| fail: |
| kfree_skb(skb); |
| return -EINVAL; |
| } |