oops in i2c_keywest_init
Benjamin Herrenschmidt
benh at kernel.crashing.org
Sun May 22 23:26:12 EST 2005
On Sun, 2005-05-22 at 14:30 +0200, Olaf Hering wrote:
> On Sat, May 21, Benjamin Herrenschmidt wrote:
>
> > + if (prom_getproplen(i2c, "interrupts") <= 0)
> > + return;
>
> Make that '>=' and everyone is happy.
Ah good. Updated patch is here, I'll send to linus/andrew tomorrow.
Index: linux-work/arch/ppc64/kernel/prom_init.c
===================================================================
--- linux-work.orig/arch/ppc64/kernel/prom_init.c 2005-05-02 10:48:08.000000000 +1000
+++ linux-work/arch/ppc64/kernel/prom_init.c 2005-05-22 23:25:17.000000000 +1000
@@ -1750,7 +1750,44 @@
prom_printf("Device tree struct 0x%x -> 0x%x\n",
RELOC(dt_struct_start), RELOC(dt_struct_end));
- }
+}
+
+
+static void fixup_device_tree(void)
+{
+ unsigned long offset = reloc_offset();
+ phandle u3, i2c, mpic;
+ u32 u3_rev;
+ u32 interrupts[2];
+ u32 parent;
+
+ /* Some G5s have a missing interrupt definition, fix it up here */
+ u3 = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000"));
+ if ((long)u3 <= 0)
+ return;
+ i2c = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000/i2c at f8001000"));
+ if ((long)i2c <= 0)
+ return;
+ mpic = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000/mpic at f8040000"));
+ if ((long)mpic <= 0)
+ return;
+
+ /* check if proper rev of u3 */
+ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+ return;
+ if (u3_rev != 0x35)
+ return;
+ /* does it need fixup ? */
+ if (prom_getproplen(i2c, "interrupts") > 0)
+ return;
+ /* interrupt on this revision of u3 is number 0 and level */
+ interrupts[0] = 0;
+ interrupts[1] = 1;
+ prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+ parent = (u32)mpic;
+ prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
static void __init prom_find_boot_cpu(void)
{
@@ -1920,6 +1957,11 @@
}
/*
+ * Fixup any known bugs in the device-tree
+ */
+ fixup_device_tree();
+
+ /*
* Now finally create the flattened device-tree
*/
prom_printf("copying OF device tree ...\n");
Index: linux-work/drivers/i2c/busses/i2c-keywest.c
===================================================================
--- linux-work.orig/drivers/i2c/busses/i2c-keywest.c 2005-05-02 10:48:09.000000000 +1000
+++ linux-work/drivers/i2c/busses/i2c-keywest.c 2005-05-21 08:38:40.000000000 +1000
@@ -516,6 +516,11 @@
u32 *psteps, *prate;
int rc;
+ if (np->n_intrs < 1 || np->n_addrs < 1) {
+ printk(KERN_ERR "%s: Missing interrupt or address !\n",
+ np->full_name);
+ return -ENODEV;
+ }
if (pmac_low_i2c_lock(np))
return -ENODEV;
More information about the Linuxppc64-dev
mailing list