[Karmic] SRU: ath5k: Fix eeprom checksum check for custom sized eeproms

Tim Gardner tim.gardner at canonical.com
Tue Jan 26 00:39:14 UTC 2010


Stefan Bader wrote:
> SRU justification:
> 
> Impact: Upstream 2.6.31.9 contained a patch that added a check for bogus
> EEPROM checksums to the ath5k driver but it seems to have missed the fact
> that custom EEPROMs might be different in size.
> 
> Fix: Upstream patch which was added to 2.6.32.4 but not carried over to
> 2.6.31.y adds code to query and work with differently sized EEPROMS.
> 
> Testcase: Bring up certain hw with custom EEPROM. Verified in the report.
> 
> -Stefan
> 
> ---
> 
> From e6efac7b7c4ce45d40f5e07d3105e07704e95673 Mon Sep 17 00:00:00 2001
> From: Luis R. Rodriguez <lrodriguez at atheros.com>
> Date: Mon, 4 Jan 2010 10:40:39 -0500
> Subject: [PATCH] ath5k: Fix eeprom checksum check for custom sized eeproms
> 
> BugLink: http://bugs.launchpad.net/bugs/506180
> 
> commit 359207c687cc8f4f9845c8dadd0d6dabad44e584 upstream.
> 
> Commit 8bf3d79bc401ca417ccf9fc076d3295d1a71dbf5 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: David Quan <david.quan at atheros.com>
> Cc: Stephen Beahm <stephenbeahm at comcast.net>
> Reported-by: Joshua Covington <joshuacov at googlemail.com>
> Signed-off-by: Luis R. Rodriguez <lrodriguez at atheros.com>
> Signed-off-by: John W. Linville <linville at tuxdriver.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
> Signed-off-by: Stefan Bader <stefan.bader at canonical.com>
> ---
>  drivers/net/wireless/ath/ath5k/eeprom.c |   32 ++++++++++++++++++++++++++++--
>  drivers/net/wireless/ath/ath5k/eeprom.h |    8 +++++++
>  2 files changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
> index 7918852..9a96550 100644
> --- a/drivers/net/wireless/ath/ath5k/eeprom.c
> +++ b/drivers/net/wireless/ath/ath5k/eeprom.c
> @@ -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;
>  	}
>  
> diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
> index 0123f35..473a483 100644
> --- a/drivers/net/wireless/ath/ath5k/eeprom.h
> +++ b/drivers/net/wireless/ath/ath5k/eeprom.h
> @@ -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)

Acked-by: Tim Gardner <tim.gardner at canonical.com>

-- 
Tim Gardner tim.gardner at canonical.com




More information about the kernel-team mailing list