diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 8b399f4b4ce4ee..7506dfcc8de039 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -1,158 +1,78 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -723,6 +723,7 @@ struct ath_spec_scan { - * @config_pci_powersave: - * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC - * -+ * @get_adc_entropy: get entropy from the raw ADC I/Q output - * @spectral_scan_config: set parameters for spectral scan and enable/disable it - * @spectral_scan_trigger: trigger a spectral scan run - * @spectral_scan_wait: wait for a spectral scan run to finish -@@ -745,6 +746,7 @@ struct ath_hw_ops { - struct ath_hw_antcomb_conf *antconf); - void (*antdiv_comb_conf_set)(struct ath_hw *ah, - struct ath_hw_antcomb_conf *antconf); -+ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); - void (*spectral_scan_config)(struct ath_hw *ah, - struct ath_spec_scan *param); - void (*spectral_scan_trigger)(struct ath_hw *ah); ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -1918,6 +1918,26 @@ void ar9003_hw_init_rate_txpower(struct +From 82880c4a6224f9e537d106b3bfe079c792bd9f09 Mon Sep 17 00:00:00 2001 +From: Rui Salvaterra +Date: Wed, 28 Oct 2020 14:02:43 +0000 +Subject: [PATCH] ath9k: implement ADC entropy collection for older generations + +Signed-off-by: Rui Salvaterra +--- + drivers/net/wireless/ath/ath9k/ar5008_phy.c | 34 +++++++++++++++++++++ + drivers/net/wireless/ath/ath9k/ar9002_phy.h | 13 +++++++- + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 32 +++++++++++++++++++ + drivers/net/wireless/ath/ath9k/hw.h | 5 +++ + drivers/net/wireless/ath/ath9k/rng.c | 34 ++++++--------------- + 5 files changed, 92 insertions(+), 26 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1340,9 +1340,38 @@ void ar5008_hw_init_rate_txpower(struct } } -+static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++static int __maybe_unused ++ar5008_hw_get_adc_entropy(struct ath_hw *ah, u32 *buf, const u32 buf_size, u32 *rng_last) +{ + int i, j; ++ u32 v1, v2, last = *rng_last; + + REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1); + REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5); -+ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0); -+ -+ memset(buf, 0, len); -+ for (i = 0; i < len; i++) { -+ for (j = 0; j < 4; j++) { -+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); -+ -+ buf[i] <<= 2; -+ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); -+ udelay(1); -+ } -+ } -+} -+ - void ar9003_hw_attach_phy_ops(struct ath_hw *ah) - { - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); -@@ -1954,6 +1974,7 @@ void ar9003_hw_attach_phy_ops(struct ath - priv_ops->set_radar_params = ar9003_hw_set_radar_params; - priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; - -+ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; - ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; - ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; - ops->spectral_scan_config = ar9003_hw_spectral_scan_config; ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -871,7 +871,8 @@ static void ath9k_init_txpower_limits(st - if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); - -- ah->curchan = curchan; -+ if (curchan) -+ ah->curchan = curchan; - } - - static const struct ieee80211_iface_limit if_limits[] = { -@@ -1049,6 +1050,18 @@ static void ath9k_set_hw_capab(struct at - wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); - } - -+static void ath_get_initial_entropy(struct ath_softc *sc) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ char buf[256]; -+ -+ /* reuse last channel initialized by the tx power test */ -+ ath9k_hw_reset(ah, ah->curchan, NULL, false); -+ -+ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); -+ add_device_randomness(buf, sizeof(buf)); -+} -+ - int ath9k_init_device(u16 devid, struct ath_softc *sc, - const struct ath_bus_ops *bus_ops) - { -@@ -1096,6 +1109,8 @@ int ath9k_init_device(u16 devid, struct - - wiphy_read_of_freq_limits(hw->wiphy); - -+ ath_get_initial_entropy(sc); ++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); + - /* Register with mac80211 */ - error = ieee80211_register_hw(hw); - if (error) ---- a/drivers/net/wireless/ath/ath9k/hw-ops.h -+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h -@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp - ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); - } - -+static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, -+ u8 *buf, size_t len) -+{ -+ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); -+} ++ for (i = 0, j = 0; i < buf_size; i++) { ++ v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; ++ v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; + - #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT - - static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -1340,9 +1340,30 @@ void ar5008_hw_init_rate_txpower(struct - } - } - -+static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) -+{ -+ int i, j; ++ /* wait for data ready */ ++ if (v1 && v2 && last != v1 && v1 != v2 && v1 != 0xffff && ++ v2 != 0xffff) ++ buf[j++] = (v1 << 16) | v2; + -+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); -+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); -+ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); ++ last = v2; ++ } + -+ memset(buf, 0, len); -+ for (i = 0; i < len; i++) { -+ for (j = 0; j < 4; j++) { -+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ *rng_last = last; + -+ buf[i] <<= 2; -+ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); -+ udelay(1); -+ } -+ } ++ return j << 2; +} + int ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); -+ struct ath_hw_ops *ops = ath9k_hw_ops(ah); ++ struct ath_hw_ops *ops __maybe_unused; ++ static const u32 ar5416_cca_regs[6] = { AR_PHY_CCA, AR_PHY_CH1_CCA, -@@ -1357,6 +1378,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ +@@ -1357,6 +1386,11 @@ int ar5008_hw_attach_phy_ops(struct ath_ if (ret) return ret; ++#ifdef CONFIG_ATH9K_HWRNG ++ ops = ath9k_hw_ops(ah); + ops->get_adc_entropy = ar5008_hw_get_adc_entropy; ++#endif + priv_ops->rf_set_freq = ar5008_hw_set_channel; priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h -@@ -20,6 +20,12 @@ +@@ -16,10 +16,16 @@ + #ifndef AR9002_PHY_H + #define AR9002_PHY_H + +-#define AR_PHY_TEST 0x9800 ++#define AR_PHY_TEST(_ah) 0x9800 #define PHY_AGC_CLR 0x10000000 #define RFSILENT_BB 0x00002000 @@ -184,3 +104,136 @@ #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1918,6 +1918,33 @@ void ar9003_hw_init_rate_txpower(struct + } + } + ++static int __maybe_unused ++ar9003_hw_get_adc_entropy(struct ath_hw *ah, u32 *buf, const u32 buf_size, u32 *rng_last) ++{ ++ int i, j; ++ u32 v1, v2, last = *rng_last; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0); ++ ++ for (i = 0, j = 0; i < buf_size; i++) { ++ v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; ++ v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; ++ ++ /* wait for data ready */ ++ if (v1 && v2 && last != v1 && v1 != v2 && v1 != 0xffff && ++ v2 != 0xffff) ++ buf[j++] = (v1 << 16) | v2; ++ ++ last = v2; ++ } ++ ++ *rng_last = last; ++ ++ return j << 2; ++} ++ + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -1963,6 +1990,11 @@ void ar9003_hw_attach_phy_ops(struct ath + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; + #endif ++ ++#ifdef CONFIG_ATH9K_HWRNG ++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; ++#endif ++ + ops->tx99_start = ar9003_hw_tx99_start; + ops->tx99_stop = ar9003_hw_tx99_stop; + ops->tx99_set_txpower = ar9003_hw_tx99_set_txpower; +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -726,6 +726,7 @@ struct ath_spec_scan { + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish ++ * @get_adc_entropy: get entropy from the raw ADC I/Q output + */ + struct ath_hw_ops { + void (*config_pci_powersave)(struct ath_hw *ah, +@@ -757,6 +758,10 @@ struct ath_hw_ops { + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); + #endif ++ ++#ifdef CONFIG_ATH9K_HWRNG ++ int (*get_adc_entropy)(struct ath_hw *ah, u32 *buf, const u32 buf_size, u32 *rng_last); ++#endif + }; + + struct ath_nf_limits { +--- a/drivers/net/wireless/ath/ath9k/rng.c ++++ b/drivers/net/wireless/ath/ath9k/rng.c +@@ -19,37 +19,25 @@ + + #include "ath9k.h" + #include "hw.h" +-#include "ar9003_phy.h" ++ ++static inline int ath9k_hw_get_adc_entropy(struct ath_hw *ah, ++ u32 *buf, const u32 buf_size, u32 *rng_last) ++{ ++ return ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, buf_size, rng_last); ++} + + static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) + { +- int i, j; +- u32 v1, v2, rng_last = sc->rng_last; + struct ath_hw *ah = sc->sc_ah; ++ int bytes_read; + + ath9k_ps_wakeup(sc); + +- REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1); +- REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5); +- REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0); +- +- for (i = 0, j = 0; i < buf_size; i++) { +- v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; +- v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; +- +- /* wait for data ready */ +- if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff && +- v2 != 0xffff) +- buf[j++] = (v1 << 16) | v2; +- +- rng_last = v2; +- } ++ bytes_read = ath9k_hw_get_adc_entropy(ah, buf, buf_size, &sc->rng_last); + + ath9k_ps_restore(sc); + +- sc->rng_last = rng_last; +- +- return j << 2; ++ return bytes_read; + } + + static u32 ath9k_rng_delay_get(u32 fail_stats) +@@ -95,14 +83,10 @@ static int ath9k_rng_read(struct hwrng * + void ath9k_rng_start(struct ath_softc *sc) + { + static atomic_t serial = ATOMIC_INIT(0); +- struct ath_hw *ah = sc->sc_ah; + + if (sc->rng_ops.read) + return; + +- if (!AR_SREV_9300_20_OR_LATER(ah)) +- return; +- + snprintf(sc->rng_name, sizeof(sc->rng_name), "ath9k_%u", + (atomic_inc_return(&serial) - 1) & U16_MAX); + sc->rng_ops.name = sc->rng_name;