summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-03-19 13:39:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-19 13:39:21 -0700
commit8fdb7e9f612b7c6ba6c3ba460c14263b5ce90f79 (patch)
tree09f007a62475c22546ba693e5171024cc67fb38c /drivers/usb
parentfc7f99cf36ebae853639dabb43bc2f0098c59aef (diff)
parent4cb80cda51ff950614701fb30c9d4e583fe5a31f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (45 commits) USB: gadget/multi: cdc_do_config: remove redundant check usb: r8a66597-hcd: fix removed from an attached hub USB: xhci: Make endpoint interval debugging clearer. USB: Fix usb_fill_int_urb for SuperSpeed devices USB: cp210x: Remove double usb_control_msg from cp210x_set_config USB: Remove last bit of CONFIG_USB_BERRY_CHARGE USB: gadget: add gadget controller number for s3c-hsotg driver USB: ftdi_sio: Fix locking for change_speed() function USB: g_mass_storage: fixed module name in Kconfig USB: gadget: f_mass_storage::fsg_bind(): fix error handling USB: g_mass_storage: fix section mismatch warnings USB: gadget: fix Blackfin builds after gadget cleansing USB: goku_udc: remove potential null dereference USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem interface is 0xff USB: serial: Fix module name typo for qcaux Kconfig entry. usb: cdc-wdm: Fix deadlock between write and resume usb: cdc-wdm: Fix order in disconnect and fix locking usb: cdc-wdm:Fix loss of data due to autosuspend usb: cdc-wdm: Fix submission of URB after suspension usb: cdc-wdm: Fix race between disconnect and debug messages ...
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/class/cdc-wdm.c134
-rw-r--r--drivers/usb/core/devio.c17
-rw-r--r--drivers/usb/core/urb.c1
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/f_mass_storage.c3
-rw-r--r--drivers/usb/gadget/gadget_chips.h8
-rw-r--r--drivers/usb/gadget/goku_udc.c2
-rw-r--r--drivers/usb/gadget/multi.c2
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c1
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-sched.c28
-rw-r--r--drivers/usb/host/ehci.h5
-rw-r--r--drivers/usb/host/r8a66597-hcd.c16
-rw-r--r--drivers/usb/host/xhci-mem.c9
-rw-r--r--drivers/usb/host/xhci.c (renamed from drivers/usb/host/xhci-hcd.c)1
-rw-r--r--drivers/usb/musb/musb_core.c13
-rw-r--r--drivers/usb/musb/musb_core.h4
-rw-r--r--drivers/usb/musb/musb_host.c2
-rw-r--r--drivers/usb/musb/musb_regs.h28
-rw-r--r--drivers/usb/serial/Kconfig4
-rw-r--r--drivers/usb/serial/cp210x.c5
-rw-r--r--drivers/usb/serial/ftdi_sio.c7
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h7
-rw-r--r--drivers/usb/serial/generic.c49
-rw-r--r--drivers/usb/serial/option.c53
-rw-r--r--drivers/usb/serial/qcserial.c29
-rw-r--r--drivers/usb/storage/unusual_devs.h23
30 files changed, 321 insertions, 142 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 975d556b4787..be6331e2c276 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf)
wb = acm->delayed_wb;
acm->delayed_wb = NULL;
spin_unlock_irq(&acm->write_lock);
- acm_start_wb(acm, acm->delayed_wb);
+ acm_start_wb(acm, wb);
} else {
spin_unlock_irq(&acm->write_lock);
}
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 18aafcb08fc8..189141ca4e05 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_READ 4
#define WDM_INT_STALL 5
#define WDM_POLL_RUNNING 6
-
+#define WDM_RESPONDING 7
+#define WDM_SUSPENDING 8
#define WDM_MAX 16
@@ -87,9 +88,7 @@ struct wdm_device {
int count;
dma_addr_t shandle;
dma_addr_t ihandle;
- struct mutex wlock;
- struct mutex rlock;
- struct mutex plock;
+ struct mutex lock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
@@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb)
int status = urb->status;
spin_lock(&desc->iuspin);
+ clear_bit(WDM_RESPONDING, &desc->flags);
if (status) {
switch (status) {
case -ENOENT:
dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ENOENT");
- break;
+ goto skip_error;
case -ECONNRESET:
dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ECONNRESET");
- break;
+ goto skip_error;
case -ESHUTDOWN:
dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ESHUTDOWN");
- break;
+ goto skip_error;
case -EPIPE:
dev_err(&desc->intf->dev,
"nonzero urb status received: -EPIPE\n");
@@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb)
desc->reslength = urb->actual_length;
memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
desc->length += desc->reslength;
+skip_error:
wake_up(&desc->wait);
set_bit(WDM_READ, &desc->flags);
@@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb)
desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
spin_lock(&desc->iuspin);
clear_bit(WDM_READ, &desc->flags);
- if (!test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ set_bit(WDM_RESPONDING, &desc->flags);
+ if (!test_bit(WDM_DISCONNECTING, &desc->flags)
+ && !test_bit(WDM_SUSPENDING, &desc->flags)) {
rv = usb_submit_urb(desc->response, GFP_ATOMIC);
dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
__func__, rv);
}
spin_unlock(&desc->iuspin);
if (rv < 0) {
+ clear_bit(WDM_RESPONDING, &desc->flags);
if (rv == -EPERM)
return;
if (rv == -ENOMEM) {
@@ -305,14 +309,38 @@ static ssize_t wdm_write
if (we < 0)
return -EIO;
- r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */
+ desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+ if (!buf) {
+ rv = -ENOMEM;
+ goto outnl;
+ }
+
+ r = copy_from_user(buf, buffer, count);
+ if (r > 0) {
+ kfree(buf);
+ rv = -EFAULT;
+ goto outnl;
+ }
+
+ /* concurrent writes and disconnect */
+ r = mutex_lock_interruptible(&desc->lock);
rv = -ERESTARTSYS;
- if (r)
+ if (r) {
+ kfree(buf);
goto outnl;
+ }
+
+ if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ kfree(buf);
+ rv = -ENODEV;
+ goto outnp;
+ }
r = usb_autopm_get_interface(desc->intf);
- if (r < 0)
+ if (r < 0) {
+ kfree(buf);
goto outnp;
+ }
if (!file->f_flags && O_NONBLOCK)
r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
@@ -320,24 +348,8 @@ static ssize_t wdm_write
else
if (test_bit(WDM_IN_USE, &desc->flags))
r = -EAGAIN;
- if (r < 0)
- goto out;
-
- if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
- rv = -ENODEV;
- goto out;
- }
-
- desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
- if (!buf) {
- rv = -ENOMEM;
- goto out;
- }
-
- r = copy_from_user(buf, buffer, count);
- if (r > 0) {
+ if (r < 0) {
kfree(buf);
- rv = -EFAULT;
goto out;
}
@@ -374,7 +386,7 @@ static ssize_t wdm_write
out:
usb_autopm_put_interface(desc->intf);
outnp:
- mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->lock);
outnl:
return rv < 0 ? rv : count;
}
@@ -387,7 +399,7 @@ static ssize_t wdm_read
struct wdm_device *desc = file->private_data;
- rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
+ rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
if (rv < 0)
return -ERESTARTSYS;
@@ -424,11 +436,8 @@ retry:
spin_lock_irq(&desc->iuspin);
if (desc->rerr) { /* read completed, error happened */
- int t = desc->rerr;
desc->rerr = 0;
spin_unlock_irq(&desc->iuspin);
- dev_err(&desc->intf->dev,
- "reading had resulted in %d\n", t);
rv = -EIO;
goto err;
}
@@ -465,9 +474,7 @@ retry:
rv = cntr;
err:
- mutex_unlock(&desc->rlock);
- if (rv < 0 && rv != -EAGAIN)
- dev_err(&desc->intf->dev, "wdm_read: exit error\n");
+ mutex_unlock(&desc->lock);
return rv;
}
@@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file)
}
intf->needs_remote_wakeup = 1;
- mutex_lock(&desc->plock);
+ mutex_lock(&desc->lock);
if (!desc->count++) {
rv = usb_submit_urb(desc->validity, GFP_KERNEL);
if (rv < 0) {
@@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file)
} else {
rv = 0;
}
- mutex_unlock(&desc->plock);
+ mutex_unlock(&desc->lock);
usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
@@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file)
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
- mutex_lock(&desc->plock);
+ mutex_lock(&desc->lock);
desc->count--;
- mutex_unlock(&desc->plock);
+ mutex_unlock(&desc->lock);
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -655,9 +662,7 @@ next_desc:
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
- mutex_init(&desc->wlock);
- mutex_init(&desc->rlock);
- mutex_init(&desc->plock);
+ mutex_init(&desc->lock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
@@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf)
/* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
- cancel_work_sync(&desc->rxwork);
+ mutex_lock(&desc->lock);
kill_urbs(desc);
+ cancel_work_sync(&desc->rxwork);
+ mutex_unlock(&desc->lock);
wake_up_all(&desc->wait);
if (!desc->count)
cleanup(desc);
mutex_unlock(&wdm_mutex);
}
+#ifdef CONFIG_PM
static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
{
struct wdm_device *desc = usb_get_intfdata(intf);
@@ -786,22 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
- mutex_lock(&desc->plock);
-#ifdef CONFIG_PM
+ /* if this is an autosuspend the caller does the locking */
+ if (!(message.event & PM_EVENT_AUTO))
+ mutex_lock(&desc->lock);
+ spin_lock_irq(&desc->iuspin);
+
if ((message.event & PM_EVENT_AUTO) &&
- test_bit(WDM_IN_USE, &desc->flags)) {
+ (test_bit(WDM_IN_USE, &desc->flags)
+ || test_bit(WDM_RESPONDING, &desc->flags))) {
+ spin_unlock_irq(&desc->iuspin);
rv = -EBUSY;
} else {
-#endif
- cancel_work_sync(&desc->rxwork);
+
+ set_bit(WDM_SUSPENDING, &desc->flags);
+ spin_unlock_irq(&desc->iuspin);
+ /* callback submits work - order is essential */
kill_urbs(desc);
-#ifdef CONFIG_PM
+ cancel_work_sync(&desc->rxwork);
}
-#endif
- mutex_unlock(&desc->plock);
+ if (!(message.event & PM_EVENT_AUTO))
+ mutex_unlock(&desc->lock);
return rv;
}
+#endif
static int recover_from_urb_loss(struct wdm_device *desc)
{
@@ -815,23 +831,27 @@ static int recover_from_urb_loss(struct wdm_device *desc)
}
return rv;
}
+
+#ifdef CONFIG_PM
static int wdm_resume(struct usb_interface *intf)
{
struct wdm_device *desc = usb_get_intfdata(intf);
int rv;
dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
- mutex_lock(&desc->plock);
+
+ clear_bit(WDM_SUSPENDING, &desc->flags);
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->plock);
+
return rv;
}
+#endif
static int wdm_pre_reset(struct usb_interface *intf)
{
struct wdm_device *desc = usb_get_intfdata(intf);
- mutex_lock(&desc->plock);
+ mutex_lock(&desc->lock);
return 0;
}
@@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf)
int rv;
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->plock);
+ mutex_unlock(&desc->lock);
return 0;
}
@@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = {
.name = "cdc_wdm",
.probe = wdm_probe,
.disconnect = wdm_disconnect,
+#ifdef CONFIG_PM
.suspend = wdm_suspend,
.resume = wdm_resume,
.reset_resume = wdm_resume,
+#endif
.pre_reset = wdm_pre_reset,
.post_reset = wdm_post_reset,
.id_table = wdm_ids,
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index e909ff7b9094..3466fdc5bb11 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
free_async(as);
return -ENOMEM;
}
+ /* Isochronous input data may end up being discontiguous
+ * if some of the packets are short. Clear the buffer so
+ * that the gaps don't leak kernel data to userspace.
+ */
+ if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
+ memset(as->urb->transfer_buffer, 0,
+ uurb->buffer_length);
}
as->urb->dev = ps->dev;
as->urb->pipe = (uurb->type << 30) |
@@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg)
void __user *addr = as->userurb;
unsigned int i;
- if (as->userbuffer && urb->actual_length)
- if (copy_to_user(as->userbuffer, urb->transfer_buffer,
- urb->actual_length))
+ if (as->userbuffer && urb->actual_length) {
+ if (urb->number_of_packets > 0) /* Isochronous */
+ i = urb->transfer_buffer_length;
+ else /* Non-Isoc */
+ i = urb->actual_length;
+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
goto err_out;
+ }
if (put_user(as->status, &userurb->status))
goto err_out;
if (put_user(urb->actual_length, &userurb->actual_length))
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 27080561a1c2..45a32dadb406 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (urb->interval > (1 << 15))
return -EINVAL;
max = 1 << 15;
+ break;
case USB_SPEED_WIRELESS:
if (urb->interval > 16)
return -EINVAL;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 7460cd797f45..11a3e0fa4331 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -747,7 +747,7 @@ config USB_MASS_STORAGE
which may be used with composite framework.
Say "y" to link the driver statically, or "m" to build
- a dynamically linked module called "g_file_storage". If unsure,
+ a dynamically linked module called "g_mass_storage". If unsure,
consider File-backed Storage Gadget.
config USB_G_SERIAL
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 65a5f94cbc04..3568de210f79 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -266,7 +266,7 @@ struct usb_ep * __init usb_ep_autoconfig (
}
#ifdef CONFIG_BLACKFIN
- } else if (gadget_is_musbhsfc(gadget) || gadget_is_musbhdrc(gadget)) {
+ } else if (gadget_is_musbhdrc(gadget)) {
if ((USB_ENDPOINT_XFER_BULK == type) ||
(USB_ENDPOINT_XFER_ISOC == type)) {
if (USB_DIR_IN & desc->bEndpointAddress)
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 5a3cdd08f1d0..f4911c09022e 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2910,7 +2910,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
}
-static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
+static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
@@ -2954,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
rc = -ENOTSUPP;
- fsg_unbind(c, f);
return rc;
}
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 1edbc12fff18..e511fec9f26d 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -136,6 +136,12 @@
#define gadget_is_r8a66597(g) 0
#endif
+#ifdef CONFIG_USB_S3C_HSOTG
+#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name))
+#else
+#define gadget_is_s3c_hsotg(g) 0
+#endif
+
/**
* usb_gadget_controller_number - support bcdDevice id convention
@@ -192,6 +198,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x24;
else if (gadget_is_r8a66597(gadget))
return 0x25;
+ else if (gadget_is_s3c_hsotg(gadget))
+ return 0x26;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index e8edc640381e..1088d08c7ed8 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* usb_gadget_driver_{register,unregister}() must change.
*/
if (the_controller) {
- WARNING(dev, "ignoring %s\n", pci_name(pdev));
+ pr_warning("ignoring %s\n", pci_name(pdev));
return -EBUSY;
}
if (!pdev->irq) {
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 76496f5d272c..a930d7fd7e7a 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -211,8 +211,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
ret = fsg_add(c->cdev, c, fsg_common);
if (ret < 0)
return ret;
- if (ret < 0)
- return ret;
return 0;
}
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 8b45145b9136..5e13d23b5f0c 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 4e0c67f1f51b..b6315aa47f7a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -12,7 +12,7 @@ fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
ifeq ($(CONFIG_FHCI_DEBUG),y)
fhci-objs += fhci-dbg.o
endif
-xhci-objs := xhci-hcd.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
+xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
obj-$(CONFIG_USB_WHCI_HCD) += whci/
@@ -25,7 +25,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
-obj-$(CONFIG_USB_XHCI_HCD) += xhci.o
+obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d8d6d3461d32..dc55a62859c6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -995,7 +995,7 @@ rescan:
/* endpoints can be iso streams. for now, we don't
* accelerate iso completions ... so spin a while.
*/
- if (qh->hw->hw_info1 == 0) {
+ if (qh->hw == NULL) {
ehci_vdbg (ehci, "iso delay\n");
goto idle_timeout;
}
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 39340ae00ac4..a0aaaaff2560 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
urb->interval);
}
- /* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */
- } else if (unlikely (stream->hw_info1 != 0)) {
+ /* if dev->ep [epnum] is a QH, hw is set */
+ } else if (unlikely (stream->hw != NULL)) {
ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
urb->dev->devpath, epnum,
usb_pipein(urb->pipe) ? "in" : "out");
@@ -1565,13 +1565,27 @@ itd_patch(
static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{
- /* always prepend ITD/SITD ... only QH tree is order-sensitive */
- itd->itd_next = ehci->pshadow [frame];
- itd->hw_next = ehci->periodic [frame];
- ehci->pshadow [frame].itd = itd;
+ union ehci_shadow *prev = &ehci->pshadow[frame];
+ __hc32 *hw_p = &ehci->periodic[frame];
+ union ehci_shadow here = *prev;
+ __hc32 type = 0;
+
+ /* skip any iso nodes which might belong to previous microframes */
+ while (here.ptr) {
+ type = Q_NEXT_TYPE(ehci, *hw_p);
+ if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
+ break;
+ prev = periodic_next_shadow(ehci, prev, type);
+ hw_p = shadow_next_periodic(ehci, &here, type);
+ here = *prev;
+ }
+
+ itd->itd_next = here;
+ itd->hw_next = *hw_p;
+ prev->itd = itd;
itd->frame = frame;
wmb ();
- ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
+ *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
}
/* fit urb's itds into the selected schedule slot; activate as needed */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2d85e21ff282..b1dce96dd621 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -394,9 +394,8 @@ struct ehci_iso_sched {
* acts like a qh would, if EHCI had them for ISO.
*/
struct ehci_iso_stream {
- /* first two fields match QH, but info1 == 0 */
- __hc32 hw_next;
- __hc32 hw_info1;
+ /* first field matches ehci_hq, but is NULL */
+ struct ehci_qh_hw *hw;
u32 refcount;
u8 bEndpointAddress;
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index bee558aed427..f71a73a93d0c 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
/* this function must be called with interrupt disabled */
static void free_usb_address(struct r8a66597 *r8a66597,
- struct r8a66597_device *dev)
+ struct r8a66597_device *dev, int reset)
{
int port;
@@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597,
dev->state = USB_STATE_DEFAULT;
r8a66597->address_map &= ~(1 << dev->address);
dev->address = 0;
- dev_set_drvdata(&dev->udev->dev, NULL);
+ /*
+ * Only when resetting USB, it is necessary to erase drvdata. When
+ * a usb device with usb hub is disconnect, "dev->udev" is already
+ * freed on usb_desconnect(). So we cannot access the data.
+ */
+ if (reset)
+ dev_set_drvdata(&dev->udev->dev, NULL);
list_del(&dev->device_list);
kfree(dev);
@@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
disable_r8a66597_pipe_all(r8a66597, dev);
- free_usb_address(r8a66597, dev);
+ free_usb_address(r8a66597, dev, 0);
start_root_hub_sampling(r8a66597, port, 0);
}
@@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597,
spin_lock_irqsave(&r8a66597->lock, flags);
dev = get_r8a66597_device(r8a66597, addr);
disable_r8a66597_pipe_all(r8a66597, dev);
- free_usb_address(r8a66597, dev);
+ free_usb_address(r8a66597, dev, 0);
put_child_connect_map(r8a66597, addr);
spin_unlock_irqrestore(&r8a66597->lock, flags);
}
@@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
rh->port |= (1 << USB_PORT_FEAT_RESET);
disable_r8a66597_pipe_all(r8a66597, dev);
- free_usb_address(r8a66597, dev);
+ free_usb_address(r8a66597, dev, 1);
r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
get_dvstctr_reg(port));
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 49f7d72f8b1b..bba9b19ed1b9 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -566,8 +566,13 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
if (interval < 3)
interval = 3;
if ((1 << interval) != 8*ep->desc.bInterval)
- dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
- ep->desc.bEndpointAddress, 1 << interval);
+ dev_warn(&udev->dev,
+ "ep %#x - rounding interval"
+ " to %d microframes, "
+ "ep desc says %d microframes\n",
+ ep->desc.bEndpointAddress,
+ 1 << interval,
+ 8*ep->desc.bInterval);
}
break;
default:
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci.c
index 4cb69e0af834..492a61c2c79d 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci.c
@@ -1173,6 +1173,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
cmd_completion = &virt_dev->cmd_completion;
cmd_status = &virt_dev->cmd_status;
}
+ init_completion(cmd_completion);
if (!ctx_change)
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b4bbf8f2c238..0e8b8ab1d168 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -379,7 +379,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
u8 devctl, u8 power)
{
irqreturn_t handled = IRQ_NONE;
- void __iomem *mbase = musb->mregs;
DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
int_usb);
@@ -394,6 +393,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (devctl & MUSB_DEVCTL_HM) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
+ void __iomem *mbase = musb->mregs;
+
switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
/* remote wakeup? later, GetPortStatus
@@ -471,6 +472,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* see manual for the order of the tests */
if (int_usb & MUSB_INTR_SESSREQ) {
+ void __iomem *mbase = musb->mregs;
+
DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
/* IRQ arrives from ID pin sense or (later, if VBUS power
@@ -519,6 +522,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_A_WAIT_BCON:
case OTG_STATE_A_WAIT_VRISE:
if (musb->vbuserr_retry) {
+ void __iomem *mbase = musb->mregs;
+
musb->vbuserr_retry--;
ignore = 1;
devctl |= MUSB_DEVCTL_SESSION;
@@ -622,6 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb);
+ void __iomem *mbase = musb->mregs;
handled = IRQ_HANDLED;
musb->is_active = 1;
@@ -2007,7 +2013,6 @@ bad_config:
/* host side needs more setup */
if (is_host_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
- u8 busctl;
otg_set_host(musb->xceiv, &hcd->self);
@@ -2018,9 +2023,9 @@ bad_config:
/* program PHY to use external vBus if required */
if (plat->extvbus) {
- busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL);
+ u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
busctl |= MUSB_ULPI_USE_EXTVBUS;
- musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl);
+ musb_write_ulpi_buscontrol(musb->mregs, busctl);
}
}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index d849fb81c131..cd9f4a9a06c6 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -469,7 +469,7 @@ struct musb_csr_regs {
struct musb_context_registers {
-#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430)
+#ifdef CONFIG_PM
u32 otg_sysconfig, otg_forcestandby;
#endif
u8 power;