diff options
Diffstat (limited to 'package/kernel/mac80211/patches/555-ath9k-Make-the-EEPROM-swapping-check-use-the-eepmisc.patch')
-rw-r--r-- | package/kernel/mac80211/patches/555-ath9k-Make-the-EEPROM-swapping-check-use-the-eepmisc.patch | 128 |
1 files changed, 128 insertions, 0 deletions
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 <martin.blumenstingl@googlemail.com> +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 <martin.blumenstingl@googlemail.com> +--- + 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; |