Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  usb: Increase timeout value for device reset
  USB: put claimed interfaces in the "suspended" state
  USB: EHCI: defer reclamation of siTDs
  USB: fix remote wakeup settings during system sleep
  USB: pl2303: add AdLink ND-6530 USB IDs
  USB: Add id for HP ev2210 a.k.a Sierra MC5725 miniPCI-e Cell Modem.
  USB: OHCI: DA8xx/OMAP-L1x: fix up macro rename
  USB: qcaux: add LG Rumor and Sanyo Katana LX device IDs
  usb: wusb: don't overflow the Keep Alive IE buffer
  USB: ehci: omap: fix kernel panic with rmmod
  USB: fixed bug in usbsevseg using USB autosuspend incorrectly
  USB: ti_usb_3410_5052: adding multitech dialup fax/modem devices
  • Loading branch information
Linus Torvalds committed Apr 23, 2010
2 parents a2340be + 6307e09 commit a4b7d3b
Show file tree
Hide file tree
Showing 16 changed files with 139 additions and 30 deletions.
49 changes: 42 additions & 7 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ static int usb_probe_interface(struct device *dev)

intf->condition = USB_INTERFACE_BINDING;

/* Bound interfaces are initially active. They are
/* Probed interfaces are initially active. They are
* runtime-PM-enabled only if the driver has autosuspend support.
* They are sensitive to their children's power states.
*/
Expand Down Expand Up @@ -437,11 +437,11 @@ int usb_driver_claim_interface(struct usb_driver *driver,

iface->condition = USB_INTERFACE_BOUND;

/* Bound interfaces are initially active. They are
/* Claimed interfaces are initially inactive (suspended). They are
* runtime-PM-enabled only if the driver has autosuspend support.
* They are sensitive to their children's power states.
*/
pm_runtime_set_active(dev);
pm_runtime_set_suspended(dev);
pm_suspend_ignore_children(dev, false);
if (driver->supports_autosuspend)
pm_runtime_enable(dev);
Expand Down Expand Up @@ -1170,7 +1170,7 @@ static int usb_resume_interface(struct usb_device *udev,
static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
{
int status = 0;
int i = 0;
int i = 0, n = 0;
struct usb_interface *intf;

if (udev->state == USB_STATE_NOTATTACHED ||
Expand All @@ -1179,7 +1179,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)

/* Suspend all the interfaces and then udev itself */
if (udev->actconfig) {
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
n = udev->actconfig->desc.bNumInterfaces;
for (i = n - 1; i >= 0; --i) {
intf = udev->actconfig->interface[i];
status = usb_suspend_interface(udev, intf, msg);
if (status != 0)
Expand All @@ -1192,7 +1193,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
/* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) {
msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
while (--i >= 0) {
while (++i < n) {
intf = udev->actconfig->interface[i];
usb_resume_interface(udev, intf, msg, 0);
}
Expand Down Expand Up @@ -1263,13 +1264,47 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
return status;
}

static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
{
int w, i;
struct usb_interface *intf;

/* Remote wakeup is needed only when we actually go to sleep.
* For things like FREEZE and QUIESCE, if the device is already
* autosuspended then its current wakeup setting is okay.
*/
if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
if (udev->state != USB_STATE_SUSPENDED)
udev->do_remote_wakeup = 0;
return;
}

/* If remote wakeup is permitted, see whether any interface drivers
* actually want it.
*/
w = 0;
if (device_may_wakeup(&udev->dev) && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
w |= intf->needs_remote_wakeup;
}
}

/* If the device is autosuspended with the wrong wakeup setting,
* autoresume now so the setting can be changed.
*/
if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup)
pm_runtime_resume(&udev->dev);
udev->do_remote_wakeup = w;
}

/* The device lock is held by the PM core */
int usb_suspend(struct device *dev, pm_message_t msg)
{
struct usb_device *udev = to_usb_device(dev);

do_unbind_rebind(udev, DO_UNBIND);
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
choose_wakeup(udev, msg);
return usb_suspend_both(udev, msg);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ static int ehci_init(struct usb_hcd *hcd)
*/
ehci->periodic_size = DEFAULT_I_TDPS;
INIT_LIST_HEAD(&ehci->cached_itd_list);
INIT_LIST_HEAD(&ehci->cached_sitd_list);
if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
return retval;

Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ehci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ static int ehci_hub_control (
* this bit; seems too long to spin routinely...
*/
retval = handshake(ehci, status_reg,
PORT_RESET, 0, 750);
PORT_RESET, 0, 1000);
if (retval != 0) {
ehci_err (ehci, "port %d reset error %d\n",
wIndex + 1, retval);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ehci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static inline void qh_put (struct ehci_qh *qh)

static void ehci_mem_cleanup (struct ehci_hcd *ehci)
{
free_cached_itd_list(ehci);
free_cached_lists(ehci);
if (ehci->async)
qh_put (ehci->async);
ehci->async = NULL;
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/host/ehci-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,11 +629,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}
snprintf(supply, sizeof(supply), "hsusb%d", i);
omap->regulator[i] = regulator_get(omap->dev, supply);
if (IS_ERR(omap->regulator[i]))
if (IS_ERR(omap->regulator[i])) {
omap->regulator[i] = NULL;
dev_dbg(&pdev->dev,
"failed to get ehci port%d regulator\n", i);
else
} else {
regulator_enable(omap->regulator[i]);
}
}

ret = omap_start_ehc(omap, hcd);
Expand Down
40 changes: 31 additions & 9 deletions drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
ehci_writel(ehci, cmd, &ehci->regs->command);
/* posted write ... */

free_cached_itd_list(ehci);
free_cached_lists(ehci);

ehci->next_uframe = -1;
return 0;
Expand Down Expand Up @@ -2139,13 +2139,27 @@ sitd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
/* OK to recycle this SITD now that its completion callback ran. */

done:
sitd->urb = NULL;
sitd->stream = NULL;
list_move(&sitd->sitd_list, &stream->free_list);
iso_stream_put(ehci, stream);

if (ehci->clock_frame != sitd->frame) {
/* OK to recycle this SITD now. */
sitd->stream = NULL;
list_move(&sitd->sitd_list, &stream->free_list);
iso_stream_put(ehci, stream);
} else {
/* HW might remember this SITD, so we can't recycle it yet.
* Move it to a safe place until a new frame starts.
*/
list_move(&sitd->sitd_list, &ehci->cached_sitd_list);
if (stream->refcount == 2) {
/* If iso_stream_put() were called here, stream
* would be freed. Instead, just prevent reuse.
*/
stream->ep->hcpriv = NULL;
stream->ep = NULL;
}
}
return retval;
}

Expand Down Expand Up @@ -2211,16 +2225,24 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,

/*-------------------------------------------------------------------------*/

static void free_cached_itd_list(struct ehci_hcd *ehci)
static void free_cached_lists(struct ehci_hcd *ehci)
{
struct ehci_itd *itd, *n;
struct ehci_sitd *sitd, *sn;

list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
struct ehci_iso_stream *stream = itd->stream;
itd->stream = NULL;
list_move(&itd->itd_list, &stream->free_list);
iso_stream_put(ehci, stream);
}

list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
struct ehci_iso_stream *stream = sitd->stream;
sitd->stream = NULL;
list_move(&sitd->sitd_list, &stream->free_list);
iso_stream_put(ehci, stream);
}
}

/*-------------------------------------------------------------------------*/
Expand All @@ -2247,7 +2269,7 @@ scan_periodic (struct ehci_hcd *ehci)
clock_frame = -1;
}
if (ehci->clock_frame != clock_frame) {
free_cached_itd_list(ehci);
free_cached_lists(ehci);
ehci->clock_frame = clock_frame;
}
clock %= mod;
Expand Down Expand Up @@ -2414,7 +2436,7 @@ scan_periodic (struct ehci_hcd *ehci)
clock = now;
clock_frame = clock >> 3;
if (ehci->clock_frame != clock_frame) {
free_cached_itd_list(ehci);
free_cached_lists(ehci);
ehci->clock_frame = clock_frame;
}
} else {
Expand Down
5 changes: 3 additions & 2 deletions drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ struct ehci_hcd { /* one per controller */
int next_uframe; /* scan periodic, start here */
unsigned periodic_sched; /* periodic activity count */

/* list of itds completed while clock_frame was still active */
/* list of itds & sitds completed while clock_frame was still active */
struct list_head cached_itd_list;
struct list_head cached_sitd_list;
unsigned clock_frame;

/* per root hub port */
Expand Down Expand Up @@ -195,7 +196,7 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
clear_bit (action, &ehci->actions);
}

static void free_cached_itd_list(struct ehci_hcd *ehci);
static void free_cached_lists(struct ehci_hcd *ehci);

/*-------------------------------------------------------------------------*/

Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ohci-da8xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
#endif

#define CFGCHIP2 DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG)
#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)

static struct clk *usb11_clk;
static struct clk *usb20_clk;
Expand Down
15 changes: 13 additions & 2 deletions drivers/usb/misc/usbsevseg.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct usb_sevsegdev {
u16 textlength;

u8 shadow_power; /* for PM */
u8 has_interface_pm;
};

/* sysfs_streq can't replace this completely
Expand All @@ -68,12 +69,16 @@ static void update_display_powered(struct usb_sevsegdev *mydev)
{
int rc;

if (!mydev->shadow_power && mydev->powered) {
if (mydev->powered && !mydev->has_interface_pm) {
rc = usb_autopm_get_interface(mydev->intf);
if (rc < 0)
return;
mydev->has_interface_pm = 1;
}

if (mydev->shadow_power != 1)
return;

rc = usb_control_msg(mydev->udev,
usb_sndctrlpipe(mydev->udev, 0),
0x12,
Expand All @@ -86,8 +91,10 @@ static void update_display_powered(struct usb_sevsegdev *mydev)
if (rc < 0)
dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc);

if (mydev->shadow_power && !mydev->powered)
if (!mydev->powered && mydev->has_interface_pm) {
usb_autopm_put_interface(mydev->intf);
mydev->has_interface_pm = 0;
}
}

static void update_display_mode(struct usb_sevsegdev *mydev)
Expand Down Expand Up @@ -351,6 +358,10 @@ static int sevseg_probe(struct usb_interface *interface,
mydev->intf = interface;
usb_set_intfdata(interface, mydev);

/* PM */
mydev->shadow_power = 1; /* currently active */
mydev->has_interface_pm = 0; /* have not issued autopm_get */

/*set defaults */
mydev->textmode = 0x02; /* ascii mode */
mydev->mode_msb = 0x06; /* 6 characters */
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/serial/pl2303.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
{ } /* Terminating entry */
};

Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/serial/pl2303.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,7 @@
/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */
#define SANWA_VENDOR_ID 0x11ad
#define SANWA_PRODUCT_ID 0x0001

/* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
#define ADLINK_VENDOR_ID 0x0b63
#define ADLINK_ND6530_PRODUCT_ID 0x6530
10 changes: 10 additions & 0 deletions drivers/usb/serial/qcaux.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
#define CMOTECH_PRODUCT_CDU550 0x5553
#define CMOTECH_PRODUCT_CDX650 0x6512

/* LG devices */
#define LG_VENDOR_ID 0x1004
#define LG_PRODUCT_VX4400_6000 0x6000 /* VX4400/VX6000/Rumor */

/* Sanyo devices */
#define SANYO_VENDOR_ID 0x0474
#define SANYO_PRODUCT_KATANA_LX 0x0754 /* SCP-3800 (Katana LX) */

static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5740, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5750, 0xff, 0x00, 0x00) },
Expand All @@ -51,6 +59,8 @@ static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_ALLTEL, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU550, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDX650, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/serial/sierra.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = {
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
{ USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
{ USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
{ USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */

{ USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
Expand Down
Loading

0 comments on commit a4b7d3b

Please sign in to comment.