powerpc: Fix vio_bus_probe oops on probe error
authorBrian King <brking@linux.vnet.ibm.com>
Tue, 12 Aug 2008 19:21:45 +0000 (05:21 +1000)
committerPaul Mackerras <paulus@samba.org>
Tue, 19 Aug 2008 23:50:22 +0000 (09:50 +1000)
When CMO is enabled and booted on a non CMO system and the VIO
device's probe function fails, an oops can result since
vio_cmo_bus_remove is called when it should not.  This fixes it by
avoiding the vio_cmo_bus_remove call on platforms that don't implement
CMO.

cpu 0x0: Vector: 300 (Data Access) at [c00000000e13b3d0]
    pc: c000000000020d34: .vio_cmo_bus_remove+0xc0/0x1f4
    lr: c000000000020ca4: .vio_cmo_bus_remove+0x30/0x1f4
    sp: c00000000e13b650
   msr: 8000000000009032
   dar: 0
 dsisr: 40000000
  current = 0xc00000000e0566c0
  paca    = 0xc0000000006f9b80
    pid   = 2428, comm = modprobe
enter ? for help
[c00000000e13b6e0c000000000021d94 .vio_bus_probe+0x2f8/0x33c
[c00000000e13b7a0c00000000029fc88 .driver_probe_device+0x13c/0x200
[c00000000e13b830c00000000029fdac .__driver_attach+0x60/0xa4
[c00000000e13b8c0c00000000029f050 .bus_for_each_dev+0x80/0xd8
[c00000000e13b980c00000000029f9ec .driver_attach+0x28/0x40
[c00000000e13ba00c00000000029f630 .bus_add_driver+0xd4/0x284
[c00000000e13baa0c0000000002a01bc .driver_register+0xc4/0x198
[c00000000e13bb50c00000000002168c .vio_register_driver+0x40/0x5c
[c00000000e13bbe0d0000000003b3f1c .ibmvfc_module_init+0x70/0x109c [ibmvfc]
[c00000000e13bc70c0000000000acf08 .sys_init_module+0x184c/0x1a10
[c00000000e13be30c000000000008748 syscall_exit+0x0/0x40

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/vio.c

index 22a3c33fd7513c5288cef156f931f62a1c4f41df..2750fbab1975b2e7e4c84d48a67589385aeb9e40 100644 (file)
@@ -1113,7 +1113,7 @@ static int vio_bus_probe(struct device *dev)
                                return error;
                }
                error = viodrv->probe(viodev, id);
-               if (error)
+               if (error && firmware_has_feature(FW_FEATURE_CMO))
                        vio_cmo_bus_remove(viodev);
        }