|
@@ -0,0 +1,824 @@
|
|
|
+From bc64d05220f3e34cf432a166b83c8fff14cd7a3d Mon Sep 17 00:00:00 2001
|
|
|
+From: Maharaja Kennadyrajan <[email protected]>
|
|
|
+Date: Wed, 14 Mar 2018 12:14:08 +0200
|
|
|
+Subject: [PATCH] ath10k: debugfs support to get final TPC stats for 10.4
|
|
|
+ variants
|
|
|
+
|
|
|
+Export the final Transmit Power Control (TPC) value, which is the
|
|
|
+minimum of control power and existing TPC value to user space via
|
|
|
+a new debugfs file "tpc_stats_final" to help with debugging.
|
|
|
+It works with the new wmi cmd and event introduced in 10.4 firmware
|
|
|
+branch.
|
|
|
+
|
|
|
+WMI command ID: WMI_PDEV_GET_TPC_TABLE_CMDID
|
|
|
+WMI event ID: WMI_PDEV_TPC_TABLE_EVENTID
|
|
|
+
|
|
|
+cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final
|
|
|
+
|
|
|
+$ cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final
|
|
|
+
|
|
|
+TPC config for channel 5180 mode 10
|
|
|
+
|
|
|
+CTL = 0x 0 Reg. Domain = 58
|
|
|
+Antenna Gain = 0 Reg. Max Antenna Gain = 0
|
|
|
+Power Limit = 60 Reg. Max Power = 60
|
|
|
+Num tx chains = 2 Num supported rates = 109
|
|
|
+
|
|
|
+******************* CDD POWER TABLE ****************
|
|
|
+
|
|
|
+No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3
|
|
|
+0 CCK 0x40 0 0
|
|
|
+1 CCK 0x41 0 0
|
|
|
+[...]
|
|
|
+107 HTCUP 0x 0 46 46
|
|
|
+108 HTCUP 0x 0 46 46
|
|
|
+
|
|
|
+******************* STBC POWER TABLE ****************
|
|
|
+
|
|
|
+No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3
|
|
|
+0 CCK 0x40 0 0
|
|
|
+1 CCK 0x41 0 0
|
|
|
+[...]
|
|
|
+107 HTCUP 0x 0 46 46
|
|
|
+108 HTCUP 0x 0 46 46
|
|
|
+
|
|
|
+***********************************
|
|
|
+TXBF not supported
|
|
|
+**********************************
|
|
|
+
|
|
|
+The existing tpc_stats debugfs file provides the dump
|
|
|
+which is minimum of target power and regulatory domain.
|
|
|
+
|
|
|
+cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats
|
|
|
+
|
|
|
+Hardware_used: QCA4019
|
|
|
+Firmware version: firmware-5.bin_10.4-3.0-00209
|
|
|
+
|
|
|
+Signed-off-by: Maharaja Kennadyrajan <[email protected]>
|
|
|
+Signed-off-by: Kalle Valo <[email protected]>
|
|
|
+---
|
|
|
+ drivers/net/wireless/ath/ath10k/core.h | 22 +++
|
|
|
+ drivers/net/wireless/ath/ath10k/debug.c | 107 +++++++++++
|
|
|
+ drivers/net/wireless/ath/ath10k/debug.h | 10 +
|
|
|
+ drivers/net/wireless/ath/ath10k/wmi-ops.h | 20 ++
|
|
|
+ drivers/net/wireless/ath/ath10k/wmi.c | 308 ++++++++++++++++++++++++++++--
|
|
|
+ drivers/net/wireless/ath/ath10k/wmi.h | 66 +++++++
|
|
|
+ 6 files changed, 518 insertions(+), 15 deletions(-)
|
|
|
+
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/core.h
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/core.h
|
|
|
+@@ -322,6 +322,27 @@ struct ath10k_tpc_stats {
|
|
|
+ struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG];
|
|
|
+ };
|
|
|
+
|
|
|
++struct ath10k_tpc_table_final {
|
|
|
++ u32 pream_idx[WMI_TPC_FINAL_RATE_MAX];
|
|
|
++ u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
|
|
|
++ char tpc_value[WMI_TPC_FINAL_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
|
|
|
++};
|
|
|
++
|
|
|
++struct ath10k_tpc_stats_final {
|
|
|
++ u32 reg_domain;
|
|
|
++ u32 chan_freq;
|
|
|
++ u32 phy_mode;
|
|
|
++ u32 twice_antenna_reduction;
|
|
|
++ u32 twice_max_rd_power;
|
|
|
++ s32 twice_antenna_gain;
|
|
|
++ u32 power_limit;
|
|
|
++ u32 num_tx_chain;
|
|
|
++ u32 ctl;
|
|
|
++ u32 rate_max;
|
|
|
++ u8 flag[WMI_TPC_FLAG];
|
|
|
++ struct ath10k_tpc_table_final tpc_table_final[WMI_TPC_FLAG];
|
|
|
++};
|
|
|
++
|
|
|
+ struct ath10k_dfs_stats {
|
|
|
+ u32 phy_errors;
|
|
|
+ u32 pulses_total;
|
|
|
+@@ -482,6 +503,7 @@ struct ath10k_debug {
|
|
|
+
|
|
|
+ /* used for tpc-dump storage, protected by data-lock */
|
|
|
+ struct ath10k_tpc_stats *tpc_stats;
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats_final;
|
|
|
+
|
|
|
+ struct completion tpc_complete;
|
|
|
+
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/debug.c
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/debug.c
|
|
|
+@@ -1737,6 +1737,19 @@ void ath10k_debug_tpc_stats_process(stru
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+ }
|
|
|
+
|
|
|
++void
|
|
|
++ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats)
|
|
|
++{
|
|
|
++ spin_lock_bh(&ar->data_lock);
|
|
|
++
|
|
|
++ kfree(ar->debug.tpc_stats_final);
|
|
|
++ ar->debug.tpc_stats_final = tpc_stats;
|
|
|
++ complete(&ar->debug.tpc_complete);
|
|
|
++
|
|
|
++ spin_unlock_bh(&ar->data_lock);
|
|
|
++}
|
|
|
++
|
|
|
+ static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
|
|
|
+ unsigned int j, char *buf, size_t *len)
|
|
|
+ {
|
|
|
+@@ -2400,6 +2413,95 @@ static const struct file_operations fops
|
|
|
+ .llseek = default_llseek,
|
|
|
+ };
|
|
|
+
|
|
|
++static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ unsigned long time_left;
|
|
|
++
|
|
|
++ lockdep_assert_held(&ar->conf_mutex);
|
|
|
++
|
|
|
++ reinit_completion(&ar->debug.tpc_complete);
|
|
|
++
|
|
|
++ ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);
|
|
|
++ if (ret) {
|
|
|
++ ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);
|
|
|
++ return ret;
|
|
|
++ }
|
|
|
++
|
|
|
++ time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
|
|
|
++ 1 * HZ);
|
|
|
++ if (time_left == 0)
|
|
|
++ return -ETIMEDOUT;
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)
|
|
|
++{
|
|
|
++ struct ath10k *ar = inode->i_private;
|
|
|
++ void *buf;
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ mutex_lock(&ar->conf_mutex);
|
|
|
++
|
|
|
++ if (ar->state != ATH10K_STATE_ON) {
|
|
|
++ ret = -ENETDOWN;
|
|
|
++ goto err_unlock;
|
|
|
++ }
|
|
|
++
|
|
|
++ buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
|
|
|
++ if (!buf) {
|
|
|
++ ret = -ENOMEM;
|
|
|
++ goto err_unlock;
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = ath10k_debug_tpc_stats_final_request(ar);
|
|
|
++ if (ret) {
|
|
|
++ ath10k_warn(ar, "failed to request tpc stats final: %d\n",
|
|
|
++ ret);
|
|
|
++ goto err_free;
|
|
|
++ }
|
|
|
++
|
|
|
++ ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
|
|
|
++ file->private_data = buf;
|
|
|
++
|
|
|
++ mutex_unlock(&ar->conf_mutex);
|
|
|
++ return 0;
|
|
|
++
|
|
|
++err_free:
|
|
|
++ vfree(buf);
|
|
|
++
|
|
|
++err_unlock:
|
|
|
++ mutex_unlock(&ar->conf_mutex);
|
|
|
++ return ret;
|
|
|
++}
|
|
|
++
|
|
|
++static int ath10k_tpc_stats_final_release(struct inode *inode,
|
|
|
++ struct file *file)
|
|
|
++{
|
|
|
++ vfree(file->private_data);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static ssize_t ath10k_tpc_stats_final_read(struct file *file,
|
|
|
++ char __user *user_buf,
|
|
|
++ size_t count, loff_t *ppos)
|
|
|
++{
|
|
|
++ const char *buf = file->private_data;
|
|
|
++ unsigned int len = strlen(buf);
|
|
|
++
|
|
|
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
|
++}
|
|
|
++
|
|
|
++static const struct file_operations fops_tpc_stats_final = {
|
|
|
++ .open = ath10k_tpc_stats_final_open,
|
|
|
++ .release = ath10k_tpc_stats_final_release,
|
|
|
++ .read = ath10k_tpc_stats_final_read,
|
|
|
++ .owner = THIS_MODULE,
|
|
|
++ .llseek = default_llseek,
|
|
|
++};
|
|
|
++
|
|
|
+ int ath10k_debug_create(struct ath10k *ar)
|
|
|
+ {
|
|
|
+ ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
|
|
|
+@@ -2525,6 +2627,11 @@ int ath10k_debug_register(struct ath10k
|
|
|
+ debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
|
|
|
+ &fops_fw_checksums);
|
|
|
+
|
|
|
++ if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))
|
|
|
++ debugfs_create_file("tpc_stats_final", 0400,
|
|
|
++ ar->debug.debugfs_phy, ar,
|
|
|
++ &fops_tpc_stats_final);
|
|
|
++
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/debug.h
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/debug.h
|
|
|
+@@ -84,6 +84,9 @@ void ath10k_debug_unregister(struct ath1
|
|
|
+ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
|
|
|
+ void ath10k_debug_tpc_stats_process(struct ath10k *ar,
|
|
|
+ struct ath10k_tpc_stats *tpc_stats);
|
|
|
++void
|
|
|
++ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats);
|
|
|
+ struct ath10k_fw_crash_data *
|
|
|
+ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
|
|
|
+
|
|
|
+@@ -151,6 +154,13 @@ static inline void ath10k_debug_tpc_stat
|
|
|
+ {
|
|
|
+ kfree(tpc_stats);
|
|
|
+ }
|
|
|
++
|
|
|
++static inline void
|
|
|
++ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats)
|
|
|
++{
|
|
|
++ kfree(tpc_stats);
|
|
|
++}
|
|
|
+
|
|
|
+ static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
|
|
|
+ int len)
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
|
|
+@@ -197,6 +197,9 @@ struct wmi_ops {
|
|
|
+ (struct ath10k *ar,
|
|
|
+ enum wmi_bss_survey_req_type type);
|
|
|
+ struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
|
|
|
++ struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar,
|
|
|
++ u32 param);
|
|
|
++
|
|
|
+ };
|
|
|
+
|
|
|
+ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
|
|
+@@ -1418,4 +1421,21 @@ ath10k_wmi_echo(struct ath10k *ar, u32 v
|
|
|
+ return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid);
|
|
|
+ }
|
|
|
+
|
|
|
++static inline int
|
|
|
++ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
|
|
|
++{
|
|
|
++ struct sk_buff *skb;
|
|
|
++
|
|
|
++ if (!ar->wmi.ops->gen_pdev_get_tpc_table_cmdid)
|
|
|
++ return -EOPNOTSUPP;
|
|
|
++
|
|
|
++ skb = ar->wmi.ops->gen_pdev_get_tpc_table_cmdid(ar, param);
|
|
|
++
|
|
|
++ if (IS_ERR(skb))
|
|
|
++ return PTR_ERR(skb);
|
|
|
++
|
|
|
++ return ath10k_wmi_cmd_send(ar, skb,
|
|
|
++ ar->wmi.cmd->pdev_get_tpc_table_cmdid);
|
|
|
++}
|
|
|
++
|
|
|
+ #endif
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
|
|
+@@ -1,6 +1,7 @@
|
|
|
+ /*
|
|
|
+ * Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
|
+ * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
|
|
|
++ * Copyright (c) 2018, 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
|
|
|
+@@ -196,6 +197,7 @@ static struct wmi_cmd_map wmi_cmd_map =
|
|
|
+ .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
++ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* 10.X WMI cmd track */
|
|
|
+@@ -362,6 +364,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
|
|
|
+ .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
++ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* 10.2.4 WMI cmd track */
|
|
|
+@@ -528,6 +531,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd
|
|
|
+ .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .pdev_bss_chan_info_request_cmdid =
|
|
|
+ WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
|
|
++ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* 10.4 WMI cmd track */
|
|
|
+@@ -1480,6 +1484,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m
|
|
|
+ .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
++ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
|
|
|
+ };
|
|
|
+
|
|
|
+ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
|
|
|
+@@ -4313,19 +4318,11 @@ static void ath10k_tpc_config_disp_table
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+-void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
|
|
|
++void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
|
|
|
++ u32 num_tx_chain)
|
|
|
+ {
|
|
|
+- u32 i, j, pream_idx, num_tx_chain;
|
|
|
+- u8 rate_code[WMI_TPC_RATE_MAX], rate_idx;
|
|
|
+- u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
|
|
|
+- struct wmi_pdev_tpc_config_event *ev;
|
|
|
+- struct ath10k_tpc_stats *tpc_stats;
|
|
|
+-
|
|
|
+- ev = (struct wmi_pdev_tpc_config_event *)skb->data;
|
|
|
+-
|
|
|
+- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
|
|
|
+- if (!tpc_stats)
|
|
|
+- return;
|
|
|
++ u32 i, j, pream_idx;
|
|
|
++ u8 rate_idx;
|
|
|
+
|
|
|
+ /* Create the rate code table based on the chains supported */
|
|
|
+ rate_idx = 0;
|
|
|
+@@ -4349,8 +4346,6 @@ void ath10k_wmi_event_pdev_tpc_config(st
|
|
|
+ pream_table[pream_idx] = rate_idx;
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+- num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
+-
|
|
|
+ /* Fill HT20 rate code */
|
|
|
+ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 8; j++) {
|
|
|
+@@ -4374,7 +4369,7 @@ void ath10k_wmi_event_pdev_tpc_config(st
|
|
|
+ pream_idx++;
|
|
|
+
|
|
|
+ /* Fill VHT20 rate code */
|
|
|
+- for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) {
|
|
|
++ for (i = 0; i < num_tx_chain; i++) {
|
|
|
+ for (j = 0; j < 10; j++) {
|
|
|
+ rate_code[rate_idx] =
|
|
|
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
|
|
|
+@@ -4418,6 +4413,26 @@ void ath10k_wmi_event_pdev_tpc_config(st
|
|
|
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
|
|
|
+
|
|
|
+ pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END;
|
|
|
++}
|
|
|
++
|
|
|
++void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
|
|
|
++{
|
|
|
++ u32 num_tx_chain;
|
|
|
++ u8 rate_code[WMI_TPC_RATE_MAX];
|
|
|
++ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
|
|
|
++ struct wmi_pdev_tpc_config_event *ev;
|
|
|
++ struct ath10k_tpc_stats *tpc_stats;
|
|
|
++
|
|
|
++ ev = (struct wmi_pdev_tpc_config_event *)skb->data;
|
|
|
++
|
|
|
++ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
|
|
|
++ if (!tpc_stats)
|
|
|
++ return;
|
|
|
++
|
|
|
++ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
++
|
|
|
++ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
|
|
|
++ num_tx_chain);
|
|
|
+
|
|
|
+ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
|
|
|
+ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
|
|
|
+@@ -4457,6 +4472,246 @@ void ath10k_wmi_event_pdev_tpc_config(st
|
|
|
+ __le32_to_cpu(ev->rate_max));
|
|
|
+ }
|
|
|
+
|
|
|
++static u8
|
|
|
++ath10k_wmi_tpc_final_get_rate(struct ath10k *ar,
|
|
|
++ struct wmi_pdev_tpc_final_table_event *ev,
|
|
|
++ u32 rate_idx, u32 num_chains,
|
|
|
++ u32 rate_code, u8 type, u32 pream_idx)
|
|
|
++{
|
|
|
++ u8 tpc, num_streams, preamble, ch, stm_idx;
|
|
|
++ s8 pow_agcdd, pow_agstbc, pow_agtxbf;
|
|
|
++ int pream;
|
|
|
++
|
|
|
++ num_streams = ATH10K_HW_NSS(rate_code);
|
|
|
++ preamble = ATH10K_HW_PREAMBLE(rate_code);
|
|
|
++ ch = num_chains - 1;
|
|
|
++ stm_idx = num_streams - 1;
|
|
|
++ pream = -1;
|
|
|
++
|
|
|
++ if (__le32_to_cpu(ev->chan_freq) <= 2483) {
|
|
|
++ switch (pream_idx) {
|
|
|
++ case WMI_TPC_PREAM_2GHZ_CCK:
|
|
|
++ pream = 0;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_2GHZ_OFDM:
|
|
|
++ pream = 1;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_2GHZ_HT20:
|
|
|
++ case WMI_TPC_PREAM_2GHZ_VHT20:
|
|
|
++ pream = 2;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_2GHZ_HT40:
|
|
|
++ case WMI_TPC_PREAM_2GHZ_VHT40:
|
|
|
++ pream = 3;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_2GHZ_VHT80:
|
|
|
++ pream = 4;
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ pream = -1;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (__le32_to_cpu(ev->chan_freq) >= 5180) {
|
|
|
++ switch (pream_idx) {
|
|
|
++ case WMI_TPC_PREAM_5GHZ_OFDM:
|
|
|
++ pream = 0;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_5GHZ_HT20:
|
|
|
++ case WMI_TPC_PREAM_5GHZ_VHT20:
|
|
|
++ pream = 1;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_5GHZ_HT40:
|
|
|
++ case WMI_TPC_PREAM_5GHZ_VHT40:
|
|
|
++ pream = 2;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_5GHZ_VHT80:
|
|
|
++ pream = 3;
|
|
|
++ break;
|
|
|
++ case WMI_TPC_PREAM_5GHZ_HTCUP:
|
|
|
++ pream = 4;
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ pream = -1;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (pream == 4)
|
|
|
++ tpc = min_t(u8, ev->rates_array[rate_idx],
|
|
|
++ ev->max_reg_allow_pow[ch]);
|
|
|
++ else
|
|
|
++ tpc = min_t(u8, min_t(u8, ev->rates_array[rate_idx],
|
|
|
++ ev->max_reg_allow_pow[ch]),
|
|
|
++ ev->ctl_power_table[0][pream][stm_idx]);
|
|
|
++
|
|
|
++ if (__le32_to_cpu(ev->num_tx_chain) <= 1)
|
|
|
++ goto out;
|
|
|
++
|
|
|
++ if (preamble == WMI_RATE_PREAMBLE_CCK)
|
|
|
++ goto out;
|
|
|
++
|
|
|
++ if (num_chains <= num_streams)
|
|
|
++ goto out;
|
|
|
++
|
|
|
++ switch (type) {
|
|
|
++ case WMI_TPC_TABLE_TYPE_STBC:
|
|
|
++ pow_agstbc = ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx];
|
|
|
++ if (pream == 4)
|
|
|
++ tpc = min_t(u8, tpc, pow_agstbc);
|
|
|
++ else
|
|
|
++ tpc = min_t(u8, min_t(u8, tpc, pow_agstbc),
|
|
|
++ ev->ctl_power_table[0][pream][stm_idx]);
|
|
|
++ break;
|
|
|
++ case WMI_TPC_TABLE_TYPE_TXBF:
|
|
|
++ pow_agtxbf = ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx];
|
|
|
++ if (pream == 4)
|
|
|
++ tpc = min_t(u8, tpc, pow_agtxbf);
|
|
|
++ else
|
|
|
++ tpc = min_t(u8, min_t(u8, tpc, pow_agtxbf),
|
|
|
++ ev->ctl_power_table[1][pream][stm_idx]);
|
|
|
++ break;
|
|
|
++ case WMI_TPC_TABLE_TYPE_CDD:
|
|
|
++ pow_agcdd = ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx];
|
|
|
++ if (pream == 4)
|
|
|
++ tpc = min_t(u8, tpc, pow_agcdd);
|
|
|
++ else
|
|
|
++ tpc = min_t(u8, min_t(u8, tpc, pow_agcdd),
|
|
|
++ ev->ctl_power_table[0][pream][stm_idx]);
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ ath10k_warn(ar, "unknown wmi tpc final table type: %d\n", type);
|
|
|
++ tpc = 0;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++out:
|
|
|
++ return tpc;
|
|
|
++}
|
|
|
++
|
|
|
++static void
|
|
|
++ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar,
|
|
|
++ struct wmi_pdev_tpc_final_table_event *ev,
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats,
|
|
|
++ u8 *rate_code, u16 *pream_table, u8 type)
|
|
|
++{
|
|
|
++ u32 i, j, pream_idx, flags;
|
|
|
++ u8 tpc[WMI_TPC_TX_N_CHAIN];
|
|
|
++ char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
|
|
|
++ char buff[WMI_TPC_BUF_SIZE];
|
|
|
++
|
|
|
++ flags = __le32_to_cpu(ev->flags);
|
|
|
++
|
|
|
++ switch (type) {
|
|
|
++ case WMI_TPC_TABLE_TYPE_CDD:
|
|
|
++ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) {
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n");
|
|
|
++ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
++ return;
|
|
|
++ }
|
|
|
++ break;
|
|
|
++ case WMI_TPC_TABLE_TYPE_STBC:
|
|
|
++ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) {
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n");
|
|
|
++ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
++ return;
|
|
|
++ }
|
|
|
++ break;
|
|
|
++ case WMI_TPC_TABLE_TYPE_TXBF:
|
|
|
++ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) {
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n");
|
|
|
++ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
|
|
|
++ return;
|
|
|
++ }
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
++ "invalid table type in wmi tpc event: %d\n", type);
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ pream_idx = 0;
|
|
|
++ for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
|
|
|
++ memset(tpc_value, 0, sizeof(tpc_value));
|
|
|
++ memset(buff, 0, sizeof(buff));
|
|
|
++ if (i == pream_table[pream_idx])
|
|
|
++ pream_idx++;
|
|
|
++
|
|
|
++ for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
|
|
|
++ if (j >= __le32_to_cpu(ev->num_tx_chain))
|
|
|
++ break;
|
|
|
++
|
|
|
++ tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1,
|
|
|
++ rate_code[i],
|
|
|
++ type, pream_idx);
|
|
|
++ snprintf(buff, sizeof(buff), "%8d ", tpc[j]);
|
|
|
++ strncat(tpc_value, buff, strlen(buff));
|
|
|
++ }
|
|
|
++ tpc_stats->tpc_table_final[type].pream_idx[i] = pream_idx;
|
|
|
++ tpc_stats->tpc_table_final[type].rate_code[i] = rate_code[i];
|
|
|
++ memcpy(tpc_stats->tpc_table_final[type].tpc_value[i],
|
|
|
++ tpc_value, sizeof(tpc_value));
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
++void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb)
|
|
|
++{
|
|
|
++ u32 num_tx_chain;
|
|
|
++ u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
|
|
|
++ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
|
|
|
++ struct wmi_pdev_tpc_final_table_event *ev;
|
|
|
++ struct ath10k_tpc_stats_final *tpc_stats;
|
|
|
++
|
|
|
++ ev = (struct wmi_pdev_tpc_final_table_event *)skb->data;
|
|
|
++
|
|
|
++ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
|
|
|
++ if (!tpc_stats)
|
|
|
++ return;
|
|
|
++
|
|
|
++ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
++
|
|
|
++ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
|
|
|
++ num_tx_chain);
|
|
|
++
|
|
|
++ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
|
|
|
++ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
|
|
|
++ tpc_stats->ctl = __le32_to_cpu(ev->ctl);
|
|
|
++ tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain);
|
|
|
++ tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain);
|
|
|
++ tpc_stats->twice_antenna_reduction =
|
|
|
++ __le32_to_cpu(ev->twice_antenna_reduction);
|
|
|
++ tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
|
|
|
++ tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
|
|
|
++ tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
|
|
|
++ tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
|
|
|
++
|
|
|
++ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
|
|
|
++ rate_code, pream_table,
|
|
|
++ WMI_TPC_TABLE_TYPE_CDD);
|
|
|
++ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
|
|
|
++ rate_code, pream_table,
|
|
|
++ WMI_TPC_TABLE_TYPE_STBC);
|
|
|
++ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
|
|
|
++ rate_code, pream_table,
|
|
|
++ WMI_TPC_TABLE_TYPE_TXBF);
|
|
|
++
|
|
|
++ ath10k_debug_tpc_stats_final_process(ar, tpc_stats);
|
|
|
++
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
++ "wmi event tpc final table channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n",
|
|
|
++ __le32_to_cpu(ev->chan_freq),
|
|
|
++ __le32_to_cpu(ev->phy_mode),
|
|
|
++ __le32_to_cpu(ev->ctl),
|
|
|
++ __le32_to_cpu(ev->reg_domain),
|
|
|
++ a_sle32_to_cpu(ev->twice_antenna_gain),
|
|
|
++ __le32_to_cpu(ev->twice_antenna_reduction),
|
|
|
++ __le32_to_cpu(ev->power_limit),
|
|
|
++ __le32_to_cpu(ev->twice_max_rd_power) / 2,
|
|
|
++ __le32_to_cpu(ev->num_tx_chain),
|
|
|
++ __le32_to_cpu(ev->rate_max));
|
|
|
++}
|
|
|
++
|
|
|
+ static void
|
|
|
+ ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
|
|
|
+ {
|
|
|
+@@ -5550,6 +5805,9 @@ static void ath10k_wmi_10_4_op_rx(struct
|
|
|
+ case WMI_10_4_TDLS_PEER_EVENTID:
|
|
|
+ ath10k_wmi_handle_tdls_peer_event(ar, skb);
|
|
|
+ break;
|
|
|
++ case WMI_10_4_PDEV_TPC_TABLE_EVENTID:
|
|
|
++ ath10k_wmi_event_tpc_final_table(ar, skb);
|
|
|
++ break;
|
|
|
+ default:
|
|
|
+ ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
|
|
+ break;
|
|
|
+@@ -7990,6 +8248,24 @@ static u32 ath10k_wmi_prepare_peer_qos(u
|
|
|
+ }
|
|
|
+
|
|
|
+ static struct sk_buff *
|
|
|
++ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
|
|
|
++{
|
|
|
++ struct wmi_pdev_get_tpc_table_cmd *cmd;
|
|
|
++ struct sk_buff *skb;
|
|
|
++
|
|
|
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
|
|
++ if (!skb)
|
|
|
++ return ERR_PTR(-ENOMEM);
|
|
|
++
|
|
|
++ cmd = (struct wmi_pdev_get_tpc_table_cmd *)skb->data;
|
|
|
++ cmd->param = __cpu_to_le32(param);
|
|
|
++
|
|
|
++ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
++ "wmi pdev get tpc table param:%d\n", param);
|
|
|
++ return skb;
|
|
|
++}
|
|
|
++
|
|
|
++static struct sk_buff *
|
|
|
+ ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar,
|
|
|
+ const struct wmi_tdls_peer_update_cmd_arg *arg,
|
|
|
+ const struct wmi_tdls_peer_capab_arg *cap,
|
|
|
+@@ -8430,6 +8706,8 @@ static const struct wmi_ops wmi_10_4_ops
|
|
|
+ .ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
|
|
|
+ .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state,
|
|
|
+ .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
|
|
|
++ .gen_pdev_get_tpc_table_cmdid =
|
|
|
++ ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
|
|
|
+
|
|
|
+ /* shared with 10.2 */
|
|
|
+ .pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
|
|
|
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
|
|
|
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
|
|
|
+@@ -1,6 +1,7 @@
|
|
|
+ /*
|
|
|
+ * Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
|
+ * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
|
|
|
++ * Copyright (c) 2018, 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
|
|
|
+@@ -197,6 +198,9 @@ enum wmi_service {
|
|
|
+ WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
|
|
|
+ WMI_SERVICE_MGMT_TX_WMI,
|
|
|
+ WMI_SERVICE_TDLS_WIDER_BANDWIDTH,
|
|
|
++ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
|
|
|
++ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT,
|
|
|
++ WMI_SERVICE_TPC_STATS_FINAL,
|
|
|
+
|
|
|
+ /* keep last */
|
|
|
+ WMI_SERVICE_MAX,
|
|
|
+@@ -339,6 +343,9 @@ enum wmi_10_4_service {
|
|
|
+ WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
|
|
|
+ WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
|
|
|
+ WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
|
|
|
++ WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
|
|
|
++ WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
|
|
|
++ WMI_10_4_SERVICE_TPC_STATS_FINAL,
|
|
|
+ };
|
|
|
+
|
|
|
+ static inline char *wmi_service_name(int service_id)
|
|
|
+@@ -448,6 +455,9 @@ static inline char *wmi_service_name(int
|
|
|
+ SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE);
|
|
|
+ SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY);
|
|
|
+ SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH);
|
|
|
++ SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
|
|
|
++ SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
|
|
|
++ SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
|
|
|
+ default:
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+@@ -746,6 +756,12 @@ static inline void wmi_10_4_svc_map(cons
|
|
|
+ WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len);
|
|
|
+ SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
|
|
|
+ WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len);
|
|
|
++ SVCMAP(WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
|
|
|
++ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len);
|
|
|
++ SVCMAP(WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
|
|
|
++ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
|
|
|
++ SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
|
|
|
++ WMI_SERVICE_TPC_STATS_FINAL, len);
|
|
|
+ }
|
|
|
+
|
|
|
+ #undef SVCMAP
|
|
|
+@@ -3992,10 +4008,12 @@ struct wmi_pdev_get_tpc_config_cmd {
|
|
|
+
|
|
|
+ #define WMI_TPC_CONFIG_PARAM 1
|
|
|
+ #define WMI_TPC_RATE_MAX 160
|
|
|
++#define WMI_TPC_FINAL_RATE_MAX 240
|
|
|
+ #define WMI_TPC_TX_N_CHAIN 4
|
|
|
+ #define WMI_TPC_PREAM_TABLE_MAX 10
|
|
|
+ #define WMI_TPC_FLAG 3
|
|
|
+ #define WMI_TPC_BUF_SIZE 10
|
|
|
++#define WMI_TPC_BEAMFORMING 2
|
|
|
+
|
|
|
+ enum wmi_tpc_table_type {
|
|
|
+ WMI_TPC_TABLE_TYPE_CDD = 0,
|
|
|
+@@ -4038,6 +4056,51 @@ enum wmi_tp_scale {
|
|
|
+ WMI_TP_SCALE_SIZE = 5, /* max num of enum */
|
|
|
+ };
|
|
|
+
|
|
|
++struct wmi_pdev_tpc_final_table_event {
|
|
|
++ __le32 reg_domain;
|
|
|
++ __le32 chan_freq;
|
|
|
++ __le32 phy_mode;
|
|
|
++ __le32 twice_antenna_reduction;
|
|
|
++ __le32 twice_max_rd_power;
|
|
|
++ a_sle32 twice_antenna_gain;
|
|
|
++ __le32 power_limit;
|
|
|
++ __le32 rate_max;
|
|
|
++ __le32 num_tx_chain;
|
|
|
++ __le32 ctl;
|
|
|
++ __le32 flags;
|
|
|
++ s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN];
|
|
|
++ s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
|
|
|
++ s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
|
|
|
++ s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
|
|
|
++ u8 rates_array[WMI_TPC_FINAL_RATE_MAX];
|
|
|
++ u8 ctl_power_table[WMI_TPC_BEAMFORMING][WMI_TPC_TX_N_CHAIN]
|
|
|
++ [WMI_TPC_TX_N_CHAIN];
|
|
|
++} __packed;
|
|
|
++
|
|
|
++struct wmi_pdev_get_tpc_table_cmd {
|
|
|
++ __le32 param;
|
|
|
++} __packed;
|
|
|
++
|
|
|
++enum wmi_tpc_pream_2ghz {
|
|
|
++ WMI_TPC_PREAM_2GHZ_CCK = 0,
|
|
|
++ WMI_TPC_PREAM_2GHZ_OFDM,
|
|
|
++ WMI_TPC_PREAM_2GHZ_HT20,
|
|
|
++ WMI_TPC_PREAM_2GHZ_HT40,
|
|
|
++ WMI_TPC_PREAM_2GHZ_VHT20,
|
|
|
++ WMI_TPC_PREAM_2GHZ_VHT40,
|
|
|
++ WMI_TPC_PREAM_2GHZ_VHT80,
|
|
|
++};
|
|
|
++
|
|
|
++enum wmi_tpc_pream_5ghz {
|
|
|
++ WMI_TPC_PREAM_5GHZ_OFDM = 1,
|
|
|
++ WMI_TPC_PREAM_5GHZ_HT20,
|
|
|
++ WMI_TPC_PREAM_5GHZ_HT40,
|
|
|
++ WMI_TPC_PREAM_5GHZ_VHT20,
|
|
|
++ WMI_TPC_PREAM_5GHZ_VHT40,
|
|
|
++ WMI_TPC_PREAM_5GHZ_VHT80,
|
|
|
++ WMI_TPC_PREAM_5GHZ_HTCUP,
|
|
|
++};
|
|
|
++
|
|
|
+ struct wmi_pdev_chanlist_update_event {
|
|
|
+ /* number of channels */
|
|
|
+ __le32 num_chan;
|
|
|
+@@ -6977,5 +7040,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(st
|
|
|
+ int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
|
|
|
+ enum wmi_vdev_subtype subtype);
|
|
|
+ int ath10k_wmi_barrier(struct ath10k *ar);
|
|
|
++void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
|
|
|
++ u32 num_tx_chain);
|
|
|
++void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb);
|
|
|
+
|
|
|
+ #endif /* _WMI_H_ */
|