aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-03-31 15:39:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-26 13:50:54 -0400
commitd53cdbb94a52a920d5420ed64d986c3523a56743 (patch)
tree39b1026c953de14ce6b14417cf9bcb66992909f0 /drivers
parent672724403b42da1d276c6cf811e8e34d15efd964 (diff)
ssb: do not read SPROM if it does not exist
Attempting to read registers that don't exist on the SSB bus can cause hangs on some boxes. At least some b43 devices are 'in the wild' that don't have SPROMs at all. When the SSB bus support loads, it attempts to read these (non-existant) SPROMs and causes hard hangs on the box -- no console output, etc. This patch adds some intelligence to determine whether or not the SPROM is present before attempting to read it. This avoids those hard hangs on those devices with no SPROM attached to their SSB bus. The SSB-attached devices (e.g. b43, et al.) won't work, but at least the box will survive to test further patches. :-) Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Cc: Larry Finger <Larry.Finger@lwfinger.net> Cc: Michael Buesch <mb@bu3sch.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ssb/driver_chipcommon.c2
-rw-r--r--drivers/ssb/pci.c5
-rw-r--r--drivers/ssb/sprom.c14
3 files changed, 21 insertions, 0 deletions
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 59c3c0fdbecd..59ae76bace14 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -233,6 +233,8 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
233{ 233{
234 if (!cc->dev) 234 if (!cc->dev)
235 return; /* We don't have a ChipCommon */ 235 return; /* We don't have a ChipCommon */
236 if (cc->dev->id.revision >= 11)
237 cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
236 ssb_pmu_init(cc); 238 ssb_pmu_init(cc);
237 chipco_powercontrol_init(cc); 239 chipco_powercontrol_init(cc);
238 ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); 240 ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 9e50896233aa..a4b2b99f2c80 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -620,6 +620,11 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
620 int err = -ENOMEM; 620 int err = -ENOMEM;
621 u16 *buf; 621 u16 *buf;
622 622
623 if (!ssb_is_sprom_available(bus)) {
624 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
625 return -ENODEV;
626 }
627
623 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); 628 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
624 if (!buf) 629 if (!buf)
625 goto out; 630 goto out;
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index d0e6762fec50..83bc088b941d 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -175,3 +175,17 @@ const struct ssb_sprom *ssb_get_fallback_sprom(void)
175{ 175{
176 return fallback_sprom; 176 return fallback_sprom;
177} 177}
178
179/* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
180bool ssb_is_sprom_available(struct ssb_bus *bus)
181{
182 /* status register only exists on chipcomon rev >= 11 and we need check
183 for >= 31 only */
184 /* this routine differs from specs as we do not access SPROM directly
185 on PCMCIA */
186 if (bus->bustype == SSB_BUSTYPE_PCI &&
187 bus->chipco.dev->id.revision >= 31)
188 return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
189
190 return true;
191}