diff options
author | Felix Fietkau <nbd@openwrt.org> | 2015-10-30 15:18:03 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-10-30 15:18:03 +0000 |
commit | ce0989439850a1306dc2e61d711b5dd50b9f2b13 (patch) | |
tree | 6787c93b9f619e553e4bd60932cae52fdaf0f811 /package/kernel/mac80211/patches | |
parent | ec3ee0969e6ecf49a2c98ce96f6977906ada0553 (diff) | |
download | master-31e0f0ae-ce0989439850a1306dc2e61d711b5dd50b9f2b13.tar.gz master-31e0f0ae-ce0989439850a1306dc2e61d711b5dd50b9f2b13.tar.bz2 master-31e0f0ae-ce0989439850a1306dc2e61d711b5dd50b9f2b13.zip |
mac80211: add pending ath9k/ath10k patches
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 47287
Diffstat (limited to 'package/kernel/mac80211/patches')
16 files changed, 2095 insertions, 5 deletions
diff --git a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch new file mode 100644 index 0000000000..bddb15ad1a --- /dev/null +++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch @@ -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); + } diff --git a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch new file mode 100644 index 0000000000..33b21e6a0a --- /dev/null +++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch @@ -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); diff --git a/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch new file mode 100644 index 0000000000..944b8e720a --- /dev/null +++ b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch @@ -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, + }; + diff --git a/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch new file mode 100644 index 0000000000..dea65bbaf2 --- /dev/null +++ b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch @@ -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; diff --git a/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch new file mode 100644 index 0000000000..e4ccac342f --- /dev/null +++ b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch @@ -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); diff --git a/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch new file mode 100644 index 0000000000..7deb19c344 --- /dev/null +++ b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch @@ -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_ */ diff --git a/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch new file mode 100644 index 0000000000..58db2b2996 --- /dev/null +++ b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch @@ -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 */ diff --git a/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch new file mode 100644 index 0000000000..a61a334f69 --- /dev/null +++ b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch @@ -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, diff --git a/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch new file mode 100644 index 0000000000..e758665118 --- /dev/null +++ b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch @@ -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; diff --git a/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch new file mode 100644 index 0000000000..5bd8833c80 --- /dev/null +++ b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch @@ -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) diff --git a/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch new file mode 100644 index 0000000000..cc79dd78cb --- /dev/null +++ b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch @@ -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, diff --git a/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch new file mode 100644 index 0000000000..b4ca9ca3ad --- /dev/null +++ b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch @@ -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; + diff --git a/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch new file mode 100644 index 0000000000..ea79b1a6f0 --- /dev/null +++ b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch @@ -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) + { diff --git a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch index 57a894d802..3c5e9f5fcd 100644 --- a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch +++ b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c -@@ -693,7 +693,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw +@@ -695,7 +695,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw { #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ struct ath_common *common = ath9k_hw_common(ah); @@ -9,7 +9,7 @@ int i; /* Enable access to the DMA observation bus */ -@@ -723,6 +723,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw +@@ -725,6 +725,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw } if (i == 0) { diff --git a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch index 6a7a77312d..af35560a15 100644 --- a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch @@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com> --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -1843,6 +1843,16 @@ int ath10k_core_register(struct ath10k * +@@ -1844,6 +1844,16 @@ int ath10k_core_register(struct ath10k * ar->chip_id = chip_id; queue_work(ar->workqueue, &ar->register_work); diff --git a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch index c957b09b58..f2718c78c9 100644 --- a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -7085,6 +7085,21 @@ struct ath10k_vif *ath10k_get_arvif(stru +@@ -7092,6 +7092,21 @@ struct ath10k_vif *ath10k_get_arvif(stru return arvif_iter.arvif; } @@ -22,7 +22,7 @@ int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { -@@ -7310,6 +7325,12 @@ int ath10k_mac_register(struct ath10k *a +@@ -7317,6 +7332,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->wiphy->cipher_suites = cipher_suites; ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |