From: Martin Blumenstingl Date: Sat, 26 Nov 2016 00:01:13 +0000 (+0100) Subject: kernel: mac80211: add pending ath9k EEPROM swapping patches X-Git-Tag: v17.01.0-rc1~685 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=3f889418a504b9c5d5781c2248bc3b3dc515ff03;p=openwrt%2Fstaging%2Fchunkeey.git 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 --- diff --git a/package/kernel/mac80211/patches/550-ath9k-Add-a-define-for-the-EEPROM-eepmisc-endianness.patch b/package/kernel/mac80211/patches/550-ath9k-Add-a-define-for-the-EEPROM-eepmisc-endianness.patch new file mode 100644 index 0000000000..a17f95682f --- /dev/null +++ b/package/kernel/mac80211/patches/550-ath9k-Add-a-define-for-the-EEPROM-eepmisc-endianness.patch @@ -0,0 +1,95 @@ +From 9692ab1ff30ae0abc1000d11b2f929b6e2e4cb7f Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:07 +0200 +Subject: [v2 PATCH 1/7] ath9k: Add a #define for the EEPROM "eepmisc" endianness + bit + +This replaces a magic number with a named #define. Additionally it +removes two "eeprom format" specific #defines for the "big endianness" +bit which are the same on all eeprom formats. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 ++- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 1 - + drivers/net/wireless/ath/ath9k/eeprom.h | 4 +++- + drivers/net/wireless/ath/ath9k/eeprom_4k.c | 2 +- + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 2 +- + drivers/net/wireless/ath/ath9k/eeprom_def.c | 2 +- + 6 files changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -3468,7 +3468,8 @@ static u32 ath9k_hw_ar9003_dump_eeprom(s + AR5416_OPFLAGS_N_5G_HT20)); + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags & + AR5416_OPFLAGS_N_5G_HT40)); +- PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01)); ++ PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & ++ AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("RF Silent", pBase->rfSilent); + PR_EEP("BT option", pBase->blueToothOptions); + PR_EEP("Device Cap", pBase->deviceCap); +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +@@ -38,7 +38,6 @@ + #define AR9300_NUM_CTLS_2G 12 + #define AR9300_NUM_BAND_EDGES_5G 8 + #define AR9300_NUM_BAND_EDGES_2G 4 +-#define AR9300_EEPMISC_BIG_ENDIAN 0x01 + #define AR9300_EEPMISC_WOW 0x02 + #define AR9300_CUSTOMER_DATA_SIZE 20 + +--- a/drivers/net/wireless/ath/ath9k/eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/eeprom.h +@@ -161,6 +161,9 @@ + #define AR5416_EEP_TXGAIN_ORIGINAL 0 + #define AR5416_EEP_TXGAIN_HIGH_POWER 1 + ++/* Endianness of EEPROM content */ ++#define AR5416_EEPMISC_BIG_ENDIAN 0x01 ++ + #define AR5416_EEP4K_START_LOC 64 + #define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 + #define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 +@@ -191,7 +194,6 @@ + #define AR9287_NUM_CTLS 12 + #define AR9287_NUM_BAND_EDGES 4 + #define AR9287_PD_GAIN_ICEPTS 1 +-#define AR9287_EEPMISC_BIG_ENDIAN 0x01 + #define AR9287_EEPMISC_WOW 0x02 + #define AR9287_MAX_CHAINS 2 + #define AR9287_ANT_16S 32 +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -154,7 +154,7 @@ static u32 ath9k_hw_4k_dump_eeprom(struc + AR5416_OPFLAGS_N_5G_HT20)); + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); +- PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); ++ PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -150,7 +150,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s + AR5416_OPFLAGS_N_5G_HT20)); + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); +- PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); ++ PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -232,7 +232,7 @@ static u32 ath9k_hw_def_dump_eeprom(stru + AR5416_OPFLAGS_N_5G_HT20)); + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); +- PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); ++ PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); diff --git a/package/kernel/mac80211/patches/551-ath9k-indicate-that-the-AR9003-EEPROM-template-value.patch b/package/kernel/mac80211/patches/551-ath9k-indicate-that-the-AR9003-EEPROM-template-value.patch new file mode 100644 index 0000000000..a4a3595531 --- /dev/null +++ b/package/kernel/mac80211/patches/551-ath9k-indicate-that-the-AR9003-EEPROM-template-value.patch @@ -0,0 +1,78 @@ +From e88ab4a2649d0fbf675193fb2c176f65375bdd2d Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:08 +0200 +Subject: [v2 PATCH 2/7] ath9k: indicate that the AR9003 EEPROM template values + are little endian + +The eepMisc field was not set explicitly. The default value of 0 means +that the values in the EEPROM (template) should be interpreted as little +endian. However, this is not clear until comparing the AR9003 code with +the other EEPROM formats. +To make the code easier to understand we explicitly state that the values +are little endian - there are no functional changes with this patch. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 10 +++++----- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 3 +++ + 2 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -53,7 +53,7 @@ static const struct ar9300_eeprom ar9300 + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, +- .eepMisc = 0, ++ .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, + }, + .rfSilent = 0, + .blueToothOptions = 0, +@@ -631,7 +631,7 @@ static const struct ar9300_eeprom ar9300 + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11A, +- .eepMisc = 0, ++ .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, + }, + .rfSilent = 0, + .blueToothOptions = 0, +@@ -1210,7 +1210,7 @@ static const struct ar9300_eeprom ar9300 + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, +- .eepMisc = 0, ++ .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, + }, + .rfSilent = 0, + .blueToothOptions = 0, +@@ -1789,7 +1789,7 @@ static const struct ar9300_eeprom ar9300 + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, +- .eepMisc = 0, ++ .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, + }, + .rfSilent = 0, + .blueToothOptions = 0, +@@ -2367,7 +2367,7 @@ static const struct ar9300_eeprom ar9300 + .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, +- .eepMisc = 0, ++ .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, + }, + .rfSilent = 0, + .blueToothOptions = 0, +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +@@ -69,6 +69,9 @@ + #define AR9300_BASE_ADDR 0x3ff + #define AR9300_BASE_ADDR_512 0x1ff + ++/* AR5416_EEPMISC_BIG_ENDIAN not set indicates little endian */ ++#define AR9300_EEPMISC_LITTLE_ENDIAN 0 ++ + #define AR9300_OTP_BASE \ + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) + #define AR9300_OTP_STATUS \ diff --git a/package/kernel/mac80211/patches/552-ath9k-Add-an-eeprom_ops-callback-for-retrieving-the-.patch b/package/kernel/mac80211/patches/552-ath9k-Add-an-eeprom_ops-callback-for-retrieving-the-.patch new file mode 100644 index 0000000000..1b4dd3d134 --- /dev/null +++ b/package/kernel/mac80211/patches/552-ath9k-Add-an-eeprom_ops-callback-for-retrieving-the-.patch @@ -0,0 +1,117 @@ +From e8f60fa28e619ad238457ac84fb292541be180d3 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:09 +0200 +Subject: [v2 PATCH 3/7] ath9k: Add an eeprom_ops callback for retrieving the + eepmisc value + +This allows deciding if we have to swap the EEPROM data (so it matches +the system's native endianness) even if no byte-swapping (swab16, based on +the first two bytes in the EEPROM) is needed. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 8 +++++++- + drivers/net/wireless/ath/ath9k/eeprom.h | 1 + + drivers/net/wireless/ath/ath9k/eeprom_4k.c | 8 +++++++- + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 8 +++++++- + drivers/net/wireless/ath/ath9k/eeprom_def.c | 8 +++++++- + 5 files changed, 29 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -5498,6 +5498,11 @@ unsigned int ar9003_get_paprd_scale_fact + } + } + ++static u8 ar9003_get_eepmisc(struct ath_hw *ah) ++{ ++ return ah->eeprom.map4k.baseEepHeader.eepMisc; ++} ++ + const struct eeprom_ops eep_ar9300_ops = { + .check_eeprom = ath9k_hw_ar9300_check_eeprom, + .get_eeprom = ath9k_hw_ar9300_get_eeprom, +@@ -5508,5 +5513,6 @@ const struct eeprom_ops eep_ar9300_ops = + .set_board_values = ath9k_hw_ar9300_set_board_values, + .set_addac = ath9k_hw_ar9300_set_addac, + .set_txpower = ath9k_hw_ar9300_set_txpower, +- .get_spur_channel = ath9k_hw_ar9300_get_spur_channel ++ .get_spur_channel = ath9k_hw_ar9300_get_spur_channel, ++ .get_eepmisc = ar9003_get_eepmisc + }; +--- a/drivers/net/wireless/ath/ath9k/eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/eeprom.h +@@ -655,6 +655,7 @@ struct eeprom_ops { + u16 cfgCtl, u8 twiceAntennaReduction, + u8 powerLimit, bool test); + u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); ++ u8 (*get_eepmisc)(struct ath_hw *ah); + }; + + void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val); +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -1064,6 +1064,11 @@ static u16 ath9k_hw_4k_get_spur_channel( + return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan; + } + ++static u8 ath9k_hw_4k_get_eepmisc(struct ath_hw *ah) ++{ ++ return ah->eeprom.map4k.baseEepHeader.eepMisc; ++} ++ + const struct eeprom_ops eep_4k_ops = { + .check_eeprom = ath9k_hw_4k_check_eeprom, + .get_eeprom = ath9k_hw_4k_get_eeprom, +@@ -1073,5 +1078,6 @@ const struct eeprom_ops eep_4k_ops = { + .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, + .set_board_values = ath9k_hw_4k_set_board_values, + .set_txpower = ath9k_hw_4k_set_txpower, +- .get_spur_channel = ath9k_hw_4k_get_spur_channel ++ .get_spur_channel = ath9k_hw_4k_get_spur_channel, ++ .get_eepmisc = ath9k_hw_4k_get_eepmisc + }; +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -986,6 +986,11 @@ static u16 ath9k_hw_ar9287_get_spur_chan + return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; + } + ++static u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah) ++{ ++ return ah->eeprom.map9287.baseEepHeader.eepMisc; ++} ++ + const struct eeprom_ops eep_ar9287_ops = { + .check_eeprom = ath9k_hw_ar9287_check_eeprom, + .get_eeprom = ath9k_hw_ar9287_get_eeprom, +@@ -995,5 +1000,6 @@ const struct eeprom_ops eep_ar9287_ops = + .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, + .set_board_values = ath9k_hw_ar9287_set_board_values, + .set_txpower = ath9k_hw_ar9287_set_txpower, +- .get_spur_channel = ath9k_hw_ar9287_get_spur_channel ++ .get_spur_channel = ath9k_hw_ar9287_get_spur_channel, ++ .get_eepmisc = ath9k_hw_ar9287_get_eepmisc + }; +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -1317,6 +1317,11 @@ static u16 ath9k_hw_def_get_spur_channel + return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; + } + ++static u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah) ++{ ++ return ah->eeprom.def.baseEepHeader.eepMisc; ++} ++ + const struct eeprom_ops eep_def_ops = { + .check_eeprom = ath9k_hw_def_check_eeprom, + .get_eeprom = ath9k_hw_def_get_eeprom, +@@ -1327,5 +1332,6 @@ const struct eeprom_ops eep_def_ops = { + .set_board_values = ath9k_hw_def_set_board_values, + .set_addac = ath9k_hw_def_set_addac, + .set_txpower = ath9k_hw_def_set_txpower, +- .get_spur_channel = ath9k_hw_def_get_spur_channel ++ .get_spur_channel = ath9k_hw_def_get_spur_channel, ++ .get_eepmisc = ath9k_hw_def_get_eepmisc + }; diff --git a/package/kernel/mac80211/patches/553-ath9k-replace-eeprom_param-EEP_MINOR_REV-with-get_ee.patch b/package/kernel/mac80211/patches/553-ath9k-replace-eeprom_param-EEP_MINOR_REV-with-get_ee.patch new file mode 100644 index 0000000000..277aa6f61c --- /dev/null +++ b/package/kernel/mac80211/patches/553-ath9k-replace-eeprom_param-EEP_MINOR_REV-with-get_ee.patch @@ -0,0 +1,117 @@ +From 9f247f908d5166e16e1cc6a50b0901e0f6733410 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:10 +0200 +Subject: [v2 PATCH 4/7] ath9k: replace eeprom_param EEP_MINOR_REV with + get_eeprom_rev + +get_eeprom(ah, EEP_MINOR_REV) and get_eeprom_rev(ah) are both doing the +same thing: returning the EEPROM revision (12 lowest bits). Make the +code consistent by using get_eeprom_rev(ah) everywhere. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/ar5008_phy.c | 2 +- + drivers/net/wireless/ath/ath9k/ar9002_hw.c | 6 ++---- + drivers/net/wireless/ath/ath9k/eeprom.h | 1 - + drivers/net/wireless/ath/ath9k/eeprom_4k.c | 5 ----- + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 6 +----- + drivers/net/wireless/ath/ath9k/eeprom_def.c | 2 -- + 6 files changed, 4 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -524,7 +524,7 @@ static bool ar5008_hw_set_rf_regs(struct + return true; + + /* Setup rf parameters */ +- eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); ++ eepMinorRev = ah->eep_ops->get_eeprom_rev(ah); + + for (i = 0; i < ah->iniBank6.ia_rows; i++) + ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex); +--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c +@@ -108,8 +108,7 @@ static void ar9280_20_hw_init_rxgain_ini + { + u32 rxgain_type; + +- if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= +- AR5416_EEP_MINOR_VER_17) { ++ if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) { + rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); + + if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) +@@ -129,8 +128,7 @@ static void ar9280_20_hw_init_rxgain_ini + + static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) + { +- if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= +- AR5416_EEP_MINOR_VER_19) { ++ if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) { + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_high_power_tx_gain_9280_2); +--- a/drivers/net/wireless/ath/ath9k/eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/eeprom.h +@@ -230,7 +230,6 @@ enum eeprom_param { + EEP_DB_5, + EEP_OB_2, + EEP_DB_2, +- EEP_MINOR_REV, + EEP_TX_MASK, + EEP_RX_MASK, + EEP_FSTCLK_5G, +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -254,9 +254,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + struct modal_eep_4k_header *pModal = &eep->modalHeader; + struct base_eep_header_4k *pBase = &eep->baseEepHeader; +- u16 ver_minor; +- +- ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK; + + switch (param) { + case EEP_NFTHRESH_2: +@@ -279,8 +276,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct + return pModal->ob_0; + case EEP_DB_2: + return pModal->db1_1; +- case EEP_MINOR_REV: +- return ver_minor; + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -250,9 +250,7 @@ static u32 ath9k_hw_ar9287_get_eeprom(st + struct ar9287_eeprom *eep = &ah->eeprom.map9287; + struct modal_eep_ar9287_header *pModal = &eep->modalHeader; + struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; +- u16 ver_minor; +- +- ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; ++ u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah); + + switch (param) { + case EEP_NFTHRESH_2: +@@ -271,8 +269,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(st + return pBase->opCapFlags; + case EEP_RF_SILENT: + return pBase->rfSilent; +- case EEP_MINOR_REV: +- return ver_minor; + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -380,8 +380,6 @@ static u32 ath9k_hw_def_get_eeprom(struc + return pModal[1].ob; + case EEP_DB_2: + return pModal[1].db; +- case EEP_MINOR_REV: +- return AR5416_VER_MASK; + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: 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 +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 +--- + 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; + diff --git a/package/kernel/mac80211/patches/555-ath9k-Make-the-EEPROM-swapping-check-use-the-eepmisc.patch b/package/kernel/mac80211/patches/555-ath9k-Make-the-EEPROM-swapping-check-use-the-eepmisc.patch new file mode 100644 index 0000000000..3e3c2ea7a3 --- /dev/null +++ b/package/kernel/mac80211/patches/555-ath9k-Make-the-EEPROM-swapping-check-use-the-eepmisc.patch @@ -0,0 +1,128 @@ +From 1f796f9265c10384a274ac330f671ef4ac6d56e5 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:12 +0200 +Subject: [v2 PATCH 6/7] ath9k: Make the EEPROM swapping check use the eepmisc + register + +There are two ways of swapping the EEPROM data in the ath9k driver: +1) swab16 based on the first two EEPROM "magic" bytes (same for all + EEPROM formats) +2) field and EEPROM format specific swab16/swab32 (different for + eeprom_def, eeprom_4k and eeprom_9287) + +The result of the first check was used to also enable the second swap. +This behavior seems incorrect, since the data may only be byte-swapped +(afterwards the data could be in the correct endianness). +Thus we introduce a separate check based on the "eepmisc" register +(which is part of the EEPROM data). When bit 0 is set, then the EEPROM +format specific values are in "big endian". This is also done by the +FreeBSD kernel, see [0] for example. + +This allows us to parse EEPROMs with the "correct" magic bytes but +swapped EEPROM format specific values. These EEPROMs (mostly found in +lantiq and broadcom based big endian MIPS based devices) only worked +due to platform specific "hacks" which swapped the EEPROM so the +magic was inverted, which also enabled the format specific swapping. +With this patch the old behavior is still supported, but neither +recommended nor needed anymore. + +[0] +https://github.com/freebsd/freebsd/blob/50719b56d9ce8d7d4beb53b16e9edb2e9a4a7a18/sys/dev/ath/ath_hal/ah_eeprom_9287.c#L351 + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/eeprom.c | 57 ++++++++++++++++++++++++--------- + 1 file changed, 41 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -155,11 +155,19 @@ bool ath9k_hw_nvram_read(struct ath_hw * + return ret; + } + ++#ifdef __BIG_ENDIAN ++#define EXPECTED_EEPMISC_ENDIAN AR5416_EEPMISC_BIG_ENDIAN ++#else ++#define EXPECTED_EEPMISC_ENDIAN 0 ++#endif ++ + int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) + { + u16 magic; + u16 *eepdata; ++ u8 eepmisc; + int i; ++ bool needs_byteswap = false; + struct ath_common *common = ath9k_hw_common(ah); + + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { +@@ -167,36 +175,53 @@ int ath9k_hw_nvram_swap_data(struct ath_ + return -EIO; + } + +- *swap_needed = false; + if (swab16(magic) == AR5416_EEPROM_MAGIC) { ++ needs_byteswap = true; ++ ath_dbg(common, EEPROM, ++ "EEPROM needs byte-swapping to correct endianness.\n"); ++ } else if (magic != AR5416_EEPROM_MAGIC) { ++ if (ath9k_hw_use_flash(ah)) { ++ ath_dbg(common, EEPROM, ++ "Ignoring invalid EEPROM magic (0x%04x).\n", ++ magic); ++ } else { ++ ath_err(common, ++ "Invalid EEPROM magic (0x%04x).\n", magic); ++ return -EINVAL; ++ } ++ } ++ ++ if (needs_byteswap) { + if (ah->ah_flags & AH_NO_EEP_SWAP) { + ath_info(common, + "Ignoring endianness difference in EEPROM magic bytes.\n"); + } else { +- *swap_needed = true; +- } +- } else if (magic != AR5416_EEPROM_MAGIC) { +- if (ath9k_hw_use_flash(ah)) +- return 0; ++ eepdata = (u16 *)(&ah->eeprom); + +- ath_err(common, +- "Invalid EEPROM Magic (0x%04x).\n", magic); +- return -EINVAL; ++ for (i = 0; i < size; i++) ++ eepdata[i] = swab16(eepdata[i]); ++ } + } + +- eepdata = (u16 *)(&ah->eeprom); +- +- if (*swap_needed) { +- ath_dbg(common, EEPROM, +- "EEPROM Endianness is not native.. Changing.\n"); ++ *swap_needed = false; + +- for (i = 0; i < size; i++) +- eepdata[i] = swab16(eepdata[i]); ++ eepmisc = ah->eep_ops->get_eepmisc(ah); ++ if ((eepmisc & AR5416_EEPMISC_BIG_ENDIAN) != EXPECTED_EEPMISC_ENDIAN) { ++ if (ah->ah_flags & AH_NO_EEP_SWAP) { ++ ath_info(common, ++ "Ignoring endianness difference in eepmisc register.\n"); ++ } else { ++ *swap_needed = true; ++ ath_dbg(common, EEPROM, ++ "EEPROM needs swapping according to the eepmisc register.\n"); ++ } + } + + return 0; + } + ++#undef EXPECTED_EEPMISC_VAL ++ + bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size) + { + u32 i, sum = 0; diff --git a/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch b/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch new file mode 100644 index 0000000000..04714f8169 --- /dev/null +++ b/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch @@ -0,0 +1,853 @@ +From 7e1047f3cf8dcdb4825f3c785f7f708d07508096 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Mon, 3 Oct 2016 00:29:13 +0200 +Subject: [v2 PATCH 7/7] ath9k: define all EEPROM fields in Little Endian format + +The ar9300_eeprom logic is already using only 8-bit (endian neutral), +__le16 and __le32 fields to state explicitly how the values should be +interpreted. +All other EEPROM implementations (4k, 9287 and def) were using u16 and +u32 fields with additional logic to swap the values (read from the +original EEPROM) so they match the current CPUs endianness. + +The EEPROM format defaults to "all values are Little Endian", indicated +by the absence of the AR5416_EEPMISC_BIG_ENDIAN in the u8 EEPMISC +register. If we detect that the EEPROM indicates Big Endian mode +(AR5416_EEPMISC_BIG_ENDIAN is set in the EEPMISC register) then we'll +swap the values to convert them into Little Endian. This is done by +activating the EEPMISC based logic in ath9k_hw_nvram_swap_data even if +AH_NO_EEP_SWAP is set (this makes ath9k behave like the FreeBSD driver, +which also does not have a flag to enable swapping based on the +AR5416_EEPMISC_BIG_ENDIAN bit). Before this logic was only used to +enable swapping when "current CPU endianness != EEPROM endianness". + +After changing all relevant fields to __le16 and __le32 sparse was used +to check that all code which reads any of these fields uses +le{16,32}_to_cpu. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/wireless/ath/ath9k/eeprom.c | 27 ++----- + drivers/net/wireless/ath/ath9k/eeprom.h | 75 ++++++++++-------- + drivers/net/wireless/ath/ath9k/eeprom_4k.c | 94 +++++++++------------- + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 98 ++++++++++------------- + drivers/net/wireless/ath/ath9k/eeprom_def.c | 114 ++++++++++++--------------- + 5 files changed, 174 insertions(+), 234 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -155,17 +155,10 @@ bool ath9k_hw_nvram_read(struct ath_hw * + return ret; + } + +-#ifdef __BIG_ENDIAN +-#define EXPECTED_EEPMISC_ENDIAN AR5416_EEPMISC_BIG_ENDIAN +-#else +-#define EXPECTED_EEPMISC_ENDIAN 0 +-#endif +- + int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) + { + u16 magic; + u16 *eepdata; +- u8 eepmisc; + int i; + bool needs_byteswap = false; + struct ath_common *common = ath9k_hw_common(ah); +@@ -203,25 +196,17 @@ int ath9k_hw_nvram_swap_data(struct ath_ + } + } + +- *swap_needed = false; +- +- eepmisc = ah->eep_ops->get_eepmisc(ah); +- if ((eepmisc & AR5416_EEPMISC_BIG_ENDIAN) != EXPECTED_EEPMISC_ENDIAN) { +- if (ah->ah_flags & AH_NO_EEP_SWAP) { +- ath_info(common, +- "Ignoring endianness difference in eepmisc register.\n"); +- } else { +- *swap_needed = true; +- ath_dbg(common, EEPROM, +- "EEPROM needs swapping according to the eepmisc register.\n"); +- } ++ if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) { ++ *swap_needed = true; ++ ath_dbg(common, EEPROM, ++ "Big Endian EEPROM detected according to EEPMISC register.\n"); ++ } else { ++ *swap_needed = false; + } + + return 0; + } + +-#undef EXPECTED_EEPMISC_VAL +- + bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size) + { + u32 i, sum = 0; +--- a/drivers/net/wireless/ath/ath9k/eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/eeprom.h +@@ -23,6 +23,17 @@ + #include + #include "ar9003_eeprom.h" + ++/* helpers to swap EEPROM fields, which are stored as __le16 or __le32. Since ++ * we are 100% sure about it we __force these to u16/u32 for the swab calls to ++ * silence the sparse checks. These macros are used when we have a Big Endian ++ * EEPROM (according to AR5416_EEPMISC_BIG_ENDIAN) and need to convert the ++ * fields to __le16/__le32. ++ */ ++#define EEPROM_FIELD_SWAB16(field) \ ++ (field = (__force __le16)swab16((__force u16)field)) ++#define EEPROM_FIELD_SWAB32(field) \ ++ (field = (__force __le32)swab32((__force u32)field)) ++ + #ifdef __BIG_ENDIAN + #define AR5416_EEPROM_MAGIC 0x5aa5 + #else +@@ -270,19 +281,19 @@ enum ath9k_hal_freq_band { + }; + + struct base_eep_header { +- u16 length; +- u16 checksum; +- u16 version; ++ __le16 length; ++ __le16 checksum; ++ __le16 version; + u8 opCapFlags; + u8 eepMisc; +- u16 regDmn[2]; ++ __le16 regDmn[2]; + u8 macAddr[6]; + u8 rxMask; + u8 txMask; +- u16 rfSilent; +- u16 blueToothOptions; +- u16 deviceCap; +- u32 binBuildNumber; ++ __le16 rfSilent; ++ __le16 blueToothOptions; ++ __le16 deviceCap; ++ __le32 binBuildNumber; + u8 deviceType; + u8 pwdclkind; + u8 fastClk5g; +@@ -300,33 +311,33 @@ struct base_eep_header { + } __packed; + + struct base_eep_header_4k { +- u16 length; +- u16 checksum; +- u16 version; ++ __le16 length; ++ __le16 checksum; ++ __le16 version; + u8 opCapFlags; + u8 eepMisc; +- u16 regDmn[2]; ++ __le16 regDmn[2]; + u8 macAddr[6]; + u8 rxMask; + u8 txMask; +- u16 rfSilent; +- u16 blueToothOptions; +- u16 deviceCap; +- u32 binBuildNumber; ++ __le16 rfSilent; ++ __le16 blueToothOptions; ++ __le16 deviceCap; ++ __le32 binBuildNumber; + u8 deviceType; + u8 txGainType; + } __packed; + + + struct spur_chan { +- u16 spurChan; ++ __le16 spurChan; + u8 spurRangeLow; + u8 spurRangeHigh; + } __packed; + + struct modal_eep_header { +- u32 antCtrlChain[AR5416_MAX_CHAINS]; +- u32 antCtrlCommon; ++ __le32 antCtrlChain[AR5416_MAX_CHAINS]; ++ __le32 antCtrlCommon; + u8 antennaGainCh[AR5416_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_MAX_CHAINS]; +@@ -361,7 +372,7 @@ struct modal_eep_header { + u8 db_ch1; + u8 lna_ctl; + u8 miscBits; +- u16 xpaBiasLvlFreq[3]; ++ __le16 xpaBiasLvlFreq[3]; + u8 futureModal[6]; + + struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; +@@ -375,8 +386,8 @@ struct calDataPerFreqOpLoop { + } __packed; + + struct modal_eep_4k_header { +- u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; +- u32 antCtrlCommon; ++ __le32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; ++ __le32 antCtrlCommon; + u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; +@@ -440,19 +451,19 @@ struct modal_eep_4k_header { + } __packed; + + struct base_eep_ar9287_header { +- u16 length; +- u16 checksum; +- u16 version; ++ __le16 length; ++ __le16 checksum; ++ __le16 version; + u8 opCapFlags; + u8 eepMisc; +- u16 regDmn[2]; ++ __le16 regDmn[2]; + u8 macAddr[6]; + u8 rxMask; + u8 txMask; +- u16 rfSilent; +- u16 blueToothOptions; +- u16 deviceCap; +- u32 binBuildNumber; ++ __le16 rfSilent; ++ __le16 blueToothOptions; ++ __le16 deviceCap; ++ __le32 binBuildNumber; + u8 deviceType; + u8 openLoopPwrCntl; + int8_t pwrTableOffset; +@@ -462,8 +473,8 @@ struct base_eep_ar9287_header { + } __packed; + + struct modal_eep_ar9287_header { +- u32 antCtrlChain[AR9287_MAX_CHAINS]; +- u32 antCtrlCommon; ++ __le32 antCtrlChain[AR9287_MAX_CHAINS]; ++ __le32 antCtrlCommon; + int8_t antennaGainCh[AR9287_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR9287_MAX_CHAINS]; +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -20,7 +20,7 @@ + + static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) + { +- u16 version = ah->eeprom.map4k.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; +@@ -28,7 +28,7 @@ static int ath9k_hw_4k_get_eeprom_ver(st + + static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) + { +- u16 version = ah->eeprom.map4k.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; + } +@@ -76,8 +76,8 @@ static bool ath9k_hw_4k_fill_eeprom(stru + static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size, + struct modal_eep_4k_header *modal_hdr) + { +- PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); +- PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); ++ PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); ++ PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); + PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); + PR_EEP("Switch Settle", modal_hdr->switchSettling); + PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]); +@@ -132,6 +132,7 @@ static u32 ath9k_hw_4k_dump_eeprom(struc + { + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + struct base_eep_header_4k *pBase = &eep->baseEepHeader; ++ u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); + + if (!dump_base_hdr) { + len += scnprintf(buf + len, size - len, +@@ -143,10 +144,10 @@ static u32 ath9k_hw_4k_dump_eeprom(struc + + 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]); +- PR_EEP("RegDomain2", pBase->regDmn[1]); ++ PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); ++ PR_EEP("Length", le16_to_cpu(pBase->length)); ++ PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); ++ PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); + PR_EEP("TX Mask", pBase->txMask); + PR_EEP("RX Mask", pBase->rxMask); + PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); +@@ -160,9 +161,9 @@ static u32 ath9k_hw_4k_dump_eeprom(struc + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); +- PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); +- PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); +- PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); ++ PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); ++ PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); ++ PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); + PR_EEP("TX Gain type", pBase->txGainType); + + len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", +@@ -194,54 +195,31 @@ static int ath9k_hw_4k_check_eeprom(stru + return err; + + if (need_swap) +- el = swab16(eep->baseEepHeader.length); ++ el = swab16((__force u16)eep->baseEepHeader.length); + else +- el = eep->baseEepHeader.length; ++ el = le16_to_cpu(eep->baseEepHeader.length); + + el = min(el / sizeof(u16), SIZE_EEPROM_4K); + if (!ath9k_hw_nvram_validate_checksum(ah, el)) + return -EINVAL; + + if (need_swap) { +- u32 integer; +- u16 word; +- +- word = swab16(eep->baseEepHeader.length); +- eep->baseEepHeader.length = word; +- +- word = swab16(eep->baseEepHeader.checksum); +- eep->baseEepHeader.checksum = word; +- +- word = swab16(eep->baseEepHeader.version); +- eep->baseEepHeader.version = word; +- +- word = swab16(eep->baseEepHeader.regDmn[0]); +- eep->baseEepHeader.regDmn[0] = word; +- +- word = swab16(eep->baseEepHeader.regDmn[1]); +- eep->baseEepHeader.regDmn[1] = word; +- +- word = swab16(eep->baseEepHeader.rfSilent); +- eep->baseEepHeader.rfSilent = word; +- +- word = swab16(eep->baseEepHeader.blueToothOptions); +- eep->baseEepHeader.blueToothOptions = word; +- +- word = swab16(eep->baseEepHeader.deviceCap); +- eep->baseEepHeader.deviceCap = word; +- +- integer = swab32(eep->modalHeader.antCtrlCommon); +- eep->modalHeader.antCtrlCommon = integer; +- +- for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { +- integer = swab32(eep->modalHeader.antCtrlChain[i]); +- eep->modalHeader.antCtrlChain[i] = integer; +- } +- +- for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { +- word = swab16(eep->modalHeader.spurChans[i].spurChan); +- eep->modalHeader.spurChans[i].spurChan = word; +- } ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); ++ EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon); ++ ++ for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) ++ EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]); ++ ++ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) ++ EEPROM_FIELD_SWAB16( ++ eep->modalHeader.spurChans[i].spurChan); + } + + if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, +@@ -270,13 +248,13 @@ static u32 ath9k_hw_4k_get_eeprom(struct + case EEP_MAC_MSW: + return get_unaligned_be16(pBase->macAddr + 4); + case EEP_REG_0: +- return pBase->regDmn[0]; ++ return le16_to_cpu(pBase->regDmn[0]); + case EEP_OP_CAP: +- return pBase->deviceCap; ++ return le16_to_cpu(pBase->deviceCap); + case EEP_OP_MODE: + return pBase->opCapFlags; + case EEP_RF_SILENT: +- return pBase->rfSilent; ++ return le16_to_cpu(pBase->rfSilent); + case EEP_OB_2: + return pModal->ob_0; + case EEP_DB_2: +@@ -724,7 +702,7 @@ static void ath9k_hw_4k_set_gain(struct + { + ENABLE_REG_RMW_BUFFER(ah); + REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, +- pModal->antCtrlChain[0], 0); ++ le32_to_cpu(pModal->antCtrlChain[0]), 0); + + REG_RMW(ah, AR_PHY_TIMING_CTRL4(0), + SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | +@@ -790,7 +768,7 @@ static void ath9k_hw_4k_set_board_values + pModal = &eep->modalHeader; + txRxAttenLocal = 23; + +- REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); ++ REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon)); + + /* Single chain for 4K EEPROM*/ + ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); +@@ -1054,7 +1032,7 @@ static void ath9k_hw_4k_set_board_values + + static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) + { +- return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan; ++ return le16_to_cpu(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan); + } + + static u8 ath9k_hw_4k_get_eepmisc(struct ath_hw *ah) +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -22,7 +22,7 @@ + + static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) + { +- u16 version = ah->eeprom.map9287.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; +@@ -30,7 +30,7 @@ static int ath9k_hw_ar9287_get_eeprom_ve + + static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) + { +- u16 version = ah->eeprom.map9287.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; + } +@@ -79,9 +79,9 @@ static bool ath9k_hw_ar9287_fill_eeprom( + static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size, + struct modal_eep_ar9287_header *modal_hdr) + { +- PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); +- PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); +- PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); ++ PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); ++ PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1])); ++ PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); + PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); + PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); + PR_EEP("Switch Settle", modal_hdr->switchSettling); +@@ -128,6 +128,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s + { + struct ar9287_eeprom *eep = &ah->eeprom.map9287; + struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; ++ u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); + + if (!dump_base_hdr) { + len += scnprintf(buf + len, size - len, +@@ -139,10 +140,10 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s + + 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]); +- PR_EEP("RegDomain2", pBase->regDmn[1]); ++ PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); ++ PR_EEP("Length", le16_to_cpu(pBase->length)); ++ PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); ++ PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); + PR_EEP("TX Mask", pBase->txMask); + PR_EEP("RX Mask", pBase->rxMask); + PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); +@@ -156,9 +157,9 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); +- PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); +- PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); +- PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); ++ PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); ++ PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); ++ PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); + PR_EEP("Power Table Offset", pBase->pwrTableOffset); + PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); + +@@ -182,8 +183,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(s + + static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) + { +- u32 el, integer; +- u16 word; ++ u32 el; + int i, err; + bool need_swap; + struct ar9287_eeprom *eep = &ah->eeprom.map9287; +@@ -193,51 +193,31 @@ static int ath9k_hw_ar9287_check_eeprom( + return err; + + if (need_swap) +- el = swab16(eep->baseEepHeader.length); ++ el = swab16((__force u16)eep->baseEepHeader.length); + else +- el = eep->baseEepHeader.length; ++ el = le16_to_cpu(eep->baseEepHeader.length); + + el = min(el / sizeof(u16), SIZE_EEPROM_AR9287); + if (!ath9k_hw_nvram_validate_checksum(ah, el)) + return -EINVAL; + + if (need_swap) { +- word = swab16(eep->baseEepHeader.length); +- eep->baseEepHeader.length = word; +- +- word = swab16(eep->baseEepHeader.checksum); +- eep->baseEepHeader.checksum = word; +- +- word = swab16(eep->baseEepHeader.version); +- eep->baseEepHeader.version = word; +- +- word = swab16(eep->baseEepHeader.regDmn[0]); +- eep->baseEepHeader.regDmn[0] = word; +- +- word = swab16(eep->baseEepHeader.regDmn[1]); +- eep->baseEepHeader.regDmn[1] = word; +- +- word = swab16(eep->baseEepHeader.rfSilent); +- eep->baseEepHeader.rfSilent = word; +- +- word = swab16(eep->baseEepHeader.blueToothOptions); +- eep->baseEepHeader.blueToothOptions = word; +- +- word = swab16(eep->baseEepHeader.deviceCap); +- eep->baseEepHeader.deviceCap = word; +- +- integer = swab32(eep->modalHeader.antCtrlCommon); +- eep->modalHeader.antCtrlCommon = integer; +- +- for (i = 0; i < AR9287_MAX_CHAINS; i++) { +- integer = swab32(eep->modalHeader.antCtrlChain[i]); +- eep->modalHeader.antCtrlChain[i] = integer; +- } +- +- for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { +- word = swab16(eep->modalHeader.spurChans[i].spurChan); +- eep->modalHeader.spurChans[i].spurChan = word; +- } ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); ++ EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon); ++ ++ for (i = 0; i < AR9287_MAX_CHAINS; i++) ++ EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]); ++ ++ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) ++ EEPROM_FIELD_SWAB16( ++ eep->modalHeader.spurChans[i].spurChan); + } + + if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER, +@@ -267,13 +247,13 @@ static u32 ath9k_hw_ar9287_get_eeprom(st + case EEP_MAC_MSW: + return get_unaligned_be16(pBase->macAddr + 4); + case EEP_REG_0: +- return pBase->regDmn[0]; ++ return le16_to_cpu(pBase->regDmn[0]); + case EEP_OP_CAP: +- return pBase->deviceCap; ++ return le16_to_cpu(pBase->deviceCap); + case EEP_OP_MODE: + return pBase->opCapFlags; + case EEP_RF_SILENT: +- return pBase->rfSilent; ++ return le16_to_cpu(pBase->rfSilent); + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: +@@ -878,13 +858,13 @@ static void ath9k_hw_ar9287_set_board_va + + pModal = &eep->modalHeader; + +- REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); ++ REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon)); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, +- pModal->antCtrlChain[i]); ++ le32_to_cpu(pModal->antCtrlChain[i])); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) +@@ -982,7 +962,9 @@ static void ath9k_hw_ar9287_set_board_va + static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, + u16 i, bool is2GHz) + { +- return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; ++ __le16 spur_ch = ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; ++ ++ return le16_to_cpu(spur_ch); + } + + static u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah) +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -79,7 +79,7 @@ static void ath9k_olc_get_pdadcs(struct + + static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) + { +- u16 version = ah->eeprom.def.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; +@@ -87,7 +87,7 @@ static int ath9k_hw_def_get_eeprom_ver(s + + static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) + { +- u16 version = ah->eeprom.def.baseEepHeader.version; ++ u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; + } +@@ -135,10 +135,10 @@ static bool ath9k_hw_def_fill_eeprom(str + static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, + struct modal_eep_header *modal_hdr) + { +- PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); +- PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); +- PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]); +- PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); ++ PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); ++ PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1])); ++ PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2])); ++ PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); + PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); + PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); + PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]); +@@ -194,9 +194,9 @@ static u32 ath9k_def_dump_modal_eeprom(c + PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1); + PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1); + PR_EEP("LNA Control", modal_hdr->lna_ctl); +- PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]); +- PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]); +- PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]); ++ PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0])); ++ PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1])); ++ PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2])); + + return len; + } +@@ -206,6 +206,7 @@ static u32 ath9k_hw_def_dump_eeprom(stru + { + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + struct base_eep_header *pBase = &eep->baseEepHeader; ++ u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); + + if (!dump_base_hdr) { + len += scnprintf(buf + len, size - len, +@@ -221,10 +222,10 @@ static u32 ath9k_hw_def_dump_eeprom(stru + + 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]); +- PR_EEP("RegDomain2", pBase->regDmn[1]); ++ PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); ++ PR_EEP("Length", le16_to_cpu(pBase->length)); ++ PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); ++ PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); + PR_EEP("TX Mask", pBase->txMask); + PR_EEP("RX Mask", pBase->rxMask); + PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); +@@ -238,9 +239,9 @@ static u32 ath9k_hw_def_dump_eeprom(stru + PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & + AR5416_OPFLAGS_N_5G_HT40)); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); +- PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); +- PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); +- PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); ++ PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); ++ PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); ++ PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); + PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); + + len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", +@@ -273,61 +274,40 @@ static int ath9k_hw_def_check_eeprom(str + return err; + + if (need_swap) +- el = swab16(eep->baseEepHeader.length); ++ el = swab16((__force u16)eep->baseEepHeader.length); + else +- el = eep->baseEepHeader.length; ++ el = le16_to_cpu(eep->baseEepHeader.length); + + el = min(el / sizeof(u16), SIZE_EEPROM_DEF); + if (!ath9k_hw_nvram_validate_checksum(ah, el)) + return -EINVAL; + + if (need_swap) { +- u32 integer, j; +- u16 word; ++ u32 j; + +- word = swab16(eep->baseEepHeader.length); +- eep->baseEepHeader.length = word; +- +- word = swab16(eep->baseEepHeader.checksum); +- eep->baseEepHeader.checksum = word; +- +- word = swab16(eep->baseEepHeader.version); +- eep->baseEepHeader.version = word; +- +- word = swab16(eep->baseEepHeader.regDmn[0]); +- eep->baseEepHeader.regDmn[0] = word; +- +- word = swab16(eep->baseEepHeader.regDmn[1]); +- eep->baseEepHeader.regDmn[1] = word; +- +- word = swab16(eep->baseEepHeader.rfSilent); +- eep->baseEepHeader.rfSilent = word; +- +- word = swab16(eep->baseEepHeader.blueToothOptions); +- eep->baseEepHeader.blueToothOptions = word; +- +- word = swab16(eep->baseEepHeader.deviceCap); +- eep->baseEepHeader.deviceCap = word; ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); ++ EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); + + for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { + struct modal_eep_header *pModal = + &eep->modalHeader[j]; +- integer = swab32(pModal->antCtrlCommon); +- pModal->antCtrlCommon = integer; ++ EEPROM_FIELD_SWAB32(pModal->antCtrlCommon); + +- for (i = 0; i < AR5416_MAX_CHAINS; i++) { +- integer = swab32(pModal->antCtrlChain[i]); +- pModal->antCtrlChain[i] = integer; +- } +- for (i = 0; i < 3; i++) { +- word = swab16(pModal->xpaBiasLvlFreq[i]); +- pModal->xpaBiasLvlFreq[i] = word; +- } ++ for (i = 0; i < AR5416_MAX_CHAINS; i++) ++ EEPROM_FIELD_SWAB32(pModal->antCtrlChain[i]); + +- for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { +- word = swab16(pModal->spurChans[i].spurChan); +- pModal->spurChans[i].spurChan = word; +- } ++ for (i = 0; i < 3; i++) ++ EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]); ++ ++ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) ++ EEPROM_FIELD_SWAB16( ++ pModal->spurChans[i].spurChan); + } + } + +@@ -337,7 +317,7 @@ static int ath9k_hw_def_check_eeprom(str + + /* Enable fixup for AR_AN_TOP2 if necessary */ + if ((ah->hw_version.devid == AR9280_DEVID_PCI) && +- ((eep->baseEepHeader.version & 0xff) > 0x0a) && ++ ((le16_to_cpu(eep->baseEepHeader.version) & 0xff) > 0x0a) && + (eep->baseEepHeader.pwdclkind == 0)) + ah->need_an_top2_fixup = true; + +@@ -370,13 +350,13 @@ static u32 ath9k_hw_def_get_eeprom(struc + case EEP_MAC_MSW: + return get_unaligned_be16(pBase->macAddr + 4); + case EEP_REG_0: +- return pBase->regDmn[0]; ++ return le16_to_cpu(pBase->regDmn[0]); + case EEP_OP_CAP: +- return pBase->deviceCap; ++ return le16_to_cpu(pBase->deviceCap); + case EEP_OP_MODE: + return pBase->opCapFlags; + case EEP_RF_SILENT: +- return pBase->rfSilent; ++ return le16_to_cpu(pBase->rfSilent); + case EEP_OB_5: + return pModal[0].ob; + case EEP_DB_5: +@@ -490,11 +470,13 @@ static void ath9k_hw_def_set_board_value + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + int i, regChainOffset; + u8 txRxAttenLocal; ++ u32 antCtrlCommon; + + pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); + txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; ++ antCtrlCommon = le32_to_cpu(pModal->antCtrlCommon); + +- REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff); ++ REG_WRITE(ah, AR_PHY_SWITCH_COM, antCtrlCommon & 0xffff); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (AR_SREV_9280(ah)) { +@@ -508,7 +490,7 @@ static void ath9k_hw_def_set_board_value + regChainOffset = i * 0x1000; + + REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, +- pModal->antCtrlChain[i]); ++ le32_to_cpu(pModal->antCtrlChain[i])); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & +@@ -655,7 +637,7 @@ static void ath9k_hw_def_set_board_value + static void ath9k_hw_def_set_addac(struct ath_hw *ah, + struct ath9k_channel *chan) + { +-#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) ++#define XPA_LVL_FREQ(cnt) (le16_to_cpu(pModal->xpaBiasLvlFreq[cnt])) + struct modal_eep_header *pModal; + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + u8 biaslevel; +@@ -1315,7 +1297,9 @@ static void ath9k_hw_def_set_txpower(str + + static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) + { +- return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; ++ __le16 spch = ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; ++ ++ return le16_to_cpu(spch); + } + + static u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah)