Skip to content

Commit

Permalink
Merge tag 'usb-3.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of fixes for the USB core and drivers for 3.4-rc2

  Lots of tiny xhci fixes here, a few usb-serial driver fixes and new
  device ids, and a smattering of other minor fixes in different USB
  drivers.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'usb-3.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (30 commits)
  USB: update usbtmc api documentation
  xHCI: Correct the #define XHCI_LEGACY_DISABLE_SMI
  xHCI: use gfp flags from caller instead of GFP_ATOMIC
  xHCI: add XHCI_RESET_ON_RESUME quirk for VIA xHCI host
  USB: fix bug of device descriptor got from superspeed device
  xhci: Fix register save/restore order.
  xhci: Restore event ring dequeue pointer on resume.
  xhci: Don't write zeroed pointers to xHC registers.
  xhci: Warn when hosts don't halt.
  xhci: don't re-enable IE constantly
  usb: xhci: fix section mismatch in linux-next
  xHCI: correct to print the true HSEE of USBCMD
  USB: serial: fix race between probe and open
  UHCI: hub_status_data should indicate if ports are resuming
  EHCI: keep track of ports being resumed and indicate in hub_status_data
  USB: fix race between root-hub suspend and remote wakeup
  USB: sierra: add support for Sierra Wireless MC7710
  USB: ftdi_sio: fix race condition in TIOCMIWAIT, and abort of TIOCMIWAIT when the device is removed
  USB: ftdi_sio: fix status line change handling for TIOCMIWAIT and TIOCGICOUNT
  USB: don't ignore suspend errors for root hubs
  ...
  • Loading branch information
Linus Torvalds committed Apr 12, 2012
2 parents f4f9c1a + 9de2922 commit 7c427f4
Show file tree
Hide file tree
Showing 32 changed files with 216 additions and 118 deletions.
14 changes: 7 additions & 7 deletions Documentation/ABI/stable/sysfs-driver-usb-usbtmc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
What: /sys/bus/usb/drivers/usbtmc/devices/*/interface_capabilities
What: /sys/bus/usb/drivers/usbtmc/devices/*/device_capabilities
What: /sys/bus/usb/drivers/usbtmc/*/interface_capabilities
What: /sys/bus/usb/drivers/usbtmc/*/device_capabilities
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
Expand All @@ -12,8 +12,8 @@ Description:
The files are read only.


What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_interface_capabilities
What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_device_capabilities
What: /sys/bus/usb/drivers/usbtmc/*/usb488_interface_capabilities
What: /sys/bus/usb/drivers/usbtmc/*/usb488_device_capabilities
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
Expand All @@ -27,7 +27,7 @@ Description:
The files are read only.


What: /sys/bus/usb/drivers/usbtmc/devices/*/TermChar
What: /sys/bus/usb/drivers/usbtmc/*/TermChar
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
Expand All @@ -40,7 +40,7 @@ Description:
sent to the device or not.


What: /sys/bus/usb/drivers/usbtmc/devices/*/TermCharEnabled
What: /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
Expand All @@ -51,7 +51,7 @@ Description:
published by the USB-IF.


What: /sys/bus/usb/drivers/usbtmc/devices/*/auto_abort
What: /sys/bus/usb/drivers/usbtmc/*/auto_abort
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
Expand Down
22 changes: 22 additions & 0 deletions Documentation/usb/URB.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,28 @@ that if the completion handler or anyone else tries to resubmit it
they will get a -EPERM error. Thus you can be sure that when
usb_kill_urb() returns, the URB is totally idle.

There is a lifetime issue to consider. An URB may complete at any
time, and the completion handler may free the URB. If this happens
while usb_unlink_urb or usb_kill_urb is running, it will cause a
memory-access violation. The driver is responsible for avoiding this,
which often means some sort of lock will be needed to prevent the URB
from being deallocated while it is still in use.

On the other hand, since usb_unlink_urb may end up calling the
completion handler, the handler must not take any lock that is held
when usb_unlink_urb is invoked. The general solution to this problem
is to increment the URB's reference count while holding the lock, then
drop the lock and call usb_unlink_urb or usb_kill_urb, and then
decrement the URB's reference count. You increment the reference
count by calling

struct urb *usb_get_urb(struct urb *urb)

(ignore the return value; it is the same as the argument) and
decrement the reference count by calling usb_free_urb. Of course,
none of this is necessary if there's no danger of the URB being freed
by the completion handler.


1.7. What about the completion handler?

Expand Down
6 changes: 3 additions & 3 deletions Documentation/usb/usbmon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,10 @@ An input control transfer to get a port status.
d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000

An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
to a storage device at address 5:
An output bulk transfer to send a SCSI command 0x28 (READ_10) in a 31-byte
Bulk wrapper to a storage device at address 5:

dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000
dd65f0e8 4128379808 C Bo:1:005:2 0 31 >

* Raw binary format and API
Expand Down
16 changes: 8 additions & 8 deletions drivers/usb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@
# USB device configuration
#

menuconfig USB_SUPPORT
bool "USB support"
depends on HAS_IOMEM
default y
---help---
This option adds core support for Universal Serial Bus (USB).
You will also need drivers from the following menu to make use of it.

# many non-PCI SOC chips embed OHCI
config USB_ARCH_HAS_OHCI
boolean
Expand Down Expand Up @@ -63,6 +55,14 @@ config USB_ARCH_HAS_XHCI
boolean
default PCI

menuconfig USB_SUPPORT
bool "USB support"
depends on HAS_IOMEM
default y
---help---
This option adds core support for Universal Serial Bus (USB).
You will also need drivers from the following menu to make use of it.

if USB_SUPPORT

config USB_COMMON
Expand Down
9 changes: 7 additions & 2 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1189,8 +1189,13 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
if (status == 0) {
status = usb_suspend_device(udev, msg);

/* Again, ignore errors during system sleep transitions */
if (!PMSG_IS_AUTO(msg))
/*
* Ignore errors from non-root-hub devices during
* system sleep transitions. For the most part,
* these devices should go to low power anyway when
* the entire bus is suspended.
*/
if (udev->parent && !PMSG_IS_AUTO(msg))
status = 0;
}

Expand Down
12 changes: 12 additions & 0 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1978,6 +1978,18 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
if (status == 0) {
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;

/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
char buffer[6];

status = hcd->driver->hub_status_data(hcd, buffer);
if (status != 0) {
dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n");
hcd_bus_resume(rhdev, PMSG_AUTO_RESUME);
status = -EBUSY;
}
}
} else {
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
Expand Down
16 changes: 16 additions & 0 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -3163,6 +3163,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (retval)
goto fail;

/*
* Some superspeed devices have finished the link training process
* and attached to a superspeed hub port, but the device descriptor
* got from those devices show they aren't superspeed devices. Warm
* reset the port attached by the devices can fix them.
*/
if ((udev->speed == USB_SPEED_SUPER) &&
(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
dev_err(&udev->dev, "got a wrong device descriptor, "
"warm reset device\n");
hub_port_reset(hub, port1, udev,
HUB_BH_RESET_TIME, true);
retval = -EINVAL;
goto fail;
}

if (udev->descriptor.bMaxPacketSize0 == 0xff ||
udev->speed == USB_SPEED_SUPER)
i = 512;
Expand Down
11 changes: 6 additions & 5 deletions drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb)
retval = usb_unlink_urb(io->urbs [i]);
if (retval != -EINPROGRESS &&
retval != -ENODEV &&
retval != -EBUSY)
retval != -EBUSY &&
retval != -EIDRM)
dev_err(&io->dev->dev,
"%s, unlink --> %d\n",
__func__, retval);
Expand All @@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb)
}
spin_lock(&io->lock);
}
urb->dev = NULL;

/* on the last completion, signal usb_sg_wait() */
io->bytes += urb->actual_length;
Expand Down Expand Up @@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io)
case -ENXIO: /* hc didn't queue this one */
case -EAGAIN:
case -ENOMEM:
io->urbs[i]->dev = NULL;
retval = 0;
yield();
break;
Expand All @@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io)

/* fail any uncompleted urbs */
default:
io->urbs[i]->dev = NULL;
io->urbs[i]->status = retval;
dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
__func__, retval);
Expand Down Expand Up @@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io)
if (!io->urbs [i]->dev)
continue;
retval = usb_unlink_urb(io->urbs [i]);
if (retval != -EINPROGRESS && retval != -EBUSY)
if (retval != -EINPROGRESS
&& retval != -ENODEV
&& retval != -EBUSY
&& retval != -EIDRM)
dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
__func__, retval);
}
Expand Down
12 changes: 12 additions & 0 deletions drivers/usb/core/urb.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,10 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
* never submitted, or it was unlinked before, or the hardware is already
* finished with it), even if the completion handler has not yet run.
*
* The URB must not be deallocated while this routine is running. In
* particular, when a driver calls this routine, it must insure that the
* completion handler cannot deallocate the URB.
*
* Unlinking and Endpoint Queues:
*
* [The behaviors and guarantees described below do not apply to virtual
Expand Down Expand Up @@ -603,6 +607,10 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
* with error -EPERM. Thus even if the URB's completion handler always
* tries to resubmit, it will not succeed and the URB will become idle.
*
* The URB must not be deallocated while this routine is running. In
* particular, when a driver calls this routine, it must insure that the
* completion handler cannot deallocate the URB.
*
* This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule().
Expand Down Expand Up @@ -640,6 +648,10 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
* with error -EPERM. Thus even if the URB's completion handler always
* tries to resubmit, it will not succeed and the URB will become idle.
*
* The URB must not be deallocated while this routine is running. In
* particular, when a driver calls this routine, it must insure that the
* completion handler cannot deallocate the URB.
*
* This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule().
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/gadget/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,6 @@ static void destroy_ep_files (struct dev_data *dev)
DBG (dev, "%s %d\n", __func__, dev->state);

/* dev->state must prevent interference */
restart:
spin_lock_irq (&dev->lock);
while (!list_empty(&dev->epfiles)) {
struct ep_data *ep;
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ static int ehci_reset (struct ehci_hcd *ehci)
if (ehci->debug)
dbgp_external_startup();

ehci->port_c_suspend = ehci->suspended_ports =
ehci->resuming_ports = 0;
return retval;
}

Expand Down Expand Up @@ -939,6 +941,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
* like usb_port_resume() does.
*/
ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
set_bit(i, &ehci->resuming_ports);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
}
Expand Down
31 changes: 16 additions & 15 deletions drivers/usb/host/ehci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
* remote wakeup, we must fail the suspend.
*/
if (hcd->self.root_hub->do_remote_wakeup) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
if (ehci->reset_done[port] != 0) {
spin_unlock_irq(&ehci->lock);
ehci_dbg(ehci, "suspend failed because "
"port %d is resuming\n",
port + 1);
return -EBUSY;
}
if (ehci->resuming_ports) {
spin_unlock_irq(&ehci->lock);
ehci_dbg(ehci, "suspend failed because a port is resuming\n");
return -EBUSY;
}
}

Expand Down Expand Up @@ -554,16 +549,12 @@ static int
ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp, status = 0;
u32 temp, status;
u32 mask;
int ports, i, retval = 1;
unsigned long flags;
u32 ppcd = 0;

/* if !USB_SUSPEND, root hub timers won't get shut down ... */
if (ehci->rh_state != EHCI_RH_RUNNING)
return 0;

/* init status to no-changes */
buf [0] = 0;
ports = HCS_N_PORTS (ehci->hcs_params);
Expand All @@ -572,6 +563,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
retval++;
}

/* Inform the core about resumes-in-progress by returning
* a non-zero value even if there are no status changes.
*/
status = ehci->resuming_ports;

/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
* may be relevant that VIA VT8235 controllers, where PORT_POWER is
Expand Down Expand Up @@ -846,6 +842,7 @@ static int ehci_hub_control (
ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_RESUME),
status_reg);
clear_bit(wIndex, &ehci->resuming_ports);
retval = handshake(ehci, status_reg,
PORT_RESUME, 0, 2000 /* 2msec */);
if (retval != 0) {
Expand All @@ -864,6 +861,7 @@ static int ehci_hub_control (
ehci->reset_done[wIndex])) {
status |= USB_PORT_STAT_C_RESET << 16;
ehci->reset_done [wIndex] = 0;
clear_bit(wIndex, &ehci->resuming_ports);

/* force reset to complete */
ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
Expand All @@ -884,8 +882,10 @@ static int ehci_hub_control (
ehci_readl(ehci, status_reg));
}

if (!(temp & (PORT_RESUME|PORT_RESET)))
if (!(temp & (PORT_RESUME|PORT_RESET))) {
ehci->reset_done[wIndex] = 0;
clear_bit(wIndex, &ehci->resuming_ports);
}

/* transfer dedicated ports to the companion hc */
if ((temp & PORT_CONNECT) &&
Expand Down Expand Up @@ -920,6 +920,7 @@ static int ehci_hub_control (
status |= USB_PORT_STAT_SUSPEND;
} else if (test_bit(wIndex, &ehci->suspended_ports)) {
clear_bit(wIndex, &ehci->suspended_ports);
clear_bit(wIndex, &ehci->resuming_ports);
ehci->reset_done[wIndex] = 0;
if (temp & PORT_PE)
set_bit(wIndex, &ehci->port_c_suspend);
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/host/ehci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ static int tegra_ehci_hub_control(
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
/* start resume signalling */
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
set_bit(wIndex-1, &ehci->resuming_ports);

spin_unlock_irqrestore(&ehci->lock, flags);
msleep(20);
Expand All @@ -236,6 +237,7 @@ static int tegra_ehci_hub_control(
pr_err("%s: timeout waiting for SUSPEND\n", __func__);

ehci->reset_done[wIndex-1] = 0;
clear_bit(wIndex-1, &ehci->resuming_ports);

tegra->port_resuming = 1;
goto done;
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ struct ehci_hcd { /* one per controller */
the change-suspend feature turned on */
unsigned long suspended_ports; /* which ports are
suspended */
unsigned long resuming_ports; /* which ports have
started to resume */

/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
Expand Down
Loading

0 comments on commit 7c427f4

Please sign in to comment.