diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-06 15:55:57 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-06 15:56:11 -0700 |
commit | eab54042cd850778febae18098e77000dd298630 (patch) | |
tree | 6bfe7d5af9aed911474896878dc42d8ac58b8663 | |
parent | 59c5f46fbe01a00eedf54a23789634438bb80603 (diff) | |
parent | cd3c18ba2fac14b34d03cae111f215009735ea06 (diff) |
Merge branch 'for-usb-linus' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus
* 'for-usb-linus' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci:
USB: xhci - fix interval calculation for FS isoc endpoints
xhci: Disable MSI for some Fresco Logic hosts.
xhci: Do not issue device reset when device is not setup
xhci: Add defines for hardcoded slot states
xhci: Bigendian fix for xhci_check_bandwidth()
xhci: Bigendian fix for skip_isoc_td()
-rw-r--r-- | drivers/usb/host/xhci-dbg.c | 8 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 14 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 14 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 6 |
6 files changed, 51 insertions, 11 deletions
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 2e0486178db..1f50b4468e8 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -438,13 +438,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { - case 0: + case SLOT_STATE_ENABLED: return "enabled/disabled"; - case 1: + case SLOT_STATE_DEFAULT: return "default"; - case 2: + case SLOT_STATE_ADDRESSED: return "addressed"; - case 3: + case SLOT_STATE_CONFIGURED: return "configured"; default: return "reserved"; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 26caba4c195..0f8e1d29a85 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -985,9 +985,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; if (interval != ep->desc.bInterval - 1) dev_warn(&udev->dev, - "ep %#x - rounding interval to %d microframes\n", + "ep %#x - rounding interval to %d %sframes\n", ep->desc.bEndpointAddress, - 1 << interval); + 1 << interval, + udev->speed == USB_SPEED_FULL ? "" : "micro"); + + if (udev->speed == USB_SPEED_FULL) { + /* + * Full speed isoc endpoints specify interval in frames, + * not microframes. We are using microframes everywhere, + * so adjust accordingly. + */ + interval += 3; /* 1 frame = 2^3 uframes */ + } return interval; } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index c408e9f6a70..17541d09eab 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -106,12 +106,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd) /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && - pdev->revision == 0x0) { + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { + if (pdev->revision == 0x0) { xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" " endpoint cmd after reset endpoint\n"); + } + /* Fresco Logic confirms: all revisions of this chip do not + * support MSI, even though some of them claim to in their PCI + * capabilities. + */ + xhci->quirks |= XHCI_BROKEN_MSI; + xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u " + "has broken MSI implementation\n", + pdev->revision); } + if (pdev->vendor == PCI_VENDOR_ID_NEC) xhci->quirks |= XHCI_NEC_HOST; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index cc1485bfed3..800f417c730 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1782,7 +1782,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, struct usb_iso_packet_descriptor *frame; int idx; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); urb_priv = td->urb->hcpriv; idx = urb_priv->td_cnt; frame = &td->urb->iso_frame_desc[idx]; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d9660eb97eb..06e7023258d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd) free_irq(hcd->irq, hcd); hcd->irq = -1; + /* Some Fresco Logic host controllers advertise MSI, but fail to + * generate interrupts. Don't even try to enable MSI. + */ + if (xhci->quirks & XHCI_BROKEN_MSI) + goto legacy_irq; + ret = xhci_setup_msix(xhci); if (ret) /* fall back to msi*/ ret = xhci_setup_msi(xhci); if (ret) { +legacy_irq: /* fall back to legacy interrupt*/ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, hcd->irq_descr, hcd); @@ -1849,8 +1856,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) /* Free any rings that were dropped, but not changed. */ for (i = 1; i < 31; ++i) { - if ((ctrl_ctx->drop_flags & (1 << (i + 1))) && - !(ctrl_ctx->add_flags & (1 << (i + 1)))) + if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) && + !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); } xhci_zero_in_ctx(xhci, virt_dev); @@ -2467,6 +2474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_command *reset_device_cmd; int timeleft; int last_freed_endpoint; + struct xhci_slot_ctx *slot_ctx; ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__); if (ret <= 0) @@ -2499,6 +2507,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) return -EINVAL; } + /* If device is not setup, there is no point in resetting it */ + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); + if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == + SLOT_STATE_DISABLED) + return 0; + xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); /* Allocate the command structure that holds the struct completion. * Assume we're in process context, since the normal device reset diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ac0196e7fcf..7d1ea3bf5e1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -560,6 +560,11 @@ struct xhci_slot_ctx { #define SLOT_STATE (0x1f << 27) #define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) +#define SLOT_STATE_DISABLED 0 +#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED +#define SLOT_STATE_DEFAULT 1 +#define SLOT_STATE_ADDRESSED 2 +#define SLOT_STATE_CONFIGURED 3 /** * struct xhci_ep_ctx @@ -1302,6 +1307,7 @@ struct xhci_hcd { * commands. */ #define XHCI_EP_LIMIT_QUIRK (1 << 5) +#define XHCI_BROKEN_MSI (1 << 6) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ |