提交 2e34b429 编写于 作者: L Linus Torvalds

Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  MAINTAINERS: add myself as maintainer of USB/IP
  usb: r8a66597-hcd: fix cannot detect low/full speed device
  USB: ehci-ath79: fix a NULL pointer dereference
  USB: Add new FT232H chip to drivers/usb/serial/ftdi_sio.c
  usb/isp1760: Fix bug preventing the unlinking of control urbs
  USB: Fix up URB error codes to reflect implementation.
  xhci: Always set urb->status to zero for isoc endpoints.
  xhci: Add reset on resume quirk for asrock p67 host
  xHCI 1.0: Incompatible Device Error
  USB: don't let errors prevent system sleep
  USB: don't let the hub driver prevent system sleep
  USB: change maintainership of ohci-hcd and ehci-hcd
  xHCI 1.0: Force Stopped Event(FSE)
  xhci: Don't warn about zeroed bMaxBurst descriptor field.
  USB: Free bandwidth when usb_disable_device is called.
  xhci: Reject double add of active endpoints.
  USB: TI 3410/5052 USB Serial Driver: Fix mem leak when firmware is too big.
  usb: musb: gadget: clear TXPKTRDY flag when set FLUSHFIFO
  usb: musb: host: compare status for negative error values
...@@ -76,6 +76,13 @@ A transfer's actual_length may be positive even when an error has been ...@@ -76,6 +76,13 @@ A transfer's actual_length may be positive even when an error has been
reported. That's because transfers often involve several packets, so that reported. That's because transfers often involve several packets, so that
one or more packets could finish before an error stops further endpoint I/O. one or more packets could finish before an error stops further endpoint I/O.
For isochronous URBs, the urb status value is non-zero only if the URB is
unlinked, the device is removed, the host controller is disabled, or the total
transferred length is less than the requested length and the URB_SHORT_NOT_OK
flag is set. Completion handlers for isochronous URBs should only see
urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
Individual frame descriptor status fields may report more status codes.
0 Transfer completed successfully 0 Transfer completed successfully
...@@ -132,7 +139,7 @@ one or more packets could finish before an error stops further endpoint I/O. ...@@ -132,7 +139,7 @@ one or more packets could finish before an error stops further endpoint I/O.
device removal events immediately. device removal events immediately.
-EXDEV ISO transfer only partially completed -EXDEV ISO transfer only partially completed
look at individual frame status for details (only set in iso_frame_desc[n].status, not urb->status)
-EINVAL ISO madness, if this happens: Log off and go home -EINVAL ISO madness, if this happens: Log off and go home
......
...@@ -6434,8 +6434,9 @@ S: Maintained ...@@ -6434,8 +6434,9 @@ S: Maintained
F: drivers/usb/misc/rio500* F: drivers/usb/misc/rio500*
USB EHCI DRIVER USB EHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Orphan S: Maintained
F: Documentation/usb/ehci.txt F: Documentation/usb/ehci.txt
F: drivers/usb/host/ehci* F: drivers/usb/host/ehci*
...@@ -6465,6 +6466,12 @@ S: Maintained ...@@ -6465,6 +6466,12 @@ S: Maintained
F: Documentation/hid/hiddev.txt F: Documentation/hid/hiddev.txt
F: drivers/hid/usbhid/ F: drivers/hid/usbhid/
USB/IP DRIVERS
M: Matt Mooney <mfm@muteddisk.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/staging/usbip/
USB ISP116X DRIVER USB ISP116X DRIVER
M: Olav Kongas <ok@artecdesign.ee> M: Olav Kongas <ok@artecdesign.ee>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
...@@ -6494,8 +6501,9 @@ S: Maintained ...@@ -6494,8 +6501,9 @@ S: Maintained
F: sound/usb/midi.* F: sound/usb/midi.*
USB OHCI DRIVER USB OHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Orphan S: Maintained
F: Documentation/usb/ohci.txt F: Documentation/usb/ohci.txt
F: drivers/usb/host/ohci* F: drivers/usb/host/ohci*
......
...@@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) ...@@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
for (i = n - 1; i >= 0; --i) { for (i = n - 1; i >= 0; --i) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
status = usb_suspend_interface(udev, intf, msg); status = usb_suspend_interface(udev, intf, msg);
/* Ignore errors during system sleep transitions */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
if (status != 0) if (status != 0)
break; break;
} }
} }
if (status == 0) if (status == 0) {
status = usb_suspend_device(udev, msg); status = usb_suspend_device(udev, msg);
/* Again, ignore errors during system sleep transitions */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
}
/* If the suspend failed, resume interfaces that did get suspended */ /* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) { if (status != 0) {
msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
......
...@@ -1634,6 +1634,7 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -1634,6 +1634,7 @@ void usb_disconnect(struct usb_device **pdev)
{ {
struct usb_device *udev = *pdev; struct usb_device *udev = *pdev;
int i; int i;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (!udev) { if (!udev) {
pr_debug ("%s nodev\n", __func__); pr_debug ("%s nodev\n", __func__);
...@@ -1661,7 +1662,9 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -1661,7 +1662,9 @@ void usb_disconnect(struct usb_device **pdev)
* so that the hardware is now fully quiesced. * so that the hardware is now fully quiesced.
*/ */
dev_dbg (&udev->dev, "unregistering device\n"); dev_dbg (&udev->dev, "unregistering device\n");
mutex_lock(hcd->bandwidth_mutex);
usb_disable_device(udev, 0); usb_disable_device(udev, 0);
mutex_unlock(hcd->bandwidth_mutex);
usb_hcd_synchronize_unlinks(udev); usb_hcd_synchronize_unlinks(udev);
usb_remove_ep_devs(&udev->ep0); usb_remove_ep_devs(&udev->ep0);
...@@ -2362,6 +2365,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) ...@@ -2362,6 +2365,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
USB_DEVICE_REMOTE_WAKEUP, 0, USB_DEVICE_REMOTE_WAKEUP, 0,
NULL, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT); USB_CTRL_SET_TIMEOUT);
/* System sleep transitions should never fail */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
} else { } else {
/* device has up to 10 msec to fully suspend */ /* device has up to 10 msec to fully suspend */
dev_dbg(&udev->dev, "usb %ssuspend\n", dev_dbg(&udev->dev, "usb %ssuspend\n",
...@@ -2611,16 +2618,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) ...@@ -2611,16 +2618,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_device *hdev = hub->hdev; struct usb_device *hdev = hub->hdev;
unsigned port1; unsigned port1;
/* fail if children aren't already suspended */ /* Warn if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) { for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev; struct usb_device *udev;
udev = hdev->children [port1-1]; udev = hdev->children [port1-1];
if (udev && udev->can_submit) { if (udev && udev->can_submit) {
if (!(msg.event & PM_EVENT_AUTO)) dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
dev_dbg(&intf->dev, "port %d nyet suspended\n", if (msg.event & PM_EVENT_AUTO)
port1); return -EBUSY;
return -EBUSY;
} }
} }
......
...@@ -1135,10 +1135,13 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, ...@@ -1135,10 +1135,13 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
* Deallocates hcd/hardware state for the endpoints (nuking all or most * Deallocates hcd/hardware state for the endpoints (nuking all or most
* pending urbs) and usbcore state for the interfaces, so that usbcore * pending urbs) and usbcore state for the interfaces, so that usbcore
* must usb_set_configuration() before any interfaces could be used. * must usb_set_configuration() before any interfaces could be used.
*
* Must be called with hcd->bandwidth_mutex held.
*/ */
void usb_disable_device(struct usb_device *dev, int skip_ep0) void usb_disable_device(struct usb_device *dev, int skip_ep0)
{ {
int i; int i;
struct usb_hcd *hcd = bus_to_hcd(dev->bus);
/* getting rid of interfaces will disconnect /* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect) * any drivers bound to them (a key side effect)
...@@ -1172,6 +1175,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -1172,6 +1175,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
skip_ep0 ? "non-ep0" : "all"); skip_ep0 ? "non-ep0" : "all");
if (hcd->driver->check_bandwidth) {
/* First pass: Cancel URBs, leave endpoint pointers intact. */
for (i = skip_ep0; i < 16; ++i) {
usb_disable_endpoint(dev, i, false);
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
}
/* Remove endpoints from the host controller internal state */
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
/* Second pass: remove endpoint pointers */
}
for (i = skip_ep0; i < 16; ++i) { for (i = skip_ep0; i < 16; ++i) {
usb_disable_endpoint(dev, i, true); usb_disable_endpoint(dev, i, true);
usb_disable_endpoint(dev, i + USB_DIR_IN, true); usb_disable_endpoint(dev, i + USB_DIR_IN, true);
...@@ -1727,6 +1740,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1727,6 +1740,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* if it's already configured, clear out old state first. /* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers. * getting rid of old interfaces means unbinding their drivers.
*/ */
mutex_lock(hcd->bandwidth_mutex);
if (dev->state != USB_STATE_ADDRESS) if (dev->state != USB_STATE_ADDRESS)
usb_disable_device(dev, 1); /* Skip ep0 */ usb_disable_device(dev, 1); /* Skip ep0 */
...@@ -1739,7 +1753,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1739,7 +1753,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
* host controller will not allow submissions to dropped endpoints. If * host controller will not allow submissions to dropped endpoints. If
* this call fails, the device state is unchanged. * this call fails, the device state is unchanged.
*/ */
mutex_lock(hcd->bandwidth_mutex);
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) { if (ret < 0) {
mutex_unlock(hcd->bandwidth_mutex); mutex_unlock(hcd->bandwidth_mutex);
......
...@@ -44,7 +44,6 @@ static int ehci_ath79_init(struct usb_hcd *hcd) ...@@ -44,7 +44,6 @@ static int ehci_ath79_init(struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct platform_device *pdev = to_platform_device(hcd->self.controller); struct platform_device *pdev = to_platform_device(hcd->self.controller);
const struct platform_device_id *id; const struct platform_device_id *id;
int hclength;
int ret; int ret;
id = platform_get_device_id(pdev); id = platform_get_device_id(pdev);
...@@ -53,20 +52,23 @@ static int ehci_ath79_init(struct usb_hcd *hcd) ...@@ -53,20 +52,23 @@ static int ehci_ath79_init(struct usb_hcd *hcd)
return -EINVAL; return -EINVAL;
} }
hclength = HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
switch (id->driver_data) { switch (id->driver_data) {
case EHCI_ATH79_IP_V1: case EHCI_ATH79_IP_V1:
ehci->has_synopsys_hc_bug = 1; ehci->has_synopsys_hc_bug = 1;
ehci->caps = hcd->regs; ehci->caps = hcd->regs;
ehci->regs = hcd->regs + hclength; ehci->regs = hcd->regs +
HC_LENGTH(ehci,
ehci_readl(ehci, &ehci->caps->hc_capbase));
break; break;
case EHCI_ATH79_IP_V2: case EHCI_ATH79_IP_V2:
hcd->has_tt = 1; hcd->has_tt = 1;
ehci->caps = hcd->regs + 0x100; ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 + hclength; ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci,
ehci_readl(ehci, &ehci->caps->hc_capbase));
break; break;
default: default:
......
/* /*
* Enhanced Host Controller Interface (EHCI) driver for USB.
*
* Maintainer: Alan Stern <stern@rowland.harvard.edu>
*
* Copyright (c) 2000-2004 by David Brownell * Copyright (c) 2000-2004 by David Brownell
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
......
...@@ -1555,7 +1555,7 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb, ...@@ -1555,7 +1555,7 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb,
/* We need to forcefully reclaim the slot since some transfers never /* We need to forcefully reclaim the slot since some transfers never
return, e.g. interrupt transfers and NAKed bulk transfers. */ return, e.g. interrupt transfers and NAKed bulk transfers. */
if (usb_pipebulk(urb->pipe)) { if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe)) {
skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
skip_map |= (1 << qh->slot); skip_map |= (1 << qh->slot);
reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
......
/* /*
* OHCI HCD (Host Controller Driver) for USB. * Open Host Controller Interface (OHCI) driver for USB.
*
* Maintainer: Alan Stern <stern@rowland.harvard.edu>
* *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
......
...@@ -2517,6 +2517,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) ...@@ -2517,6 +2517,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&r8a66597->child_device); INIT_LIST_HEAD(&r8a66597->child_device);
hcd->rsrc_start = res->start; hcd->rsrc_start = res->start;
hcd->has_tt = 1;
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger); ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger);
if (ret != 0) { if (ret != 0) {
......
...@@ -1215,8 +1215,6 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ...@@ -1215,8 +1215,6 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
/* dig out max burst from ep companion desc */ /* dig out max burst from ep companion desc */
max_packet = ep->ss_ep_comp.bMaxBurst; max_packet = ep->ss_ep_comp.bMaxBurst;
if (!max_packet)
xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n");
ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet)); ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet));
break; break;
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
#define PCI_VENDOR_ID_ETRON 0x1b6f
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
static const char hcd_name[] = "xhci_hcd"; static const char hcd_name[] = "xhci_hcd";
/* called after powerup, by probe or system-pm "wakeup" */ /* called after powerup, by probe or system-pm "wakeup" */
...@@ -134,6 +137,11 @@ static int xhci_pci_setup(struct usb_hcd *hcd) ...@@ -134,6 +137,11 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->quirks |= XHCI_EP_LIMIT_QUIRK;
xhci->limit_active_eps = 64; xhci->limit_active_eps = 64;
} }
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
}
/* Make sure the HC is halted. */ /* Make sure the HC is halted. */
retval = xhci_halt(xhci); retval = xhci_halt(xhci);
......
...@@ -1733,6 +1733,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -1733,6 +1733,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
frame->status = -EOVERFLOW; frame->status = -EOVERFLOW;
skip_td = true; skip_td = true;
break; break;
case COMP_DEV_ERR:
case COMP_STALL: case COMP_STALL:
frame->status = -EPROTO; frame->status = -EPROTO;
skip_td = true; skip_td = true;
...@@ -1767,9 +1768,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -1767,9 +1768,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
} }
} }
if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS)
*status = 0;
return finish_td(xhci, td, event_trb, event, ep, status, false); return finish_td(xhci, td, event_trb, event, ep, status, false);
} }
...@@ -1787,8 +1785,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -1787,8 +1785,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
idx = urb_priv->td_cnt; idx = urb_priv->td_cnt;
frame = &td->urb->iso_frame_desc[idx]; frame = &td->urb->iso_frame_desc[idx];
/* The transfer is partly done */ /* The transfer is partly done. */
*status = -EXDEV;
frame->status = -EXDEV; frame->status = -EXDEV;
/* calc actual length */ /* calc actual length */
...@@ -2016,6 +2013,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2016,6 +2013,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
ep_index); ep_index);
goto cleanup; goto cleanup;
case COMP_DEV_ERR:
xhci_warn(xhci, "WARN: detect an incompatible device");
status = -EPROTO;
break;
case COMP_MISSED_INT: case COMP_MISSED_INT:
/* /*
* When encounter missed service error, one or more isoc tds * When encounter missed service error, one or more isoc tds
...@@ -2063,6 +2064,20 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2063,6 +2064,20 @@ static int handle_tx_event(struct xhci_hcd *xhci,
/* Is this a TRB in the currently executing TD? */ /* Is this a TRB in the currently executing TD? */
event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
td->last_trb, event_dma); td->last_trb, event_dma);
/*
* Skip the Force Stopped Event. The event_trb(event_dma) of FSE
* is not in the current TD pointed by ep_ring->dequeue because
* that the hardware dequeue pointer still at the previous TRB
* of the current TD. The previous TRB maybe a Link TD or the
* last TRB of the previous TD. The command completion handle
* will take care the rest.
*/
if (!event_seg && trb_comp_code == COMP_STOP_INVAL) {
ret = 0;
goto cleanup;
}
if (!event_seg) { if (!event_seg) {
if (!ep->skip || if (!ep->skip ||
!usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
...@@ -2158,6 +2173,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2158,6 +2173,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
urb->transfer_buffer_length, urb->transfer_buffer_length,
status); status);
spin_unlock(&xhci->lock); spin_unlock(&xhci->lock);
/* EHCI, UHCI, and OHCI always unconditionally set the
* urb->status of an isochronous endpoint to 0.
*/
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
status = 0;
usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status); usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
spin_lock(&xhci->lock); spin_lock(&xhci->lock);
} }
......
...@@ -759,6 +759,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) ...@@ -759,6 +759,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
msleep(100); msleep(100);
spin_lock_irq(&xhci->lock); spin_lock_irq(&xhci->lock);
if (xhci->quirks & XHCI_RESET_ON_RESUME)
hibernated = true;
if (!hibernated) { if (!hibernated) {
/* step 1: restore register */ /* step 1: restore register */
...@@ -1401,6 +1403,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -1401,6 +1403,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
u32 added_ctxs; u32 added_ctxs;
unsigned int last_ctx; unsigned int last_ctx;
u32 new_add_flags, new_drop_flags, new_slot_info; u32 new_add_flags, new_drop_flags, new_slot_info;
struct xhci_virt_device *virt_dev;
int ret = 0; int ret = 0;
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
...@@ -1425,11 +1428,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -1425,11 +1428,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return 0; return 0;
} }
in_ctx = xhci->devs[udev->slot_id]->in_ctx; virt_dev = xhci->devs[udev->slot_id];
out_ctx = xhci->devs[udev->slot_id]->out_ctx; in_ctx = virt_dev->in_ctx;
out_ctx = virt_dev->out_ctx;
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
ep_index = xhci_get_endpoint_index(&ep->desc); ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
/* If this endpoint is already in use, and the upper layers are trying
* to add it again without dropping it, reject the addition.
*/
if (virt_dev->eps[ep_index].ring &&
!(le32_to_cpu(ctrl_ctx->drop_flags) &
xhci_get_endpoint_flag(&ep->desc))) {
xhci_warn(xhci, "Trying to add endpoint 0x%x "
"without dropping it.\n",
(unsigned int) ep->desc.bEndpointAddress);
return -EINVAL;
}
/* If the HCD has already noted the endpoint is enabled, /* If the HCD has already noted the endpoint is enabled,
* ignore this request. * ignore this request.
*/ */
...@@ -1445,8 +1462,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -1445,8 +1462,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* process context, not interrupt context (or so documenation * process context, not interrupt context (or so documenation
* for usb_set_interface() and usb_set_configuration() claim). * for usb_set_interface() and usb_set_configuration() claim).
*/ */
if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) {
udev, ep, GFP_NOIO) < 0) {
dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
__func__, ep->desc.bEndpointAddress); __func__, ep->desc.bEndpointAddress);
return -ENOMEM; return -ENOMEM;
...@@ -1537,6 +1553,11 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, ...@@ -1537,6 +1553,11 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
"and endpoint is not disabled.\n"); "and endpoint is not disabled.\n");
ret = -EINVAL; ret = -EINVAL;
break; break;
case COMP_DEV_ERR:
dev_warn(&udev->dev, "ERROR: Incompatible device for endpoint "
"configure command.\n");
ret = -ENODEV;
break;
case COMP_SUCCESS: case COMP_SUCCESS:
dev_dbg(&udev->dev, "Successful Endpoint Configure command\n"); dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
ret = 0; ret = 0;
...@@ -1571,6 +1592,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, ...@@ -1571,6 +1592,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
ret = -EINVAL; ret = -EINVAL;
break; break;
case COMP_DEV_ERR:
dev_warn(&udev->dev, "ERROR: Incompatible device for evaluate "
"context command.\n");
ret = -ENODEV;
break;
case COMP_MEL_ERR: case COMP_MEL_ERR:
/* Max Exit Latency too large error */ /* Max Exit Latency too large error */
dev_warn(&udev->dev, "WARN: Max Exit Latency too large\n"); dev_warn(&udev->dev, "WARN: Max Exit Latency too large\n");
...@@ -2853,6 +2879,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -2853,6 +2879,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
dev_warn(&udev->dev, "Device not responding to set address.\n"); dev_warn(&udev->dev, "Device not responding to set address.\n");
ret = -EPROTO; ret = -EPROTO;
break; break;
case COMP_DEV_ERR:
dev_warn(&udev->dev, "ERROR: Incompatible device for address "
"device command.\n");
ret = -ENODEV;
break;
case COMP_SUCCESS: case COMP_SUCCESS:
xhci_dbg(xhci, "Successful Address Device command\n"); xhci_dbg(xhci, "Successful Address Device command\n");
break; break;
......
...@@ -874,6 +874,8 @@ struct xhci_transfer_event { ...@@ -874,6 +874,8 @@ struct xhci_transfer_event {
#define COMP_PING_ERR 20 #define COMP_PING_ERR 20
/* Event Ring is full */ /* Event Ring is full */
#define COMP_ER_FULL 21 #define COMP_ER_FULL 21
/* Incompatible Device Error */
#define COMP_DEV_ERR 22
/* Missed Service Error - HC couldn't service an isoc ep within interval */ /* Missed Service Error - HC couldn't service an isoc ep within interval */
#define COMP_MISSED_INT 23 #define COMP_MISSED_INT 23
/* Successfully stopped command ring */ /* Successfully stopped command ring */
...@@ -1308,6 +1310,7 @@ struct xhci_hcd { ...@@ -1308,6 +1310,7 @@ struct xhci_hcd {
*/ */
#define XHCI_EP_LIMIT_QUIRK (1 << 5) #define XHCI_EP_LIMIT_QUIRK (1 << 5)
#define XHCI_BROKEN_MSI (1 << 6) #define XHCI_BROKEN_MSI (1 << 6)
#define XHCI_RESET_ON_RESUME (1 << 7)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */ /* There are two roothubs to keep track of bus suspend info for */
......
...@@ -1524,6 +1524,12 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep) ...@@ -1524,6 +1524,12 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
csr = musb_readw(epio, MUSB_TXCSR); csr = musb_readw(epio, MUSB_TXCSR);
if (csr & MUSB_TXCSR_FIFONOTEMPTY) { if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS; csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS;
/*
* Setting both TXPKTRDY and FLUSHFIFO makes controller
* to interrupt current FIFO loading, but not flushing
* the already loaded ones.
*/
csr &= ~MUSB_TXCSR_TXPKTRDY;
musb_writew(epio, MUSB_TXCSR, csr); musb_writew(epio, MUSB_TXCSR, csr);
/* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */ /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
musb_writew(epio, MUSB_TXCSR, csr); musb_writew(epio, MUSB_TXCSR, csr);
......
...@@ -1575,7 +1575,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1575,7 +1575,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
/* even if there was an error, we did the dma /* even if there was an error, we did the dma
* for iso_frame_desc->length * for iso_frame_desc->length
*/ */
if (d->status != EILSEQ && d->status != -EOVERFLOW) if (d->status != -EILSEQ && d->status != -EOVERFLOW)
d->status = 0; d->status = 0;
if (++qh->iso_idx >= urb->number_of_packets) if (++qh->iso_idx >= urb->number_of_packets)
......
...@@ -179,6 +179,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -179,6 +179,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
...@@ -848,7 +849,8 @@ static const char *ftdi_chip_name[] = { ...@@ -848,7 +849,8 @@ static const char *ftdi_chip_name[] = {
[FT2232C] = "FT2232C", [FT2232C] = "FT2232C",
[FT232RL] = "FT232RL", [FT232RL] = "FT232RL",
[FT2232H] = "FT2232H", [FT2232H] = "FT2232H",
[FT4232H] = "FT4232H" [FT4232H] = "FT4232H",
[FT232H] = "FT232H"
}; };
...@@ -1168,6 +1170,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, ...@@ -1168,6 +1170,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
break; break;
case FT2232H: /* FT2232H chip */ case FT2232H: /* FT2232H chip */
case FT4232H: /* FT4232H chip */ case FT4232H: /* FT4232H chip */
case FT232H: /* FT232H chip */
if ((baud <= 12000000) & (baud >= 1200)) { if ((baud <= 12000000) & (baud >= 1200)) {
div_value = ftdi_2232h_baud_to_divisor(baud); div_value = ftdi_2232h_baud_to_divisor(baud);
} else if (baud < 1200) { } else if (baud < 1200) {
...@@ -1429,9 +1432,12 @@ static void ftdi_determine_type(struct usb_serial_port *port) ...@@ -1429,9 +1432,12 @@ static void ftdi_determine_type(struct usb_serial_port *port)
} else if (version < 0x600) { } else if (version < 0x600) {
/* Assume it's an FT232BM (or FT245BM) */ /* Assume it's an FT232BM (or FT245BM) */
priv->chip_type = FT232BM; priv->chip_type = FT232BM;
} else { } else if (version < 0x900) {
/* Assume it's an FT232R */ /* Assume it's an FT232RL */
priv->chip_type = FT232RL; priv->chip_type = FT232RL;
} else {
/* Assume it's an FT232H */
priv->chip_type = FT232H;
} }
dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
} }
...@@ -1559,7 +1565,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port) ...@@ -1559,7 +1565,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT2232C || priv->chip_type == FT2232C ||
priv->chip_type == FT232RL || priv->chip_type == FT232RL ||
priv->chip_type == FT2232H || priv->chip_type == FT2232H ||
priv->chip_type == FT4232H)) { priv->chip_type == FT4232H ||
priv->chip_type == FT232H)) {
retval = device_create_file(&port->dev, retval = device_create_file(&port->dev,
&dev_attr_latency_timer); &dev_attr_latency_timer);
} }
...@@ -1580,7 +1587,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) ...@@ -1580,7 +1587,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT2232C || priv->chip_type == FT2232C ||
priv->chip_type == FT232RL || priv->chip_type == FT232RL ||
priv->chip_type == FT2232H || priv->chip_type == FT2232H ||
priv->chip_type == FT4232H) { priv->chip_type == FT4232H ||
priv->chip_type == FT232H) {
device_remove_file(&port->dev, &dev_attr_latency_timer); device_remove_file(&port->dev, &dev_attr_latency_timer);
} }
} }
...@@ -2212,6 +2220,7 @@ static int ftdi_tiocmget(struct tty_struct *tty) ...@@ -2212,6 +2220,7 @@ static int ftdi_tiocmget(struct tty_struct *tty)
case FT232RL: case FT232RL:
case FT2232H: case FT2232H:
case FT4232H: case FT4232H:
case FT232H:
len = 2; len = 2;
break; break;
default: default:
......
...@@ -156,7 +156,8 @@ enum ftdi_chip_type { ...@@ -156,7 +156,8 @@ enum ftdi_chip_type {
FT2232C = 4, FT2232C = 4,
FT232RL = 5, FT232RL = 5,
FT2232H = 6, FT2232H = 6,
FT4232H = 7 FT4232H = 7,
FT232H = 8
}; };
enum ftdi_sio_baudrate { enum ftdi_sio_baudrate {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */
#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
......
...@@ -1745,6 +1745,7 @@ static int ti_download_firmware(struct ti_device *tdev) ...@@ -1745,6 +1745,7 @@ static int ti_download_firmware(struct ti_device *tdev)
} }
if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size); dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size);
release_firmware(fw_p);
return -ENOENT; return -ENOENT;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册