浏览代码

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: ftdi_sio - really enable EM1010PC
  USB: remove incorrect struct class_device from the printer gadget
  USB: pxa2xx_udc: fix misuse of clock enable/disable calls
  USB: ftdi_sio: Workaround for broken Matrix Orbital serial port
  USB: Add support for AXESSTEL MV110H CDMA modem
  usb-storage: update earlier scatter-gather bug fix
  USB: isp116x: fix enumeration on boot
  USB: ehci: handle large bulk URBs correctly (again)
  USB: spruce up the device blacklist
  USB: fix comment of struct usb_interface
  USB: update Kconfig entry for USB_SUSPEND
  usb: Add support for the mos7820/7840-based B&B USB/RS485 converter to mos7840.c
Linus Torvalds 17 年之前
父节点
当前提交
10955d2251

+ 5 - 4
drivers/usb/core/Kconfig

@@ -87,12 +87,13 @@ config USB_DYNAMIC_MINORS
 	  If you are unsure about this, say N here.
 	  If you are unsure about this, say N here.
 
 
 config USB_SUSPEND
 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
 	help
 	  If you say Y here, you can use driver calls or the sysfs
 	  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
 	  Also, USB "remote wakeup" signaling is supported, whereby some
 	  USB devices (like keyboards and network adapters) can wake up
 	  USB devices (like keyboards and network adapters) can wake up

+ 12 - 9
drivers/usb/core/quirks.c

@@ -28,35 +28,38 @@
  * devices is broken...
  * devices is broken...
  */
  */
 static const struct usb_device_id usb_quirk_list[] = {
 static const struct usb_device_id usb_quirk_list[] = {
-	/* Action Semiconductor flash disk */
-	{ USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255},
-
 	/* CBM - Flash disk */
 	/* CBM - Flash disk */
 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* HP 5300/5370C scanner */
 	/* 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 },
 
 
 	/* Creative SB Audigy 2 NX */
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ 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 */
 	/* Roland SC-8820 */
 	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 
 
 	/* Edirol SD-20 */
 	/* Edirol SD-20 */
 	{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
 
 
-	/* INTEL VALUE SSD */
-	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
-
 	/* M-Systems Flash Disk Pioneers */
 	/* M-Systems Flash Disk Pioneers */
 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
 
-	/* Philips PSC805 audio device */
-	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Action Semiconductor flash disk */
+	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
+			USB_QUIRK_STRING_FETCH_255 },
 
 
 	/* SKYMEDI USB_DRIVE */
 	/* SKYMEDI USB_DRIVE */
 	{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
 	{ 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 */
 	{ }  /* terminating entry must be last */
 };
 };
 
 

+ 0 - 1
drivers/usb/gadget/printer.c

@@ -92,7 +92,6 @@ struct printer_dev {
 	u8			*current_rx_buf;
 	u8			*current_rx_buf;
 	u8			printer_status;
 	u8			printer_status;
 	u8			reset_printer;
 	u8			reset_printer;
-	struct class_device	*printer_class_dev;
 	struct cdev		printer_cdev;
 	struct cdev		printer_cdev;
 	struct device		*pdev;
 	struct device		*pdev;
 	u8			printer_cdev_open;
 	u8			printer_cdev_open;

+ 50 - 38
drivers/usb/gadget/pxa2xx_udc.c

@@ -103,6 +103,12 @@ static const char ep0name [] = "ep0";
 #error "Can't configure both IXP and PXA"
 #error "Can't configure both IXP and PXA"
 #endif
 #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
 #endif
 
 
 #include "pxa2xx_udc.h"
 #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
 /* We disable the UDC -- and its 48 MHz clock -- whenever it's not
  * in active use.
  * 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");
 	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;
 	return 0;
 }
 }
@@ -958,9 +975,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
 	struct pxa2xx_udc	*udc;
 	struct pxa2xx_udc	*udc;
 
 
 	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
 	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");
 	DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
-	pullup(udc, is_active);
+	pullup(udc);
 	return 0;
 	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)
 	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 
 
-	is_active = (is_active != 0);
-	udc->pullup = is_active;
-	pullup(udc, is_active);
+	udc->pullup = (is_active != 0);
+	pullup(udc);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -997,7 +1013,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = {
 #ifdef CONFIG_USB_GADGET_DEBUG_FS
 #ifdef CONFIG_USB_GADGET_DEBUG_FS
 
 
 static int
 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;
 	struct pxa2xx_udc	*dev = m->private;
 	unsigned long		flags;
 	unsigned long		flags;
@@ -1146,11 +1162,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
 
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 
 
-#ifdef	CONFIG_ARCH_PXA
-        /* Disable clock for USB device */
-	clk_disable(dev->clk);
-#endif
-
 	ep0_idle (dev);
 	ep0_idle (dev);
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
 }
 }
@@ -1191,11 +1202,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
 {
 {
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 	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 */
 	/* try to clear these bits before we enable the udc */
 	udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
 	udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
 
 
@@ -1286,7 +1292,7 @@ fail:
 	 * for set_configuration as well as eventual disconnect.
 	 * for set_configuration as well as eventual disconnect.
 	 */
 	 */
 	DMSG("registered gadget driver '%s'\n", driver->driver.name);
 	DMSG("registered gadget driver '%s'\n", driver->driver.name);
-	pullup(dev, 1);
+	pullup(dev);
 	dump_state(dev);
 	dump_state(dev);
 	return 0;
 	return 0;
 }
 }
@@ -1329,7 +1335,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	local_irq_disable();
 	local_irq_disable();
-	pullup(dev, 0);
+	dev->pullup = 0;
+	pullup(dev);
 	stop_activity(dev, driver);
 	stop_activity(dev, driver);
 	local_irq_enable();
 	local_irq_enable();
 
 
@@ -2131,13 +2138,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 	if (irq < 0)
 	if (irq < 0)
 		return -ENODEV;
 		return -ENODEV;
 
 
-#ifdef	CONFIG_ARCH_PXA
 	dev->clk = clk_get(&pdev->dev, "UDCCLK");
 	dev->clk = clk_get(&pdev->dev, "UDCCLK");
 	if (IS_ERR(dev->clk)) {
 	if (IS_ERR(dev->clk)) {
 		retval = PTR_ERR(dev->clk);
 		retval = PTR_ERR(dev->clk);
 		goto err_clk;
 		goto err_clk;
 	}
 	}
-#endif
 
 
 	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
 	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
 		dev->has_cfr ? "" : " (!cfr)",
 		dev->has_cfr ? "" : " (!cfr)",
@@ -2250,10 +2255,8 @@ lubbock_fail0:
 	if (dev->mach->gpio_vbus)
 	if (dev->mach->gpio_vbus)
 		gpio_free(dev->mach->gpio_vbus);
 		gpio_free(dev->mach->gpio_vbus);
  err_gpio_vbus:
  err_gpio_vbus:
-#ifdef	CONFIG_ARCH_PXA
 	clk_put(dev->clk);
 	clk_put(dev->clk);
  err_clk:
  err_clk:
-#endif
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2269,7 +2272,9 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
 	if (dev->driver)
 	if (dev->driver)
 		return -EBUSY;
 		return -EBUSY;
 
 
-	udc_disable(dev);
+	dev->pullup = 0;
+	pullup(dev);
+
 	remove_debug_files(dev);
 	remove_debug_files(dev);
 
 
 	if (dev->got_irq) {
 	if (dev->got_irq) {
@@ -2289,9 +2294,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
 	if (dev->mach->gpio_pullup)
 	if (dev->mach->gpio_pullup)
 		gpio_free(dev->mach->gpio_pullup);
 		gpio_free(dev->mach->gpio_pullup);
 
 
-#ifdef	CONFIG_ARCH_PXA
 	clk_put(dev->clk);
 	clk_put(dev->clk);
-#endif
 
 
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 	the_controller = 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)
 static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 {
 {
 	struct pxa2xx_udc	*udc = platform_get_drvdata(dev);
 	struct pxa2xx_udc	*udc = platform_get_drvdata(dev);
+	unsigned long flags;
 
 
 	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
 	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
 		WARN("USB host won't detect disconnect!\n");
 		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;
 	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)
 static int pxa2xx_udc_resume(struct platform_device *dev)
 {
 {
 	struct pxa2xx_udc	*udc = platform_get_drvdata(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;
 	return 0;
 }
 }

+ 3 - 1
drivers/usb/gadget/pxa2xx_udc.h

@@ -119,7 +119,9 @@ struct pxa2xx_udc {
 						has_cfr : 1,
 						has_cfr : 1,
 						req_pending : 1,
 						req_pending : 1,
 						req_std : 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))
 #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
 	struct timer_list			timer;
 	struct timer_list			timer;

+ 1 - 1
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)) {
 			if (likely (last->urb != urb)) {
 				ehci_urb_done(ehci, last->urb, last_status);
 				ehci_urb_done(ehci, last->urb, last_status);
 				count++;
 				count++;
+				last_status = -EINPROGRESS;
 			}
 			}
 			ehci_qtd_free (ehci, last);
 			ehci_qtd_free (ehci, last);
 			last = NULL;
 			last = NULL;
-			last_status = -EINPROGRESS;
 		}
 		}
 
 
 		/* ignore urbs submitted during completions we reported */
 		/* ignore urbs submitted during completions we reported */

+ 6 - 9
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;
 		buf[0] = 0;
 
 
 	for (i = 0; i < ports; i++) {
 	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
 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
 			      | RH_PS_OCIC | RH_PS_PRSC)) {
 			      | RH_PS_OCIC | RH_PS_PRSC)) {
@@ -1031,7 +1030,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
 		DBG("GetPortStatus\n");
 		DBG("GetPortStatus\n");
 		if (!wIndex || wIndex > ports)
 		if (!wIndex || wIndex > ports)
 			goto error;
 			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);
 		*(__le32 *) buf = cpu_to_le32(tmp);
 		DBG("GetPortStatus: port[%d]  %08x\n", wIndex + 1, tmp);
 		DBG("GetPortStatus: port[%d]  %08x\n", wIndex + 1, tmp);
 		break;
 		break;
@@ -1080,8 +1081,6 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
 		spin_lock_irqsave(&isp116x->lock, flags);
 		spin_lock_irqsave(&isp116x->lock, flags);
 		isp116x_write_reg32(isp116x, wIndex
 		isp116x_write_reg32(isp116x, wIndex
 				    ? HCRHPORT2 : HCRHPORT1, tmp);
 				    ? HCRHPORT2 : HCRHPORT1, tmp);
-		isp116x->rhport[wIndex] =
-		    isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
 		spin_unlock_irqrestore(&isp116x->lock, flags);
 		spin_unlock_irqrestore(&isp116x->lock, flags);
 		break;
 		break;
 	case SetPortFeature:
 	case SetPortFeature:
@@ -1095,24 +1094,22 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
 			spin_lock_irqsave(&isp116x->lock, flags);
 			spin_lock_irqsave(&isp116x->lock, flags);
 			isp116x_write_reg32(isp116x, wIndex
 			isp116x_write_reg32(isp116x, wIndex
 					    ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS);
 					    ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS);
+			spin_unlock_irqrestore(&isp116x->lock, flags);
 			break;
 			break;
 		case USB_PORT_FEAT_POWER:
 		case USB_PORT_FEAT_POWER:
 			DBG("USB_PORT_FEAT_POWER\n");
 			DBG("USB_PORT_FEAT_POWER\n");
 			spin_lock_irqsave(&isp116x->lock, flags);
 			spin_lock_irqsave(&isp116x->lock, flags);
 			isp116x_write_reg32(isp116x, wIndex
 			isp116x_write_reg32(isp116x, wIndex
 					    ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS);
 					    ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS);
+			spin_unlock_irqrestore(&isp116x->lock, flags);
 			break;
 			break;
 		case USB_PORT_FEAT_RESET:
 		case USB_PORT_FEAT_RESET:
 			DBG("USB_PORT_FEAT_RESET\n");
 			DBG("USB_PORT_FEAT_RESET\n");
 			root_port_reset(isp116x, wIndex);
 			root_port_reset(isp116x, wIndex);
-			spin_lock_irqsave(&isp116x->lock, flags);
 			break;
 			break;
 		default:
 		default:
 			goto error;
 			goto error;
 		}
 		}
-		isp116x->rhport[wIndex] =
-		    isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
-		spin_unlock_irqrestore(&isp116x->lock, flags);
 		break;
 		break;
 
 
 	default:
 	default:

+ 0 - 1
drivers/usb/host/isp116x.h

@@ -270,7 +270,6 @@ struct isp116x {
 	u32 rhdesca;
 	u32 rhdesca;
 	u32 rhdescb;
 	u32 rhdescb;
 	u32 rhstatus;
 	u32 rhstatus;
-	u32 rhport[2];
 
 
 	/* async schedule: control, bulk */
 	/* async schedule: control, bulk */
 	struct list_head async;
 	struct list_head async;

+ 25 - 0
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_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_USB_UIRT_setup	(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_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,
 	.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 = {
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
 	.port_probe = ftdi_USB_UIRT_setup,
 	.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_4_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_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_PERLE_ULTRAPORT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_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_FS20SIG_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_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, FTDI_ELV_WS500_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
@@ -1088,6 +1096,23 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
 	return 0;
 	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
 /* ftdi_shutdown is called from usbserial:usb_serial_disconnect
  *   it is called when the usb device is disconnected
  *   it is called when the usb device is disconnected
  *
  *

+ 7 - 0
drivers/usb/serial/ftdi_sio.h

@@ -102,6 +102,13 @@
  * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
  * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
 #define FTDI_OOCDLINK_PID	0xbaf8	/* Amontec JTAGkey */
 #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 */
 /* Interbiometrics USB I/O Board */
 /* Developed for Interbiometrics by Rudolf Gugler */
 /* Developed for Interbiometrics by Rudolf Gugler */
 #define INTERBIOMETRICS_VID              0x1209
 #define INTERBIOMETRICS_VID              0x1209

+ 14 - 1
drivers/usb/serial/mos7840.c

@@ -110,11 +110,20 @@
 
 
 /* vendor id and device id defines */
 /* vendor id and device id defines */
 
 
+/* The native mos7840/7820 component */
 #define USB_VENDOR_ID_MOSCHIP           0x9710
 #define USB_VENDOR_ID_MOSCHIP           0x9710
 #define MOSCHIP_DEVICE_ID_7840          0x7840
 #define MOSCHIP_DEVICE_ID_7840          0x7840
 #define MOSCHIP_DEVICE_ID_7820          0x7820
 #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_RLS      0x06
 #define SERIAL_IIR_MS       0x00
 #define SERIAL_IIR_MS       0x00
@@ -159,12 +168,16 @@
 static struct usb_device_id moschip_port_id_table[] = {
 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_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
 	{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 */
 	{}			/* terminating entry */
 };
 };
 
 
 static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
 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_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
 	{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 */
 	{}			/* terminating entry */
 };
 };
 
 

+ 4 - 0
drivers/usb/serial/option.c

@@ -120,6 +120,9 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define ANYDATA_PRODUCT_ADU_E100A		0x6501
 #define ANYDATA_PRODUCT_ADU_E100A		0x6501
 #define ANYDATA_PRODUCT_ADU_500A		0x6502
 #define ANYDATA_PRODUCT_ADU_500A		0x6502
 
 
+#define AXESSTEL_VENDOR_ID			0x1726
+#define AXESSTEL_PRODUCT_MV110H			0x1000
+
 #define BANDRICH_VENDOR_ID			0x1A8D
 #define BANDRICH_VENDOR_ID			0x1A8D
 #define BANDRICH_PRODUCT_C100_1			0x1002
 #define BANDRICH_PRODUCT_C100_1			0x1002
 #define BANDRICH_PRODUCT_C100_2			0x1003
 #define BANDRICH_PRODUCT_C100_2			0x1003
@@ -192,6 +195,7 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) },	/* Dell Wireless HSDPA 5520 */
 	{ 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_E100A) },
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
 	{ 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_1) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },

+ 1 - 1
drivers/usb/storage/protocol.c

@@ -170,7 +170,6 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
 
 
 	if (!sg)
 	if (!sg)
 		sg = scsi_sglist(srb);
 		sg = scsi_sglist(srb);
-	buflen = min(buflen, scsi_bufflen(srb));
 
 
 	/* This loop handles a single s-g list entry, which may
 	/* This loop handles a single s-g list entry, which may
 	 * include multiple pages.  Find the initial page structure
 	 * include multiple pages.  Find the initial page structure
@@ -232,6 +231,7 @@ void usb_stor_set_xfer_buf(unsigned char *buffer,
 	unsigned int offset = 0;
 	unsigned int offset = 0;
 	struct scatterlist *sg = NULL;
 	struct scatterlist *sg = NULL;
 
 
+	buflen = min(buflen, scsi_bufflen(srb));
 	buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
 	buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
 			TO_XFER_BUF);
 			TO_XFER_BUF);
 	if (buflen < scsi_bufflen(srb))
 	if (buflen < scsi_bufflen(srb))

+ 1 - 2
include/linux/usb.h

@@ -94,10 +94,9 @@ enum usb_interface_condition {
  * @altsetting: array of interface structures, one for each alternate
  * @altsetting: array of interface structures, one for each alternate
  * 	setting that may be selected.  Each one includes a set of
  * 	setting that may be selected.  Each one includes a set of
  * 	endpoint configurations.  They will be in no particular order.
  * 	endpoint configurations.  They will be in no particular order.
- * @num_altsetting: number of altsettings defined.
  * @cur_altsetting: the current altsetting.
  * @cur_altsetting: the current altsetting.
+ * @num_altsetting: number of altsettings defined.
  * @intf_assoc: interface association descriptor
  * @intf_assoc: interface association descriptor
- * @driver: the USB driver that is bound to this interface.
  * @minor: the minor number assigned to this interface, if this
  * @minor: the minor number assigned to this interface, if this
  *	interface is bound to a driver that uses the USB major number.
  *	interface is bound to a driver that uses the USB major number.
  *	If this interface does not use the USB major, this field should
  *	If this interface does not use the USB major, this field should