Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 47287master
parent
ec3ee0969e
commit
ce09894398
@ -0,0 +1,31 @@ |
|||||||
|
From: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
Date: Sun, 7 Jun 2015 13:53:35 +0200
|
||||||
|
Subject: [PATCH] ath9k: force rx_clear when disabling rx
|
||||||
|
|
||||||
|
This makes stopping Rx more reliable and should reduce the frequency of
|
||||||
|
Rx related DMA stop warnings
|
||||||
|
|
||||||
|
Cc: stable@vger.kernel.org
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||||
|
@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
|
||||||
|
|
||||||
|
ath9k_ani_reset(ah, is_scanning);
|
||||||
|
|
||||||
|
- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||||
|
+ REG_CLR_BIT(ah, AR_DIAG_SW,
|
||||||
|
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
|
||||||
|
|
||||||
|
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
|
||||||
|
{
|
||||||
|
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
|
||||||
|
+ REG_SET_BIT(ah, AR_DIAG_SW,
|
||||||
|
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||||
|
|
||||||
|
ath9k_hw_disable_mib_counters(ah);
|
||||||
|
}
|
@ -0,0 +1,121 @@ |
|||||||
|
From: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
Date: Thu, 2 Jul 2015 15:20:56 +0200
|
||||||
|
Subject: [PATCH] ath9k: limit retries for powersave response frames
|
||||||
|
|
||||||
|
In some cases, the channel might be busy enough that an ath9k AP's
|
||||||
|
response to PS-Poll frames might be too slow and the station has already
|
||||||
|
gone to sleep. To avoid wasting too much airtime on this, limit the
|
||||||
|
number of retries on such frames and ensure that no sample rate gets
|
||||||
|
used.
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
|
@@ -136,10 +136,25 @@ static void ath_send_bar(struct ath_atx_
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||||
|
- struct ath_buf *bf)
|
||||||
|
+ struct ath_buf *bf, bool ps)
|
||||||
|
{
|
||||||
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||||
|
+
|
||||||
|
+ if (ps) {
|
||||||
|
+ /* Clear the first rate to avoid using a sample rate for PS frames */
|
||||||
|
+ info->control.rates[0].idx = -1;
|
||||||
|
+ info->control.rates[0].count = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||||
|
ARRAY_SIZE(bf->rates));
|
||||||
|
+ if (!ps)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (bf->rates[0].count > 2)
|
||||||
|
+ bf->rates[0].count = 2;
|
||||||
|
+
|
||||||
|
+ bf->rates[1].idx = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
|
@@ -1419,7 +1434,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||||
|
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||||
|
break;
|
||||||
|
|
||||||
|
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||||
|
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1450,7 +1465,7 @@ static bool ath_tx_sched_aggr(struct ath
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||||
|
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||||
|
if (aggr)
|
||||||
|
last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
|
||||||
|
tid_q, &aggr_len);
|
||||||
|
@@ -1632,7 +1647,7 @@ void ath9k_release_buffered_frames(struc
|
||||||
|
|
||||||
|
__skb_unlink(bf->bf_mpdu, tid_q);
|
||||||
|
list_add_tail(&bf->list, &bf_q);
|
||||||
|
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||||
|
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
|
||||||
|
if (bf_isampdu(bf)) {
|
||||||
|
ath_tx_addto_baw(sc, tid, bf);
|
||||||
|
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||||
|
@@ -2278,7 +2293,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||||
|
struct ath_txq *txq = txctl->txq;
|
||||||
|
struct ath_atx_tid *tid = NULL;
|
||||||
|
struct ath_buf *bf;
|
||||||
|
- bool queue, skip_uapsd = false, ps_resp;
|
||||||
|
+ bool queue, ps_resp;
|
||||||
|
int q, ret;
|
||||||
|
|
||||||
|
if (vif)
|
||||||
|
@@ -2325,13 +2340,13 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||||
|
if (!txctl->an)
|
||||||
|
txctl->an = &avp->mcast_node;
|
||||||
|
queue = true;
|
||||||
|
- skip_uapsd = true;
|
||||||
|
+ ps_resp = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txctl->an && queue)
|
||||||
|
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||||
|
|
||||||
|
- if (!skip_uapsd && ps_resp) {
|
||||||
|
+ if (ps_resp) {
|
||||||
|
ath_txq_unlock(sc, txq);
|
||||||
|
txq = sc->tx.uapsdq;
|
||||||
|
ath_txq_lock(sc, txq);
|
||||||
|
@@ -2369,7 +2384,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||||
|
if (txctl->paprd)
|
||||||
|
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||||
|
|
||||||
|
- ath_set_rates(vif, sta, bf);
|
||||||
|
+ ath_set_rates(vif, sta, bf, ps_resp);
|
||||||
|
ath_tx_send_normal(sc, txq, tid, skb);
|
||||||
|
|
||||||
|
out:
|
||||||
|
@@ -2408,7 +2423,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||||
|
break;
|
||||||
|
|
||||||
|
bf->bf_lastbf = bf;
|
||||||
|
- ath_set_rates(vif, NULL, bf);
|
||||||
|
+ ath_set_rates(vif, NULL, bf, false);
|
||||||
|
ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
|
||||||
|
duration += info.rates[0].PktDuration;
|
||||||
|
if (bf_tail)
|
||||||
|
@@ -2911,7 +2926,7 @@ int ath9k_tx99_send(struct ath_softc *sc
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ath_set_rates(sc->tx99_vif, NULL, bf);
|
||||||
|
+ ath_set_rates(sc->tx99_vif, NULL, bf, false);
|
||||||
|
|
||||||
|
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
|
||||||
|
ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
|
@ -0,0 +1,108 @@ |
|||||||
|
From: Zefir Kurtisi <zefir.kurtisi@neratec.com>
|
||||||
|
Date: Tue, 20 Oct 2015 14:19:26 +0200
|
||||||
|
Subject: [PATCH] ath9k: fix phyerror codes
|
||||||
|
|
||||||
|
Some of the ath9k_phyerr enums were wrong from the
|
||||||
|
beginning (and even before). Most of the time the
|
||||||
|
codes were used for counters to be displayed over
|
||||||
|
debugfs, which made this a non-functional issue.
|
||||||
|
|
||||||
|
Some (e.g. ATH9K_PHYERR_FALSE_RADAR_EXT) are used
|
||||||
|
for radar detection and require the correct code
|
||||||
|
to work as intended.
|
||||||
|
|
||||||
|
This patch includes:
|
||||||
|
a) fixes
|
||||||
|
ATH9K_PHYERR_FALSE_RADAR_EXT: 24 => 36
|
||||||
|
ATH9K_PHYERR_CCK_LENGTH_ILLEGAL: 32 => 28
|
||||||
|
ATH9K_PHYERR_CCK_POWER_DROP: 33 => 29
|
||||||
|
ATH9K_PHYERR_HT_CRC_ERROR: 34 => 32
|
||||||
|
ATH9K_PHYERR_HT_LENGTH_ILLEGAL: 35 => 33
|
||||||
|
ATH9K_PHYERR_HT_RATE_ILLEGAL: 36 => 34
|
||||||
|
|
||||||
|
b) extensions
|
||||||
|
ATH9K_PHYERR_CCK_BLOCKER = 24
|
||||||
|
ATH9K_PHYERR_HT_ZLF = 35
|
||||||
|
ATH9K_PHYERR_GREEN_FIELD = 37
|
||||||
|
|
||||||
|
Aside from the correction and completion made in
|
||||||
|
the enum, the patch also extends the display of
|
||||||
|
the related counters in the debugfs.
|
||||||
|
|
||||||
|
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
|
||||||
|
@@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct
|
||||||
|
PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
|
||||||
|
PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
|
||||||
|
PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
|
||||||
|
+
|
||||||
|
PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
|
||||||
|
PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
|
||||||
|
PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
|
||||||
|
@@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct
|
||||||
|
PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
|
||||||
|
PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
|
||||||
|
PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
|
||||||
|
- PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
|
||||||
|
+
|
||||||
|
+ PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER);
|
||||||
|
PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
|
||||||
|
PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
|
||||||
|
PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
|
||||||
|
- PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
|
||||||
|
- PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
|
||||||
|
PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
|
||||||
|
PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
|
||||||
|
+ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
|
||||||
|
+ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
|
||||||
|
+
|
||||||
|
PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
|
||||||
|
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
|
||||||
|
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
|
||||||
|
+ PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF);
|
||||||
|
+
|
||||||
|
+ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
|
||||||
|
+ PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD);
|
||||||
|
+ PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL);
|
||||||
|
|
||||||
|
if (len > size)
|
||||||
|
len = size;
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/mac.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/mac.h
|
||||||
|
@@ -209,21 +209,25 @@ enum ath9k_phyerr {
|
||||||
|
ATH9K_PHYERR_OFDM_POWER_DROP = 21,
|
||||||
|
ATH9K_PHYERR_OFDM_SERVICE = 22,
|
||||||
|
ATH9K_PHYERR_OFDM_RESTART = 23,
|
||||||
|
- ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
|
||||||
|
|
||||||
|
+ ATH9K_PHYERR_CCK_BLOCKER = 24,
|
||||||
|
ATH9K_PHYERR_CCK_TIMING = 25,
|
||||||
|
ATH9K_PHYERR_CCK_HEADER_CRC = 26,
|
||||||
|
ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
|
||||||
|
+ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28,
|
||||||
|
+ ATH9K_PHYERR_CCK_POWER_DROP = 29,
|
||||||
|
ATH9K_PHYERR_CCK_SERVICE = 30,
|
||||||
|
ATH9K_PHYERR_CCK_RESTART = 31,
|
||||||
|
- ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
|
||||||
|
- ATH9K_PHYERR_CCK_POWER_DROP = 33,
|
||||||
|
|
||||||
|
- ATH9K_PHYERR_HT_CRC_ERROR = 34,
|
||||||
|
- ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
|
||||||
|
- ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
|
||||||
|
+ ATH9K_PHYERR_HT_CRC_ERROR = 32,
|
||||||
|
+ ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33,
|
||||||
|
+ ATH9K_PHYERR_HT_RATE_ILLEGAL = 34,
|
||||||
|
+ ATH9K_PHYERR_HT_ZLF = 35,
|
||||||
|
+
|
||||||
|
+ ATH9K_PHYERR_FALSE_RADAR_EXT = 36,
|
||||||
|
+ ATH9K_PHYERR_GREEN_FIELD = 37,
|
||||||
|
+ ATH9K_PHYERR_SPECTRAL = 38,
|
||||||
|
|
||||||
|
- ATH9K_PHYERR_SPECTRAL = 38,
|
||||||
|
ATH9K_PHYERR_MAX = 39,
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,239 @@ |
|||||||
|
From: Maharaja <c_mkenna@qti.qualcomm.com>
|
||||||
|
Date: Wed, 21 Oct 2015 11:49:18 +0300
|
||||||
|
Subject: [PATCH] ath10k: enable adaptive CCA
|
||||||
|
|
||||||
|
European Union has made it mandatory that all devices working in 2.4 GHz
|
||||||
|
has to adhere to the ETSI specification (ETSI EN 300 328 V1.9.1)
|
||||||
|
beginnig this year. The standard basically speaks about interferences
|
||||||
|
in 2.4Ghz band.
|
||||||
|
For example, when 802.11 device detects interference, TX must be stopped
|
||||||
|
as long as interference is present.
|
||||||
|
|
||||||
|
Adaptive CCA is a feature, when enabled the device learns from the
|
||||||
|
environment and configures CCA levels adaptively. This will improve
|
||||||
|
detecting interferences and the device can stop trasmissions till the
|
||||||
|
interference is present eventually leading to good performances in
|
||||||
|
varying interference conditions.
|
||||||
|
|
||||||
|
The patch includes code for enabling adaptive CCA for 10.2.4 firmware on
|
||||||
|
QCA988X.
|
||||||
|
|
||||||
|
Signed-off-by: Maharaja <c_mkenna@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||||
|
@@ -151,6 +151,7 @@ static const char *const ath10k_core_fw_
|
||||||
|
[ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
|
||||||
|
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
|
||||||
|
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
|
||||||
|
+ [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
@@ -497,6 +497,9 @@ enum ath10k_fw_features {
|
||||||
|
*/
|
||||||
|
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,
|
||||||
|
|
||||||
|
+ /* Firmware Supports Adaptive CCA*/
|
||||||
|
+ ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
|
||||||
|
+
|
||||||
|
/* keep last */
|
||||||
|
ATH10K_FW_FEATURE_COUNT,
|
||||||
|
};
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
@@ -3905,6 +3905,18 @@ static int ath10k_start(struct ieee80211
|
||||||
|
goto err_core_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
|
||||||
|
+ ar->fw_features)) {
|
||||||
|
+ ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1,
|
||||||
|
+ WMI_CCA_DETECT_LEVEL_AUTO,
|
||||||
|
+ WMI_CCA_DETECT_MARGIN_AUTO);
|
||||||
|
+ if (ret) {
|
||||||
|
+ ath10k_warn(ar, "failed to enable adaptive cca: %d\n",
|
||||||
|
+ ret);
|
||||||
|
+ goto err_core_stop;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = ath10k_wmi_pdev_set_param(ar,
|
||||||
|
ar->wmi.pdev_param->ani_enable, 1);
|
||||||
|
if (ret) {
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
||||||
|
@@ -182,6 +182,10 @@ struct wmi_ops {
|
||||||
|
void (*fw_stats_fill)(struct ath10k *ar,
|
||||||
|
struct ath10k_fw_stats *fw_stats,
|
||||||
|
char *buf);
|
||||||
|
+ struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar,
|
||||||
|
+ u8 enable,
|
||||||
|
+ u32 detect_level,
|
||||||
|
+ u32 detect_margin);
|
||||||
|
};
|
||||||
|
|
||||||
|
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||||
|
@@ -1302,4 +1306,25 @@ ath10k_wmi_fw_stats_fill(struct ath10k *
|
||||||
|
ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+static inline int
|
||||||
|
+ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
|
||||||
|
+ u32 detect_level, u32 detect_margin)
|
||||||
|
+{
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+
|
||||||
|
+ if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca)
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+
|
||||||
|
+ skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable,
|
||||||
|
+ detect_level,
|
||||||
|
+ detect_margin);
|
||||||
|
+
|
||||||
|
+ if (IS_ERR(skb))
|
||||||
|
+ return PTR_ERR(skb);
|
||||||
|
+
|
||||||
|
+ return ath10k_wmi_cmd_send(ar, skb,
|
||||||
|
+ ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
@@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map =
|
||||||
|
.gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
|
||||||
|
.gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
|
||||||
|
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
@@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
|
||||||
|
.gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
|
||||||
|
.gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
|
||||||
|
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
@@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd
|
||||||
|
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
|
||||||
|
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
|
||||||
|
.pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
|
||||||
|
+ .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS,
|
||||||
|
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
@@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m
|
||||||
|
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
|
||||||
|
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
|
||||||
|
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||||
|
@@ -6996,6 +7000,28 @@ unlock:
|
||||||
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static struct sk_buff *
|
||||||
|
+ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
|
||||||
|
+ u32 detect_level, u32 detect_margin)
|
||||||
|
+{
|
||||||
|
+ struct wmi_pdev_set_adaptive_cca_params *cmd;
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+
|
||||||
|
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
||||||
|
+ if (!skb)
|
||||||
|
+ return ERR_PTR(-ENOMEM);
|
||||||
|
+
|
||||||
|
+ cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data;
|
||||||
|
+ cmd->enable = __cpu_to_le32(enable);
|
||||||
|
+ cmd->cca_detect_level = __cpu_to_le32(detect_level);
|
||||||
|
+ cmd->cca_detect_margin = __cpu_to_le32(detect_margin);
|
||||||
|
+
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||||
|
+ "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n",
|
||||||
|
+ enable, detect_level, detect_margin);
|
||||||
|
+ return skb;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct wmi_ops wmi_ops = {
|
||||||
|
.rx = ath10k_wmi_op_rx,
|
||||||
|
.map_svc = wmi_main_svc_map,
|
||||||
|
@@ -7059,6 +7085,7 @@ static const struct wmi_ops wmi_ops = {
|
||||||
|
/* .gen_prb_tmpl not implemented */
|
||||||
|
/* .gen_p2p_go_bcn_ie not implemented */
|
||||||
|
/* .gen_adaptive_qcs not implemented */
|
||||||
|
+ /* .gen_pdev_enable_adaptive_cca not implemented */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wmi_ops wmi_10_1_ops = {
|
||||||
|
@@ -7125,6 +7152,7 @@ static const struct wmi_ops wmi_10_1_ops
|
||||||
|
/* .gen_prb_tmpl not implemented */
|
||||||
|
/* .gen_p2p_go_bcn_ie not implemented */
|
||||||
|
/* .gen_adaptive_qcs not implemented */
|
||||||
|
+ /* .gen_pdev_enable_adaptive_cca not implemented */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wmi_ops wmi_10_2_ops = {
|
||||||
|
@@ -7188,6 +7216,7 @@ static const struct wmi_ops wmi_10_2_ops
|
||||||
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
||||||
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||||
|
.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
||||||
|
+ /* .gen_pdev_enable_adaptive_cca not implemented */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wmi_ops wmi_10_2_4_ops = {
|
||||||
|
@@ -7251,6 +7280,8 @@ static const struct wmi_ops wmi_10_2_4_o
|
||||||
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||||
|
.gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
|
||||||
|
.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
||||||
|
+ .gen_pdev_enable_adaptive_cca =
|
||||||
|
+ ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
|
||||||
|
/* .gen_bcn_tmpl not implemented */
|
||||||
|
/* .gen_prb_tmpl not implemented */
|
||||||
|
/* .gen_p2p_go_bcn_ie not implemented */
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
|
||||||
|
@@ -772,6 +772,7 @@ struct wmi_cmd_map {
|
||||||
|
u32 mu_cal_start_cmdid;
|
||||||
|
u32 set_cca_params_cmdid;
|
||||||
|
u32 pdev_bss_chan_info_request_cmdid;
|
||||||
|
+ u32 pdev_enable_adaptive_cca_cmdid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id {
|
||||||
|
WMI_10_2_VDEV_ATF_REQUEST_CMDID,
|
||||||
|
WMI_10_2_PEER_ATF_REQUEST_CMDID,
|
||||||
|
WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
|
||||||
|
+ WMI_10_2_MU_CAL_START_CMDID,
|
||||||
|
+ WMI_10_2_SET_LTEU_CONFIG_CMDID,
|
||||||
|
+ WMI_10_2_SET_CCA_PARAMS,
|
||||||
|
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -6094,6 +6098,15 @@ enum wmi_txbf_conf {
|
||||||
|
WMI_TXBF_CONF_AFTER_ASSOC,
|
||||||
|
};
|
||||||
|
|
||||||
|
+#define WMI_CCA_DETECT_LEVEL_AUTO 0
|
||||||
|
+#define WMI_CCA_DETECT_MARGIN_AUTO 0
|
||||||
|
+
|
||||||
|
+struct wmi_pdev_set_adaptive_cca_params {
|
||||||
|
+ __le32 enable;
|
||||||
|
+ __le32 cca_detect_level;
|
||||||
|
+ __le32 cca_detect_margin;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
struct ath10k;
|
||||||
|
struct ath10k_vif;
|
||||||
|
struct ath10k_fw_stats_pdev;
|
@ -0,0 +1,331 @@ |
|||||||
|
From: Alan Liu <alanliu@qca.qualcomm.com>
|
||||||
|
Date: Wed, 28 Oct 2015 21:38:32 +0200
|
||||||
|
Subject: [PATCH] ath10k: add FW API support to test mode
|
||||||
|
|
||||||
|
Add WMI-TLV and FW API support in ath10k testmode.
|
||||||
|
Ath10k can get right wmi command format from UTF image
|
||||||
|
to communicate UTF firmware.
|
||||||
|
|
||||||
|
Signed-off-by: Alan Liu <alanliu@qca.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||||
|
@@ -569,8 +569,8 @@ static int ath10k_download_fw(struct ath
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATH10K_FIRMWARE_MODE_UTF:
|
||||||
|
- data = ar->testmode.utf->data;
|
||||||
|
- data_len = ar->testmode.utf->size;
|
||||||
|
+ data = ar->testmode.utf_firmware_data;
|
||||||
|
+ data_len = ar->testmode.utf_firmware_len;
|
||||||
|
mode_name = "utf";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
@@ -817,9 +817,12 @@ struct ath10k {
|
||||||
|
struct {
|
||||||
|
/* protected by conf_mutex */
|
||||||
|
const struct firmware *utf;
|
||||||
|
+ char utf_version[32];
|
||||||
|
+ const void *utf_firmware_data;
|
||||||
|
+ size_t utf_firmware_len;
|
||||||
|
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||||
|
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
|
||||||
|
-
|
||||||
|
+ enum ath10k_fw_wmi_op_version op_version;
|
||||||
|
/* protected by data_lock */
|
||||||
|
bool utf_monitor;
|
||||||
|
} testmode;
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/hw.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/hw.h
|
||||||
|
@@ -94,6 +94,7 @@ enum qca6174_chip_id_rev {
|
||||||
|
#define ATH10K_FW_API5_FILE "firmware-5.bin"
|
||||||
|
|
||||||
|
#define ATH10K_FW_UTF_FILE "utf.bin"
|
||||||
|
+#define ATH10K_FW_UTF_API2_FILE "utf-2.bin"
|
||||||
|
|
||||||
|
/* includes also the null byte */
|
||||||
|
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/testmode.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
|
||||||
|
@@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(str
|
||||||
|
return cfg80211_testmode_reply(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||||
|
+static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ size_t len, magic_len, ie_len;
|
||||||
|
+ struct ath10k_fw_ie *hdr;
|
||||||
|
+ char filename[100];
|
||||||
|
+ __le32 *version;
|
||||||
|
+ const u8 *data;
|
||||||
|
+ int ie_id, ret;
|
||||||
|
+
|
||||||
|
+ snprintf(filename, sizeof(filename), "%s/%s",
|
||||||
|
+ ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
|
||||||
|
+
|
||||||
|
+ /* load utf firmware image */
|
||||||
|
+ ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||||
|
+ if (ret) {
|
||||||
|
+ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||||
|
+ filename, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ data = ar->testmode.utf->data;
|
||||||
|
+ len = ar->testmode.utf->size;
|
||||||
|
+
|
||||||
|
+ /* FIXME: call release_firmware() in error cases */
|
||||||
|
+
|
||||||
|
+ /* magic also includes the null byte, check that as well */
|
||||||
|
+ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
|
||||||
|
+
|
||||||
|
+ if (len < magic_len) {
|
||||||
|
+ ath10k_err(ar, "utf firmware file is too small to contain magic\n");
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||||
|
+ ath10k_err(ar, "invalid firmware magic\n");
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* jump over the padding */
|
||||||
|
+ magic_len = ALIGN(magic_len, 4);
|
||||||
|
+
|
||||||
|
+ len -= magic_len;
|
||||||
|
+ data += magic_len;
|
||||||
|
+
|
||||||
|
+ /* loop elements */
|
||||||
|
+ while (len > sizeof(struct ath10k_fw_ie)) {
|
||||||
|
+ hdr = (struct ath10k_fw_ie *)data;
|
||||||
|
+
|
||||||
|
+ ie_id = le32_to_cpu(hdr->id);
|
||||||
|
+ ie_len = le32_to_cpu(hdr->len);
|
||||||
|
+
|
||||||
|
+ len -= sizeof(*hdr);
|
||||||
|
+ data += sizeof(*hdr);
|
||||||
|
+
|
||||||
|
+ if (len < ie_len) {
|
||||||
|
+ ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
|
||||||
|
+ ie_id, len, ie_len);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (ie_id) {
|
||||||
|
+ case ATH10K_FW_IE_FW_VERSION:
|
||||||
|
+ if (ie_len > sizeof(ar->testmode.utf_version) - 1)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ memcpy(ar->testmode.utf_version, data, ie_len);
|
||||||
|
+ ar->testmode.utf_version[ie_len] = '\0';
|
||||||
|
+
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||||
|
+ "testmode found fw utf version %s\n",
|
||||||
|
+ ar->testmode.utf_version);
|
||||||
|
+ break;
|
||||||
|
+ case ATH10K_FW_IE_TIMESTAMP:
|
||||||
|
+ /* ignore timestamp, but don't warn about it either */
|
||||||
|
+ break;
|
||||||
|
+ case ATH10K_FW_IE_FW_IMAGE:
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||||
|
+ "testmode found fw image ie (%zd B)\n",
|
||||||
|
+ ie_len);
|
||||||
|
+
|
||||||
|
+ ar->testmode.utf_firmware_data = data;
|
||||||
|
+ ar->testmode.utf_firmware_len = ie_len;
|
||||||
|
+ break;
|
||||||
|
+ case ATH10K_FW_IE_WMI_OP_VERSION:
|
||||||
|
+ if (ie_len != sizeof(u32))
|
||||||
|
+ break;
|
||||||
|
+ version = (__le32 *)data;
|
||||||
|
+ ar->testmode.op_version = le32_to_cpup(version);
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
|
||||||
|
+ ar->testmode.op_version);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
|
||||||
|
+ le32_to_cpu(hdr->id));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* jump over the padding */
|
||||||
|
+ ie_len = ALIGN(ie_len, 4);
|
||||||
|
+
|
||||||
|
+ len -= ie_len;
|
||||||
|
+ data += ie_len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
|
||||||
|
+ ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ release_firmware(ar->testmode.utf);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||||
|
{
|
||||||
|
char filename[100];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ snprintf(filename, sizeof(filename), "%s/%s",
|
||||||
|
+ ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||||
|
+
|
||||||
|
+ /* load utf firmware image */
|
||||||
|
+ ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||||
|
+ if (ret) {
|
||||||
|
+ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||||
|
+ filename, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* We didn't find FW UTF API 1 ("utf.bin") does not advertise
|
||||||
|
+ * firmware features. Do an ugly hack where we force the firmware
|
||||||
|
+ * features to match with 10.1 branch so that wmi.c will use the
|
||||||
|
+ * correct WMI interface.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||||
|
+ ar->testmode.utf_firmware_data = ar->testmode.utf->data;
|
||||||
|
+ ar->testmode.utf_firmware_len = ar->testmode.utf->size;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
|
||||||
|
+ if (ret == 0) {
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
|
||||||
|
+ if (ret) {
|
||||||
|
+ ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||||
|
+{
|
||||||
|
+ const char *ver;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
|
||||||
|
|
||||||
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
@@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struc
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
- snprintf(filename, sizeof(filename), "%s/%s",
|
||||||
|
- ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||||
|
-
|
||||||
|
- /* load utf firmware image */
|
||||||
|
- ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||||
|
+ ret = ath10k_tm_fetch_firmware(ar);
|
||||||
|
if (ret) {
|
||||||
|
- ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||||
|
- filename, ret);
|
||||||
|
+ ath10k_err(ar, "failed to fetch UTF firmware: %d", ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_bh(&ar->data_lock);
|
||||||
|
-
|
||||||
|
ar->testmode.utf_monitor = true;
|
||||||
|
-
|
||||||
|
spin_unlock_bh(&ar->data_lock);
|
||||||
|
-
|
||||||
|
BUILD_BUG_ON(sizeof(ar->fw_features) !=
|
||||||
|
sizeof(ar->testmode.orig_fw_features));
|
||||||
|
|
||||||
|
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
|
||||||
|
sizeof(ar->fw_features));
|
||||||
|
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
|
||||||
|
-
|
||||||
|
- /* utf.bin firmware image does not advertise firmware features. Do
|
||||||
|
- * an ugly hack where we force the firmware features so that wmi.c
|
||||||
|
- * will use the correct WMI interface.
|
||||||
|
- */
|
||||||
|
memset(ar->fw_features, 0, sizeof(ar->fw_features));
|
||||||
|
- ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||||
|
+
|
||||||
|
+ ar->wmi.op_version = ar->testmode.op_version;
|
||||||
|
+
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
|
||||||
|
+ ar->wmi.op_version);
|
||||||
|
|
||||||
|
ret = ath10k_hif_power_up(ar);
|
||||||
|
if (ret) {
|
||||||
|
@@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struc
|
||||||
|
|
||||||
|
ar->state = ATH10K_STATE_UTF;
|
||||||
|
|
||||||
|
- ath10k_info(ar, "UTF firmware started\n");
|
||||||
|
+ if (strlen(ar->testmode.utf_version) > 0)
|
||||||
|
+ ver = ar->testmode.utf_version;
|
||||||
|
+ else
|
||||||
|
+ ver = "API 1";
|
||||||
|
+
|
||||||
|
+ ath10k_info(ar, "UTF firmware %s started\n", ver);
|
||||||
|
|
||||||
|
mutex_unlock(&ar->conf_mutex);
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include "wmi-ops.h"
|
||||||
|
#include "wmi-tlv.h"
|
||||||
|
#include "p2p.h"
|
||||||
|
+#include "testmode.h"
|
||||||
|
|
||||||
|
/***************/
|
||||||
|
/* TLV helpers */
|
||||||
|
@@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct
|
||||||
|
{
|
||||||
|
struct wmi_cmd_hdr *cmd_hdr;
|
||||||
|
enum wmi_tlv_event_id id;
|
||||||
|
+ bool consumed;
|
||||||
|
|
||||||
|
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
|
||||||
|
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||||
|
@@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct
|
||||||
|
|
||||||
|
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||||
|
|
||||||
|
+ consumed = ath10k_tm_event_wmi(ar, id, skb);
|
||||||
|
+
|
||||||
|
+ /* Ready event must be handled normally also in UTF mode so that we
|
||||||
|
+ * know the UTF firmware has booted, others we are just bypass WMI
|
||||||
|
+ * events to testmode.
|
||||||
|
+ */
|
||||||
|
+ if (consumed && id != WMI_TLV_READY_EVENTID) {
|
||||||
|
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||||
|
+ "wmi tlv testmode consumed 0x%x\n", id);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
switch (id) {
|
||||||
|
case WMI_TLV_MGMT_RX_EVENTID:
|
||||||
|
ath10k_wmi_event_mgmt_rx(ar, skb);
|
@ -0,0 +1,468 @@ |
|||||||
|
From: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
|
||||||
|
Date: Wed, 28 Oct 2015 21:38:33 +0200
|
||||||
|
Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware
|
||||||
|
|
||||||
|
This patch adds support for getting firmware debug stats in 10.4 fw.
|
||||||
|
|
||||||
|
Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
@@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
|
||||||
|
s32 hw_queued;
|
||||||
|
s32 hw_reaped;
|
||||||
|
s32 underrun;
|
||||||
|
+ u32 hw_paused;
|
||||||
|
s32 tx_abort;
|
||||||
|
s32 mpdus_requed;
|
||||||
|
u32 tx_ko;
|
||||||
|
@@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
|
||||||
|
u32 pdev_resets;
|
||||||
|
u32 phy_underrun;
|
||||||
|
u32 txop_ovf;
|
||||||
|
+ u32 seq_posted;
|
||||||
|
+ u32 seq_failed_queueing;
|
||||||
|
+ u32 seq_completed;
|
||||||
|
+ u32 seq_restarted;
|
||||||
|
+ u32 mu_seq_posted;
|
||||||
|
+ u32 mpdus_sw_flush;
|
||||||
|
+ u32 mpdus_hw_filter;
|
||||||
|
+ u32 mpdus_truncated;
|
||||||
|
+ u32 mpdus_ack_failed;
|
||||||
|
+ u32 mpdus_expired;
|
||||||
|
|
||||||
|
/* PDEV RX stats */
|
||||||
|
s32 mid_ppdu_route_change;
|
||||||
|
@@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
|
||||||
|
s32 phy_errs;
|
||||||
|
s32 phy_err_drop;
|
||||||
|
s32 mpdu_errs;
|
||||||
|
+ s32 rx_ovfl_errs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ath10k_fw_stats {
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
@@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const
|
||||||
|
dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
|
||||||
|
+ struct ath10k_fw_stats_pdev *dst)
|
||||||
|
+{
|
||||||
|
+ dst->comp_queued = __le32_to_cpu(src->comp_queued);
|
||||||
|
+ dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
|
||||||
|
+ dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
|
||||||
|
+ dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
|
||||||
|
+ dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
|
||||||
|
+ dst->local_enqued = __le32_to_cpu(src->local_enqued);
|
||||||
|
+ dst->local_freed = __le32_to_cpu(src->local_freed);
|
||||||
|
+ dst->hw_queued = __le32_to_cpu(src->hw_queued);
|
||||||
|
+ dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
|
||||||
|
+ dst->underrun = __le32_to_cpu(src->underrun);
|
||||||
|
+ dst->tx_abort = __le32_to_cpu(src->tx_abort);
|
||||||
|
+ dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
|
||||||
|
+ dst->tx_ko = __le32_to_cpu(src->tx_ko);
|
||||||
|
+ dst->data_rc = __le32_to_cpu(src->data_rc);
|
||||||
|
+ dst->self_triggers = __le32_to_cpu(src->self_triggers);
|
||||||
|
+ dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
|
||||||
|
+ dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
|
||||||
|
+ dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
|
||||||
|
+ dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
|
||||||
|
+ dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
|
||||||
|
+ dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
|
||||||
|
+ dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
|
||||||
|
+ dst->hw_paused = __le32_to_cpu(src->hw_paused);
|
||||||
|
+ dst->seq_posted = __le32_to_cpu(src->seq_posted);
|
||||||
|
+ dst->seq_failed_queueing =
|
||||||
|
+ __le32_to_cpu(src->seq_failed_queueing);
|
||||||
|
+ dst->seq_completed = __le32_to_cpu(src->seq_completed);
|
||||||
|
+ dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
|
||||||
|
+ dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
|
||||||
|
+ dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
|
||||||
|
+ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
|
||||||
|
+ dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
|
||||||
|
+ dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
|
||||||
|
+ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
|
||||||
|
+ dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
|
||||||
|
struct ath10k_fw_stats_pdev *dst)
|
||||||
|
{
|
||||||
|
@@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ struct ath10k_fw_stats *stats)
|
||||||
|
+{
|
||||||
|
+ const struct wmi_10_2_stats_event *ev = (void *)skb->data;
|
||||||
|
+ u32 num_pdev_stats;
|
||||||
|
+ u32 num_pdev_ext_stats;
|
||||||
|
+ u32 num_vdev_stats;
|
||||||
|
+ u32 num_peer_stats;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ if (!skb_pull(skb, sizeof(*ev)))
|
||||||
|
+ return -EPROTO;
|
||||||
|
+
|
||||||
|
+ num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
|
||||||
|
+ num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
|
||||||
|
+ num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
|
||||||
|
+ num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < num_pdev_stats; i++) {
|
||||||
|
+ const struct wmi_10_4_pdev_stats *src;
|
||||||
|
+ struct ath10k_fw_stats_pdev *dst;
|
||||||
|
+
|
||||||
|
+ src = (void *)skb->data;
|
||||||
|
+ if (!skb_pull(skb, sizeof(*src)))
|
||||||
|
+ return -EPROTO;
|
||||||
|
+
|
||||||
|
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||||
|
+ if (!dst)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
|
||||||
|
+ ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
|
||||||
|
+ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
|
||||||
|
+ dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
|
||||||
|
+ ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
|
||||||
|
+
|
||||||
|
+ list_add_tail(&dst->list, &stats->pdevs);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < num_pdev_ext_stats; i++) {
|
||||||
|
+ const struct wmi_10_2_pdev_ext_stats *src;
|
||||||
|
+
|
||||||
|
+ src = (void *)skb->data;
|
||||||
|
+ if (!skb_pull(skb, sizeof(*src)))
|
||||||
|
+ return -EPROTO;
|
||||||
|
+
|
||||||
|
+ /* FIXME: expose values to userspace
|
||||||
|
+ *
|
||||||
|
+ * Note: Even though this loop seems to do nothing it is
|
||||||
|
+ * required to parse following sub-structures properly.
|
||||||
|
+ */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* fw doesn't implement vdev stats */
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < num_peer_stats; i++) {
|
||||||
|
+ const struct wmi_10_4_peer_stats *src;
|
||||||
|
+ struct ath10k_fw_stats_peer *dst;
|
||||||
|
+
|
||||||
|
+ src = (void *)skb->data;
|
||||||
|
+ if (!skb_pull(skb, sizeof(*src)))
|
||||||
|
+ return -EPROTO;
|
||||||
|
+
|
||||||
|
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||||
|
+ if (!dst)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
|
||||||
|
+ dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
|
||||||
|
+ dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
|
||||||
|
+ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
|
||||||
|
+ /* FIXME: expose 10.4 specific values */
|
||||||
|
+
|
||||||
|
+ list_add_tail(&dst->list, &stats->peers);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
|
||||||
|
@@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct
|
||||||
|
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||||
|
"received event id %d not implemented\n", id);
|
||||||
|
break;
|
||||||
|
+ case WMI_10_4_UPDATE_STATS_EVENTID:
|
||||||
|
+ ath10k_wmi_event_update_stats(ar, skb);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||||
|
break;
|
||||||
|
@@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||||
|
+ struct ath10k_fw_stats *fw_stats,
|
||||||
|
+ char *buf)
|
||||||
|
+{
|
||||||
|
+ u32 len = 0;
|
||||||
|
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
||||||
|
+ const struct ath10k_fw_stats_pdev *pdev;
|
||||||
|
+ const struct ath10k_fw_stats_vdev *vdev;
|
||||||
|
+ const struct ath10k_fw_stats_peer *peer;
|
||||||
|
+ size_t num_peers;
|
||||||
|
+ size_t num_vdevs;
|
||||||
|
+
|
||||||
|
+ spin_lock_bh(&ar->data_lock);
|
||||||
|
+
|
||||||
|
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
|
||||||
|
+ struct ath10k_fw_stats_pdev, list);
|
||||||
|
+ if (!pdev) {
|
||||||
|
+ ath10k_warn(ar, "failed to get pdev stats\n");
|
||||||
|
+ goto unlock;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
||||||
|
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
||||||
|
+
|
||||||
|
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
||||||
|
+ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
|
||||||
|
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
|
||||||
|
+
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "HW paused", pdev->hw_paused);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "Seqs posted", pdev->seq_posted);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "Seqs failed queueing", pdev->seq_failed_queueing);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "Seqs completed", pdev->seq_completed);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "Seqs restarted", pdev->seq_restarted);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MU Seqs posted", pdev->mu_seq_posted);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MPDUs SW flushed", pdev->mpdus_sw_flush);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MPDUs HW filtered", pdev->mpdus_hw_filter);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MPDUs truncated", pdev->mpdus_truncated);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MPDUs receive no ACK", pdev->mpdus_ack_failed);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "MPDUs expired", pdev->mpdus_expired);
|
||||||
|
+
|
||||||
|
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||||
|
+ "Num Rx Overflow errors", pdev->rx_ovfl_errs);
|
||||||
|
+
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
||||||
|
+ "ath10k VDEV stats", num_vdevs);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
||||||
|
+ "=================");
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
|
||||||
|
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
||||||
|
+ "ath10k PEER stats", num_peers);
|
||||||
|
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
||||||
|
+ "=================");
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(peer, &fw_stats->peers, list) {
|
||||||
|
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+unlock:
|
||||||
|
+ spin_unlock_bh(&ar->data_lock);
|
||||||
|
+
|
||||||
|
+ if (len >= buf_len)
|
||||||
|
+ buf[len - 1] = 0;
|
||||||
|
+ else
|
||||||
|
+ buf[len] = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct wmi_ops wmi_ops = {
|
||||||
|
.rx = ath10k_wmi_op_rx,
|
||||||
|
.map_svc = wmi_main_svc_map,
|
||||||
|
@@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops
|
||||||
|
.rx = ath10k_wmi_10_4_op_rx,
|
||||||
|
.map_svc = wmi_10_4_svc_map,
|
||||||
|
|
||||||
|
+ .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
|
||||||
|
.pull_scan = ath10k_wmi_op_pull_scan_ev,
|
||||||
|
.pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
|
||||||
|
.pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
|
||||||
|
@@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops
|
||||||
|
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
||||||
|
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
||||||
|
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||||
|
+ .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
|
||||||
|
|
||||||
|
/* shared with 10.2 */
|
||||||
|
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
|
||||||
|
+ .gen_request_stats = ath10k_wmi_op_gen_request_stats,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ath10k_wmi_attach(struct ath10k *ar)
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
|
||||||
|
@@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx {
|
||||||
|
__le32 txop_ovf;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
+struct wmi_10_4_pdev_stats_tx {
|
||||||
|
+ /* Num HTT cookies queued to dispatch list */
|
||||||
|
+ __le32 comp_queued;
|
||||||
|
+
|
||||||
|
+ /* Num HTT cookies dispatched */
|
||||||
|
+ __le32 comp_delivered;
|
||||||
|
+
|
||||||
|
+ /* Num MSDU queued to WAL */
|
||||||
|
+ __le32 msdu_enqued;
|
||||||
|
+
|
||||||
|
+ /* Num MPDU queue to WAL */
|
||||||
|
+ __le32 mpdu_enqued;
|
||||||
|
+
|
||||||
|
+ /* Num MSDUs dropped by WMM limit */
|
||||||
|
+ __le32 wmm_drop;
|
||||||
|
+
|
||||||
|
+ /* Num Local frames queued */
|
||||||
|
+ __le32 local_enqued;
|
||||||
|
+
|
||||||
|
+ /* Num Local frames done */
|
||||||
|
+ __le32 local_freed;
|
||||||
|
+
|
||||||
|
+ /* Num queued to HW */
|
||||||
|
+ __le32 hw_queued;
|
||||||
|
+
|
||||||
|
+ /* Num PPDU reaped from HW */
|
||||||
|
+ __le32 hw_reaped;
|
||||||
|
+
|
||||||
|
+ /* Num underruns */
|
||||||
|
+ __le32 underrun;
|
||||||
|
+
|
||||||
|
+ /* HW Paused. */
|
||||||
|
+ __le32 hw_paused;
|
||||||
|
+
|
||||||
|
+ /* Num PPDUs cleaned up in TX abort */
|
||||||
|
+ __le32 tx_abort;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs requed by SW */
|
||||||
|
+ __le32 mpdus_requed;
|
||||||
|
+
|
||||||
|
+ /* excessive retries */
|
||||||
|
+ __le32 tx_ko;
|
||||||
|
+
|
||||||
|
+ /* data hw rate code */
|
||||||
|
+ __le32 data_rc;
|
||||||
|
+
|
||||||
|
+ /* Scheduler self triggers */
|
||||||
|
+ __le32 self_triggers;
|
||||||
|
+
|
||||||
|
+ /* frames dropped due to excessive sw retries */
|
||||||
|
+ __le32 sw_retry_failure;
|
||||||
|
+
|
||||||
|
+ /* illegal rate phy errors */
|
||||||
|
+ __le32 illgl_rate_phy_err;
|
||||||
|
+
|
||||||
|
+ /* wal pdev continuous xretry */
|
||||||
|
+ __le32 pdev_cont_xretry;
|
||||||
|
+
|
||||||
|
+ /* wal pdev tx timeouts */
|
||||||
|
+ __le32 pdev_tx_timeout;
|
||||||
|
+
|
||||||
|
+ /* wal pdev resets */
|
||||||
|
+ __le32 pdev_resets;
|
||||||
|
+
|
||||||
|
+ /* frames dropped due to non-availability of stateless TIDs */
|
||||||
|
+ __le32 stateless_tid_alloc_failure;
|
||||||
|
+
|
||||||
|
+ __le32 phy_underrun;
|
||||||
|
+
|
||||||
|
+ /* MPDU is more than txop limit */
|
||||||
|
+ __le32 txop_ovf;
|
||||||
|
+
|
||||||
|
+ /* Number of Sequences posted */
|
||||||
|
+ __le32 seq_posted;
|
||||||
|
+
|
||||||
|
+ /* Number of Sequences failed queueing */
|
||||||
|
+ __le32 seq_failed_queueing;
|
||||||
|
+
|
||||||
|
+ /* Number of Sequences completed */
|
||||||
|
+ __le32 seq_completed;
|
||||||
|
+
|
||||||
|
+ /* Number of Sequences restarted */
|
||||||
|
+ __le32 seq_restarted;
|
||||||
|
+
|
||||||
|
+ /* Number of MU Sequences posted */
|
||||||
|
+ __le32 mu_seq_posted;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
|
||||||
|
+ __le32 mpdus_sw_flush;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
|
||||||
|
+ __le32 mpdus_hw_filter;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs truncated by PDG
|
||||||
|
+ * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
|
||||||
|
+ */
|
||||||
|
+ __le32 mpdus_truncated;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs that was tried but didn't receive ACK or BA */
|
||||||
|
+ __le32 mpdus_ack_failed;
|
||||||
|
+
|
||||||
|
+ /* Num MPDUs that was dropped due to expiry. */
|
||||||
|
+ __le32 mpdus_expired;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
struct wmi_pdev_stats_rx {
|
||||||
|
/* Cnts any change in ring routing mid-ppdu */
|
||||||
|
__le32 mid_ppdu_route_change;
|
||||||
|
@@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
|
||||||
|
struct wmi_pdev_stats_extra extra;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
+struct wmi_10_4_pdev_stats {
|
||||||
|
+ struct wmi_pdev_stats_base base;
|
||||||
|
+ struct wmi_10_4_pdev_stats_tx tx;
|
||||||
|
+ struct wmi_pdev_stats_rx rx;
|
||||||
|
+ __le32 rx_ovfl_errs;
|
||||||
|
+ struct wmi_pdev_stats_mem mem;
|
||||||
|
+ __le32 sram_free_size;
|
||||||
|
+ struct wmi_pdev_stats_extra extra;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* VDEV statistics
|
||||||
|
* TODO: add all VDEV stats here
|
||||||
|
@@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
|
||||||
|
__le32 unknown_value; /* FIXME: what is this word? */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
+struct wmi_10_4_peer_stats {
|
||||||
|
+ struct wmi_mac_addr peer_macaddr;
|
||||||
|
+ __le32 peer_rssi;
|
||||||
|
+ __le32 peer_rssi_seq_num;
|
||||||
|
+ __le32 peer_tx_rate;
|
||||||
|
+ __le32 peer_rx_rate;
|
||||||
|
+ __le32 current_per;
|
||||||
|
+ __le32 retries;
|
||||||
|
+ __le32 tx_rate_count;
|
||||||
|
+ __le32 max_4ms_frame_len;
|
||||||
|
+ __le32 total_sub_frames;
|
||||||
|
+ __le32 tx_bytes;
|
||||||
|
+ __le32 num_pkt_loss_overflow[4];
|
||||||
|
+ __le32 num_pkt_loss_excess_retry[4];
|
||||||
|
+ __le32 peer_rssi_changed;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
struct wmi_10_2_pdev_ext_stats {
|
||||||
|
__le32 rx_rssi_comb;
|
||||||
|
__le32 rx_rssi[4];
|
||||||
|
@@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str
|
||||||
|
char *buf);
|
||||||
|
size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
|
||||||
|
size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
|
||||||
|
+void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||||
|
+ struct ath10k_fw_stats *fw_stats,
|
||||||
|
+ char *buf);
|
||||||
|
|
||||||
|
#endif /* _WMI_H_ */
|
@ -0,0 +1,60 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Fri, 23 Oct 2015 18:01:03 +0530
|
||||||
|
Subject: [PATCH] ath10k: use local memory instead of shadow descriptor
|
||||||
|
in ce_send
|
||||||
|
|
||||||
|
Currently to avoid uncached memory access while filling up copy engine
|
||||||
|
descriptors, shadow descriptors are used. This can be optimized further
|
||||||
|
by removing shadow descriptors. To achieve that first shadow ring
|
||||||
|
dependency in ce_send is removed by creating local copy of the
|
||||||
|
descriptor on stack and make a one-shot copy into the "uncached"
|
||||||
|
descriptor.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
@@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_
|
||||||
|
{
|
||||||
|
struct ath10k *ar = ce_state->ar;
|
||||||
|
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||||
|
- struct ce_desc *desc, *sdesc;
|
||||||
|
+ struct ce_desc *desc, sdesc;
|
||||||
|
unsigned int nentries_mask = src_ring->nentries_mask;
|
||||||
|
unsigned int sw_index = src_ring->sw_index;
|
||||||
|
unsigned int write_index = src_ring->write_index;
|
||||||
|
@@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_
|
||||||
|
|
||||||
|
desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
|
||||||
|
write_index);
|
||||||
|
- sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index);
|
||||||
|
|
||||||
|
desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
|
||||||
|
|
||||||
|
@@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_
|
||||||
|
if (flags & CE_SEND_FLAG_BYTE_SWAP)
|
||||||
|
desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
|
||||||
|
|
||||||
|
- sdesc->addr = __cpu_to_le32(buffer);
|
||||||
|
- sdesc->nbytes = __cpu_to_le16(nbytes);
|
||||||
|
- sdesc->flags = __cpu_to_le16(desc_flags);
|
||||||
|
+ sdesc.addr = __cpu_to_le32(buffer);
|
||||||
|
+ sdesc.nbytes = __cpu_to_le16(nbytes);
|
||||||
|
+ sdesc.flags = __cpu_to_le16(desc_flags);
|
||||||
|
|
||||||
|
- *desc = *sdesc;
|
||||||
|
+ *desc = sdesc;
|
||||||
|
|
||||||
|
src_ring->per_transfer_context[write_index] = per_transfer_context;
|
||||||
|
|
||||||
|
@@ -614,7 +613,7 @@ int ath10k_ce_completed_send_next_nolock
|
||||||
|
if (read_index == sw_index)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
- sbase = src_ring->shadow_base;
|
||||||
|
+ sbase = src_ring->base_addr_owner_space;
|
||||||
|
sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
|
||||||
|
|
||||||
|
/* Return data from completed source descriptor */
|
@ -0,0 +1,49 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Fri, 23 Oct 2015 18:01:04 +0530
|
||||||
|
Subject: [PATCH] ath10k: remove send completion validation in diag
|
||||||
|
read/write
|
||||||
|
|
||||||
|
CE diag window access is serialized (it has to be by design) so
|
||||||
|
there's no way to get a different send completion. so there's no
|
||||||
|
need for post completion validation.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
@@ -920,16 +920,6 @@ static int ath10k_pci_diag_read_mem(stru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (nbytes != completed_nbytes) {
|
||||||
|
- ret = -EIO;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (buf != (u32)address) {
|
||||||
|
- ret = -EIO;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
i = 0;
|
||||||
|
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||||
|
&completed_nbytes,
|
||||||
|
@@ -1094,16 +1084,6 @@ static int ath10k_pci_diag_write_mem(str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (nbytes != completed_nbytes) {
|
||||||
|
- ret = -EIO;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (buf != ce_data) {
|
||||||
|
- ret = -EIO;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
i = 0;
|
||||||
|
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||||
|
&completed_nbytes,
|
@ -0,0 +1,165 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Fri, 23 Oct 2015 18:01:05 +0530
|
||||||
|
Subject: [PATCH] ath10k: cleanup copy engine send completion
|
||||||
|
|
||||||
|
The physical address necessary to unmap DMA ('bufferp') is stored
|
||||||
|
in ath10k_skb_cb as 'paddr'. ath10k doesn't rely on the meta/transfer_id
|
||||||
|
when handling send completion (htc ep id is stored in sk_buff control
|
||||||
|
buffer). So the unused output arguments {bufferp, nbytesp and transfer_idp}
|
||||||
|
are removed from CE send completion. This change is needed before removing
|
||||||
|
the shadow copy of copy engine (CE) descriptors in follow up patch.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
@@ -578,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct at
|
||||||
|
* The caller takes responsibility for any necessary locking.
|
||||||
|
*/
|
||||||
|
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||||
|
- void **per_transfer_contextp,
|
||||||
|
- u32 *bufferp,
|
||||||
|
- unsigned int *nbytesp,
|
||||||
|
- unsigned int *transfer_idp)
|
||||||
|
+ void **per_transfer_contextp)
|
||||||
|
{
|
||||||
|
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||||
|
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||||
|
struct ath10k *ar = ce_state->ar;
|
||||||
|
unsigned int nentries_mask = src_ring->nentries_mask;
|
||||||
|
unsigned int sw_index = src_ring->sw_index;
|
||||||
|
- struct ce_desc *sdesc, *sbase;
|
||||||
|
unsigned int read_index;
|
||||||
|
|
||||||
|
if (src_ring->hw_index == sw_index) {
|
||||||
|
@@ -613,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock
|
||||||
|
if (read_index == sw_index)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
- sbase = src_ring->base_addr_owner_space;
|
||||||
|
- sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
|
||||||
|
-
|
||||||
|
- /* Return data from completed source descriptor */
|
||||||
|
- *bufferp = __le32_to_cpu(sdesc->addr);
|
||||||
|
- *nbytesp = __le16_to_cpu(sdesc->nbytes);
|
||||||
|
- *transfer_idp = MS(__le16_to_cpu(sdesc->flags),
|
||||||
|
- CE_DESC_FLAGS_META_DATA);
|
||||||
|
-
|
||||||
|
if (per_transfer_contextp)
|
||||||
|
*per_transfer_contextp =
|
||||||
|
src_ring->per_transfer_context[sw_index];
|
||||||
|
@@ -696,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct at
|
||||||
|
}
|
||||||
|
|
||||||
|
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||||
|
- void **per_transfer_contextp,
|
||||||
|
- u32 *bufferp,
|
||||||
|
- unsigned int *nbytesp,
|
||||||
|
- unsigned int *transfer_idp)
|
||||||
|
+ void **per_transfer_contextp)
|
||||||
|
{
|
||||||
|
struct ath10k *ar = ce_state->ar;
|
||||||
|
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||||
|
@@ -707,9 +691,7 @@ int ath10k_ce_completed_send_next(struct
|
||||||
|
|
||||||
|
spin_lock_bh(&ar_pci->ce_lock);
|
||||||
|
ret = ath10k_ce_completed_send_next_nolock(ce_state,
|
||||||
|
- per_transfer_contextp,
|
||||||
|
- bufferp, nbytesp,
|
||||||
|
- transfer_idp);
|
||||||
|
+ per_transfer_contextp);
|
||||||
|
spin_unlock_bh(&ar_pci->ce_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/ce.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/ce.h
|
||||||
|
@@ -192,16 +192,10 @@ int ath10k_ce_completed_recv_next(struct
|
||||||
|
* Pops 1 completed send buffer from Source ring.
|
||||||
|
*/
|
||||||
|
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||||
|
- void **per_transfer_contextp,
|
||||||
|
- u32 *bufferp,
|
||||||
|
- unsigned int *nbytesp,
|
||||||
|
- unsigned int *transfer_idp);
|
||||||
|
+ void **per_transfer_contextp);
|
||||||
|
|
||||||
|
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||||
|
- void **per_transfer_contextp,
|
||||||
|
- u32 *bufferp,
|
||||||
|
- unsigned int *nbytesp,
|
||||||
|
- unsigned int *transfer_idp);
|
||||||
|
+ void **per_transfer_contextp);
|
||||||
|
|
||||||
|
/*==================CE Engine Initialization=======================*/
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
@@ -910,9 +910,8 @@ static int ath10k_pci_diag_read_mem(stru
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||||
|
- &completed_nbytes,
|
||||||
|
- &id) != 0) {
|
||||||
|
+ while (ath10k_ce_completed_send_next_nolock(ce_diag,
|
||||||
|
+ NULL) != 0) {
|
||||||
|
mdelay(1);
|
||||||
|
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
@@ -1073,9 +1072,8 @@ static int ath10k_pci_diag_write_mem(str
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||||
|
- &completed_nbytes,
|
||||||
|
- &id) != 0) {
|
||||||
|
+ while (ath10k_ce_completed_send_next_nolock(ce_diag,
|
||||||
|
+ NULL) != 0) {
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||||
|
@@ -1139,13 +1137,9 @@ static void ath10k_pci_htc_tx_cb(struct
|
||||||
|
struct ath10k *ar = ce_state->ar;
|
||||||
|
struct sk_buff_head list;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
- u32 ce_data;
|
||||||
|
- unsigned int nbytes;
|
||||||
|
- unsigned int transfer_id;
|
||||||
|
|
||||||
|
__skb_queue_head_init(&list);
|
||||||
|
- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
|
||||||
|
- &nbytes, &transfer_id) == 0) {
|
||||||
|
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
|
||||||
|
/* no need to call tx completion for NULL pointers */
|
||||||
|
if (skb == NULL)
|
||||||
|
continue;
|
||||||
|
@@ -1215,12 +1209,8 @@ static void ath10k_pci_htt_tx_cb(struct
|
||||||
|
{
|
||||||
|
struct ath10k *ar = ce_state->ar;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
- u32 ce_data;
|
||||||
|
- unsigned int nbytes;
|
||||||
|
- unsigned int transfer_id;
|
||||||
|
|
||||||
|
- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
|
||||||
|
- &nbytes, &transfer_id) == 0) {
|
||||||
|
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
|
||||||
|
/* no need to call tx completion for NULL pointers */
|
||||||
|
if (!skb)
|
||||||
|
continue;
|
||||||
|
@@ -1796,12 +1786,8 @@ err_dma:
|
||||||
|
static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
|
||||||
|
{
|
||||||
|
struct bmi_xfer *xfer;
|
||||||
|
- u32 ce_data;
|
||||||
|
- unsigned int nbytes;
|
||||||
|
- unsigned int transfer_id;
|
||||||
|
|
||||||
|
- if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data,
|
||||||
|
- &nbytes, &transfer_id))
|
||||||
|
+ if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
xfer->tx_done = true;
|
@ -0,0 +1,90 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Fri, 23 Oct 2015 18:01:06 +0530
|
||||||
|
Subject: [PATCH] ath10k: remove shadow copy of CE descriptors for source
|
||||||
|
ring
|
||||||
|
|
||||||
|
For the messages from host to target, shadow copy of CE descriptors
|
||||||
|
are maintained in source ring. Before writing actual CE descriptor,
|
||||||
|
first shadow copy is filled and then it is copied to CE address space.
|
||||||
|
To optimize in download path and to reduce d-cache pressure, removing
|
||||||
|
shadow copy of CE descriptors. This will also reduce driver memory
|
||||||
|
consumption by 33KB during on device probing.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/ce.c
|
||||||
|
@@ -921,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *
|
||||||
|
src_ring->base_addr_ce_space_unaligned,
|
||||||
|
CE_DESC_RING_ALIGN);
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Also allocate a shadow src ring in regular
|
||||||
|
- * mem to use for faster access.
|
||||||
|
- */
|
||||||
|
- src_ring->shadow_base_unaligned =
|
||||||
|
- kmalloc((nentries * sizeof(struct ce_desc) +
|
||||||
|
- CE_DESC_RING_ALIGN), GFP_KERNEL);
|
||||||
|
- if (!src_ring->shadow_base_unaligned) {
|
||||||
|
- dma_free_coherent(ar->dev,
|
||||||
|
- (nentries * sizeof(struct ce_desc) +
|
||||||
|
- CE_DESC_RING_ALIGN),
|
||||||
|
- src_ring->base_addr_owner_space,
|
||||||
|
- src_ring->base_addr_ce_space);
|
||||||
|
- kfree(src_ring);
|
||||||
|
- return ERR_PTR(-ENOMEM);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- src_ring->shadow_base = PTR_ALIGN(
|
||||||
|
- src_ring->shadow_base_unaligned,
|
||||||
|
- CE_DESC_RING_ALIGN);
|
||||||
|
-
|
||||||
|
return src_ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1120,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *
|
||||||
|
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
|
||||||
|
|
||||||
|
if (ce_state->src_ring) {
|
||||||
|
- kfree(ce_state->src_ring->shadow_base_unaligned);
|
||||||
|
dma_free_coherent(ar->dev,
|
||||||
|
(ce_state->src_ring->nentries *
|
||||||
|
sizeof(struct ce_desc) +
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/ce.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/ce.h
|
||||||
|
@@ -100,12 +100,6 @@ struct ath10k_ce_ring {
|
||||||
|
|
||||||
|
/* CE address space */
|
||||||
|
u32 base_addr_ce_space;
|
||||||
|
- /*
|
||||||
|
- * Start of shadow copy of descriptors, within regular memory.
|
||||||
|
- * Aligned to descriptor-size boundary.
|
||||||
|
- */
|
||||||
|
- void *shadow_base_unaligned;
|
||||||
|
- struct ce_desc *shadow_base;
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
void *per_transfer_context[0];
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
||||||
|
@@ -1594,7 +1594,6 @@ static void ath10k_pci_tx_pipe_cleanup(s
|
||||||
|
struct ath10k_pci *ar_pci;
|
||||||
|
struct ath10k_ce_pipe *ce_pipe;
|
||||||
|
struct ath10k_ce_ring *ce_ring;
|
||||||
|
- struct ce_desc *ce_desc;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
@@ -1609,10 +1608,6 @@ static void ath10k_pci_tx_pipe_cleanup(s
|
||||||
|
if (!pci_pipe->buf_sz)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- ce_desc = ce_ring->shadow_base;
|
||||||
|
- if (WARN_ON(!ce_desc))
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
for (i = 0; i < ce_ring->nentries; i++) {
|
||||||
|
skb = ce_ring->per_transfer_context[i];
|
||||||
|
if (!skb)
|
@ -0,0 +1,77 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Tue, 27 Oct 2015 17:51:11 +0530
|
||||||
|
Subject: [PATCH] ath10k: remove supported chain mask
|
||||||
|
|
||||||
|
Removing supported chainmask fields as it can be always derived
|
||||||
|
from num_rf_chains.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||||
|
@@ -745,8 +745,6 @@ struct ath10k {
|
||||||
|
int num_started_vdevs;
|
||||||
|
|
||||||
|
/* Protected by conf-mutex */
|
||||||
|
- u8 supp_tx_chainmask;
|
||||||
|
- u8 supp_rx_chainmask;
|
||||||
|
u8 cfg_tx_chainmask;
|
||||||
|
u8 cfg_rx_chainmask;
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
@@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct iee
|
||||||
|
|
||||||
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
|
- if (ar->cfg_tx_chainmask) {
|
||||||
|
- *tx_ant = ar->cfg_tx_chainmask;
|
||||||
|
- *rx_ant = ar->cfg_rx_chainmask;
|
||||||
|
- } else {
|
||||||
|
- *tx_ant = ar->supp_tx_chainmask;
|
||||||
|
- *rx_ant = ar->supp_rx_chainmask;
|
||||||
|
- }
|
||||||
|
+ *tx_ant = ar->cfg_tx_chainmask;
|
||||||
|
+ *rx_ant = ar->cfg_rx_chainmask;
|
||||||
|
|
||||||
|
mutex_unlock(&ar->conf_mutex);
|
||||||
|
|
||||||
|
@@ -3884,9 +3879,7 @@ static int ath10k_start(struct ieee80211
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (ar->cfg_tx_chainmask)
|
||||||
|
- __ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
|
||||||
|
- ar->cfg_rx_chainmask);
|
||||||
|
+ __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default FW set ARP frames ac to voice (6). In that case ARP
|
||||||
|
@@ -7169,8 +7162,8 @@ int ath10k_mac_register(struct ath10k *a
|
||||||
|
BIT(NL80211_IFTYPE_AP) |
|
||||||
|
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||||
|
|
||||||
|
- ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
|
||||||
|
- ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
|
||||||
|
+ ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask;
|
||||||
|
+ ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask;
|
||||||
|
|
||||||
|
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
|
||||||
|
ar->hw->wiphy->interface_modes |=
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||||
|
@@ -4460,8 +4460,10 @@ static void ath10k_wmi_event_service_rea
|
||||||
|
ar->num_rf_chains = ar->max_spatial_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||||
|
- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||||
|
+ if (!ar->cfg_tx_chainmask) {
|
||||||
|
+ ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||||
|
+ ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (strlen(ar->hw->wiphy->fw_version) == 0) {
|
||||||
|
snprintf(ar->hw->wiphy->fw_version,
|
@ -0,0 +1,37 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Tue, 27 Oct 2015 17:51:12 +0530
|
||||||
|
Subject: [PATCH] ath10k: fill HT/VHT MCS rateset only for configured
|
||||||
|
chainmask
|
||||||
|
|
||||||
|
HT/VHT MCS rateset should be filled only for configured chainmask
|
||||||
|
rather that max supported chainmask. Fix that by checking configured
|
||||||
|
chainmask while filling HT/VHT MCS rate map.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
@@ -6984,7 +6984,7 @@ static struct ieee80211_sta_vht_cap ath1
|
||||||
|
|
||||||
|
mcs_map = 0;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
- if (i < ar->num_rf_chains)
|
||||||
|
+ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||||
|
mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
|
||||||
|
else
|
||||||
|
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
|
||||||
|
@@ -7051,8 +7051,10 @@ static struct ieee80211_sta_ht_cap ath10
|
||||||
|
if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
|
||||||
|
ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
|
||||||
|
- for (i = 0; i < ar->num_rf_chains; i++)
|
||||||
|
- ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||||
|
+ for (i = 0; i < ar->num_rf_chains; i++) {
|
||||||
|
+ if (ar->cfg_rx_chainmask & BIT(i))
|
||||||
|
+ ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||||
|
|
@ -0,0 +1,314 @@ |
|||||||
|
From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Date: Tue, 27 Oct 2015 17:51:13 +0530
|
||||||
|
Subject: [PATCH] ath10k: move static HT/VHT capability setup functions
|
||||||
|
|
||||||
|
Move HT and VHT capabiltity setup static functions to avoid
|
||||||
|
forward declaration.
|
||||||
|
|
||||||
|
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
|
||||||
|
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||||
|
@@ -3757,6 +3757,146 @@ static void ath10k_check_chain_mask(stru
|
||||||
|
dbg, cm);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ int nsts = ar->vht_cap_info;
|
||||||
|
+
|
||||||
|
+ nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||||
|
+ nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||||
|
+
|
||||||
|
+ /* If firmware does not deliver to host number of space-time
|
||||||
|
+ * streams supported, assume it support up to 4 BF STS and return
|
||||||
|
+ * the value for VHT CAP: nsts-1)
|
||||||
|
+ */
|
||||||
|
+ if (nsts == 0)
|
||||||
|
+ return 3;
|
||||||
|
+
|
||||||
|
+ return nsts;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ int sound_dim = ar->vht_cap_info;
|
||||||
|
+
|
||||||
|
+ sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||||
|
+ sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||||
|
+
|
||||||
|
+ /* If the sounding dimension is not advertised by the firmware,
|
||||||
|
+ * let's use a default value of 1
|
||||||
|
+ */
|
||||||
|
+ if (sound_dim == 0)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ return sound_dim;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ struct ieee80211_sta_vht_cap vht_cap = {0};
|
||||||
|
+ u16 mcs_map;
|
||||||
|
+ u32 val;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ vht_cap.vht_supported = 1;
|
||||||
|
+ vht_cap.cap = ar->vht_cap_info;
|
||||||
|
+
|
||||||
|
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||||
|
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
|
||||||
|
+ val = ath10k_mac_get_vht_cap_bf_sts(ar);
|
||||||
|
+ val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||||
|
+ val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||||
|
+
|
||||||
|
+ vht_cap.cap |= val;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||||
|
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
|
||||||
|
+ val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
|
||||||
|
+ val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||||
|
+ val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||||
|
+
|
||||||
|
+ vht_cap.cap |= val;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mcs_map = 0;
|
||||||
|
+ for (i = 0; i < 8; i++) {
|
||||||
|
+ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||||
|
+ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
|
||||||
|
+ else
|
||||||
|
+ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||||
|
+ vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||||
|
+
|
||||||
|
+ return vht_cap;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+ struct ieee80211_sta_ht_cap ht_cap = {0};
|
||||||
|
+
|
||||||
|
+ if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
|
||||||
|
+ return ht_cap;
|
||||||
|
+
|
||||||
|
+ ht_cap.ht_supported = 1;
|
||||||
|
+ ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||||
|
+ ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
|
||||||
|
+ ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
|
||||||
|
+ u32 smps;
|
||||||
|
+
|
||||||
|
+ smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
|
||||||
|
+ smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||||
|
+
|
||||||
|
+ ht_cap.cap |= smps;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
|
||||||
|
+ u32 stbc;
|
||||||
|
+
|
||||||
|
+ stbc = ar->ht_cap_info;
|
||||||
|
+ stbc &= WMI_HT_CAP_RX_STBC;
|
||||||
|
+ stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
|
||||||
|
+ stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
|
||||||
|
+ stbc &= IEEE80211_HT_CAP_RX_STBC;
|
||||||
|
+
|
||||||
|
+ ht_cap.cap |= stbc;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||||
|
+
|
||||||
|
+ if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
|
||||||
|
+
|
||||||
|
+ /* max AMSDU is implicitly taken from vht_cap_info */
|
||||||
|
+ if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
|
||||||
|
+ ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < ar->num_rf_chains; i++) {
|
||||||
|
+ if (ar->cfg_rx_chainmask & BIT(i))
|
||||||
|
+ ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||||
|
+
|
||||||
|
+ return ht_cap;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
@@ -4068,39 +4208,6 @@ static u32 get_nss_from_chainmask(u16 ch
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
|
||||||
|
-{
|
||||||
|
- int nsts = ar->vht_cap_info;
|
||||||
|
-
|
||||||
|
- nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||||
|
- nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||||
|
-
|
||||||
|
- /* If firmware does not deliver to host number of space-time
|
||||||
|
- * streams supported, assume it support up to 4 BF STS and return
|
||||||
|
- * the value for VHT CAP: nsts-1)
|
||||||
|
- * */
|
||||||
|
- if (nsts == 0)
|
||||||
|
- return 3;
|
||||||
|
-
|
||||||
|
- return nsts;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
|
||||||
|
-{
|
||||||
|
- int sound_dim = ar->vht_cap_info;
|
||||||
|
-
|
||||||
|
- sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||||
|
- sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||||
|
-
|
||||||
|
- /* If the sounding dimension is not advertised by the firmware,
|
||||||
|
- * let's use a default value of 1
|
||||||
|
- */
|
||||||
|
- if (sound_dim == 0)
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- return sound_dim;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
|
||||||
|
{
|
||||||
|
u32 value = 0;
|
||||||
|
@@ -6954,113 +7061,6 @@ static const struct ieee80211_iface_comb
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||||
|
-{
|
||||||
|
- struct ieee80211_sta_vht_cap vht_cap = {0};
|
||||||
|
- u16 mcs_map;
|
||||||
|
- u32 val;
|
||||||
|
- int i;
|
||||||
|
-
|
||||||
|
- vht_cap.vht_supported = 1;
|
||||||
|
- vht_cap.cap = ar->vht_cap_info;
|
||||||
|
-
|
||||||
|
- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||||
|
- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
|
||||||
|
- val = ath10k_mac_get_vht_cap_bf_sts(ar);
|
||||||
|
- val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||||
|
- val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||||
|
-
|
||||||
|
- vht_cap.cap |= val;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||||
|
- IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
|
||||||
|
- val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
|
||||||
|
- val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||||
|
- val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||||
|
-
|
||||||
|
- vht_cap.cap |= val;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- mcs_map = 0;
|
||||||
|
- for (i = 0; i < 8; i++) {
|
||||||
|
- if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||||
|
- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
|
||||||
|
- else
|
||||||
|
- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||||
|
- vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||||
|
-
|
||||||
|
- return vht_cap;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- struct ieee80211_sta_ht_cap ht_cap = {0};
|
||||||
|
-
|
||||||
|
- if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
|
||||||
|
- return ht_cap;
|
||||||
|
-
|
||||||
|
- ht_cap.ht_supported = 1;
|
||||||
|
- ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||||
|
- ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
|
||||||
|
- ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
|
||||||
|
- u32 smps;
|
||||||
|
-
|
||||||
|
- smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
|
||||||
|
- smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||||
|
-
|
||||||
|
- ht_cap.cap |= smps;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
|
||||||
|
- u32 stbc;
|
||||||
|
-
|
||||||
|
- stbc = ar->ht_cap_info;
|
||||||
|
- stbc &= WMI_HT_CAP_RX_STBC;
|
||||||
|
- stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
|
||||||
|
- stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
|
||||||
|
- stbc &= IEEE80211_HT_CAP_RX_STBC;
|
||||||
|
-
|
||||||
|
- ht_cap.cap |= stbc;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||||
|
-
|
||||||
|
- if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
|
||||||
|
-
|
||||||
|
- /* max AMSDU is implicitly taken from vht_cap_info */
|
||||||
|
- if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
|
||||||
|
- ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
-
|
||||||
|
- for (i = 0; i < ar->num_rf_chains; i++) {
|
||||||
|
- if (ar->cfg_rx_chainmask & BIT(i))
|
||||||
|
- ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||||
|
-
|
||||||
|
- return ht_cap;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void ath10k_get_arvif_iter(void *data, u8 *mac,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
Loading…
Reference in new issue