Merge branch 'for-usb-linus' of git+ssh://master.kernel.org/pub/scm/linux/kernel...
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 1 Aug 2011 23:38:38 +0000 (16:38 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 1 Aug 2011 23:39:14 +0000 (16:39 -0700)
* 'for-usb-linus' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci:
  usb/config: use proper endian access for wMaxPacketSize
  USB: xhci: fix OS want to own HC
  xhci: Don't submit commands or URBs to halted hosts.

drivers/usb/core/config.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci.c

index c962608..26678ca 100644 (file)
@@ -123,10 +123,11 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
        }
 
        if (usb_endpoint_xfer_isoc(&ep->desc))
-               max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) *
-                       (desc->bmAttributes + 1);
+               max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
+                       le16_to_cpu(ep->desc.wMaxPacketSize);
        else if (usb_endpoint_xfer_int(&ep->desc))
-               max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
+               max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) *
+                       (desc->bMaxBurst + 1);
        else
                max_tx = 999999;
        if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
@@ -134,10 +135,10 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
                                "config %d interface %d altsetting %d ep %d: "
                                "setting to %d\n",
                                usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
-                               desc->wBytesPerInterval,
+                               le16_to_cpu(desc->wBytesPerInterval),
                                cfgno, inum, asnum, ep->desc.bEndpointAddress,
                                max_tx);
-               ep->ss_ep_comp.wBytesPerInterval = max_tx;
+               ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
        }
 }
 
index a9d3159..f4d1b69 100644 (file)
@@ -817,7 +817,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
 
        /* If the BIOS owns the HC, signal that the OS wants it, and wait */
        if (val & XHCI_HC_BIOS_OWNED) {
-               writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset);
+               writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
 
                /* Wait for 5 seconds with 10 microsecond polling interval */
                timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED,
index 763f484..1c4432d 100644 (file)
@@ -345,7 +345,8 @@ static void xhci_event_ring_work(unsigned long arg)
        spin_lock_irqsave(&xhci->lock, flags);
        temp = xhci_readl(xhci, &xhci->op_regs->status);
        xhci_dbg(xhci, "op reg status = 0x%x\n", temp);
-       if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) {
+       if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_dbg(xhci, "HW died, polling stopped.\n");
                spin_unlock_irqrestore(&xhci->lock, flags);
                return;
@@ -939,8 +940,11 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
                return 0;
        }
 
+       xhci = hcd_to_xhci(hcd);
+       if (xhci->xhc_state & XHCI_STATE_HALTED)
+               return -ENODEV;
+
        if (check_virt_dev) {
-               xhci = hcd_to_xhci(hcd);
                if (!udev->slot_id || !xhci->devs
                        || !xhci->devs[udev->slot_id]) {
                        printk(KERN_DEBUG "xHCI %s called with unaddressed "
@@ -1242,7 +1246,8 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                xhci_urb_free_priv(xhci, urb_priv);
                return ret;
        }
-       if (xhci->xhc_state & XHCI_STATE_DYING) {
+       if ((xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on "
                                "non-responsive xHCI host.\n",
                                urb->ep->desc.bEndpointAddress, urb);
@@ -2665,7 +2670,10 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        int i, ret;
 
        ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
-       if (ret <= 0)
+       /* If the host is halted due to driver unload, we still need to free the
+        * device.
+        */
+       if (ret <= 0 && ret != -ENODEV)
                return;
 
        virt_dev = xhci->devs[udev->slot_id];
@@ -2679,7 +2687,8 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        spin_lock_irqsave(&xhci->lock, flags);
        /* Don't disable the slot if the host controller is dead. */
        state = xhci_readl(xhci, &xhci->op_regs->status);
-       if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) {
+       if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_free_virt_device(xhci, udev->slot_id);
                spin_unlock_irqrestore(&xhci->lock, flags);
                return;