Don't touch USB controller IO registers when they are disabled
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 1 Nov 2005 05:12:40 +0000 (21:12 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 1 Nov 2005 05:12:40 +0000 (21:12 -0800)
The USB "handoff" code is an early PCI quirk to make sure we own the USB
controller (as opposed to the BIOS/SMM).  But if the controller isn't
even enabled yet, don't try to access it.

Acked-by: Paul Mackerras <paulus@samba.org> (who had an alternate patch)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/usb/host/pci-quirks.c

index b7fd3f644e1e557bb6924987181eced909f28cd7..b1aa350fd32f04d5b59322bfb0ea946c00c25083 100644 (file)
@@ -138,11 +138,23 @@ reset_needed:
 }
 EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
 
+static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
+{
+       u16 cmd;
+       return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
+}
+
+#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
+#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
+
 static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
 {
        unsigned long base = 0;
        int i;
 
+       if (!pio_enabled(pdev))
+               return;
+
        for (i = 0; i < PCI_ROM_RESOURCE; i++)
                if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
                        base = pci_resource_start(pdev, i);
@@ -153,12 +165,20 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
                uhci_check_and_reset_hc(pdev, base);
 }
 
+static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
+{
+       return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
+}
+
 static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
        void __iomem *base;
        int wait_time;
        u32 control;
 
+       if (!mmio_resource_enabled(pdev, 0))
+               return;
+
        base = ioremap_nocache(pci_resource_start(pdev, 0),
                                     pci_resource_len(pdev, 0));
        if (base == NULL) return;
@@ -201,6 +221,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
        u32 hcc_params, val, temp;
        u8 cap_length;
 
+       if (!mmio_resource_enabled(pdev, 0))
+               return;
+
        base = ioremap_nocache(pci_resource_start(pdev, 0),
                                pci_resource_len(pdev, 0));
        if (base == NULL) return;