aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/atm/usbatm.h1
-rw-r--r--drivers/usb/class/cdc-acm.c10
-rw-r--r--drivers/usb/class/usblp.c1
-rw-r--r--drivers/usb/core/Kconfig9
-rw-r--r--drivers/usb/core/hub.c1
-rw-r--r--drivers/usb/core/message.c5
-rw-r--r--drivers/usb/core/quirks.c28
-rw-r--r--drivers/usb/core/usb.c8
-rw-r--r--drivers/usb/gadget/Kconfig6
-rw-r--r--drivers/usb/gadget/at91_udc.c1
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c158
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h9
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c1
-rw-r--r--drivers/usb/gadget/inode.c4
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c1
-rw-r--r--drivers/usb/gadget/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c2
-rw-r--r--drivers/usb/gadget/printer.c3
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c90
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h4
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c2
-rw-r--r--drivers/usb/host/Kconfig5
-rw-r--r--drivers/usb/host/ehci-hcd.c90
-rw-r--r--drivers/usb/host/ehci-hub.c5
-rw-r--r--drivers/usb/host/ehci-orion.c37
-rw-r--r--drivers/usb/host/ehci-pci.c14
-rw-r--r--drivers/usb/host/ehci-q.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c23
-rw-r--r--drivers/usb/host/isp116x.h1
-rw-r--r--drivers/usb/host/ohci-at91.c3
-rw-r--r--drivers/usb/host/ohci-au1xxx.c1
-rw-r--r--drivers/usb/host/ohci-ep93xx.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-lh7a404.c1
-rw-r--r--drivers/usb/host/ohci-omap.c1
-rw-r--r--drivers/usb/host/ohci-pnx4008.c4
-rw-r--r--drivers/usb/host/ohci-pnx8550.c5
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ohci-pxa27x.c3
-rw-r--r--drivers/usb/host/ohci-q.c2
-rw-r--r--drivers/usb/host/ohci-s3c2410.c1
-rw-r--r--drivers/usb/host/ohci-sh.c1
-rw-r--r--drivers/usb/host/ohci-sm501.c1
-rw-r--r--drivers/usb/host/r8a66597-hcd.c2
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/u132-hcd.c16
-rw-r--r--drivers/usb/misc/appledisplay.c1
-rw-r--r--drivers/usb/misc/ldusb.c2
-rw-r--r--drivers/usb/misc/trancevibrator.c4
-rw-r--r--drivers/usb/misc/usbtest.c3
-rw-r--r--drivers/usb/serial/cp2101.c1
-rw-r--r--drivers/usb/serial/cypress_m8.c2
-rw-r--r--drivers/usb/serial/cypress_m8.h4
-rw-r--r--drivers/usb/serial/ftdi_sio.c30
-rw-r--r--drivers/usb/serial/ftdi_sio.h10
-rw-r--r--drivers/usb/serial/generic.c10
-rw-r--r--drivers/usb/serial/io_ti.c1
-rw-r--r--drivers/usb/serial/keyspan.h4
-rw-r--r--drivers/usb/serial/mos7840.c15
-rw-r--r--drivers/usb/serial/option.c176
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h1
-rw-r--r--drivers/usb/serial/sierra.c19
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c5
-rw-r--r--drivers/usb/serial/usb-serial.c2
-rw-r--r--drivers/usb/serial/visor.c2
-rw-r--r--drivers/usb/storage/isd200.c6
-rw-r--r--drivers/usb/storage/protocol.c27
-rw-r--r--drivers/usb/storage/sddr55.c4
-rw-r--r--drivers/usb/storage/transport.c14
-rw-r--r--drivers/usb/storage/unusual_devs.h141
72 files changed, 772 insertions, 285 deletions
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index ff8551e9337..fc6c2be5999 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -24,7 +24,6 @@
#ifndef _USBATM_H_
#define _USBATM_H_
-#include <asm/semaphore.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/completion.h>
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index bcc42136c93..0147ea39340 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -496,13 +496,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
otherwise it is scheduled, and with high data rates data can get lost. */
tty->low_latency = 1;
- if (usb_autopm_get_interface(acm->control)) {
- mutex_unlock(&open_mutex);
- return -EIO;
- }
+ if (usb_autopm_get_interface(acm->control) < 0)
+ goto early_bail;
mutex_lock(&acm->mutex);
- mutex_unlock(&open_mutex);
if (acm->used++) {
usb_autopm_put_interface(acm->control);
goto done;
@@ -536,6 +533,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
done:
err_out:
mutex_unlock(&acm->mutex);
+ mutex_unlock(&open_mutex);
return rv;
full_bailout:
@@ -544,6 +542,8 @@ bail_out:
usb_autopm_put_interface(acm->control);
acm->used--;
mutex_unlock(&acm->mutex);
+early_bail:
+ mutex_unlock(&open_mutex);
return -EIO;
}
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index ad632f2d6f9..0647164d36d 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -428,6 +428,7 @@ static int usblp_open(struct inode *inode, struct file *file)
usblp->rcomplete = 0;
if (handle_bidir(usblp) < 0) {
+ usb_autopm_put_interface(intf);
usblp->used = 0;
file->private_data = NULL;
retval = -EIO;
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 5c33cdb9cac..a2b0aa48b8e 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -87,12 +87,13 @@ config USB_DYNAMIC_MINORS
If you are unsure about this, say N here.
config USB_SUSPEND
- bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
- depends on USB && PM && EXPERIMENTAL
+ bool "USB selective suspend/resume and wakeup"
+ depends on USB && PM
help
If you say Y here, you can use driver calls or the sysfs
- "power/state" file to suspend or resume individual USB
- peripherals.
+ "power/level" file to suspend or resume individual USB
+ peripherals and to enable or disable autosuspend (see
+ Documentation/usb/power-management.txt for more details).
Also, USB "remote wakeup" signaling is supported, whereby some
USB devices (like keyboards and network adapters) can wake up
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 68fc5219ca1..57aeca160f3 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -23,7 +23,6 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
-#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fefb92296e8..c311f67b7f0 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1206,7 +1206,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return -EINVAL;
}
- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ if (dev->quirks & USB_QUIRK_NO_SET_INTF)
+ ret = -EPIPE;
+ else
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
alternate, interface, NULL, 0, 5000);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index d42c561c75f..dfc5418ea10 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -30,21 +30,39 @@
static const struct usb_device_id usb_quirk_list[] = {
/* CBM - Flash disk */
{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* HP 5300/5370C scanner */
- { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+ { USB_DEVICE(0x03f0, 0x0701), .driver_info =
+ USB_QUIRK_STRING_FETCH_255 },
- /* INTEL VALUE SSD */
- { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Creative SB Audigy 2 NX */
+ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Philips PSC805 audio device */
+ { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Roland SC-8820 */
+ { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Edirol SD-20 */
+ { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
- /* Philips PSC805 audio device */
- { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
+ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
+
+ /* Action Semiconductor flash disk */
+ { USB_DEVICE(0x10d6, 0x2200), .driver_info =
+ USB_QUIRK_STRING_FETCH_255 },
/* SKYMEDI USB_DRIVE */
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* INTEL VALUE SSD */
+ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+
{ } /* terminating entry must be last */
};
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4e984060c98..1f0db51190c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -99,8 +99,7 @@ struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
/**
- * usb_altnum_to_altsetting - get the altsetting structure with a given
- * alternate setting number.
+ * usb_altnum_to_altsetting - get the altsetting structure with a given alternate setting number.
* @intf: the interface containing the altsetting in question
* @altnum: the desired alternate setting number
*
@@ -234,7 +233,7 @@ static int ksuspend_usb_init(void)
* singlethreaded. Its job doesn't justify running on more
* than one CPU.
*/
- ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+ ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
if (!ksuspend_usb_wq)
return -ENOMEM;
return 0;
@@ -442,8 +441,7 @@ EXPORT_SYMBOL_GPL(usb_put_intf);
*/
/**
- * usb_lock_device_for_reset - cautiously acquire the lock for a
- * usb device structure
+ * usb_lock_device_for_reset - cautiously acquire the lock for a usb device structure
* @udev: device that's being locked
* @iface: interface bound to the driver making the request (optional)
*
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c1395516468..d681bb27fa5 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -118,10 +118,10 @@ config USB_AMD5536UDC
config USB_GADGET_ATMEL_USBA
boolean "Atmel USBA"
select USB_GADGET_DUALSPEED
- depends on AVR32
+ depends on AVR32 || ARCH_AT91CAP9
help
USBA is the integrated high-speed USB Device controller on
- the AT32AP700x processors from Atmel.
+ the AT32AP700x and AT91CAP9 processors from Atmel.
config USB_ATMEL_USBA
tristate
@@ -131,7 +131,7 @@ config USB_ATMEL_USBA
config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
- depends on MPC834x || PPC_MPC831x
+ depends on FSL_SOC
select USB_GADGET_DUALSPEED
help
Some of Freescale PowerPC processors have a High Speed
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index a83e8b798ec..fd15ced899d 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1884,3 +1884,4 @@ module_exit(udc_exit_module);
MODULE_DESCRIPTION("AT91 udc driver");
MODULE_AUTHOR("Thomas Rathbone, David Brownell");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at91_udc");
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index af8b2a3a2d4..e756023362c 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h>
#include <asm/gpio.h>
@@ -27,6 +28,7 @@
static struct usba_udc the_udc;
+static struct usba_ep *usba_ep;
#ifdef CONFIG_USB_GADGET_DEBUG_FS
#include <linux/debugfs.h>
@@ -324,53 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
return 1;
}
-static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
+#if defined(CONFIG_AVR32)
+
+static void toggle_bias(int is_on)
{
- unsigned long tmp;
-
- DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len);
- for (; len > 0; len -= 4, buf += 4, fifo += 4) {
- tmp = *(unsigned long *)buf;
- if (len >= 4) {
- DBG(DBG_FIFO, " -> %08lx\n", tmp);
- __raw_writel(tmp, fifo);
- } else {
- do {
- DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24);
- __raw_writeb(tmp >> 24, fifo);
- fifo++;
- tmp <<= 8;
- } while (--len);
- break;
- }
- }
}
-static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
+#elif defined(CONFIG_ARCH_AT91)
+
+#include <asm/arch/at91_pmc.h>
+
+static void toggle_bias(int is_on)
{
- union {
- unsigned long *w;
- unsigned char *b;
- } p;
- unsigned long tmp;
-
- DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
- for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
- if (len >= 4) {
- tmp = __raw_readl(fifo);
- *p.w = tmp;
- DBG(DBG_FIFO, " -> %08lx\n", tmp);
- } else {
- do {
- tmp = __raw_readb(fifo);
- *p.b = tmp;
- DBG(DBG_FIFO, " -> %02lx\n", tmp);
- fifo++, p.b++;
- } while (--len);
- }
- }
+ unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
+
+ if (is_on)
+ at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
+ else
+ at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
}
+#endif /* CONFIG_ARCH_AT91 */
+
static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
{
unsigned int transaction_len;
@@ -387,7 +364,7 @@ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
ep->ep.name, req, transaction_len,
req->last_transaction ? ", done" : "");
- copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+ memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
req->req.actual += transaction_len;
}
@@ -476,7 +453,7 @@ static void receive_data(struct usba_ep *ep)
bytecount = req->req.length - req->req.actual;
}
- copy_from_fifo(req->req.buf + req->req.actual,
+ memcpy_fromio(req->req.buf + req->req.actual,
ep->fifo, bytecount);
req->req.actual += bytecount;
@@ -1029,33 +1006,6 @@ static const struct usb_gadget_ops usba_udc_ops = {
.set_selfpowered = usba_udc_set_selfpowered,
};
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
-{ \
- .ep = { \
- .ops = &usba_ep_ops, \
- .name = nam, \
- .maxpacket = maxpkt, \
- }, \
- .udc = &the_udc, \
- .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \
- .fifo_size = maxpkt, \
- .nr_banks = maxbk, \
- .index = idx, \
- .can_dma = dma, \
- .can_isoc = isoc, \
-}
-
-static struct usba_ep usba_ep[] = {
- EP("ep0", 0, 64, 1, 0, 0),
- EP("ep1in-bulk", 1, 512, 2, 1, 1),
- EP("ep2out-bulk", 2, 512, 2, 1, 1),
- EP("ep3in-int", 3, 64, 3, 1, 0),
- EP("ep4out-int", 4, 64, 3, 1, 0),
- EP("ep5in-iso", 5, 1024, 3, 1, 1),
- EP("ep6out-iso", 6, 1024, 3, 1, 1),
-};
-#undef EP
-
static struct usb_endpoint_descriptor usba_ep0_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -1074,7 +1024,6 @@ static void nop_release(struct device *dev)
static struct usba_udc the_udc = {
.gadget = {
.ops = &usba_udc_ops,
- .ep0 = &usba_ep[0].ep,
.ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
.is_dualspeed = 1,
.name = "atmel_usba_udc",
@@ -1231,7 +1180,7 @@ static int do_test_mode(struct usba_udc *udc)
} else {
usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
usba_writel(udc, TST, USBA_TST_PKT_MODE);
- copy_to_fifo(ep->fifo, test_packet_buffer,
+ memcpy_toio(ep->fifo, test_packet_buffer,
sizeof(test_packet_buffer));
usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
dev_info(dev, "Entering Test_Packet mode...\n");
@@ -1530,13 +1479,13 @@ restart:
DBG(DBG_HW, "Packet length: %u\n", pkt_len);
if (pkt_len != sizeof(crq)) {
pr_warning("udc: Invalid packet length %u "
- "(expected %lu)\n", pkt_len, sizeof(crq));
+ "(expected %zu)\n", pkt_len, sizeof(crq));
set_protocol_stall(udc, ep);
return;
}
DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
- copy_from_fifo(crq.data, ep->fifo, sizeof(crq));
+ memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
/* Free up one bank in the FIFO so that we can
* generate or receive a reply right away. */
@@ -1688,6 +1637,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
DBG(DBG_INT, "irq, status=%#08x\n", status);
if (status & USBA_DET_SUSPEND) {
+ toggle_bias(0);
usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
DBG(DBG_BUS, "Suspend detected\n");
if (udc->gadget.speed != USB_SPEED_UNKNOWN
@@ -1699,6 +1649,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
}
if (status & USBA_WAKE_UP) {
+ toggle_bias(1);
usba_writel(udc, INT_CLR, USBA_WAKE_UP);
DBG(DBG_BUS, "Wake Up CPU detected\n");
}
@@ -1792,12 +1743,14 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
vbus = gpio_get_value(udc->vbus_pin);
if (vbus != udc->vbus_prev) {
if (vbus) {
- usba_writel(udc, CTRL, USBA_EN_USBA);
+ toggle_bias(1);
+ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
} else {
udc->gadget.speed = USB_SPEED_UNKNOWN;
reset_all_endpoints(udc);
- usba_writel(udc, CTRL, 0);
+ toggle_bias(0);
+ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget);
spin_lock(&udc->lock);
@@ -1850,7 +1803,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* If Vbus is present, enable the controller and wait for reset */
spin_lock_irqsave(&udc->lock, flags);
if (vbus_is_present(udc) && udc->vbus_prev == 0) {
- usba_writel(udc, CTRL, USBA_EN_USBA);
+ toggle_bias(1);
+ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1883,7 +1837,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
spin_unlock_irqrestore(&udc->lock, flags);
/* This will also disable the DP pullup */
- usba_writel(udc, CTRL, 0);
+ toggle_bias(0);
+ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
@@ -1908,7 +1863,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
- if (!regs || !fifo)
+ if (!regs || !fifo || !pdata)
return -ENXIO;
irq = platform_get_irq(pdev, 0);
@@ -1953,19 +1908,48 @@ static int __init usba_udc_probe(struct platform_device *pdev)
/* Make sure we start from a clean slate */
clk_enable(pclk);
- usba_writel(udc, CTRL, 0);
+ toggle_bias(0);
+ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
clk_disable(pclk);
+ usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep,
+ GFP_KERNEL);
+ if (!usba_ep)
+ goto err_alloc_ep;
+
+ the_udc.gadget.ep0 = &usba_ep[0].ep;
+
INIT_LIST_HEAD(&usba_ep[0].ep.ep_list);
usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
- for (i = 1; i < ARRAY_SIZE(usba_ep); i++) {
+ usba_ep[0].ep.ops = &usba_ep_ops;
+ usba_ep[0].ep.name = pdata->ep[0].name;
+ usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size;
+ usba_ep[0].udc = &the_udc;
+ INIT_LIST_HEAD(&usba_ep[0].queue);
+ usba_ep[0].fifo_size = pdata->ep[0].fifo_size;
+ usba_ep[0].nr_banks = pdata->ep[0].nr_banks;
+ usba_ep[0].index = pdata->ep[0].index;
+ usba_ep[0].can_dma = pdata->ep[0].can_dma;
+ usba_ep[0].can_isoc = pdata->ep[0].can_isoc;
+
+ for (i = 1; i < pdata->num_ep; i++) {
struct usba_ep *ep = &usba_ep[i];
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+ ep->ep.ops = &usba_ep_ops;
+ ep->ep.name = pdata->ep[i].name;
+ ep->ep.maxpacket = pdata->ep[i].fifo_size;
+ ep->udc = &the_udc;
+ INIT_LIST_HEAD(&ep->queue);
+ ep->fifo_size = pdata->ep[i].fifo_size;
+ ep->nr_banks = pdata->ep[i].nr_banks;
+ ep->index = pdata->ep[i].index;
+ ep->can_dma = pdata->ep[i].can_dma;
+ ep->can_isoc = pdata->ep[i].can_isoc;
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
@@ -1984,7 +1968,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
goto err_device_add;
}
- if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) {
+ if (pdata->vbus_pin >= 0) {
if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
udc->vbus_pin = pdata->vbus_pin;
@@ -2004,7 +1988,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
}
usba_init_debugfs(udc);
- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
+ for (i = 1; i < pdata->num_ep; i++)
usba_ep_init_debugfs(udc, &usba_ep[i]);
return 0;
@@ -2012,6 +1996,8 @@ static int __init usba_udc_probe(struct platform_device *pdev)
err_device_add:
free_irq(irq, udc);
err_request_irq:
+ kfree(usba_ep);
+err_alloc_ep:
iounmap(udc->fifo);
err_map_fifo:
iounmap(udc->regs);
@@ -2029,10 +2015,11 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
{
struct usba_udc *udc;
int i;
+ struct usba_platform_data *pdata = pdev->dev.platform_data;
udc = platform_get_drvdata(pdev);
- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
+ for (i = 1; i < pdata->num_ep; i++)
usba_ep_cleanup_debugfs(&usba_ep[i]);
usba_cleanup_debugfs(udc);
@@ -2040,6 +2027,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
gpio_free(udc->vbus_pin);
free_irq(udc->irq, udc);
+ kfree(usba_ep);
iounmap(udc->fifo);
iounmap(udc->regs);
clk_put(udc->hclk);
@@ -2054,6 +2042,7 @@ static struct platform_driver udc_driver = {
.remove = __exit_p(usba_udc_remove),
.driver = {
.name = "atmel_usba_udc",
+ .owner = THIS_MODULE,
},
};
@@ -2072,3 +2061,4 @@ module_exit(udc_exit);
MODULE_DESCRIPTION("Atmel USBA UDC driver");
MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_usba_udc");
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 08bf6f9aaf7..f7baea307f0 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -41,6 +41,15 @@
#define USBA_EN_USBA (1 << 8)
#define USBA_DETACH (1 << 9)
#define USBA_REMOTE_WAKE_UP (1 << 10)
+#define USBA_PULLD_DIS (1 << 11)
+
+#if defined(CONFIG_AVR32)
+#define USBA_ENABLE_MASK USBA_EN_USBA
+#define USBA_DISABLE_MASK 0
+#elif defined(CONFIG_ARCH_AT91)
+#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
+#define USBA_DISABLE_MASK USBA_DETACH
+#endif /* CONFIG_ARCH_AT91 */
/* Bitfields in FNUM */
#define USBA_MICRO_FRAME_NUM_OFFSET 0
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index a70e255402b..e9987230814 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1561,6 +1561,7 @@ done_set_intf:
memcpy(req->buf, buf, n);
req->complete = rndis_response_complete;
rndis_free_response(dev->rndis_config, buf);
+ value = n;
}
/* else stalls ... spec says to avoid that */
}
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 63e8fa3a69e..254012ad2b9 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -2475,3 +2475,4 @@ module_exit(udc_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:fsl-usb2-udc");
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 805602a687c..0a6feafc8d2 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1458,7 +1458,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* currently one config, two speeds */
case USB_REQ_SET_CONFIGURATION:
if (ctrl->bRequestType != 0)
- break;
+ goto unrecognized;
if (0 == (u8) w_value) {
value = 0;
dev->current_config = 0;
@@ -1505,7 +1505,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* PXA automagically handles this request too */
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != 0x80)
- break;
+ goto unrecognized;
*(u8 *)req->buf = dev->current_config;
value = min (w_length, (u16) 1);
break;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 37243ef7104..078f7246767 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -2146,3 +2146,4 @@ module_exit(udc_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Mikko Lahteenmaki, Bo Henriksen");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lh7a40x_udc");
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 835948f0715..ee6b35fa870 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -35,6 +35,7 @@
MODULE_DESCRIPTION("M66592 USB gadget driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:m66592_udc");
#define DRIVER_VERSION "18 Oct 2007"
@@ -1671,6 +1672,7 @@ static struct platform_driver m66592_driver = {
.remove = __exit_p(m66592_remove),
.driver = {
.name = (char *) udc_name,
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index e6d68bda428..ee1e9a314cd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -3109,4 +3109,4 @@ module_exit(udc_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:omap_udc");
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 9fdabc8fcac..2c32bd08ee7 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -92,7 +92,6 @@ struct printer_dev {
u8 *current_rx_buf;
u8 printer_status;
u8 reset_printer;
- struct class_device *printer_class_dev;
struct cdev printer_cdev;
struct device *pdev;
u8 printer_cdev_open;
@@ -1299,7 +1298,7 @@ printer_unbind(struct usb_gadget *gadget)
printer_req_free(dev->in_ep, req);
}
- if (dev->current_rx_req != NULL);
+ if (dev->current_rx_req != NULL)
printer_req_free(dev->out_ep, dev->current_rx_req);
while (!list_empty(&dev->rx_reqs)) {
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 4402d6f042d..c00cd8b9d3d 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -103,6 +103,12 @@ static const char ep0name [] = "ep0";
#error "Can't configure both IXP and PXA"
#endif
+/* IXP doesn't yet support <linux/clk.h> */
+#define clk_get(dev,name) NULL
+#define clk_enable(clk) do { } while (0)
+#define clk_disable(clk) do { } while (0)
+#define clk_put(clk) do { } while (0)
+
#endif
#include "pxa2xx_udc.h"
@@ -934,20 +940,31 @@ static void udc_disable(struct pxa2xx_udc *);
/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
* in active use.
*/
-static int pullup(struct pxa2xx_udc *udc, int is_active)
+static int pullup(struct pxa2xx_udc *udc)
{
- is_active = is_active && udc->vbus && udc->pullup;
+ int is_active = udc->vbus && udc->pullup && !udc->suspended;
DMSG("%s\n", is_active ? "active" : "inactive");
- if (is_active)
- udc_enable(udc);
- else {
- if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
- DMSG("disconnect %s\n", udc->driver
- ? udc->driver->driver.name
- : "(no driver)");
- stop_activity(udc, udc->driver);
+ if (is_active) {
+ if (!udc->active) {
+ udc->active = 1;
+ /* Enable clock for USB device */
+ clk_enable(udc->clk);
+ udc_enable(udc);
}
- udc_disable(udc);
+ } else {
+ if (udc->active) {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+ DMSG("disconnect %s\n", udc->driver
+ ? udc->driver->driver.name
+ : "(no driver)");
+ stop_activity(udc, udc->driver);
+ }
+ udc_disable(udc);
+ /* Disable clock for USB device */
+ clk_disable(udc->clk);
+ udc->active = 0;
+ }
+
}
return 0;
}
@@ -958,9 +975,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
struct pxa2xx_udc *udc;
udc = container_of(_gadget, struct pxa2xx_udc, gadget);
- udc->vbus = is_active = (is_active != 0);
+ udc->vbus = (is_active != 0);
DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
- pullup(udc, is_active);
+ pullup(udc);
return 0;
}
@@ -975,9 +992,8 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
return -EOPNOTSUPP;
- is_active = (is_active != 0);
- udc->pullup = is_active;
- pullup(udc, is_active);
+ udc->pullup = (is_active != 0);
+ pullup(udc);
return 0;
}
@@ -997,7 +1013,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = {
#ifdef CONFIG_USB_GADGET_DEBUG_FS
static int
-udc_seq_show(struct seq_file *m, void *d)
+udc_seq_show(struct seq_file *m, void *_d)
{
struct pxa2xx_udc *dev = m->private;
unsigned long flags;
@@ -1146,11 +1162,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
udc_clear_mask_UDCCR(UDCCR_UDE);
-#ifdef CONFIG_ARCH_PXA
- /* Disable clock for USB device */
- clk_disable(dev->clk);
-#endif
-
ep0_idle (dev);
dev->gadget.speed = USB_SPEED_UNKNOWN;
}
@@ -1191,11 +1202,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
{
udc_clear_mask_UDCCR(UDCCR_UDE);
-#ifdef CONFIG_ARCH_PXA
- /* Enable clock for USB device */
- clk_enable(dev->clk);
-#endif
-
/* try to clear these bits before we enable the udc */
udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
@@ -1286,7 +1292,7 @@ fail:
* for set_configuration as well as eventual disconnect.
*/
DMSG("registered gadget driver '%s'\n", driver->driver.name);
- pullup(dev, 1);
+ pullup(dev);
dump_state(dev);
return 0;
}
@@ -1329,7 +1335,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
local_irq_disable();
- pullup(dev, 0);
+ dev->pullup = 0;
+ pullup(dev);
stop_activity(dev, driver);
local_irq_enable();
@@ -2131,13 +2138,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
-#ifdef CONFIG_ARCH_PXA
dev->clk = clk_get(&pdev->dev, "UDCCLK");
if (IS_ERR(dev->clk)) {
retval = PTR_ERR(dev->clk);
goto err_clk;
}
-#endif
pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
dev->has_cfr ? "" : " (!cfr)",
@@ -2250,10 +2255,8 @@ lubbock_fail0:
if (dev->mach->gpio_vbus)
gpio_free(dev->mach->gpio_vbus);
err_gpio_vbus:
-#ifdef CONFIG_ARCH_PXA
clk_put(dev->clk);
err_clk:
-#endif
return retval;
}
@@ -2269,7 +2272,9 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
if (dev->driver)
return -EBUSY;
- udc_disable(dev);
+ dev->pullup = 0;
+ pullup(dev);
+
remove_debug_files(dev);
if (dev->got_irq) {
@@ -2289,9 +2294,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
if (dev->mach->gpio_pullup)
gpio_free(dev->mach->gpio_pullup);
-#ifdef CONFIG_ARCH_PXA
clk_put(dev->clk);
-#endif
platform_set_drvdata(pdev, NULL);
the_controller = NULL;
@@ -2317,10 +2320,15 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
{
struct pxa2xx_udc *udc = platform_get_drvdata(dev);
+ unsigned long flags;
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
WARN("USB host won't detect disconnect!\n");
- pullup(udc, 0);
+ udc->suspended = 1;
+
+ local_irq_save(flags);
+ pullup(udc);
+ local_irq_restore(flags);
return 0;
}
@@ -2328,8 +2336,12 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
static int pxa2xx_udc_resume(struct platform_device *dev)
{
struct pxa2xx_udc *udc = platform_get_drvdata(dev);
+ unsigned long flags;
- pullup(udc, 1);
+ udc->suspended = 0;
+ local_irq_save(flags);
+ pullup(udc);
+ local_irq_restore(flags);
return 0;
}
@@ -2368,4 +2380,4 @@ module_exit(udc_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:pxa2xx-udc");
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index b67e3ff5e4e..e2c19e88c87 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -119,7 +119,9 @@ struct pxa2xx_udc {
has_cfr : 1,
req_pending : 1,
req_std : 1,
- req_config : 1;
+ req_config : 1,
+ suspended : 1,
+ active : 1;
#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
struct timer_list timer;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index aadc4204d6f..6b1ef488043 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -2047,3 +2047,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c2410-usbgadget");
+MODULE_ALIAS("platform:s3c2440-usbgadget");
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d97b16b52ef..bf8be2a41a4 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -69,10 +69,9 @@ config USB_EHCI_BIG_ENDIAN_DESC
default y
config USB_EHCI_FSL
- bool
- depends on USB_EHCI_HCD
+ bool "Support for Freescale on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT
- default y if MPC834x || PPC_MPC831x
---help---
Variation of ARC USB block used in some Freescale chips.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4caa6a8b9a3..85074cb36f3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -281,23 +281,44 @@ static void ehci_iaa_watchdog(unsigned long param)
{
struct ehci_hcd *ehci = (struct ehci_hcd *) param;
unsigned long flags;
- u32 status, cmd;
spin_lock_irqsave (&ehci->lock, flags);
- WARN_ON(!ehci->reclaim);
- status = ehci_readl(ehci, &ehci->regs->status);
- cmd = ehci_readl(ehci, &ehci->regs->command);
- ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
-
- /* lost IAA irqs wedge things badly; seen first with a vt8235 */
- if (ehci->reclaim) {
- if (status & STS_IAA) {
- ehci_vdbg (ehci, "lost IAA\n");
+ /* Lost IAA irqs wedge things badly; seen first with a vt8235.
+ * So we need this watchdog, but must protect it against both
+ * (a) SMP races against real IAA firing and retriggering, and
+ * (b) clean HC shutdown, when IAA watchdog was pending.
+ */
+ if (ehci->reclaim
+ && !timer_pending(&ehci->iaa_watchdog)
+ && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+ u32 cmd, status;
+
+ /* If we get here, IAA is *REALLY* late. It's barely
+ * conceivable that the system is so busy that CMD_IAAD
+ * is still legitimately set, so let's be sure it's
+ * clear before we read STS_IAA. (The HC should clear
+ * CMD_IAAD when it sets STS_IAA.)
+ */
+ cmd = ehci_readl(ehci, &ehci->regs->command);
+ if (cmd & CMD_IAAD)
+ ehci_writel(ehci, cmd & ~CMD_IAAD,
+ &ehci->regs->command);
+
+ /* If IAA is set here it either legitimately triggered
+ * before we cleared IAAD above (but _way_ late, so we'll
+ * still count it as lost) ... or a silicon erratum:
+ * - VIA seems to set IAA without triggering the IRQ;
+ * - IAAD potentially cleared without setting IAA.
+ */
+ status = ehci_readl(ehci, &ehci->regs->status);
+ if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
COUNT (ehci->stats.lost_iaa);
ehci_writel(ehci, STS_IAA, &ehci->regs->status);
}
- ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
+
+ ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
+ status, cmd);
end_unlink_async(ehci);
}
@@ -631,7 +652,7 @@ static int ehci_run (struct usb_hcd *hcd)
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 status, pcd_status = 0;
+ u32 status, pcd_status = 0, cmd;
int bh;
spin_lock (&ehci->lock);
@@ -652,7 +673,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* clear (just) interrupts */
ehci_writel(ehci, status, &ehci->regs->status);
- ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */
+ cmd = ehci_readl(ehci, &ehci->regs->command);
bh = 0;
#ifdef EHCI_VERBOSE_DEBUG
@@ -673,8 +694,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* complete the unlinking of some qh [4.15.2.3] */
if (status & STS_IAA) {
- COUNT (ehci->stats.reclaim);
- end_unlink_async(ehci);
+ /* guard against (alleged) silicon errata */
+ if (cmd & CMD_IAAD) {
+ ehci_writel(ehci, cmd & ~CMD_IAAD,
+ &ehci->regs->command);
+ ehci_dbg(ehci, "IAA with IAAD still set?\n");
+ }
+ if (ehci->reclaim) {
+ COUNT(ehci->stats.reclaim);
+ end_unlink_async(ehci);
+ } else
+ ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
}
/* remote wakeup [4.3.1] */
@@ -781,7 +811,7 @@ static int ehci_urb_enqueue (
static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
/* failfast */
- if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+ if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
end_unlink_async(ehci);
/* if it's not linked then there's nothing to do */
@@ -862,18 +892,18 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
&& HC_IS_RUNNING (hcd->state)) {
- int schedule_status;
-
- schedule_status = qh_schedule (ehci, qh);
- spin_unlock_irqrestore (&ehci->lock, flags);
-
- if (schedule_status != 0) {
- // shouldn't happen often, but ...
- // FIXME kill those tds' urbs
- err ("can't reschedule qh %p, err %d",
- qh, schedule_status);
- }
- return status;
+ rc = qh_schedule(ehci, qh);
+
+ /* An error here likely indicates handshake failure
+ * or no space left in the schedule. Neither fault
+ * should happen often ...
+ *
+ * FIXME kill the now-dysfunctional queued urbs
+ */
+ if (rc != 0)
+ ehci_err(ehci,
+ "can't reschedule qh %p, err %d",
+ qh, rc);
}
break;
@@ -1003,7 +1033,7 @@ MODULE_LICENSE ("GPL");
#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
#endif
-#ifdef CONFIG_ARCH_ORION
+#ifdef CONFIG_PLAT_ORION
#include "ehci-orion.c"
#define PLATFORM_DRIVER ehci_orion_driver
#endif
@@ -1014,7 +1044,7 @@ MODULE_LICENSE ("GPL");
#endif
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER)
+ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
#error "missing bus glue for ehci-hcd"
#endif
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 40e8240b785..4e065e556e4 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -135,8 +135,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
hcd->state = HC_STATE_QUIESCING;
}
ehci->command = ehci_readl(ehci, &ehci->regs->command);
- if (ehci->reclaim)
- end_unlink_async(ehci);
ehci_work(ehci);
/* Unlike other USB host controller types, EHCI doesn't have
@@ -180,6 +178,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci_halt (ehci);
hcd->state = HC_STATE_SUSPENDED;
+ if (ehci->reclaim)
+ end_unlink_async(ehci);
+
/* allow remote wakeup */
mask = INTR_MASK;
if (!device_may_wakeup(&hcd->self.root_hub->dev))
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index e129981f139..d187d031374 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -11,15 +11,18 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <asm/arch/orion.h>
+#include <linux/mbus.h>
+#include <asm/plat-orion/ehci-orion.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
-#define USB_CAUSE 0x310
-#define USB_MASK 0x314
#define USB_CMD 0x140
#define USB_MODE 0x1a8
+#define USB_CAUSE 0x310
+#define USB_MASK 0x314
+#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4))
+#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
#define USB_IPG 0x360
#define USB_PHY_PWR_CTRL 0x400
#define USB_PHY_TX_CTRL 0x420
@@ -162,8 +165,30 @@ static const struct hc_driver ehci_orion_hc_driver = {
.bus_resume = ehci_bus_resume,
};
+static void __init
+ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
+ struct mbus_dram_target_info *dram)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ wrl(USB_WINDOW_CTRL(i), 0);
+ wrl(USB_WINDOW_BASE(i), 0);
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ wrl(USB_WINDOW_CTRL(i), ((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1);
+ wrl(USB_WINDOW_BASE(i), cs->base);
+ }
+}
+
static int __init ehci_orion_drv_probe(struct platform_device *pdev)
{
+ struct orion_ehci_data *pd = pdev->dev.platform_data;
struct resource *res;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
@@ -227,6 +252,12 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
ehci->sbrn = 0x20;
/*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (pd != NULL && pd->dram != NULL)
+ ehci_orion_conf_mbus_windows(hcd, pd->dram);
+
+ /*
* setup Orion USB controller
*/
orion_usb_setup(hcd);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 3ba01664f82..72ccd56e36d 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -152,6 +152,20 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
break;
}
break;
+ case PCI_VENDOR_ID_VIA:
+ if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) {
+ u8 tmp;
+
+ /* The VT6212 defaults to a 1 usec EHCI sleep time which
+ * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes
+ * that sleep time use the conventional 10 usec.
+ */
+ pci_read_config_byte(pdev, 0x4b, &tmp);
+ if (tmp & 0x20)
+ break;
+ pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
+ }
+ break;
}
ehci_reset(ehci);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 776a97f3391..2e49de820b1 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -319,10 +319,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (likely (last->urb != urb)) {
ehci_urb_done(ehci, last->urb, last_status);
count++;
+ last_status = -EINPROGRESS;
}
ehci_qtd_free (ehci, last);
last = NULL;
- last_status = -EINPROGRESS;
}
/* ignore urbs submitted during completions we reported */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 0130fd8571e..203a3359a64 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -911,8 +911,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
buf[0] = 0;
for (i = 0; i < ports; i++) {
- u32 status = isp116x->rhport[i] =
- isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
+ u32 status = isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
| RH_PS_OCIC | RH_PS_PRSC)) {
@@ -1031,7 +1030,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
DBG("GetPortStatus\n");
if (!wIndex || wIndex > ports)
goto error;
- tmp = isp116x->rhport[--wIndex];
+ spin_lock_irqsave(&isp116x->lock, flags);
+ tmp = isp116x_read_reg32(isp116x, (--wIndex) ? HCRHPORT2 : HCRHPORT1);
+ spin_unlock_irqrestore(&isp116x->lock, flags);
*(__le32 *) buf = cpu_to_le32(tmp);
DBG("GetPortStatus: port[%d] %08x\n", wIndex + 1, tmp);
break;
@@ -1080,8 +1081,6 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags);
isp116x_write_reg32(isp116x, wIndex
? HCRHPORT2 : HCRHPORT1, tmp);
- isp116x->rhport[wIndex] =
- isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
spin_unlock_irqrestore(&isp116x->lock, flags);
break;
case SetPortFeature:
@@ -1095,24 +1094,22 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags);
isp116x_write_reg32(isp116x, wIndex
? HCRHPORT2 : HCRHPORT1, RH_PS_PSS);
+ spin_unlock_irqrestore(&isp116x->lock, flags);
break;
case USB_PORT_FEAT_POWER:
DBG("USB_PORT_FEAT_POWER\n");
spin_lock_irqsave(&isp116x->lock, flags);
isp116x_write_reg32(isp116x, wIndex
? HCRHPORT2 : HCRHPORT1, RH_PS_PPS);
+ spin_unlock_irqrestore(&isp116x->lock, flags);
break;
case USB_PORT_FEAT_RESET:
DBG("USB_PORT_FEAT_RESET\n");
root_port_reset(isp116x, wIndex);
- spin_lock_irqsave(&isp116x->lock, flags);
break;
default:
goto error;
}
- isp116x->rhport[wIndex] =
- isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
- spin_unlock_irqrestore(&isp116x->lock, flags);
break;
default:
@@ -1687,14 +1684,18 @@ static int isp116x_resume(struct platform_device *dev)
#endif
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:isp116x-hcd");
+
static struct platform_driver isp116x_driver = {
.probe = isp116x_probe,
.remove = isp116x_remove,
.suspend = isp116x_suspend,
.resume = isp116x_resume,
.driver = {
- .name = (char *)hcd_name,
- },
+ .name = (char *)hcd_name,
+ .owner = THIS_MODULE,
+ },
};
/*-----------------------------------------------------------------*/
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index b91e2edd9c5..595b90a9984 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -270,7 +270,6 @@ struct isp116x {
u32 rhdesca;
u32 rhdescb;
u32 rhstatus;
- u32 rhport[2];
/* async schedule: control, bulk */
struct list_head async;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 126fcbdd640..d72dc07dda0 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -355,7 +355,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
#define ohci_hcd_at91_drv_resume NULL
#endif
-MODULE_ALIAS("at91_ohci");
+MODULE_ALIAS("platform:at91_ohci");
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
@@ -368,4 +368,3 @@ static struct platform_driver ohci_hcd_at91_driver = {
.owner = THIS_MODULE,
},
};
-
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 663a0600b6e..f90fe0c7373 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -345,3 +345,4 @@ static struct platform_driver ohci_hcd_au1xxx_driver = {
},
};
+MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index a68ce9d3c52..156e93a9d0d 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -211,6 +211,8 @@ static struct platform_driver ohci_hcd_ep93xx_driver = {
#endif
.driver = {
.name = "ep93xx-ohci",
+ .owner = THIS_MODULE,
},
};
+MODULE_ALIAS("platform:ep93xx-ohci");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index dd4798ee028..33f1c1c32ed 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -467,7 +467,7 @@ static void unlink_watchdog_func(unsigned long _ohci)
out:
kfree(seen);
if (ohci->eds_scheduled)
- mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ));
+ mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
done:
spin_unlock_irqrestore(&ohci->lock, flags);
}
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 4a043abd85e..13c12ed2225 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -251,3 +251,4 @@ static struct platform_driver ohci_hcd_lh7a404_driver = {
},
};
+MODULE_ALIAS("platform:lh7a404-ohci");
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 74e1f4be10b..7bfca1ed1b5 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -544,3 +544,4 @@ static struct platform_driver ohci_hcd_omap_driver = {
},
};
+MODULE_ALIAS("platform:ohci");
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 6c52c66b659..28b458f20cc 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -456,9 +456,13 @@ static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
return 0;
}
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:usb-ohci");
+
static struct platform_driver usb_hcd_pnx4008_driver = {
.driver = {
.name = "usb-ohci",
+ .owner = THIS_MODULE,
},
.probe = usb_hcd_pnx4008_probe,
.remove = usb_hcd_pnx4008_remove,
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
index 85fdfd2a7ad..605d59cba28 100644
--- a/drivers/usb/host/ohci-pnx8550.c
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -230,11 +230,12 @@ static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
return 0;
}
-MODULE_ALIAS("pnx8550-ohci");
+MODULE_ALIAS("platform:pnx8550-ohci");
static struct platform_driver ohci_hcd_pnx8550_driver = {
.driver = {
- .name = "pnx8550-ohci",
+ .name = "pnx8550-ohci",
+ .owner = THIS_MODULE,
},
.probe = ohci_hcd_pnx8550_drv_probe,
.remove = ohci_hcd_pnx8550_drv_remove,
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index f95be1896b0..523c3012557 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -213,3 +213,4 @@ static struct platform_driver ohci_hcd_ppc_soc_driver = {
},
};
+MODULE_ALIAS("platform:ppc-soc-ohci");
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index ff9a7984347..8ad9b3b604b 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -364,6 +364,8 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
}
#endif
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:pxa27x-ohci");
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
@@ -375,6 +377,7 @@ static struct platform_driver ohci_hcd_pxa27x_driver = {
#endif
.driver = {
.name = "pxa27x-ohci",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 51817322232..9c9f3b59186 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -169,7 +169,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
if (quirk_zfmicro(ohci)
&& (ed->type == PIPE_INTERRUPT)
&& !(ohci->eds_scheduled++))
- mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ));
+ mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
wmb ();
/* we care about rm_list when setting CLE/BLE in case the HC was at
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 44b79e8a6e2..ead4772f0f2 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -501,3 +501,4 @@ static struct platform_driver ohci_hcd_s3c2410_driver = {
},
};
+MODULE_ALIAS("platform:s3c2410-ohci");
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index 5309ac039e1..e7ee607278f 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -141,3 +141,4 @@ static struct platform_driver ohci_hcd_sh_driver = {
},
};
+MODULE_ALIAS("platform:sh_ohci");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index a9707014286..4ea92762fb2 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -262,3 +262,4 @@ static struct platform_driver ohci_hcd_sm501_driver = {
.name = "sm501-usb",
},
};
+MODULE_ALIAS("platform:sm501-usb");
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 0ce2fc5e396..9f80e528557 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -44,6 +44,7 @@
MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:r8a66597_hcd");
#define DRIVER_VERSION "29 May 2007"
@@ -2219,6 +2220,7 @@ static struct platform_driver r8a66597_driver = {
.resume = r8a66597_resume,
.driver = {
.name = (char *) hcd_name,
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index ba370c56172..629bca0ebe8 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -58,6 +58,7 @@
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sl811-hcd");
#define DRIVER_VERSION "19 May 2005"
@@ -1766,6 +1767,7 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
retval = sl811h_bus_suspend(hcd);
break;
case PM_EVENT_SUSPEND:
+ case PM_EVENT_HIBERNATE:
case PM_EVENT_PRETHAW: /* explicitly discard hw state */
port_power(sl811, 0);
break;
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index ac283b09a63..8e117a795e9 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -3213,15 +3213,20 @@ static int u132_suspend(struct platform_device *pdev, pm_message_t state)
dev_err(&u132->platform_dev->dev, "device is being removed\n");
return -ESHUTDOWN;
} else {
- int retval = 0;
- if (state.event == PM_EVENT_FREEZE) {
+ int retval = 0, ports;
+
+ switch (state.event) {
+ case PM_EVENT_FREEZE:
retval = u132_bus_suspend(hcd);
- } else if (state.event == PM_EVENT_SUSPEND) {
- int ports = MAX_U132_PORTS;
+ break;
+ case PM_EVENT_SUSPEND:
+ case PM_EVENT_HIBERNATE:
+ ports = MAX_U132_PORTS;
while (ports-- > 0) {
port_power(u132, ports, 0);
}
- }
+ break;
+ }
if (retval == 0)
pdev->dev.power.power_state = state;
return retval;
@@ -3311,3 +3316,4 @@ static void __exit u132_hcd_exit(void)
module_exit(u132_hcd_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:u132_hcd");
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 1cb56f2d5c8..a5e4c3545c7 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -29,7 +29,6 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
-#include <asm/semaphore.h>
#define APPLE_VENDOR_ID 0x05AC
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 8208496dfc6..c730d20eec6 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -61,6 +61,7 @@
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
#define USB_DEVICE_ID_VERNIER_SKIP 0x0003
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
+#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_MICROCHIP 0x04d8
#define USB_DEVICE_ID_PICDEM 0x000c
@@ -92,6 +93,7 @@ static struct usb_device_id ld_usb_table [] = {
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
{ USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) },
+ { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ld_usb_table);
diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
index 67e2fc20eee..03368edf3f2 100644
--- a/drivers/usb/misc/trancevibrator.c
+++ b/drivers/usb/misc/trancevibrator.c
@@ -59,13 +59,14 @@ static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
{
struct usb_interface *intf = to_usb_interface(dev);
struct trancevibrator *tv = usb_get_intfdata(intf);
- int temp, retval;
+ int temp, retval, old;
temp = simple_strtoul(buf, NULL, 10);
if (temp > 255)
temp = 255;
else if (temp < 0)
temp = 0;
+ old = tv->speed;
tv->speed = temp;
dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
@@ -77,6 +78,7 @@ static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
tv->speed, /* speed value */
0, NULL, 0, USB_CTRL_GET_TIMEOUT);
if (retval) {
+ tv->speed = old;
dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
return retval;
}
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index da922dfc0dc..b6b5b2affad 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -378,6 +378,7 @@ alloc_sglist (int nents, int max, int vary)
sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
if (!sg)
return NULL;
+ sg_init_table(sg, nents);
for (i = 0; i < nents; i++) {
char *buf;
@@ -390,7 +391,7 @@ alloc_sglist (int nents, int max, int vary)
}
/* kmalloc pages are always physically contiguous! */
- sg_init_one(&sg[i], buf, size);
+ sg_set_buf(&sg[i], buf, size);
switch (pattern) {
case 0:
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index f3ca66017a0..324bb61d68f 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -75,6 +75,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
+ { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 08c65c1a377..779d07851a4 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -94,6 +94,7 @@ static struct usb_device_id id_table_earthmate [] = {
static struct usb_device_id id_table_cyphidcomrs232 [] = {
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+ { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ } /* Terminating entry */
};
@@ -106,6 +107,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+ { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index e1c7c27e18b..0388065bb79 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -19,6 +19,10 @@
#define VENDOR_ID_CYPRESS 0x04b4
#define PRODUCT_ID_CYPHIDCOM 0x5500
+/* Powercom UPS, chip CY7C63723 */
+#define VENDOR_ID_POWERCOM 0x0d9f
+#define PRODUCT_ID_UPS 0x0002
+
/* Nokia CA-42 USB to serial cable */
#define VENDOR_ID_DAZZLE 0x07d0
#define PRODUCT_ID_CA42 0x4101
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 90dcc625f70..3abb3c86364 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -92,6 +92,7 @@ struct ftdi_sio_quirk {
};
static int ftdi_jtag_probe (struct usb_serial *serial);
+static int ftdi_mtxorb_hack_setup (struct usb_serial *serial);
static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
@@ -99,6 +100,10 @@ static struct ftdi_sio_quirk ftdi_jtag_quirk = {
.probe = ftdi_jtag_probe,
};
+static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
+ .probe = ftdi_mtxorb_hack_setup,
+};
+
static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
.port_probe = ftdi_USB_UIRT_setup,
};
@@ -161,6 +166,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
+ { USB_DEVICE(MTXORB_VK_VID, MTXORB_VK_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -274,6 +281,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
@@ -351,6 +359,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
@@ -393,8 +402,8 @@ static const char *ftdi_chip_name[] = {
#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
/* End TIOCMIWAIT */
-#define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \
- ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
+#define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \
+ | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
@@ -1088,6 +1097,23 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
return 0;
}
+/*
+ * The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
+ * We have to correct it if we want to read from it.
+ */
+static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
+{
+ struct usb_host_endpoint *ep = serial->dev->ep_in[1];
+ struct usb_endpoint_descriptor *ep_desc = &ep->desc;
+
+ if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
+ ep_desc->wMaxPacketSize = 0x40;
+ info("Fixing invalid wMaxPacketSize on read pipe");
+ }
+
+ return 0;
+}
+
/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
* it is called when the usb device is disconnected
*
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 6eee2ab914e..6da539ede0e 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -102,6 +102,13 @@
* (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */
+/*
+ * The following are the values for the Matrix Orbital VK204-25-USB
+ * display, which use the FT232RL.
+ */
+#define MTXORB_VK_VID 0x1b3d
+#define MTXORB_VK_PID 0x0158
+
/* Interbiometrics USB I/O Board */
/* Developed for Interbiometrics by Rudolf Gugler */
#define INTERBIOMETRICS_VID 0x1209
@@ -550,6 +557,9 @@
#define TML_VID 0x1B91 /* Vendor ID */
#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */
+/* Propox devices */
+#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 97fa3c42843..7cfce9dabb9 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -323,7 +323,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
room = tty_buffer_request_room(tty, urb->actual_length);
if (room) {
tty_insert_flip_string(tty, urb->transfer_buffer, room);
- tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+ tty_flip_buffer_push(tty);
}
}
@@ -349,10 +349,12 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
- if (!(port->throttled = port->throttle_req))
- /* Handle data and continue reading from device */
+ if (!(port->throttled = port->throttle_req)) {
+ spin_unlock_irqrestore(&port->lock, flags);
flush_and_resubmit_read_urb(port);
- spin_unlock_irqrestore(&port->lock, flags);
+ } else {
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index cd3405953f7..e5ea5ef6335 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -38,7 +38,6 @@
#include <linux/serial.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 8a0d1740152..74ce8bca3e6 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -637,6 +637,7 @@ static struct usb_serial_driver keyspan_pre_device = {
.description = "Keyspan - (without firmware)",
.id_table = keyspan_pre_ids,
.num_interrupt_in = NUM_DONT_CARE,
+ .num_interrupt_out = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
@@ -651,6 +652,7 @@ static struct usb_serial_driver keyspan_1port_device = {
.description = "Keyspan 1 port adapter",
.id_table = keyspan_1port_ids,
.num_interrupt_in = NUM_DONT_CARE,
+ .num_interrupt_out = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
@@ -678,6 +680,7 @@ static struct usb_serial_driver keyspan_2port_device = {
.description = "Keyspan 2 port adapter",
.id_table = keyspan_2port_ids,
.num_interrupt_in = NUM_DONT_CARE,
+ .num_interrupt_out = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 2,
@@ -705,6 +708,7 @@ static struct usb_serial_driver keyspan_4port_device = {
.description = "Keyspan 4 port adapter",
.id_table = keyspan_4port_ids,
.num_interrupt_in = NUM_DONT_CARE,
+ .num_interrupt_out = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 4,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 869ecd374cb..aeeb9cb2099 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -110,11 +110,20 @@
/* vendor id and device id defines */
+/* The native mos7840/7820 component */
#define USB_VENDOR_ID_MOSCHIP 0x9710
#define MOSCHIP_DEVICE_ID_7840 0x7840
#define MOSCHIP_DEVICE_ID_7820 0x7820
+/* The native component can have its vendor/device id's overridden
+ * in vendor-specific implementations. Such devices can be handled
+ * by making a change here, in moschip_port_id_table, and in
+ * moschip_id_table_combined
+ */
+#define USB_VENDOR_ID_BANDB 0x0856
+#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44
+#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42
-/* Interrupt Rotinue Defines */
+/* Interrupt Routine Defines */
#define SERIAL_IIR_RLS 0x06
#define SERIAL_IIR_MS 0x00
@@ -159,12 +168,16 @@
static struct usb_device_id moschip_port_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
{} /* terminating entry */
};
static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
{} /* terminating entry */
};
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5e8bf1bc1e5..d101025a4c6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -109,18 +109,92 @@ static int option_send_setup(struct usb_serial_port *port);
#define HUAWEI_PRODUCT_E600 0x1001
#define HUAWEI_PRODUCT_E220 0x1003
#define HUAWEI_PRODUCT_E220BIS 0x1004
+#define HUAWEI_PRODUCT_E1401 0x1401
+#define HUAWEI_PRODUCT_E1403 0x1403
+#define HUAWEI_PRODUCT_E1405 0x1405
+#define HUAWEI_PRODUCT_E1406 0x1406
+#define HUAWEI_PRODUCT_E1408 0x1408
+#define HUAWEI_PRODUCT_E1409 0x1409
+#define HUAWEI_PRODUCT_E1410 0x1410
+#define HUAWEI_PRODUCT_E1411 0x1411
+#define HUAWEI_PRODUCT_E1412 0x1412
+#define HUAWEI_PRODUCT_E1413 0x1413
+#define HUAWEI_PRODUCT_E1414 0x1414
+#define HUAWEI_PRODUCT_E1415 0x1415
+#define HUAWEI_PRODUCT_E1416 0x1416
+#define HUAWEI_PRODUCT_E1417 0x1417
+#define HUAWEI_PRODUCT_E1418 0x1418
+#define HUAWEI_PRODUCT_E1419 0x1419
#define NOVATELWIRELESS_VENDOR_ID 0x1410
+
+/* MERLIN EVDO PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_V640 0x1100
+#define NOVATELWIRELESS_PRODUCT_V620 0x1110
+#define NOVATELWIRELESS_PRODUCT_V740 0x1120
+#define NOVATELWIRELESS_PRODUCT_V720 0x1130
+
+/* MERLIN HSDPA/HSPA PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_U730 0x1400
+#define NOVATELWIRELESS_PRODUCT_U740 0x1410
+#define NOVATELWIRELESS_PRODUCT_U870 0x1420
+#define NOVATELWIRELESS_PRODUCT_XU870 0x1430
+#define NOVATELWIRELESS_PRODUCT_X950D 0x1450
+
+/* EXPEDITE PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_EV620 0x2100
+#define NOVATELWIRELESS_PRODUCT_ES720 0x2110
+#define NOVATELWIRELESS_PRODUCT_E725 0x2120
+#define NOVATELWIRELESS_PRODUCT_ES620 0x2130
+#define NOVATELWIRELESS_PRODUCT_EU730 0x2400
+#define NOVATELWIRELESS_PRODUCT_EU740 0x2410
+#define NOVATELWIRELESS_PRODUCT_EU870D 0x2420
+
+/* OVATION PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_MC727 0x4100
+#define NOVATELWIRELESS_PRODUCT_MC950D 0x4400
+
+#define NOVATELWIRELESS_PRODUCT_U727 0x5010
+
+/* FUTURE NOVATEL PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_EVDO_1 0x6000
+#define NOVATELWIRELESS_PRODUCT_HSPA_1 0x7000
+#define NOVATELWIRELESS_PRODUCT_EMBEDDED_1 0x8000
+#define NOVATELWIRELESS_PRODUCT_GLOBAL_1 0x9000
+#define NOVATELWIRELESS_PRODUCT_EVDO_2 0x6001
+#define NOVATELWIRELESS_PRODUCT_HSPA_2 0x7001
+#define NOVATELWIRELESS_PRODUCT_EMBEDDED_2 0x8001
+#define NOVATELWIRELESS_PRODUCT_GLOBAL_2 0x9001
+
+/* AMOI PRODUCTS */
+#define AMOI_VENDOR_ID 0x1614
+#define AMOI_PRODUCT_H01 0x0800
+#define AMOI_PRODUCT_H01A 0x7002
+#define AMOI_PRODUCT_H02 0x0802
+
#define DELL_VENDOR_ID 0x413C
+#define KYOCERA_VENDOR_ID 0x0c88
+#define KYOCERA_PRODUCT_KPC680 0x180a
+
#define ANYDATA_VENDOR_ID 0x16d5
#define ANYDATA_PRODUCT_ADU_E100A 0x6501
#define ANYDATA_PRODUCT_ADU_500A 0x6502
+#define AXESSTEL_VENDOR_ID 0x1726
+#define AXESSTEL_PRODUCT_MV110H 0x1000
+
#define BANDRICH_VENDOR_ID 0x1A8D
#define BANDRICH_PRODUCT_C100_1 0x1002
#define BANDRICH_PRODUCT_C100_2 0x1003
+#define AMOI_VENDOR_ID 0x1614
+#define AMOI_PRODUCT_9508 0x0800
+
+#define QUALCOMM_VENDOR_ID 0x05C6
+
+#define MAXON_VENDOR_ID 0x16d8
+
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -160,32 +234,73 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4100) }, /* Novatel U727 */
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4400) }, /* Novatel MC950 */
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel U727 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_1) }, /* Novatel Global product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_2) }, /* Novatel EVDO product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_2) }, /* Novatel HSPA product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_2) }, /* Novatel Embedded product */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_2) }, /* Novatel Global product */
+
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
+
{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8117) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8128) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
+ { USB_DEVICE(DELL_VENDOR_ID, 0x8129) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite ET620 CDMA/EV-DO */
+ { USB_DEVICE(DELL_VENDOR_ID, 0x8133) }, /* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
+ { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
+ { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -247,10 +362,10 @@ static int debug;
struct option_port_private {
/* Input endpoints and buffer for this port */
struct urb *in_urbs[N_IN_URB];
- char in_buffer[N_IN_URB][IN_BUFLEN];
+ u8 *in_buffer[N_IN_URB];
/* Output endpoints and buffer for this port */
struct urb *out_urbs[N_OUT_URB];
- char out_buffer[N_OUT_URB][OUT_BUFLEN];
+ u8 *out_buffer[N_OUT_URB];
unsigned long out_busy; /* Bit vector of URBs in use */
/* Settings for the port */
@@ -737,9 +852,10 @@ static int option_send_setup(struct usb_serial_port *port)
static int option_startup(struct usb_serial *serial)
{
- int i, err;
+ int i, j, err;
struct usb_serial_port *port;
struct option_port_private *portdata;
+ u8 *buffer;
dbg("%s", __FUNCTION__);
@@ -753,6 +869,20 @@ static int option_startup(struct usb_serial *serial)
return (1);
}
+ for (j = 0; j < N_IN_URB; j++) {
+ buffer = (u8 *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error;
+ portdata->in_buffer[j] = buffer;
+ }
+
+ for (j = 0; j < N_OUT_URB; j++) {
+ buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error2;
+ portdata->out_buffer[j] = buffer;
+ }
+
usb_set_serial_port_data(port, portdata);
if (! port->interrupt_in_urb)
@@ -766,6 +896,16 @@ static int option_startup(struct usb_serial *serial)
option_setup_urbs(serial);
return (0);
+
+bail_out_error2:
+ for (j = 0; j < N_OUT_URB; j++)
+ kfree(portdata->out_buffer[j]);
+bail_out_error:
+ for (j = 0; j < N_IN_URB; j++)
+ if (portdata->in_buffer[j])
+ free_page((unsigned long)portdata->in_buffer[j]);
+ kfree(portdata);
+ return 1;
}
static void option_shutdown(struct usb_serial *serial)
@@ -794,12 +934,14 @@ static void option_shutdown(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; j++) {
if (portdata->in_urbs[j]) {
usb_free_urb(portdata->in_urbs[j]);
+ free_page((unsigned long)portdata->in_buffer[j]);
portdata->in_urbs[j] = NULL;
}
}
for (j = 0; j < N_OUT_URB; j++) {
if (portdata->out_urbs[j]) {
usb_free_urb(portdata->out_urbs[j]);
+ kfree(portdata->out_buffer[j]);
portdata->out_urbs[j] = NULL;
}
}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ae3ec1a6400..2af778555bd 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -55,6 +55,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 237a41f6638..10cf872e5ec 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -13,6 +13,7 @@
#define PL2303_PRODUCT_ID_DCU11 0x1234
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
+#define PL2303_PRODUCT_ID_ALDIGA 0x0611
#define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 4c925e3e8a6..ed678811e6a 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -14,7 +14,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/
-#define DRIVER_VERSION "v.1.2.7"
+#define DRIVER_VERSION "v.1.2.8"
#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -163,6 +163,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
{ USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
{ USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */
+ { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
{ USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
{ USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
{ USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
@@ -178,7 +179,6 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
{ USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
- { USB_DEVICE(0x05C6, 0x6613), .driver_info = DEVICE_1_PORT }, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
{ }
@@ -197,9 +197,9 @@ struct sierra_port_private {
spinlock_t lock; /* lock the structure */
int outstanding_urbs; /* number of out urbs in flight */
- /* Input endpoints and buffer for this port */
+ /* Input endpoints and buffers for this port */
struct urb *in_urbs[N_IN_URB];
- char in_buffer[N_IN_URB][IN_BUFLEN];
+ char *in_buffer[N_IN_URB];
/* Settings for the port */
int rts_state; /* Handshaking pins (outputs) */
@@ -639,6 +639,15 @@ static int sierra_startup(struct usb_serial *serial)
return -ENOMEM;
}
spin_lock_init(&portdata->lock);
+ for (j = 0; j < N_IN_URB; j++) {
+ portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL);
+ if (!portdata->in_buffer[j]) {
+ for (--j; j >= 0; j--)
+ kfree(portdata->in_buffer[j]);
+ kfree(portdata);
+ return -ENOMEM;
+ }
+ }
usb_set_serial_port_data(port, portdata);
@@ -682,7 +691,7 @@ static void sierra_shutdown(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; j++) {
usb_kill_urb(portdata->in_urbs[j]);
usb_free_urb(portdata->in_urbs[j]);
- portdata->in_urbs[j] = NULL;
+ kfree(portdata->in_buffer[j]);
}
kfree(portdata);
usb_set_serial_port_data(port, NULL);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index b517f93352e..3a377667733 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -82,7 +82,6 @@
#include <linux/circ_buf.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -265,8 +264,8 @@ static struct usb_serial_driver ti_1port_device = {
.description = "TI USB 3410 1 port adapter",
.usb_driver = &ti_usb_driver,
.id_table = ti_id_table_3410,
- .num_interrupt_in = 1,
- .num_bulk_in = 1,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = 1,
.num_ports = 1,
.attach = ti_startup,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 3ce98e8d7bc..2138ba8aeb6 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -854,6 +854,7 @@ int usb_serial_probe(struct usb_interface *interface,
serial->num_interrupt_in = num_interrupt_in;
serial->num_interrupt_out = num_interrupt_out;
+#if 0
/* check that the device meets the driver's requirements */
if ((type->num_interrupt_in != NUM_DONT_CARE &&
type->num_interrupt_in != num_interrupt_in)
@@ -867,6 +868,7 @@ int usb_serial_probe(struct usb_interface *interface,
kfree(serial);
return -EIO;
}
+#endif
/* found all that we need */
dev_info(&interface->dev, "%s converter detected\n",
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 22b3f78a388..c2b01f7c319 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -191,7 +191,7 @@ static struct usb_serial_driver handspring_device = {
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 2,
- .num_bulk_out = 2,
+ .num_bulk_out = NUM_DONT_CARE,
.num_ports = 2,
.open = visor_open,
.close = visor_close,
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 2ae1e8673b1..971d13dd5e6 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1230,6 +1230,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
/* Free driver structure */
us->extra_destructor(info);
+ kfree(info);
us->extra = NULL;
us->extra_destructor = NULL;
}
@@ -1469,6 +1470,7 @@ static void isd200_free_info_ptrs(void *info_)
if (info) {
kfree(info->id);
kfree(info->RegsBuf);
+ kfree(info->srb.sense_buffer);
}
}
@@ -1494,7 +1496,9 @@ static int isd200_init_info(struct us_data *us)
kzalloc(sizeof(struct hd_driveid), GFP_KERNEL);
info->RegsBuf = (unsigned char *)
kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
- if (!info->id || !info->RegsBuf) {
+ info->srb.sense_buffer =
+ kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+ if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
isd200_free_info_ptrs(info);
kfree(info);
retStatus = ISD200_ERROR;
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index a41ce21c069..b9b8ede61fb 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -150,13 +150,14 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
/* Copy a buffer of length buflen to/from the srb's transfer buffer.
* Update the **sgptr and *offset variables so that the next copy will
- * pick up from where this one left off. */
-
+ * pick up from where this one left off.
+ */
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
unsigned int cnt;
+ struct scatterlist *sg = *sgptr;
/* We have to go through the list one entry
* at a time. Each s-g entry contains some number of pages, and
@@ -164,22 +165,22 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
* in kernel-addressable memory then kmap() will return its address.
* If the page is not directly accessible -- such as a user buffer
* located in high memory -- then kmap() will map it to a temporary
- * position in the kernel's virtual address space. */
- struct scatterlist *sg = *sgptr;
+ * position in the kernel's virtual address space.
+ */
if (!sg)
sg = scsi_sglist(srb);
/* This loop handles a single s-g list entry, which may
- * include multiple pages. Find the initial page structure
- * and the starting offset within the page, and update
- * the *offset and **sgptr values for the next loop. */
+ * include multiple pages. Find the initial page structure
+ * and the starting offset within the page, and update
+ * the *offset and **sgptr values for the next loop.
+ */
cnt = 0;
- while (cnt < buflen) {
+ while (cnt < buflen && sg) {
struct page *page = sg_page(sg) +
((sg->offset + *offset) >> PAGE_SHIFT);
- unsigned int poff =
- (sg->offset + *offset) & (PAGE_SIZE-1);
+ unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
unsigned int sglen = sg->length - *offset;
if (sglen > buflen - cnt) {
@@ -222,14 +223,16 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
}
/* Store the contents of buffer into srb's transfer buffer and set the
- * SCSI residue. */
+ * SCSI residue.
+ */
void usb_stor_set_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
- usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
+ buflen = min(buflen, scsi_bufflen(srb));
+ buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
TO_XFER_BUF);
if (buflen < scsi_bufflen(srb))
scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index d43a3415e12..6d14327c921 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -522,8 +522,8 @@ int sddr55_reset(struct us_data *us) {
static unsigned long sddr55_get_capacity(struct us_data *us) {
- unsigned char manufacturerID;
- unsigned char deviceID;
+ unsigned char uninitialized_var(manufacturerID);
+ unsigned char uninitialized_var(deviceID);
int result;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index d9f4912f873..bdd4334bed5 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -891,17 +891,6 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
if (result > 0)
return us->iobuf[0];
- /*
- * Some devices (i.e. Iomega Zip100) need this -- apparently
- * the bulk pipes get STALLed when the GetMaxLUN request is
- * processed. This is, in theory, harmless to all other devices
- * (regardless of if they stall or not).
- */
- if (result == -EPIPE) {
- usb_stor_clear_halt(us, us->recv_bulk_pipe);
- usb_stor_clear_halt(us, us->send_bulk_pipe);
- }
-
/*
* Some devices don't like GetMaxLUN. They may STALL the control
* pipe, they may return a zero-length result, they may do nothing at
@@ -1020,7 +1009,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status);
- if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) {
+ if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) ||
+ bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index fe12737e0e2..91252075e6e 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -357,7 +357,7 @@ UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200,
US_FL_FIX_CAPACITY),
/* Reported by Emil Larsson <emil@swip.net> */
-UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101,
+UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0110,
"NIKON",
"NIKON DSC D80",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -759,6 +759,18 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210,
"Digital Camera EX-20 DSC",
US_SC_8070, US_PR_DEVICE, NULL, 0 ),
+/* Reported by Andre Welter <a.r.welter@gmx.de>
+ * This antique device predates the release of the Bulk-only Transport
+ * spec, and if it gets a Get-Max-LUN then it requires the host to do a
+ * Clear-Halt on the bulk endpoints. The SINGLE_LUN flag will prevent
+ * us from sending the request.
+ */
+UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100,
+ "Iomega",
+ "ZIP 100",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
/* Reported by <Hendryk.Pfeiffer@gmx.de> */
UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000,
"LaCie",
@@ -1412,6 +1424,17 @@ UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
+/* Patch by Leonid Petrov mail at lpetrov.net
+ * Reported by Robert Spitzenpfeil <robert@spitzenpfeil.org>
+ * http://www.qbik.ch/usb/devices/showdev.php?id=1705
+ * Updated to 103 device by MJ Ray mjr at phonecoop.coop
+ */
+UNUSUAL_DEV( 0x0f19, 0x0103, 0x0100, 0x0100,
+ "Oracom Co., Ltd",
+ "ORC-200M",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* David Kuehling <dvdkhlng@gmx.de>:
* for MP3-Player AVOX WSX-300ER (bought in Japan). Reports lots of SCSI
* errors when trying to write.
@@ -1477,6 +1500,15 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
0 ),
+/* Reported by Fabio Venturi <f.venturi@tdnet.it>
+ * The device reports a vendor-specific bDeviceClass.
+ */
+UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100,
+ "Actions Semiconductor",
+ "Mtp device",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 0),
+
/* Reported by Kevin Lloyd <linux@sierrawireless.com>
* Entry is needed for the initializer function override,
* which instructs the device to load as a modem
@@ -1498,16 +1530,104 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* Reported by fangxiaozhi <fangxiaozhi60675@huawei.com>
- * and by linlei <linlei83@huawei.com>
- * Patch reworked by Johann Wilhelm <johann.wilhelm@student.tugraz.at>
- * This brings the HUAWEI E220 devices into multi-port mode
+/* Reported by fangxiaozhi <huananhu@huawei.com>
+ * This brings the HUAWEI data card devices into multi-port mode
*/
+UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
+UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
@@ -1557,6 +1677,17 @@ UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/*
+ * Patch by Constantin Baranov <const@tltsu.ru>
+ * Report by Andreas Koenecke.
+ * Motorola ROKR Z6.
+ */
+UNUSUAL_DEV( 0x22b8, 0x6426, 0x0101, 0x0101,
+ "Motorola",
+ "MSnc.",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG),
+
/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
"MPIO",