* [PATCH] Don't touch USB controllers with MMIO disabled in quirks
@ 2005-11-01 4:03 Paul Mackerras
2005-11-01 4:33 ` Linus Torvalds
2005-11-01 4:50 ` David Brownell
0 siblings, 2 replies; 8+ messages in thread
From: Paul Mackerras @ 2005-11-01 4:03 UTC (permalink / raw)
To: akpm, torvalds
Cc: David Brownell, Alan Stern, Greg Kroah-Hartman, linux-kernel
Recently a quirk was added which attempts to do usb-handoff on all USB
host controllers on all platforms. This is causing machine checks on
various machines such as my G4 powerbook, because the quirk code
attempts to do MMIO to the device without calling pci_enable_device,
or even checking that MMIO is enabled.
I still think that a FIXUP_HEADER header is the wrong place to be
doing this sort of thing, and that code that touches a device without
doing pci_enable_device is just asking for trouble; however, in order
to get my machine to be able to boot, this patch adds a check that
MMIO is enabled for the device, and if it isn't, leaves the device
alone. With this patch my powerbook will boot.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff -urN powerpc-merge/drivers/usb/host/pci-quirks.c merge-hack/drivers/usb/host/pci-quirks.c
--- powerpc-merge/drivers/usb/host/pci-quirks.c 2005-10-31 13:15:27.000000000 +1100
+++ merge-hack/drivers/usb/host/pci-quirks.c 2005-11-01 14:47:47.000000000 +1100
@@ -286,6 +286,11 @@
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{
+ u16 cmd;
+
+ if (pci_read_config_word(pdev, PCI_COMMAND, &cmd) ||
+ (cmd & PCI_COMMAND_MEMORY) == 0)
+ return;
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 4:03 [PATCH] Don't touch USB controllers with MMIO disabled in quirks Paul Mackerras @ 2005-11-01 4:33 ` Linus Torvalds 2005-11-01 4:48 ` Paul Mackerras 2005-11-01 15:32 ` Alan Stern 2005-11-01 4:50 ` David Brownell 1 sibling, 2 replies; 8+ messages in thread From: Linus Torvalds @ 2005-11-01 4:33 UTC (permalink / raw) To: Paul Mackerras Cc: akpm, David Brownell, Alan Stern, Greg Kroah-Hartman, linux-kernel On Tue, 1 Nov 2005, Paul Mackerras wrote: > > I still think that a FIXUP_HEADER header is the wrong place to be > doing this sort of thing, and that code that touches a device without > doing pci_enable_device is just asking for trouble; however, in order > to get my machine to be able to boot, this patch adds a check that > MMIO is enabled for the device, and if it isn't, leaves the device > alone. With this patch my powerbook will boot. Well, this can't be right, because depending on which controller type it is, the handoff code uses PIO, not MMIO. In fact, a uhci controller wouldn't necessarily ever have PCI_COMMAND_MEMORY set afaik, since it doesn't even _have_ MMIO. Would something like the appended work instead? Linus --- diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index b7fd3f6..b1aa350 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -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_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_ 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; ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 4:33 ` Linus Torvalds @ 2005-11-01 4:48 ` Paul Mackerras 2005-11-01 15:32 ` Alan Stern 1 sibling, 0 replies; 8+ messages in thread From: Paul Mackerras @ 2005-11-01 4:48 UTC (permalink / raw) To: Linus Torvalds Cc: akpm, David Brownell, Alan Stern, Greg Kroah-Hartman, linux-kernel Linus Torvalds writes: > Would something like the appended work instead? Looks fine to me, and it fixes the problem on my powerbook. Paul. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 4:33 ` Linus Torvalds 2005-11-01 4:48 ` Paul Mackerras @ 2005-11-01 15:32 ` Alan Stern 2005-11-01 15:54 ` Linus Torvalds 1 sibling, 1 reply; 8+ messages in thread From: Alan Stern @ 2005-11-01 15:32 UTC (permalink / raw) To: Linus Torvalds Cc: Paul Mackerras, akpm, David Brownell, Greg Kroah-Hartman, linux-kernel On Mon, 31 Oct 2005, Linus Torvalds wrote: > Well, this can't be right, because depending on which controller type it > is, the handoff code uses PIO, not MMIO. In fact, a uhci controller > wouldn't necessarily ever have PCI_COMMAND_MEMORY set afaik, since it > doesn't even _have_ MMIO. > > Would something like the appended work instead? > > Linus > > --- > diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c > index b7fd3f6..b1aa350 100644 > --- a/drivers/usb/host/pci-quirks.c > +++ b/drivers/usb/host/pci-quirks.c > @@ -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; > + In theory, is it possible for a UHCI controller still to be running, doing DMA and/or generating interrupts, even if PCI_COMMAND_IO isn't set? If it is, is there anything wrong with enabling the device fully in order to shut it off? Or is this scenario not worth worrying about? Alan Stern ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 15:32 ` Alan Stern @ 2005-11-01 15:54 ` Linus Torvalds 2005-11-01 16:43 ` Alan Stern 2005-11-02 21:13 ` Benjamin Herrenschmidt 0 siblings, 2 replies; 8+ messages in thread From: Linus Torvalds @ 2005-11-01 15:54 UTC (permalink / raw) To: Alan Stern Cc: Paul Mackerras, akpm, David Brownell, Greg Kroah-Hartman, linux-kernel On Tue, 1 Nov 2005, Alan Stern wrote: > > In theory, is it possible for a UHCI controller still to be running, doing > DMA and/or generating interrupts, even if PCI_COMMAND_IO isn't set? Yes, it's possible in theory. I guess we could check whether BUS_MASTER is enabled (which _does_ need to be enabled, otherwise it couldn't function), and then enable it. > Or is this scenario not worth worrying about? It's probably not worth worrying about. After all, this is really just for when something else (firmware) has enabled the USB controller for its own nefarious purposes (ie it also wanted keyboard input), and left it running. If something has left it running by mistake, it won't have disabled IO access either. And if it _has_ disabled IO access, we wouldn't know how to enable it at this point. Sure, we could enable the command bit, but this is too early for us to know where in the IO address space it would be safe to enable it. But an alternative strategy (which might be very sensible) is to forget about the handoff entirely, and just shut down the bus master flag unconditionally. Just make sure that the eventual driver will reset the controller before it re-enables bus mastering. That would seem to be the simplest possible "handoff". The only danger is that I could imagine that there would be controllers out there that get really confused (ie "I'm not going to play nice any more") if we shut them up that way. Linus ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 15:54 ` Linus Torvalds @ 2005-11-01 16:43 ` Alan Stern 2005-11-02 21:13 ` Benjamin Herrenschmidt 1 sibling, 0 replies; 8+ messages in thread From: Alan Stern @ 2005-11-01 16:43 UTC (permalink / raw) To: Linus Torvalds Cc: Paul Mackerras, akpm, David Brownell, Greg Kroah-Hartman, linux-kernel On Tue, 1 Nov 2005, Linus Torvalds wrote: > On Tue, 1 Nov 2005, Alan Stern wrote: > > > > In theory, is it possible for a UHCI controller still to be running, doing > > DMA and/or generating interrupts, even if PCI_COMMAND_IO isn't set? > > Yes, it's possible in theory. I guess we could check whether BUS_MASTER is > enabled (which _does_ need to be enabled, otherwise it couldn't function), > and then enable it. > > > Or is this scenario not worth worrying about? > > It's probably not worth worrying about. After all, this is really just for > when something else (firmware) has enabled the USB controller for its own > nefarious purposes (ie it also wanted keyboard input), and left it > running. If something has left it running by mistake, it won't have > disabled IO access either. > > And if it _has_ disabled IO access, we wouldn't know how to enable it at > this point. Sure, we could enable the command bit, but this is too early > for us to know where in the IO address space it would be safe to enable > it. > > But an alternative strategy (which might be very sensible) is to forget > about the handoff entirely, and just shut down the bus master flag > unconditionally. Just make sure that the eventual driver will reset the > controller before it re-enables bus mastering. > > That would seem to be the simplest possible "handoff". The only danger is > that I could imagine that there would be controllers out there that get > really confused (ie "I'm not going to play nice any more") if we shut them > up that way. Then here's a patch to do that. Unfortunately, the current setup _does_ enable bus mastering before resetting the controller. That deserves to be fixed in a separate patch. Alan Stern Signed-off-by: Alan Stern <stern@rowland.harvard.edu> --- Index: usb-2.6/drivers/usb/host/pci-quirks.c =================================================================== --- usb-2.6.orig/drivers/usb/host/pci-quirks.c +++ usb-2.6/drivers/usb/host/pci-quirks.c @@ -138,11 +138,47 @@ reset_needed: } EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); +static int __devinit io_type_enabled(struct pci_dev *pdev, unsigned int mask) +{ + u16 cmd = 0; + + if (pci_read_config_word(pdev, PCI_COMMAND, &cmd) || !(cmd & mask)) { + + /* The controller is at least partially disabled. + * To be on the safe side, we'll turn off the COMMAND_MASTER + * bit so that it can't do DMA. + */ + if (cmd & PCI_COMMAND_MASTER) + pci_write_config_word(pdev, PCI_COMMAND, + cmd & ~PCI_COMMAND_MASTER); + cmd = 0; + } + return cmd; +} + +#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO) +#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY) + +static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) +{ + return mmio_enabled(pdev) && pci_resource_start(pdev, idx); +} + static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) { unsigned long base = 0; int i; + if (!pio_enabled(pdev)) { + + /* The controller is at least partially disabled. + * To be safe, we'll disable PIRQD and SMI so that + * it can't generate interrupts. + */ + pci_write_config_word(pdev, UHCI_USBLEGSUP, 0); + return; + } + for (i = 0; i < PCI_ROM_RESOURCE; i++) if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { base = pci_resource_start(pdev, i); @@ -159,6 +195,9 @@ static void __devinit quirk_usb_handoff_ 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 +240,9 @@ static void __devinit quirk_usb_disable_ 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; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 15:54 ` Linus Torvalds 2005-11-01 16:43 ` Alan Stern @ 2005-11-02 21:13 ` Benjamin Herrenschmidt 1 sibling, 0 replies; 8+ messages in thread From: Benjamin Herrenschmidt @ 2005-11-02 21:13 UTC (permalink / raw) To: Linus Torvalds Cc: Alan Stern, Paul Mackerras, akpm, David Brownell, Greg Kroah-Hartman, linux-kernel > But an alternative strategy (which might be very sensible) is to forget > about the handoff entirely, and just shut down the bus master flag > unconditionally. Just make sure that the eventual driver will reset the > controller before it re-enables bus mastering. Unfortunately, I know quite a few devices (including USB controllers) that will react badly to the bus master flag being just cleared like that. By badly, I mean it ranges from simply ignoring it and happily continuing whatever bus master was being done, to completely screwing up and crapping all over your memory/bus. > That would seem to be the simplest possible "handoff". The only danger is > that I could imagine that there would be controllers out there that get > really confused (ie "I'm not going to play nice any more") if we shut them > up that way. I suspect with the IO/MEM enable test fix we did, it shoul work fine in practice for all cases. Let's address the "potential" issues if they happen to show up in real life, which I doubt. Ben. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Don't touch USB controllers with MMIO disabled in quirks 2005-11-01 4:03 [PATCH] Don't touch USB controllers with MMIO disabled in quirks Paul Mackerras 2005-11-01 4:33 ` Linus Torvalds @ 2005-11-01 4:50 ` David Brownell 1 sibling, 0 replies; 8+ messages in thread From: David Brownell @ 2005-11-01 4:50 UTC (permalink / raw) To: Paul Mackerras Cc: akpm, torvalds, Alan Stern, Greg Kroah-Hartman, linux-kernel On Monday 31 October 2005 8:03 pm, Paul Mackerras wrote: > static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) > { > + u16 cmd; > + > + if (pci_read_config_word(pdev, PCI_COMMAND, &cmd) || > + (cmd & PCI_COMMAND_MEMORY) == 0) I suspect that should be (tabs) || (cmd & (PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) == 0 Admittedly that'll matter only for UHCI, which isn't much used out of x86 and ia64 ... but testing for both is more correct. Other than that, this looks good to me. - Dave > + return; > if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) > quirk_usb_handoff_uhci(pdev); > else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-11-02 21:17 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-11-01 4:03 [PATCH] Don't touch USB controllers with MMIO disabled in quirks Paul Mackerras 2005-11-01 4:33 ` Linus Torvalds 2005-11-01 4:48 ` Paul Mackerras 2005-11-01 15:32 ` Alan Stern 2005-11-01 15:54 ` Linus Torvalds 2005-11-01 16:43 ` Alan Stern 2005-11-02 21:13 ` Benjamin Herrenschmidt 2005-11-01 4:50 ` David Brownell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox