ohci-pci: add qemu quirk
authorGerd Hoffmann <kraxel@redhat.com>
Mon, 20 Mar 2017 08:11:49 +0000 (09:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 May 2017 13:44:36 +0000 (15:44 +0200)
commit 21a60f6e65181cad64fd66ccc8080d413721ba27 upstream.

On a loaded virtualization host (dozen guests booting at the same time)
it may happen that the ohci controller emulation doesn't manage to do
timely frame processing, with the result that the io watchdog fires and
considers the controller being dead, even though it's only the emulation
being unusual slow due to the load peak.

So, add a quirk for qemu and don't use the watchdog in case we figure we
are running on emulated ohci.  The virtual ohci controller masquerades
as apple ohci controller, but we can identify it by subsystem id.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci.h

index 86612ac3fda220e3d1c9b1b5c959f45f723d543d..f6c7a2744e5c90e2ae4c8717850c014b8b21961d 100644 (file)
@@ -231,7 +231,8 @@ static int ohci_urb_enqueue (
 
                /* Start up the I/O watchdog timer, if it's not running */
                if (!timer_pending(&ohci->io_watchdog) &&
-                               list_empty(&ohci->eds_in_use)) {
+                               list_empty(&ohci->eds_in_use) &&
+                               !(ohci->flags & OHCI_QUIRK_QEMU)) {
                        ohci->prev_frame_no = ohci_frame_no(ohci);
                        mod_timer(&ohci->io_watchdog,
                                        jiffies + IO_WATCHDOG_DELAY);
index bb1509675727b374586d61917920578cc7631a45..a84aebe9b0a97880ef1f83a17b483e7586f190b1 100644 (file)
@@ -164,6 +164,15 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
        return 0;
 }
 
+static int ohci_quirk_qemu(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+       ohci->flags |= OHCI_QUIRK_QEMU;
+       ohci_dbg(ohci, "enabled qemu quirk\n");
+       return 0;
+}
+
 /* List of quirks for OHCI */
 static const struct pci_device_id ohci_pci_quirks[] = {
        {
@@ -214,6 +223,13 @@ static const struct pci_device_id ohci_pci_quirks[] = {
                PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
                .driver_data = (unsigned long)ohci_quirk_amd700,
        },
+       {
+               .vendor         = PCI_VENDOR_ID_APPLE,
+               .device         = 0x003f,
+               .subvendor      = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+               .subdevice      = PCI_SUBDEVICE_ID_QEMU,
+               .driver_data    = (unsigned long)ohci_quirk_qemu,
+       },
 
        /* FIXME for some of the early AMD 760 southbridges, OHCI
         * won't work at all.  blacklist them.
index 37f1725e7a469c45fa035a46ed9827a5b92bc6c7..a51b189bdbd8dc0f71085032f626500eab410ae0 100644 (file)
@@ -418,6 +418,7 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_AMD_PLL      0x200                   /* AMD PLL quirk*/
 #define        OHCI_QUIRK_AMD_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
 #define        OHCI_QUIRK_GLOBAL_SUSPEND       0x800           /* must suspend ports */
+#define        OHCI_QUIRK_QEMU         0x1000                  /* relax timing expectations */
 
        // there are also chip quirks/bugs in init logic