wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/301-debugfs-support-for-ani-parameters.patch
John Crispin 8cd26b4b50 ipq807x: update to 11.4-CS
Signed-off-by: John Crispin <john@phrozen.org>
2021-09-14 09:16:23 +02:00

549 lines
15 KiB
Diff

From b6b05d6e9b69d76053cc6997e1cedf2e4c9c24c0 Mon Sep 17 00:00:00 2001
From: Hari Chandrakanthan <haric@codeaurora.org>
Date: Sun, 18 Apr 2021 16:51:56 +0530
Subject: [PATCH] debugfs-support-for-ani-parameters
Signed-off-by: Hari Chandrakanthan <haric@codeaurora.org>
---
drivers/net/wireless/ath/ath11k/core.h | 8 +
drivers/net/wireless/ath/ath11k/debugfs.c | 308 ++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath11k/debugfs.h | 6 +
drivers/net/wireless/ath/ath11k/mac.c | 3 +
drivers/net/wireless/ath/ath11k/wmi.c | 74 +++++++
drivers/net/wireless/ath/ath11k/wmi.h | 18 ++
6 files changed, 417 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 07a7175..c1dc737 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -740,6 +740,7 @@ struct ath11k {
struct ath11k_cfr cfr;
#endif
u8 cfr_enabled;
+ bool ani_enabled;
};
struct ath11k_band_cap {
@@ -988,6 +989,13 @@ struct ath11k_base {
u32 rx_hash;
bool stats_disable;
+ u32 ani_poll_period;
+ u32 ani_listen_period;
+ int ani_ofdm_level;
+ int ani_cck_level;
+ struct completion ani_ofdm_event;
+ struct completion ani_cck_event;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 2636931..f04395a 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -3692,6 +3692,302 @@ static const struct file_operations fops_disable_dyn_bw = {
.open = simple_open
};
+static ssize_t ath11k_read_ani_enable(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int len = 0;
+ char buf[32];
+
+ len = scnprintf(buf, sizeof(buf) - len, "%d\n",ar->ani_enabled);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath11k_write_ani_enable(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int ret;
+ u8 enable;
+
+ if (kstrtou8_from_user(user_buf, count, 0, &enable))
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->ani_enabled == enable) {
+ ret = count;
+ goto exit;
+ }
+
+ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ANI_ENABLE,
+ enable, ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
+ goto exit;
+ }
+ ar->ani_enabled = enable;
+ ret = count;
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static const struct file_operations fops_ani_enable = {
+ .read = ath11k_read_ani_enable,
+ .write = ath11k_write_ani_enable,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath11k_read_ani_poll_period(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int len = 0;
+ char buf[32];
+
+ len = scnprintf(buf, sizeof(buf) - len, "%u\n", ar->ab->ani_poll_period);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath11k_write_ani_poll_period(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int ret;
+ u32 ani_poll_period;
+
+ if (kstrtou32_from_user(user_buf, count, 0, &ani_poll_period))
+ return -EINVAL;
+
+ if(ani_poll_period > ATH11K_ANI_POLL_PERIOD_MAX)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ANI_POLL_PERIOD,
+ ani_poll_period, ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "ani poll period write failed in debugfs: %d\n", ret);
+ goto exit;
+ }
+ ar->ab->ani_poll_period = ani_poll_period;
+ ret = count;
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static const struct file_operations fops_ani_poll_period = {
+ .read = ath11k_read_ani_poll_period,
+ .write = ath11k_write_ani_poll_period,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath11k_read_ani_listen_period(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int len = 0;
+ char buf[32];
+
+ len = scnprintf(buf, sizeof(buf) - len, "%u\n", ar->ab->ani_listen_period);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath11k_write_ani_listen_period(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ int ret;
+ u32 ani_listen_period = 0;
+
+ if (kstrtou32_from_user(user_buf, count, 0, &ani_listen_period))
+ return -EINVAL;
+
+ if(ani_listen_period > ATH11K_ANI_LISTEN_PERIOD_MAX)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ANI_LISTEN_PERIOD,
+ ani_listen_period, ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "ani listen period write failed in debugfs: %d\n", ret);
+ goto exit;
+ }
+ ar->ab->ani_listen_period = ani_listen_period;
+ ret = count;
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static const struct file_operations fops_ani_listen_period = {
+ .read = ath11k_read_ani_listen_period,
+ .write = ath11k_write_ani_listen_period,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static int ath11k_debug_get_ani_level(struct ath11k *ar)
+{
+ unsigned long time_left;
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ reinit_completion(&(ar->ab->ani_ofdm_event));
+
+ ret = ath11k_wmi_pdev_get_ani_level(ar, WMI_PDEV_GET_ANI_OFDM_CONFIG_CMDID,
+ ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "failed to request ofdm ani level: %d\n", ret);
+ return ret;
+ }
+ time_left = wait_for_completion_timeout(&ar->ab->ani_ofdm_event, 1 * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+
+ if (ar->ab->target_caps.phy_capability & WHAL_WLAN_11G_CAPABILITY) {
+ reinit_completion(&(ar->ab->ani_cck_event));
+ ret = ath11k_wmi_pdev_get_ani_level(ar, WMI_PDEV_GET_ANI_CCK_CONFIG_CMDID,
+ ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "failed to request cck ani level: %d\n", ret);
+ return ret;
+ }
+ time_left = wait_for_completion_timeout(&ar->ab->ani_cck_event, 1 * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static ssize_t ath11k_read_ani_level(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ char buf[128];
+ int ret, len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+ if (ar->state != ATH11K_STATE_ON) {
+ ret = -ENETDOWN;
+ goto unlock;
+ }
+
+ if(!ar->ani_enabled) {
+ len += scnprintf(buf, sizeof(buf), "ANI is disabled\n");
+ } else {
+ ret = ath11k_debug_get_ani_level(ar);
+ if (ret) {
+ ath11k_warn(ar, "failed to request ani level: %d\n", ret);
+ goto unlock;
+ }
+ len += scnprintf(buf, sizeof(buf), "ofdm level %d cck level %d\n",
+ ar->ab->ani_ofdm_level, ar->ab->ani_cck_level);
+ }
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+unlock:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static ssize_t ath11k_write_ani_level(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ char buf[32] = {0};
+ ssize_t rc;
+ u32 ofdm_param = 0, cck_param = 0;
+ int ofdm_level, cck_level;
+ int ret;
+
+ rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+ if (rc < 0)
+ return rc;
+
+ buf[*ppos - 1] = '\0';
+
+ ret = sscanf(buf, "%d %d", &ofdm_level, &cck_level);
+
+ if (ret != 2)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_ON && ar->state != ATH11K_STATE_RESTARTED) {
+ ret = -ENETDOWN;
+ goto exit;
+ }
+
+ if ((ofdm_level >= ATH11K_ANI_LEVEL_MIN && ofdm_level <= ATH11K_ANI_LEVEL_MAX) ||
+ (ofdm_level == ATH11K_ANI_LEVEL_AUTO)) {
+ ofdm_param = WMI_PDEV_PARAM_ANI_OFDM_LEVEL;
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if((ar->ab->target_caps.phy_capability & WHAL_WLAN_11G_CAPABILITY)) {
+ if ((cck_level >= ATH11K_ANI_LEVEL_MIN &&
+ cck_level <= ATH11K_ANI_LEVEL_MAX) ||
+ (cck_level == ATH11K_ANI_LEVEL_AUTO)) {
+ cck_param = WMI_PDEV_PARAM_ANI_CCK_LEVEL;
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+
+ ret = ath11k_wmi_pdev_set_param(ar, ofdm_param, ofdm_level, ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "failed to set ANI ofdm level :%d\n", ret);
+ goto exit;
+ }
+
+ if (cck_param) {
+ ret = ath11k_wmi_pdev_set_param(ar, cck_param, cck_level,
+ ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar, "failed to set ANI cck level :%d\n", ret);
+ goto exit;
+ }
+ }
+
+ ret = count;
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static const struct file_operations fops_ani_level = {
+ .write = ath11k_write_ani_level,
+ .read = ath11k_read_ani_level,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath11k_debugfs_register(struct ath11k *ar)
{
struct ath11k_base *ab = ar->ab;
@@ -3716,6 +4012,8 @@ int ath11k_debugfs_register(struct ath11k *ar)
ath11k_debugfs_fw_stats_init(ar);
ath11k_init_pktlog(ar);
init_completion(&ar->tpc_complete);
+ init_completion(&ab->ani_ofdm_event);
+ init_completion(&ab->ani_cck_event);
debugfs_create_file("ext_tx_stats", 0644,
ar->debug.debugfs_pdev, ar,
@@ -3781,6 +4079,16 @@ int ath11k_debugfs_register(struct ath11k *ar)
debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
ar, &fops_dbr_debug);
+
+ debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_pdev, ar, &fops_ani_enable);
+ debugfs_create_file("ani_level", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_pdev, ar, &fops_ani_level);
+ debugfs_create_file("ani_poll_period", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_pdev, ar, &fops_ani_poll_period);
+ debugfs_create_file("ani_listen_period", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_pdev, ar, &fops_ani_listen_period);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
index e08034c..95a8372 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
@@ -211,6 +211,12 @@ do { \
#define ATH11K_MEMORY_STATS_DEC(_struct, _field, _size)
#endif
+#define ATH11K_ANI_LEVEL_MAX 30
+#define ATH11K_ANI_LEVEL_MIN -5
+#define ATH11K_ANI_LEVEL_AUTO 0x80
+#define ATH11K_ANI_POLL_PERIOD_MAX 3000
+#define ATH11K_ANI_LISTEN_PERIOD_MAX 3000
+
#ifdef CPTCFG_ATH11K_DEBUGFS
int ath11k_debugfs_create(void);
void ath11k_debugfs_destroy(void);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 29cbc33..a68ab06 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6153,6 +6153,9 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
&ab->pdevs[ar->pdev_idx]);
+ /*ani is enabled by default*/
+ ar->ani_enabled = true;
+
return 0;
err:
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 173d217..1fbba1b 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -8370,6 +8370,74 @@ ath11k_wmi_pdev_csa_switch_count_status_event(struct ath11k_base *ab,
kfree(tb);
}
+int ath11k_wmi_pdev_get_ani_level(struct ath11k *ar, u32 cmd_id, u8 pdev_id)
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct wmi_pdev_get_ani_level_cmd *cmd = NULL;
+ struct sk_buff *skb;
+ int ret;
+ enum wmi_tlv_tag temp_tlv_tag;
+
+ switch(cmd_id) {
+ case WMI_PDEV_GET_ANI_OFDM_CONFIG_CMDID:
+ temp_tlv_tag = WMI_TAG_PDEV_GET_ANI_OFDM_CONFIG_CMD;
+ break;
+ case WMI_PDEV_GET_ANI_CCK_CONFIG_CMDID:
+ temp_tlv_tag = WMI_TAG_PDEV_GET_ANI_CCK_CONFIG_CMD;
+ break;
+ default:
+ ath11k_warn(ar->ab, "Invalid cmd %d\n", cmd_id);
+ return -EINVAL;
+ }
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_pdev_get_ani_level_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, temp_tlv_tag) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->pdev_id = pdev_id;
+
+ ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_PARAM cmd\n");
+ dev_kfree_skb(skb);
+ }
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI pdev pdev id %d\n", pdev_id);
+
+ return ret;
+}
+
+static int ath11k_wmi_event_ani_ofdm_level(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ const struct wmi_pdev_ani_event *ev;
+
+ ev = (struct wmi_pdev_ani_event *)skb->data;
+ if (WARN_ON(skb->len < sizeof(*ev)))
+ return -EPROTO;
+
+ ab->ani_ofdm_level = ev->ani_level;
+ complete(&ab->ani_ofdm_event);
+ return 0;
+}
+
+static int ath11k_wmi_event_ani_cck_level(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ const struct wmi_pdev_ani_event *ev;
+
+ ev = (struct wmi_pdev_ani_event *)skb->data;
+ if (WARN_ON(skb->len < sizeof(*ev)))
+ return -EPROTO;
+
+ ab->ani_cck_level = ev->ani_level;
+ complete(&(ab->ani_cck_event));
+ return 0;
+}
+
static void
ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff *skb)
{
@@ -9587,6 +9655,12 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_PEER_CFR_CAPTURE_EVENTID:
ath11k_wmi_parse_cfr_capture_event(ab, skb);
break;
+ case WMI_PDEV_ANI_CCK_LEVEL_EVENTID:
+ ath11k_wmi_event_ani_cck_level(ab, skb);
+ break;
+ case WMI_PDEV_ANI_OFDM_LEVEL_EVENTID:
+ ath11k_wmi_event_ani_ofdm_level(ab, skb);
+ break;
/* TODO: Add remaining events */
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 55f51fa..d74128f 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -117,6 +117,12 @@ enum {
WMI_HOST_WLAN_2G_5G_CAP = 0x3,
};
+enum wlan_mode_capability {
+ WHAL_WLAN_11A_CAPABILITY = 0x1,
+ WHAL_WLAN_11G_CAPABILITY = 0x2,
+ WHAL_WLAN_11AG_CAPABILITY = 0x3,
+};
+
/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
* Used only for HE auto rate mode.
*/
@@ -2753,6 +2759,11 @@ struct wmi_p2p_noa_descriptor {
u32 start_time;
};
+struct wmi_pdev_ani_event {
+ u32 tlv_header;
+ u32 ani_level;
+} __packed;
+
struct channel_param {
u8 chan_id;
u8 pwr;
@@ -3148,6 +3159,12 @@ struct wmi_fwtest_set_param_cmd_param {
u32 param_value;
};
+struct wmi_pdev_get_ani_level_cmd {
+ u32 tlv_header;
+ u32 pdev_id;
+ u32 param_id;
+} __packed;
+
struct wmi_pdev_set_param_cmd {
u32 tlv_header;
u32 pdev_id;
@@ -6694,4 +6711,5 @@ int ath11k_wmi_dbglog_cfg(struct ath11k *ar, u32 param, u64 value);
int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
u32 vdev_id, const u8 *mac,
struct wmi_peer_cfr_capture_conf_arg *arg);
+int ath11k_wmi_pdev_get_ani_level(struct ath11k *ar, u32 param_id, u8 pdev_id);
#endif
--
2.7.4