mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	This commit refreshes and updates the VHT160 ath10k support fix patches and adds a number of backports from ath-next: * 8ed05ed06fca ath10k: handle tdls peer events * 229329ff345f ath10k: wmi: modify svc bitmap parsing for wcn3990 * 14d65775687c ath10k: advertise TDLS wider bandwidth support for 5GHz * bc64d05220f3 ath10k: debugfs support to get final TPC stats for 10.4 variants * 8b2d93dd2261 ath10k: Fix kernel panic while using worker (ath10k_sta_rc_update_wk) * 4b190675ad06 ath10k: fix kernel panic while reading tpc_stats * be8cce96f14d ath10k: add support to configure channel dwell time * f40105e67478 ath: add support to get the detected radar specifications * 6f6eb1bcbeff ath10k: DFS Host Confirmation * 260e629bbf44 ath10k: fix memory leak of tpc_stats * 38441fb6fcbb ath10k: support use of channel 173 * 2e9bcd0d7324 ath10k: fix spectral scan for QCA9984 and QCA9888 chipsets Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com> [move backported patches in the 3xx number space, bring in upstream order, replace incomplete patch files with git format-patch ones, rewrite commit message, fix subject] Signed-off-by: Jo-Philipp Wich <jo@mein.io>
		
			
				
	
	
		
			825 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			825 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From bc64d05220f3e34cf432a166b83c8fff14cd7a3d Mon Sep 17 00:00:00 2001
 | |
| From: Maharaja Kennadyrajan <mkenna@codeaurora.org>
 | |
| 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 <mkenna@codeaurora.org>
 | |
| Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | |
| ---
 | |
|  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_ */
 |