Commit 359207c6 authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville

ath5k: Fix eeprom checksum check for custom sized eeproms

Commit 8bf3d79b enabled EEPROM
checksum checks to avoid bogus bug reports but failed to address
updating the code to consider devices with custom EEPROM sizes.
Devices with custom sized EEPROMs have the upper limit size stuffed
in the EEPROM. Use this as the upper limit instead of the static
default size. In case of a checksum error also provide back the
max size and whether or not this was the default size or a custom
one. If the EEPROM is busted we add a failsafe check to ensure
we don't loop forever or try to read bogus areas of hardware.

This closes bug 14874

http://bugzilla.kernel.org/show_bug.cgi?id=14874

Cc: stable@kernel.org
Cc: David Quan <david.quan@atheros.com>
Cc: Stephen Beahm <stephenbeahm@comcast.net>
Reported-by: default avatarJoshua Covington <joshuacov@googlemail.com>
Signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7de3c5dc
......@@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
int ret;
u16 val;
u32 cksum, offset;
u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
/*
* Read values from EEPROM and store them in the capability structure
......@@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
* Validate the checksum of the EEPROM date. There are some
* devices with invalid EEPROMs.
*/
for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val);
if (val) {
eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val);
eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE;
/*
* Fail safe check to prevent stupid loops due
* to busted EEPROMs. XXX: This value is likely too
* big still, waiting on a better value.
*/
if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
"%d (0x%04x) max expected: %d (0x%04x)\n",
eep_max, eep_max,
3 * AR5K_EEPROM_INFO_MAX,
3 * AR5K_EEPROM_INFO_MAX);
return -EIO;
}
}
for (cksum = 0, offset = 0; offset < eep_max; offset++) {
AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
cksum ^= val;
}
if (cksum != AR5K_EEPROM_INFO_CKSUM) {
ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
"checksum: 0x%04x eep_max: 0x%04x (%s)\n",
cksum, eep_max,
eep_max == AR5K_EEPROM_INFO_MAX ?
"default size" : "custom size");
return -EIO;
}
......
......@@ -37,6 +37,14 @@
#define AR5K_EEPROM_RFKILL_POLARITY_S 1
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
/* FLASH(EEPROM) Defines for AR531X chips */
#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */
#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */
#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0
#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4
#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment