diff --git a/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h b/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h new file mode 100644 index 0000000000..39bae6fae6 --- /dev/null +++ b/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h @@ -0,0 +1,138 @@ +/* + * 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: declares driver functions interfacing with linux kernel + */ + +#ifndef _WLAN_CFG80211_SPECTRAL_H_ +#define _WLAN_CFG80211_SPECTRAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIG_REQUESTED(type) ((type == \ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG) || \ + (type == QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG)) + +#define SCAN_REQUESTED(type) ((type == \ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG) || \ + (type == QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN)) + +/** + * wlan_cfg80211_register_spectral_cmd_handler() - Registration api for spectral + * @pdev: Pointer to pdev + * @idx: Index in function table + * @handler: Pointer to handler + * + * Return: 0 on success, negative value on failure + */ +void wlan_cfg80211_register_spectral_cmd_handler(struct wlan_objmgr_pdev *pdev, + int idx, + void *handler); + +/** + * wlan_cfg80211_spectral_scan_config_and_start() - Start spectral scan + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); + +/** + * wlan_cfg80211_spectral_scan_stop() - Stop spectral scan + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); + +/** + * wlan_cfg80211_spectral_scan_get_config() - Get spectral scan config + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); + +/** + * wlan_cfg80211_spectral_scan_get_cap() - Get spectral system capabilities + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); + +/** + * wlan_cfg80211_spectral_scan_get_diag_stats() - Get spectral diag stats + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); + +/** + * wlan_cfg80211_spectral_scan_get_status() - Get spectral scan status + * @wiphy: Pointer to wiphy + * @pdev: Pointer to pdev + * @data: Reference to data + * @data_len: Length of @data + * + * Return: 0 on success, negative value on failure + */ +int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + const void *data, + int data_len); +#endif diff --git a/os_if/linux/spectral/src/wlan_cfg80211_spectral.c b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c new file mode 100644 index 0000000000..fdb160a456 --- /dev/null +++ b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c @@ -0,0 +1,671 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#ifdef WLAN_POLICY_MGR_ENABLE +#include +#endif +#include +#include +#include + +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; +} diff --git a/spectral/Kbuild b/spectral/Kbuild index eac23f465c..6d7469ef8a 100644 --- a/spectral/Kbuild +++ b/spectral/Kbuild @@ -23,6 +23,8 @@ INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/mgmt_txrx/dispatcher/inc INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/regulatory/dispatcher/inc INCS += -I$(obj)/$(DEPTH)/umac/son/dispatcher/inc INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/dfs/dispatcher/inc +INCS += -I$(obj)/$(DEPTH)/cmn_dev/os_if/linux/spectral/inc +INCS += -I$(obj)/$(DEPTH)/cmn_dev/os_if/linux/scan/inc ifeq ($(WLAN_CONV_CRYPTO_SUPPORTED), 1) INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/crypto/inc @@ -181,7 +183,8 @@ SPECTRAL_CMN_OBJS += core/spectral_direct_attach.o \ dispatcher/src/wlan_spectral_utils_api.o \ dispatcher/src/wlan_spectral_ucfg_api.o \ dispatcher/src/wlan_spectral_tgt_api.o \ - core/spectral_module.o + core/spectral_module.o \ + $(DEPTH)/cmn_dev/os_if/linux/spectral/src/wlan_cfg80211_spectral.o qca_spectral-objs += ${SPECTRAL_CMN_OBJS} \ ${SPECTRAL_TIF_OBJS} \ diff --git a/spectral/core/spectral_common.c b/spectral/core/spectral_common.c index bb0eaf6446..07d228fee8 100644 --- a/spectral/core/spectral_common.c +++ b/spectral/core/spectral_common.c @@ -25,6 +25,7 @@ #include #include #include +#include /** * spectral_get_vdev() - Get pointer to vdev to be used for Spectral @@ -64,6 +65,34 @@ spectral_get_vdev(struct wlan_objmgr_pdev *pdev) return vdev; } +static void spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev) +{ + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_START_HANDLER_IDX, + wlan_cfg80211_spectral_scan_config_and_start); + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_STOP_HANDLER_IDX, + wlan_cfg80211_spectral_scan_stop); + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_GET_CONFIG_HANDLER_IDX, + wlan_cfg80211_spectral_scan_get_config); + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_GET_DIAG_STATS_HANDLER_IDX, + wlan_cfg80211_spectral_scan_get_diag_stats); + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_GET_CAP_HANDLER_IDX, + wlan_cfg80211_spectral_scan_get_cap); + wlan_cfg80211_register_spectral_cmd_handler( + pdev, + SPECTRAL_SCAN_GET_STATUS_HANDLER_IDX, + wlan_cfg80211_spectral_scan_get_status); +} + int spectral_control_cmn( struct wlan_objmgr_pdev *pdev, u_int id, @@ -348,6 +377,18 @@ int spectral_control_cmn( } break; +case SPECTRAL_GET_DEBUG_LEVEL: + { + if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof(u_int32_t); + *((u_int32_t *)outdata) = + (u_int32_t)sc->sptrlc_get_debug_level(pdev); + } + break; + case SPECTRAL_ACTIVATE_SCAN: { sc->sptrlc_start_spectral_scan(pdev); @@ -511,6 +552,8 @@ wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg) qdf_mem_zero(ps, sizeof(struct pdev_spectral)); ps->psptrl_pdev = pdev; + + spectral_register_cfg80211_handlers(pdev); if (sc->sptrlc_pdev_spectral_init) { target_handle = sc->sptrlc_pdev_spectral_init(pdev); if (!target_handle) { diff --git a/spectral/core/spectral_module.c b/spectral/core/spectral_module.c index ce42e639b8..2283f05b9b 100644 --- a/spectral/core/spectral_module.c +++ b/spectral/core/spectral_module.c @@ -22,6 +22,8 @@ #include #include +MODULE_LICENSE("Dual BSD/GPL"); + /** * spectral_init_module() - Initialize Spectral module * diff --git a/spectral/dispatcher/inc/spectral_ioctl.h b/spectral/dispatcher/inc/spectral_ioctl.h new file mode 100644 index 0000000000..66988ade96 --- /dev/null +++ b/spectral/dispatcher/inc/spectral_ioctl.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011, 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. + */ + +#ifndef _SPECTRAL_IOCTL_H_ +#define _SPECTRAL_IOCTL_H_ + +#include + +/* + * ioctl defines + */ + +#define SPECTRAL_SET_CONFIG (DFS_LAST_IOCTL + 1) +#define SPECTRAL_GET_CONFIG (DFS_LAST_IOCTL + 2) +#define SPECTRAL_SHOW_INTERFERENCE (DFS_LAST_IOCTL + 3) +#define SPECTRAL_ENABLE_SCAN (DFS_LAST_IOCTL + 4) +#define SPECTRAL_DISABLE_SCAN (DFS_LAST_IOCTL + 5) +#define SPECTRAL_ACTIVATE_SCAN (DFS_LAST_IOCTL + 6) +#define SPECTRAL_STOP_SCAN (DFS_LAST_IOCTL + 7) +#define SPECTRAL_SET_DEBUG_LEVEL (DFS_LAST_IOCTL + 8) +#define SPECTRAL_IS_ACTIVE (DFS_LAST_IOCTL + 9) +#define SPECTRAL_IS_ENABLED (DFS_LAST_IOCTL + 10) +#define SPECTRAL_CLASSIFY_SCAN (DFS_LAST_IOCTL + 11) +#define SPECTRAL_GET_CLASSIFIER_CONFIG (DFS_LAST_IOCTL + 12) +#define SPECTRAL_EACS (DFS_LAST_IOCTL + 13) +#define SPECTRAL_ACTIVATE_FULL_SCAN (DFS_LAST_IOCTL + 14) +#define SPECTRAL_STOP_FULL_SCAN (DFS_LAST_IOCTL + 15) +#define SPECTRAL_GET_CAPABILITY_INFO (DFS_LAST_IOCTL + 16) +#define SPECTRAL_GET_DIAG_STATS (DFS_LAST_IOCTL + 17) +#define SPECTRAL_GET_CHAN_WIDTH (DFS_LAST_IOCTL + 18) +#define SPECTRAL_GET_CHANINFO (DFS_LAST_IOCTL + 19) +#define SPECTRAL_CLEAR_CHANINFO (DFS_LAST_IOCTL + 20) +#define SPECTRAL_SET_ICM_ACTIVE (DFS_LAST_IOCTL + 21) +#define SPECTRAL_GET_NOMINAL_NOISEFLOOR (DFS_LAST_IOCTL + 22) +#define SPECTRAL_GET_DEBUG_LEVEL (DFS_LAST_IOCTL + 23) + +/* + * ioctl parameter types + */ + +#define SPECTRAL_PARAM_FFT_PERIOD (1) +#define SPECTRAL_PARAM_SCAN_PERIOD (2) +#define SPECTRAL_PARAM_SCAN_COUNT (3) +#define SPECTRAL_PARAM_SHORT_REPORT (4) +#define SPECTRAL_PARAM_SPECT_PRI (5) +#define SPECTRAL_PARAM_FFT_SIZE (6) +#define SPECTRAL_PARAM_GC_ENA (7) +#define SPECTRAL_PARAM_RESTART_ENA (8) +#define SPECTRAL_PARAM_NOISE_FLOOR_REF (9) +#define SPECTRAL_PARAM_INIT_DELAY (10) +#define SPECTRAL_PARAM_NB_TONE_THR (11) +#define SPECTRAL_PARAM_STR_BIN_THR (12) +#define SPECTRAL_PARAM_WB_RPT_MODE (13) +#define SPECTRAL_PARAM_RSSI_RPT_MODE (14) +#define SPECTRAL_PARAM_RSSI_THR (15) +#define SPECTRAL_PARAM_PWR_FORMAT (16) +#define SPECTRAL_PARAM_RPT_MODE (17) +#define SPECTRAL_PARAM_BIN_SCALE (18) +#define SPECTRAL_PARAM_DBM_ADJ (19) +#define SPECTRAL_PARAM_CHN_MASK (20) +#define SPECTRAL_PARAM_ACTIVE (21) +#define SPECTRAL_PARAM_STOP (22) +#define SPECTRAL_PARAM_ENABLE (23) + +struct spectral_ioctl_params { + int16_t spectral_fft_period; + int16_t pectral_period; + int16_t spectral_count; + u_int16_t spectral_short_report; + u_int16_t spectral_pri; +}; + +struct ath_spectral_caps { + u_int8_t phydiag_cap; + u_int8_t radar_cap; + u_int8_t spectral_cap; + u_int8_t advncd_spectral_cap; +}; + +#define SPECTRAL_IOCTL_PARAM_NOVAL (65535) + +#endif diff --git a/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/spectral/dispatcher/inc/wlan_spectral_public_structs.h index 9ba5b60cf8..15963d7fb6 100644 --- a/spectral/dispatcher/inc/wlan_spectral_public_structs.h +++ b/spectral/dispatcher/inc/wlan_spectral_public_structs.h @@ -124,6 +124,16 @@ #define SPECTRAL_SCAN_SHORT_REPORT_DEFAULT (1) #define SPECTRAL_SCAN_FFT_PERIOD_DEFAULT (1) +enum wlan_cfg80211_spectral_vendorcmd_handler_idx { + SPECTRAL_SCAN_START_HANDLER_IDX, + SPECTRAL_SCAN_STOP_HANDLER_IDX, + SPECTRAL_SCAN_GET_CONFIG_HANDLER_IDX, + SPECTRAL_SCAN_GET_DIAG_STATS_HANDLER_IDX, + SPECTRAL_SCAN_GET_CAP_HANDLER_IDX, + SPECTRAL_SCAN_GET_STATUS_HANDLER_IDX, + SPECTRAL_SCAN_VENDOR_CMD_HANDLER_MAX, +}; + /** * enum spectral_debug - Spectral debug level * @ATH_DEBUG_SPECTRAL: Minimal SPECTRAL debug @@ -296,12 +306,15 @@ struct spectral_config { }; /** - * struct spectral_caps - Spectral capabilities structure - * @phydiag_cap: Phydiag capability - * @radar_cap: Radar detection capability - * @spectral_cap: Spectral capability - * @advncd_spectral_cap: Advanced spectral capability + * struct spectral_scan_state - State of spectral scan + * @is_active: Is spectral scan active + * @is_enabled: Is spectral scan enabled */ +struct spectral_scan_state { + uint8_t is_active; + uint8_t is_enabled; +}; + typedef enum _dcs_int_type { SPECTRAL_DCS_INT_NONE, SPECTRAL_DCS_INT_CW, diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c index 416a91805a..089451ad79 100644 --- a/target_if/spectral/target_if_spectral.c +++ b/target_if/spectral/target_if_spectral.c @@ -2363,8 +2363,7 @@ static int target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, */ static u_int32_t target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) { - qdf_print("target_if_get_debug_level is unimplemented\n"); - return 0; + return spectral_debug_level; } /**