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

Leann Ogasawara leann.ogasawara at canonical.com
Tue Jan 26 05:00:33 UTC 2010


On Mon, 2010-01-25 at 17:39 -0700, Tim Gardner wrote:
> 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>

Acked-by: Leann Ogasawara <leann.ogasawara at canonical.com>






More information about the kernel-team mailing list