|
Jesse Keating |
2f82dda |
From 380bed7aa858cbe2d4eeb783e2bed7d01828518d Mon Sep 17 00:00:00 2001
|
|
Jesse Keating |
2f82dda |
From: John W. Linville <linville@tuxdriver.com>
|
|
Jesse Keating |
2f82dda |
Date: Fri, 19 Mar 2010 14:58:01 -0400
|
|
Jesse Keating |
2f82dda |
Subject: [PATCH v4] ssb: do not read SPROM if it does not exist
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
Attempting to read registers that don't exist on the SSB bus can cause
|
|
Jesse Keating |
2f82dda |
hangs on some boxes. At least some b43 devices are 'in the wild' that
|
|
Jesse Keating |
2f82dda |
don't have SPROMs at all. When the SSB bus support loads, it attempts
|
|
Jesse Keating |
2f82dda |
to read these (non-existant) SPROMs and causes hard hangs on the box --
|
|
Jesse Keating |
2f82dda |
no console output, etc.
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
This patch adds some intelligence to determine whether or not the SPROM
|
|
Jesse Keating |
2f82dda |
is present before attempting to read it. This avoids those hard hangs
|
|
Jesse Keating |
2f82dda |
on those devices with no SPROM attached to their SSB bus. The
|
|
Jesse Keating |
2f82dda |
SSB-attached devices (e.g. b43, et al.) won't work, but at least the box
|
|
Jesse Keating |
2f82dda |
will survive to test further patches. :-)
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
Jesse Keating |
2f82dda |
Cc: Larry Finger <Larry.Finger@lwfinger.net>
|
|
Jesse Keating |
2f82dda |
Cc: Michael Buesch <mb@bu3sch.de>
|
|
Jesse Keating |
2f82dda |
Cc: stable@kernel.org
|
|
Jesse Keating |
2f82dda |
---
|
|
Jesse Keating |
2f82dda |
Version 4, move read of ChipCommon status register to ssb_chipcommon_init
|
|
Jesse Keating |
2f82dda |
Version 3, add missing semi-colon... :-(
|
|
Jesse Keating |
2f82dda |
Version 2, check the correct place for ChipCommon core revision... :-)
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
drivers/ssb/driver_chipcommon.c | 3 +++
|
|
Jesse Keating |
2f82dda |
drivers/ssb/pci.c | 3 +++
|
|
Jesse Keating |
2f82dda |
drivers/ssb/sprom.c | 22 ++++++++++++++++++++++
|
|
Jesse Keating |
2f82dda |
include/linux/ssb/ssb.h | 3 +++
|
|
Jesse Keating |
2f82dda |
include/linux/ssb/ssb_driver_chipcommon.h | 15 +++++++++++++++
|
|
Jesse Keating |
2f82dda |
5 files changed, 46 insertions(+), 0 deletions(-)
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
|
|
Jesse Keating |
2f82dda |
index 9681536..6cf288d 100644
|
|
Jesse Keating |
2f82dda |
--- a/drivers/ssb/driver_chipcommon.c
|
|
Jesse Keating |
2f82dda |
+++ b/drivers/ssb/driver_chipcommon.c
|
|
Jesse Keating |
2f82dda |
@@ -233,6 +233,9 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
|
|
Jesse Keating |
2f82dda |
{
|
|
Jesse Keating |
2f82dda |
if (!cc->dev)
|
|
Jesse Keating |
2f82dda |
return; /* We don't have a ChipCommon */
|
|
Jesse Keating |
2f82dda |
+ if (cc->dev->id.revision >= 11) {
|
|
Jesse Keating |
2f82dda |
+ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
|
|
Jesse Keating |
2f82dda |
+ }
|
|
Jesse Keating |
2f82dda |
ssb_pmu_init(cc);
|
|
Jesse Keating |
2f82dda |
chipco_powercontrol_init(cc);
|
|
Jesse Keating |
2f82dda |
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
|
|
Jesse Keating |
2f82dda |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
|
|
Jesse Keating |
2f82dda |
index 9e50896..2f7b16d 100644
|
|
Jesse Keating |
2f82dda |
--- a/drivers/ssb/pci.c
|
|
Jesse Keating |
2f82dda |
+++ b/drivers/ssb/pci.c
|
|
Jesse Keating |
2f82dda |
@@ -620,6 +620,9 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
|
|
Jesse Keating |
2f82dda |
int err = -ENOMEM;
|
|
Jesse Keating |
2f82dda |
u16 *buf;
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
+ if (!ssb_is_sprom_available(bus))
|
|
Jesse Keating |
2f82dda |
+ return -ENODEV;
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
|
|
Jesse Keating |
2f82dda |
if (!buf)
|
|
Jesse Keating |
2f82dda |
goto out;
|
|
Jesse Keating |
2f82dda |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
index d0e6762..55eb9b0 100644
|
|
Jesse Keating |
2f82dda |
--- a/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
+++ b/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
@@ -175,3 +175,25 @@ const struct ssb_sprom *ssb_get_fallback_sprom(void)
|
|
Jesse Keating |
2f82dda |
{
|
|
Jesse Keating |
2f82dda |
return fallback_sprom;
|
|
Jesse Keating |
2f82dda |
}
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
+bool ssb_is_sprom_available(struct ssb_bus *bus)
|
|
Jesse Keating |
2f82dda |
+{
|
|
Jesse Keating |
2f82dda |
+ /* status register only exists on chipcomon rev >= 11 */
|
|
Jesse Keating |
2f82dda |
+ if (bus->chipco.dev->id.revision < 11)
|
|
Jesse Keating |
2f82dda |
+ return true;
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
+ switch (bus->chip_id) {
|
|
Jesse Keating |
2f82dda |
+ case 0x4312:
|
|
Jesse Keating |
2f82dda |
+ return SSB_CHIPCO_CHST_4312_SPROM_PRESENT(bus->chipco.status);
|
|
Jesse Keating |
2f82dda |
+ case 0x4322:
|
|
Jesse Keating |
2f82dda |
+ return SSB_CHIPCO_CHST_4322_SPROM_PRESENT(bus->chipco.status);
|
|
Jesse Keating |
2f82dda |
+ case 0x4325:
|
|
Jesse Keating |
2f82dda |
+ return SSB_CHIPCO_CHST_4325_SPROM_PRESENT(bus->chipco.status);
|
|
Jesse Keating |
2f82dda |
+ default:
|
|
Jesse Keating |
2f82dda |
+ break;
|
|
Jesse Keating |
2f82dda |
+ }
|
|
Jesse Keating |
2f82dda |
+ if (bus->chipco.dev->id.revision >= 31)
|
|
Jesse Keating |
2f82dda |
+ return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
+ return true;
|
|
Jesse Keating |
2f82dda |
+}
|
|
Jesse Keating |
2f82dda |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
|
|
Jesse Keating |
2f82dda |
index 24f9885..3b4da23 100644
|
|
Jesse Keating |
2f82dda |
--- a/include/linux/ssb/ssb.h
|
|
Jesse Keating |
2f82dda |
+++ b/include/linux/ssb/ssb.h
|
|
Jesse Keating |
2f82dda |
@@ -394,6 +394,9 @@ extern int ssb_bus_sdiobus_register(struct ssb_bus *bus,
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
extern void ssb_bus_unregister(struct ssb_bus *bus);
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
+/* Does the device have an SPROM? */
|
|
Jesse Keating |
2f82dda |
+extern bool ssb_is_sprom_available(struct ssb_bus *bus);
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
/* Set a fallback SPROM.
|
|
Jesse Keating |
2f82dda |
* See kdoc at the function definition for complete documentation. */
|
|
Jesse Keating |
2f82dda |
extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
|
|
Jesse Keating |
2f82dda |
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
|
|
Jesse Keating |
2f82dda |
index 4e27acf..2cdf249 100644
|
|
Jesse Keating |
2f82dda |
--- a/include/linux/ssb/ssb_driver_chipcommon.h
|
|
Jesse Keating |
2f82dda |
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
|
|
Jesse Keating |
2f82dda |
@@ -53,6 +53,7 @@
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CAP_64BIT 0x08000000 /* 64-bit Backplane */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */
|
|
Jesse Keating |
2f82dda |
+#define SSB_CHIPCO_CAP_SPROM 0x40000000 /* SPROM present */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CORECTL 0x0008
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
|
|
Jesse Keating |
2f82dda |
@@ -385,6 +386,7 @@
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
/** Chip specific Chip-Status register contents. */
|
|
Jesse Keating |
2f82dda |
+#define SSB_CHIPCO_CHST_4322_SPROM_EXISTS 0x00000040 /* SPROM present */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL 0x00000003
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CHST_4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CHST_4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
|
|
Jesse Keating |
2f82dda |
@@ -398,6 +400,18 @@
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CHST_4325_RCAL_VALUE_SHIFT 4
|
|
Jesse Keating |
2f82dda |
#define SSB_CHIPCO_CHST_4325_PMUTOP_2B 0x00000200 /* 1 for 2b, 0 for to 2a */
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
+/** Macros to determine SPROM presence based on Chip-Status register. */
|
|
Jesse Keating |
2f82dda |
+#define SSB_CHIPCO_CHST_4312_SPROM_PRESENT(status) \
|
|
Jesse Keating |
2f82dda |
+ ((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
|
|
Jesse Keating |
2f82dda |
+ SSB_CHIPCO_CHST_4325_OTP_SEL)
|
|
Jesse Keating |
2f82dda |
+#define SSB_CHIPCO_CHST_4322_SPROM_PRESENT(status) \
|
|
Jesse Keating |
2f82dda |
+ (status & SSB_CHIPCO_CHST_4322_SPROM_EXISTS)
|
|
Jesse Keating |
2f82dda |
+#define SSB_CHIPCO_CHST_4325_SPROM_PRESENT(status) \
|
|
Jesse Keating |
2f82dda |
+ (((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
|
|
Jesse Keating |
2f82dda |
+ SSB_CHIPCO_CHST_4325_DEFCIS_SEL) && \
|
|
Jesse Keating |
2f82dda |
+ ((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
|
|
Jesse Keating |
2f82dda |
+ SSB_CHIPCO_CHST_4325_OTP_SEL))
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
/** Clockcontrol masks and values **/
|
|
Jesse Keating |
2f82dda |
@@ -564,6 +578,7 @@ struct ssb_chipcommon_pmu {
|
|
Jesse Keating |
2f82dda |
struct ssb_chipcommon {
|
|
Jesse Keating |
2f82dda |
struct ssb_device *dev;
|
|
Jesse Keating |
2f82dda |
u32 capabilities;
|
|
Jesse Keating |
2f82dda |
+ u32 status;
|
|
Jesse Keating |
2f82dda |
/* Fast Powerup Delay constant */
|
|
Jesse Keating |
2f82dda |
u16 fast_pwrup_delay;
|
|
Jesse Keating |
2f82dda |
struct ssb_chipcommon_pmu pmu;
|
|
Jesse Keating |
2f82dda |
--
|
|
Jesse Keating |
2f82dda |
1.6.2.5
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
From ec032742062ad1b01dfe75cfccdbc5b850837c23 Mon Sep 17 00:00:00 2001
|
|
Jesse Keating |
2f82dda |
From: John W. Linville <linville@tuxdriver.com>
|
|
Jesse Keating |
2f82dda |
Date: Tue, 30 Mar 2010 13:47:39 -0400
|
|
Jesse Keating |
2f82dda |
Subject: [PATCH] ssb: avoid null ptr deref in ssb_is_sprom_available
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
Some older devices don't have chipcommon, but they do have SPROM.
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
Jesse Keating |
2f82dda |
---
|
|
Jesse Keating |
2f82dda |
drivers/ssb/sprom.c | 4 ++++
|
|
Jesse Keating |
2f82dda |
1 files changed, 4 insertions(+), 0 deletions(-)
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
index 55eb9b0..874d8f1 100644
|
|
Jesse Keating |
2f82dda |
--- a/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
+++ b/drivers/ssb/sprom.c
|
|
Jesse Keating |
2f82dda |
@@ -178,6 +178,10 @@ const struct ssb_sprom *ssb_get_fallback_sprom(void)
|
|
Jesse Keating |
2f82dda |
|
|
Jesse Keating |
2f82dda |
bool ssb_is_sprom_available(struct ssb_bus *bus)
|
|
Jesse Keating |
2f82dda |
{
|
|
Jesse Keating |
2f82dda |
+ /* some older devices don't have chipcommon, but they have sprom */
|
|
Jesse Keating |
2f82dda |
+ if (!bus->chipco.dev)
|
|
Jesse Keating |
2f82dda |
+ return true;
|
|
Jesse Keating |
2f82dda |
+
|
|
Jesse Keating |
2f82dda |
/* status register only exists on chipcomon rev >= 11 */
|
|
Jesse Keating |
2f82dda |
if (bus->chipco.dev->id.revision < 11)
|
|
Jesse Keating |
2f82dda |
return true;
|
|
Jesse Keating |
2f82dda |
--
|
|
Jesse Keating |
2f82dda |
1.6.2.5
|
|
Jesse Keating |
2f82dda |
|