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()
This commit is contained in:
commit
eab54042cd
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user