aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
diff options
context:
space:
mode:
authorMartin Blumenstingl <martin.blumenstingl@googlemail.com>2016-11-26 01:01:13 +0100
committerMathias Kresin <dev@kresin.me>2016-11-29 21:40:16 +0100
commit3f889418a504b9c5d5781c2248bc3b3dc515ff03 (patch)
tree29af20d775cb4717ac325764fd70def3d3cfd2ce /package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
parent1847248fc1560d10cb49c88b343598c9cb673f38 (diff)
downloadupstream-3f889418a504b9c5d5781c2248bc3b3dc515ff03.tar.gz
upstream-3f889418a504b9c5d5781c2248bc3b3dc515ff03.tar.bz2
upstream-3f889418a504b9c5d5781c2248bc3b3dc515ff03.zip
kernel: mac80211: add pending ath9k EEPROM swapping patches
There are two types of swapping the EEPROM data in the ath9k driver. Before this series one type of swapping could not be used without the other. The first type of swapping looks at the "magic bytes" at the start of the EEPROM data and performs swab16 on the EEPROM contents if needed. The second type of swapping is EEPROM format specific and swaps specific fields within the EEPROM itself (swab16, swab32 - depends on the EEPROM format). With this series the second part now looks at the EEPMISC register inside the EEPROM, which uses a bit to indicate if the EEPROM data is Big Endian (this is also done by the FreeBSD kernel). This has a nice advantage: currently there are some out-of-tree hacks (in OpenWrt and LEDE) where the EEPROM has a Big Endian header on a Big Endian system (= no swab16 is performed) but the EEPROM itself indicates that it's data is Little Endian. Until now the out-of-tree code simply did a swab16 before passing the data to ath9k, so ath9k first did the swab16 - this also enabled the format specific swapping. These out-of-tree hacks are still working with the new logic, but it is recommended to remove them. This implementation is based on a discussion with Arnd Bergmann who raised concerns about the robustness and portability of the swapping logic in the original OF support patch review, see [0]. After a second round of patches (= v1 of this series) neither Arnd Bergmann nor I were really happy with the complexity of the EEPROM swapping logic. Based on a discussion (see [1] and [2]) we decided that ath9k should use a defined format (specifying the endianness of the data - I went with __le16 and __le32) when accessing the EEPROM fields. A benefit of this is that we enable the EEPMISC based swapping logic by default, just like the FreeBSD driver, see [3]. On the devices which I have tested (see below) ath9k now works without having to specify the "endian_check" field in ath9k_platform_data (or a similar logic which could provide this via devicetree) as ath9k now detects the endianness automatically. Only EEPROMs which are mangled by some out-of-tree code still need the endian_check flag (or one can simply remove that mangling from the out-of-tree code). [0] http://www.spinics.net/lists/linux-wireless/msg152634.html [1] https://marc.info/?l=linux-wireless&m=147250597503174&w=2 [2] https://marc.info/?l=linux-wireless&m=147254388611344&w=2 [3] https://github.com/freebsd/freebsd/blob/50719b56d9ce8d7d4beb53b16e9edb2e9a4a7a18/sys/dev/ath/ath_hal/ah_eeprom_9287.c#L351 Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Diffstat (limited to 'package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch')
-rw-r--r--package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch342
1 files changed, 342 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch b/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
new file mode 100644
index 0000000000..64e70467a3
--- /dev/null
+++ b/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
@@ -0,0 +1,342 @@
+From c763af71bcc2f01bd5ef6e65c7c34b46c7235a16 Mon Sep 17 00:00:00 2001
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Date: Mon, 3 Oct 2016 00:29:11 +0200
+Subject: [v2 PATCH 5/7] ath9k: consistently use get_eeprom_rev(ah)
+
+The AR5416_VER_MASK macro does the same as get_eeprom_rev, except that
+one has to know the actual EEPROM type (and providing a reference to
+that in a variable named "eep"). Additionally the eeprom_*.c
+implementations used the same shifting logic multiple times to get the
+eeprom revision which was also unnecessary duplication of
+get_eeprom_rev.
+
+Also use the AR5416_EEP_VER_MINOR_MASK macro where needed and introduce
+a similar macro (AR5416_EEP_VER_MAJOR_MASK) for the major version.
+Finally drop AR9287_EEP_VER_MINOR_MASK since it simply duplicates the
+already defined AR5416_EEP_VER_MINOR_MASK.
+
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+---
+ drivers/net/wireless/ath/ath9k/eeprom.h | 4 +--
+ drivers/net/wireless/ath/ath9k/eeprom_4k.c | 32 ++++++++++------------
+ drivers/net/wireless/ath/ath9k/eeprom_9287.c | 19 +++++++------
+ drivers/net/wireless/ath/ath9k/eeprom_def.c | 41 +++++++++++++++-------------
+ drivers/net/wireless/ath/ath9k/xmit.c | 3 +-
+ 5 files changed, 52 insertions(+), 47 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/eeprom.h
+@@ -99,7 +99,6 @@
+ #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
+ #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
+
+-#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
+ #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
+ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+ #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
+@@ -121,6 +120,8 @@
+
+ #define AR5416_EEP_NO_BACK_VER 0x1
+ #define AR5416_EEP_VER 0xE
++#define AR5416_EEP_VER_MAJOR_SHIFT 12
++#define AR5416_EEP_VER_MAJOR_MASK 0xF000
+ #define AR5416_EEP_VER_MINOR_MASK 0x0FFF
+ #define AR5416_EEP_MINOR_VER_2 0x2
+ #define AR5416_EEP_MINOR_VER_3 0x3
+@@ -177,7 +178,6 @@
+ #define AR9280_TX_GAIN_TABLE_SIZE 22
+
+ #define AR9287_EEP_VER 0xE
+-#define AR9287_EEP_VER_MINOR_MASK 0xFFF
+ #define AR9287_EEP_MINOR_VER_1 0x1
+ #define AR9287_EEP_MINOR_VER_2 0x2
+ #define AR9287_EEP_MINOR_VER_3 0x3
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -20,12 +20,17 @@
+
+ static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
+ {
+- return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
++ u16 version = ah->eeprom.map4k.baseEepHeader.version;
++
++ return (version & AR5416_EEP_VER_MAJOR_MASK) >>
++ AR5416_EEP_VER_MAJOR_SHIFT;
+ }
+
+ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
+ {
+- return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
++ u16 version = ah->eeprom.map4k.baseEepHeader.version;
++
++ return version & AR5416_EEP_VER_MINOR_MASK;
+ }
+
+ #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+@@ -136,8 +141,8 @@ static u32 ath9k_hw_4k_dump_eeprom(struc
+ goto out;
+ }
+
+- PR_EEP("Major Version", pBase->version >> 12);
+- PR_EEP("Minor Version", pBase->version & 0xFFF);
++ PR_EEP("Major Version", ath9k_hw_4k_get_eeprom_ver(ah));
++ PR_EEP("Minor Version", ath9k_hw_4k_get_eeprom_rev(ah));
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+@@ -314,14 +319,12 @@ static void ath9k_hw_set_4k_power_cal_ta
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
+ pdGainOverlap_t2 =
+ pEepData->modalHeader.pdGainOverlap;
+- } else {
++ else
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+- }
+
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
+@@ -607,10 +610,8 @@ static void ath9k_hw_4k_set_txpower(stru
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+- }
+
+ ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+@@ -730,8 +731,7 @@ static void ath9k_hw_4k_set_gain(struct
+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF);
+
+- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_3) {
++ if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[0];
+
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+@@ -1009,16 +1009,14 @@ static void ath9k_hw_4k_set_board_values
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+
+- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_3) {
++ if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -22,12 +22,17 @@
+
+ static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
+ {
+- return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
++ u16 version = ah->eeprom.map9287.baseEepHeader.version;
++
++ return (version & AR5416_EEP_VER_MAJOR_MASK) >>
++ AR5416_EEP_VER_MAJOR_SHIFT;
+ }
+
+ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
+ {
+- return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
++ u16 version = ah->eeprom.map9287.baseEepHeader.version;
++
++ return version & AR5416_EEP_VER_MINOR_MASK;
+ }
+
+ static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+@@ -132,8 +137,8 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s
+ goto out;
+ }
+
+- PR_EEP("Major Version", pBase->version >> 12);
+- PR_EEP("Minor Version", pBase->version & 0xFFF);
++ PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah));
++ PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah));
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+@@ -383,8 +388,7 @@ static void ath9k_hw_set_ar9287_power_ca
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+- if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+- AR9287_EEP_MINOR_VER_2)
++ if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
+ pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
+ else
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+@@ -733,8 +737,7 @@ static void ath9k_hw_ar9287_set_txpower(
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+- if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+- AR9287_EEP_MINOR_VER_2)
++ if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+
+ ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -79,12 +79,17 @@ static void ath9k_olc_get_pdadcs(struct
+
+ static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
+ {
+- return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
++ u16 version = ah->eeprom.def.baseEepHeader.version;
++
++ return (version & AR5416_EEP_VER_MAJOR_MASK) >>
++ AR5416_EEP_VER_MAJOR_SHIFT;
+ }
+
+ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
+ {
+- return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
++ u16 version = ah->eeprom.def.baseEepHeader.version;
++
++ return version & AR5416_EEP_VER_MINOR_MASK;
+ }
+
+ #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+@@ -214,8 +219,8 @@ static u32 ath9k_hw_def_dump_eeprom(stru
+ goto out;
+ }
+
+- PR_EEP("Major Version", pBase->version >> 12);
+- PR_EEP("Minor Version", pBase->version & 0xFFF);
++ PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah));
++ PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah));
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+@@ -391,27 +396,27 @@ static u32 ath9k_hw_def_get_eeprom(struc
+ case EEP_TXGAIN_TYPE:
+ return pBase->txGainType;
+ case EEP_OL_PWRCTRL:
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
+ return pBase->openLoopPwrCntl ? true : false;
+ else
+ return false;
+ case EEP_RC_CHAIN_MASK:
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
+ return pBase->rcChainMask;
+ else
+ return 0;
+ case EEP_DAC_HPWR_5G:
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20)
+ return pBase->dacHiPwrMode_5G;
+ else
+ return 0;
+ case EEP_FRAC_N_5G:
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_22)
+ return pBase->frac_n_5g;
+ else
+ return 0;
+ case EEP_PWR_TABLE_OFFSET:
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21)
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_21)
+ return pBase->pwr_table_offset;
+ else
+ return AR5416_PWR_TABLE_OFFSET_DB;
+@@ -434,7 +439,7 @@ static void ath9k_hw_def_set_gain(struct
+ u8 txRxAttenLocal, int regChainOffset, int i)
+ {
+ ENABLE_REG_RMW_BUFFER(ah);
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+@@ -603,7 +608,7 @@ static void ath9k_hw_def_set_board_value
+ pModal->thresh62);
+ }
+
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+@@ -611,7 +616,7 @@ static void ath9k_hw_def_set_board_value
+ pModal->txFrameToPaOn);
+ }
+
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+@@ -619,13 +624,14 @@ static void ath9k_hw_def_set_board_value
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
+- AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
++ ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
+ REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
+ AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+ pModal->miscBits);
+
+
+- if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
++ if (AR_SREV_9280_20(ah) &&
++ ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) {
+ if (IS_CHAN_2GHZ(chan))
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+ eep->baseEepHeader.dacLpMode);
+@@ -796,8 +802,7 @@ static void ath9k_hw_set_def_power_cal_t
+
+ pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
+
+- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader[modalIdx].pdGainOverlap;
+ } else {
+@@ -1169,10 +1174,8 @@ static void ath9k_hw_def_set_txpower(str
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- AR5416_EEP_MINOR_VER_2) {
++ if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+- }
+
+ ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1177,8 +1177,9 @@ static u8 ath_get_rate_txpower(struct at
+ if (is_40) {
+ u8 power_ht40delta;
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
++ u16 eeprom_rev = ah->eep_ops->get_eeprom_rev(ah);
+
+- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
++ if (eeprom_rev >= AR5416_EEP_MINOR_VER_2) {
+ bool is_2ghz;
+ struct modal_eep_header *pmodal;
+