Эх сурвалжийг харах

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: (21 commits)
  USB: musb: fix srp sysfs entry deletion
  USB: musb: resume suspended root hub on disconnect
  USB: musb: use right poll limit for low speed devices
  USB: musb: be careful with 64K+ transfer lengths, host side
  USB: musb: fix data toggle saving with shared FIFO
  USB: musb: host endpoint_disable() oops fixes
  USB: musb: fix urb_dequeue() method
  USB: musb: fix musb_host_tx() for shared endpoint FIFO
  USB: musb: be careful with 64K+ transfer lengths (gadget side)
  usb: musb: make Davinci *work* in mainline
  USB: usb_get_string should check the descriptor type
  USB: gadget: fix build error in omap_apollon_2420_defconfig
  USB: g_file_storage: automatically disable stalls under Atmel
  USB: usb-storage: add IGNORE_RESIDUE flag for Genesys Logic adapters
  USB: Quirk for Hummingbird huc56s / Conexant ACM modem
  USB: serial: add support for second revision of Ericsson F3507G WWAN card
  USB: cdc-acm: add usb id for motomagx phones
  USB: option: add BenQ 3g modem information
  usb: gadget: obex: select correct ep descriptors
  USB: EHCI: slow down ITD reuse
  ...
Linus Torvalds 16 жил өмнө
parent
commit
3c4f1158cd

+ 3 - 3
arch/arm/mach-davinci/board-evm.c

@@ -311,6 +311,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_direction_output(gpio + 7, 1);
 	gpio_direction_output(gpio + 7, 1);
 
 
+	/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
+	setup_usb(500, 8);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -417,9 +420,6 @@ static __init void davinci_evm_init(void)
 	platform_add_devices(davinci_evm_devices,
 	platform_add_devices(davinci_evm_devices,
 			     ARRAY_SIZE(davinci_evm_devices));
 			     ARRAY_SIZE(davinci_evm_devices));
 	evm_init_i2c();
 	evm_init_i2c();
-
-	/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
-	setup_usb(500, 8);
 }
 }
 
 
 static __init void davinci_evm_irq_init(void)
 static __init void davinci_evm_irq_init(void)

+ 5 - 0
arch/arm/mach-davinci/clock.c

@@ -230,6 +230,11 @@ static struct clk davinci_clks[] = {
 		.rate = &commonrate,
 		.rate = &commonrate,
 		.lpsc = DAVINCI_LPSC_GPIO,
 		.lpsc = DAVINCI_LPSC_GPIO,
 	},
 	},
+	{
+		.name = "usb",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_USB,
+	},
 	{
 	{
 		.name = "AEMIFCLK",
 		.name = "AEMIFCLK",
 		.rate = &commonrate,
 		.rate = &commonrate,

+ 1 - 0
arch/arm/mach-davinci/usb.c

@@ -47,6 +47,7 @@ static struct musb_hdrc_platform_data usb_data = {
 #elif defined(CONFIG_USB_MUSB_HOST)
 #elif defined(CONFIG_USB_MUSB_HOST)
 	.mode           = MUSB_HOST,
 	.mode           = MUSB_HOST,
 #endif
 #endif
+	.clock		= "usb",
 	.config		= &musb_config,
 	.config		= &musb_config,
 };
 };
 
 

+ 9 - 0
drivers/usb/class/cdc-acm.c

@@ -1376,6 +1376,15 @@ static struct usb_device_id acm_ids[] = {
 	{ USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */
 	{ USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
 	},
+	{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
+	},
+	{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
+	.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
+					   data interface instead of
+					   communications interface.
+					   Maybe we should define a new
+					   quirk for this. */
+	},
 
 
 	/* control interfaces with various AT-command sets */
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,

+ 8 - 3
drivers/usb/core/message.c

@@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
 		if (result <= 0 && result != -ETIMEDOUT)
 		if (result <= 0 && result != -ETIMEDOUT)
 			continue;
 			continue;
 		if (result > 1 && ((u8 *)buf)[1] != type) {
 		if (result > 1 && ((u8 *)buf)[1] != type) {
-			result = -EPROTO;
+			result = -ENODATA;
 			continue;
 			continue;
 		}
 		}
 		break;
 		break;
@@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 			(USB_DT_STRING << 8) + index, langid, buf, size,
 			(USB_DT_STRING << 8) + index, langid, buf, size,
 			USB_CTRL_GET_TIMEOUT);
 			USB_CTRL_GET_TIMEOUT);
-		if (!(result == 0 || result == -EPIPE))
-			break;
+		if (result == 0 || result == -EPIPE)
+			continue;
+		if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
+			result = -ENODATA;
+			continue;
+		}
+		break;
 	}
 	}
 	return result;
 	return result;
 }
 }

+ 1 - 0
drivers/usb/gadget/Kconfig

@@ -191,6 +191,7 @@ config USB_GADGET_OMAP
 	boolean "OMAP USB Device Controller"
 	boolean "OMAP USB Device Controller"
 	depends on ARCH_OMAP
 	depends on ARCH_OMAP
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
+	select USB_OTG_UTILS if ARCH_OMAP
 	help
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
 	   speed USB device controllers, with support for up to 30

+ 2 - 2
drivers/usb/gadget/f_obex.c

@@ -366,9 +366,9 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 		f->hs_descriptors = usb_copy_descriptors(hs_function);
 		f->hs_descriptors = usb_copy_descriptors(hs_function);
 
 
 		obex->hs.obex_in = usb_find_endpoint(hs_function,
 		obex->hs.obex_in = usb_find_endpoint(hs_function,
-				f->descriptors, &obex_hs_ep_in_desc);
+				f->hs_descriptors, &obex_hs_ep_in_desc);
 		obex->hs.obex_out = usb_find_endpoint(hs_function,
 		obex->hs.obex_out = usb_find_endpoint(hs_function,
-				f->descriptors, &obex_hs_ep_out_desc);
+				f->hs_descriptors, &obex_hs_ep_out_desc);
 	}
 	}
 
 
 	/* Avoid letting this gadget enumerate until the userspace
 	/* Avoid letting this gadget enumerate until the userspace

+ 5 - 1
drivers/usb/gadget/file_storage.c

@@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg)
 	mod_data.protocol_type = USB_SC_SCSI;
 	mod_data.protocol_type = USB_SC_SCSI;
 	mod_data.protocol_name = "Transparent SCSI";
 	mod_data.protocol_name = "Transparent SCSI";
 
 
-	if (gadget_is_sh(fsg->gadget))
+	/* Some peripheral controllers are known not to be able to
+	 * halt bulk endpoints correctly.  If one of them is present,
+	 * disable stalls.
+	 */
+	if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
 		mod_data.can_stall = 0;
 		mod_data.can_stall = 0;
 
 
 	if (mod_data.release == 0xffff) {	// Parameter wasn't set
 	if (mod_data.release == 0xffff) {	// Parameter wasn't set

+ 3 - 0
drivers/usb/gadget/fsl_usb2_udc.c

@@ -404,7 +404,10 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
 	}
 	}
 	if (zlt)
 	if (zlt)
 		tmp |= EP_QUEUE_HEAD_ZLT_SEL;
 		tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+
 	p_QH->max_pkt_length = cpu_to_le32(tmp);
 	p_QH->max_pkt_length = cpu_to_le32(tmp);
+	p_QH->next_dtd_ptr = 1;
+	p_QH->size_ioc_int_sts = 0;
 
 
 	return;
 	return;
 }
 }

+ 2 - 0
drivers/usb/host/ehci-hcd.c

@@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd)
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
 	 */
 	ehci->periodic_size = DEFAULT_I_TDPS;
 	ehci->periodic_size = DEFAULT_I_TDPS;
+	INIT_LIST_HEAD(&ehci->cached_itd_list);
 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
 		return retval;
 		return retval;
 
 
@@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd)
 
 
 	ehci->reclaim = NULL;
 	ehci->reclaim = NULL;
 	ehci->next_uframe = -1;
 	ehci->next_uframe = -1;
+	ehci->clock_frame = -1;
 
 
 	/*
 	/*
 	 * dedicate a qh for the async ring head, since we couldn't unlink
 	 * dedicate a qh for the async ring head, since we couldn't unlink

+ 1 - 0
drivers/usb/host/ehci-mem.c

@@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh)
 
 
 static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 {
 {
+	free_cached_itd_list(ehci);
 	if (ehci->async)
 	if (ehci->async)
 		qh_put (ehci->async);
 		qh_put (ehci->async);
 	ehci->async = NULL;
 	ehci->async = NULL;

+ 48 - 8
drivers/usb/host/ehci-sched.c

@@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 
 
 		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		stream->bEndpointAddress &= 0x0f;
 		stream->bEndpointAddress &= 0x0f;
-		stream->ep->hcpriv = NULL;
+		if (stream->ep)
+			stream->ep->hcpriv = NULL;
 
 
 		if (stream->rescheduled) {
 		if (stream->rescheduled) {
 			ehci_info (ehci, "ep%d%s-iso rescheduled "
 			ehci_info (ehci, "ep%d%s-iso rescheduled "
@@ -1653,14 +1654,28 @@ itd_complete (
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	}
 	iso_stream_put (ehci, stream);
 	iso_stream_put (ehci, stream);
-	/* OK to recycle this ITD now that its completion callback ran. */
+
 done:
 done:
 	usb_put_urb(urb);
 	usb_put_urb(urb);
 	itd->urb = NULL;
 	itd->urb = NULL;
-	itd->stream = NULL;
-	list_move(&itd->itd_list, &stream->free_list);
-	iso_stream_put(ehci, stream);
-
+	if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
+		/* OK to recycle this ITD now. */
+		itd->stream = NULL;
+		list_move(&itd->itd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	} else {
+		/* HW might remember this ITD, so we can't recycle it yet.
+		 * Move it to a safe place until a new frame starts.
+		 */
+		list_move(&itd->itd_list, &ehci->cached_itd_list);
+		if (stream->refcount == 2) {
+			/* If iso_stream_put() were called here, stream
+			 * would be freed.  Instead, just prevent reuse.
+			 */
+			stream->ep->hcpriv = NULL;
+			stream->ep = NULL;
+		}
+	}
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2101,6 +2116,20 @@ done:
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
+static void free_cached_itd_list(struct ehci_hcd *ehci)
+{
+	struct ehci_itd *itd, *n;
+
+	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
+		struct ehci_iso_stream	*stream = itd->stream;
+		itd->stream = NULL;
+		list_move(&itd->itd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
 static void
 static void
 scan_periodic (struct ehci_hcd *ehci)
 scan_periodic (struct ehci_hcd *ehci)
 {
 {
@@ -2115,10 +2144,17 @@ scan_periodic (struct ehci_hcd *ehci)
 	 * Touches as few pages as possible:  cache-friendly.
 	 * Touches as few pages as possible:  cache-friendly.
 	 */
 	 */
 	now_uframe = ehci->next_uframe;
 	now_uframe = ehci->next_uframe;
-	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+	if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
-	else
+		clock_frame = (clock >> 3) % ehci->periodic_size;
+	} else  {
 		clock = now_uframe + mod - 1;
 		clock = now_uframe + mod - 1;
+		clock_frame = -1;
+	}
+	if (ehci->clock_frame != clock_frame) {
+		free_cached_itd_list(ehci);
+		ehci->clock_frame = clock_frame;
+	}
 	clock %= mod;
 	clock %= mod;
 	clock_frame = clock >> 3;
 	clock_frame = clock >> 3;
 
 
@@ -2277,6 +2313,10 @@ restart:
 			/* rescan the rest of this frame, then ... */
 			/* rescan the rest of this frame, then ... */
 			clock = now;
 			clock = now;
 			clock_frame = clock >> 3;
 			clock_frame = clock >> 3;
+			if (ehci->clock_frame != clock_frame) {
+				free_cached_itd_list(ehci);
+				ehci->clock_frame = clock_frame;
+			}
 		} else {
 		} else {
 			now_uframe++;
 			now_uframe++;
 			now_uframe %= mod;
 			now_uframe %= mod;

+ 6 - 0
drivers/usb/host/ehci.h

@@ -87,6 +87,10 @@ struct ehci_hcd {			/* one per controller */
 	int			next_uframe;	/* scan periodic, start here */
 	int			next_uframe;	/* scan periodic, start here */
 	unsigned		periodic_sched;	/* periodic activity count */
 	unsigned		periodic_sched;	/* periodic activity count */
 
 
+	/* list of itds completed while clock_frame was still active */
+	struct list_head	cached_itd_list;
+	unsigned		clock_frame;
+
 	/* per root hub port */
 	/* per root hub port */
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
 
 
@@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 	}
 	}
 }
 }
 
 
+static void free_cached_itd_list(struct ehci_hcd *ehci);
+
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/ehci_def.h>

+ 4 - 11
drivers/usb/musb/davinci.c

@@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb)
 	u32		revision;
 	u32		revision;
 
 
 	musb->mregs += DAVINCI_BASE_OFFSET;
 	musb->mregs += DAVINCI_BASE_OFFSET;
-#if 0
-	/* REVISIT there's something odd about clocking, this
-	 * didn't appear do the job ...
-	 */
-	musb->clock = clk_get(pDevice, "usb");
-	if (IS_ERR(musb->clock))
-		return PTR_ERR(musb->clock);
 
 
-	status = clk_enable(musb->clock);
-	if (status < 0)
-		return -ENODEV;
-#endif
+	clk_enable(musb->clock);
 
 
 	/* returns zero if e.g. not clocked */
 	/* returns zero if e.g. not clocked */
 	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
 	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
@@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb)
 	}
 	}
 
 
 	phy_off();
 	phy_off();
+
+	clk_disable(musb->clock);
+
 	return 0;
 	return 0;
 }
 }

+ 7 - 6
drivers/usb/musb/musb_core.c

@@ -115,7 +115,7 @@
 
 
 
 
 unsigned musb_debug;
 unsigned musb_debug;
-module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
 
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
@@ -767,6 +767,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 		case OTG_STATE_A_HOST:
 		case OTG_STATE_A_HOST:
 		case OTG_STATE_A_SUSPEND:
 		case OTG_STATE_A_SUSPEND:
+			usb_hcd_resume_root_hub(musb_to_hcd(musb));
 			musb_root_disconnect(musb);
 			musb_root_disconnect(musb);
 			if (musb->a_wait_bcon != 0)
 			if (musb->a_wait_bcon != 0)
 				musb_platform_try_idle(musb, jiffies
 				musb_platform_try_idle(musb, jiffies
@@ -1815,7 +1816,7 @@ static void musb_free(struct musb *musb)
 #ifdef CONFIG_SYSFS
 #ifdef CONFIG_SYSFS
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_vbus);
 	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	device_remove_file(musb->controller, &dev_attr_srp);
 	device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
 #endif
 #endif
@@ -2063,7 +2064,7 @@ fail2:
 #ifdef CONFIG_SYSFS
 #ifdef CONFIG_SYSFS
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_vbus);
 	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	device_remove_file(musb->controller, &dev_attr_srp);
 	device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
 #endif
 #endif
@@ -2243,10 +2244,10 @@ static int __init musb_init(void)
 	return platform_driver_probe(&musb_driver, musb_probe);
 	return platform_driver_probe(&musb_driver, musb_probe);
 }
 }
 
 
-/* make us init after usbcore and before usb
- * gadget and host-side drivers start to register
+/* make us init after usbcore and i2c (transceivers, regulators, etc)
+ * and before usb gadget and host-side drivers start to register
  */
  */
-subsys_initcall(musb_init);
+fs_initcall(musb_init);
 
 
 static void __exit musb_cleanup(void)
 static void __exit musb_cleanup(void)
 {
 {

+ 2 - 2
drivers/usb/musb/musb_gadget.c

@@ -575,7 +575,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 	struct usb_request	*request = &req->request;
 	struct usb_request	*request = &req->request;
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
-	u16			fifo_count = 0;
+	unsigned		fifo_count = 0;
 	u16			len = musb_ep->packet_sz;
 	u16			len = musb_ep->packet_sz;
 
 
 	csr = musb_readw(epio, MUSB_RXCSR);
 	csr = musb_readw(epio, MUSB_RXCSR);
@@ -687,7 +687,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 					len, fifo_count,
 					len, fifo_count,
 					musb_ep->packet_sz);
 					musb_ep->packet_sz);
 
 
-			fifo_count = min(len, fifo_count);
+			fifo_count = min_t(unsigned, len, fifo_count);
 
 
 #ifdef	CONFIG_USB_TUSB_OMAP_DMA
 #ifdef	CONFIG_USB_TUSB_OMAP_DMA
 			if (tusb_dma_omap() && musb_ep->dma) {
 			if (tusb_dma_omap() && musb_ep->dma) {

+ 58 - 35
drivers/usb/musb/musb_host.c

@@ -335,16 +335,11 @@ musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb)
 static struct musb_qh *
 static struct musb_qh *
 musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
 musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
 {
 {
-	int			is_in;
 	struct musb_hw_ep	*ep = qh->hw_ep;
 	struct musb_hw_ep	*ep = qh->hw_ep;
 	struct musb		*musb = ep->musb;
 	struct musb		*musb = ep->musb;
+	int			is_in = usb_pipein(urb->pipe);
 	int			ready = qh->is_ready;
 	int			ready = qh->is_ready;
 
 
-	if (ep->is_shared_fifo)
-		is_in = 1;
-	else
-		is_in = usb_pipein(urb->pipe);
-
 	/* save toggle eagerly, for paranoia */
 	/* save toggle eagerly, for paranoia */
 	switch (qh->type) {
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_BULK:
 	case USB_ENDPOINT_XFER_BULK:
@@ -432,7 +427,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
 	else
 	else
 		qh = musb_giveback(qh, urb, urb->status);
 		qh = musb_giveback(qh, urb, urb->status);
 
 
-	if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
+	if (qh != NULL && qh->is_ready) {
 		DBG(4, "... next ep%d %cX urb %p\n",
 		DBG(4, "... next ep%d %cX urb %p\n",
 				hw_ep->epnum, is_in ? 'R' : 'T',
 				hw_ep->epnum, is_in ? 'R' : 'T',
 				next_urb(qh));
 				next_urb(qh));
@@ -942,8 +937,8 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
 	switch (musb->ep0_stage) {
 	switch (musb->ep0_stage) {
 	case MUSB_EP0_IN:
 	case MUSB_EP0_IN:
 		fifo_dest = urb->transfer_buffer + urb->actual_length;
 		fifo_dest = urb->transfer_buffer + urb->actual_length;
-		fifo_count = min(len, ((u16) (urb->transfer_buffer_length
-					- urb->actual_length)));
+		fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
+				   urb->actual_length);
 		if (fifo_count < len)
 		if (fifo_count < len)
 			urb->status = -EOVERFLOW;
 			urb->status = -EOVERFLOW;
 
 
@@ -976,10 +971,9 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
 		}
 		}
 		/* FALLTHROUGH */
 		/* FALLTHROUGH */
 	case MUSB_EP0_OUT:
 	case MUSB_EP0_OUT:
-		fifo_count = min(qh->maxpacket, ((u16)
-				(urb->transfer_buffer_length
-				- urb->actual_length)));
-
+		fifo_count = min_t(size_t, qh->maxpacket,
+				   urb->transfer_buffer_length -
+				   urb->actual_length);
 		if (fifo_count) {
 		if (fifo_count) {
 			fifo_dest = (u8 *) (urb->transfer_buffer
 			fifo_dest = (u8 *) (urb->transfer_buffer
 					+ urb->actual_length);
 					+ urb->actual_length);
@@ -1161,7 +1155,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
 	struct urb		*urb;
 	struct urb		*urb;
 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
 	void __iomem		*epio = hw_ep->regs;
 	void __iomem		*epio = hw_ep->regs;
-	struct musb_qh		*qh = hw_ep->out_qh;
+	struct musb_qh		*qh = hw_ep->is_shared_fifo ? hw_ep->in_qh
+							    : hw_ep->out_qh;
 	u32			status = 0;
 	u32			status = 0;
 	void __iomem		*mbase = musb->mregs;
 	void __iomem		*mbase = musb->mregs;
 	struct dma_channel	*dma;
 	struct dma_channel	*dma;
@@ -1308,7 +1303,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
 		 * packets before updating TXCSR ... other docs disagree ...
 		 * packets before updating TXCSR ... other docs disagree ...
 		 */
 		 */
 		/* PIO:  start next packet in this URB */
 		/* PIO:  start next packet in this URB */
-		wLength = min(qh->maxpacket, (u16) wLength);
+		if (wLength > qh->maxpacket)
+			wLength = qh->maxpacket;
 		musb_write_fifo(hw_ep, wLength, buf);
 		musb_write_fifo(hw_ep, wLength, buf);
 		qh->segsize = wLength;
 		qh->segsize = wLength;
 
 
@@ -1867,19 +1863,21 @@ static int musb_urb_enqueue(
 	}
 	}
 	qh->type_reg = type_reg;
 	qh->type_reg = type_reg;
 
 
-	/* precompute rxinterval/txinterval register */
-	interval = min((u8)16, epd->bInterval);	/* log encoding */
+	/* Precompute RXINTERVAL/TXINTERVAL register */
 	switch (qh->type) {
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_INT:
 	case USB_ENDPOINT_XFER_INT:
-		/* fullspeed uses linear encoding */
-		if (USB_SPEED_FULL == urb->dev->speed) {
-			interval = epd->bInterval;
-			if (!interval)
-				interval = 1;
+		/*
+		 * Full/low speeds use the  linear encoding,
+		 * high speed uses the logarithmic encoding.
+		 */
+		if (urb->dev->speed <= USB_SPEED_FULL) {
+			interval = max_t(u8, epd->bInterval, 1);
+			break;
 		}
 		}
 		/* FALLTHROUGH */
 		/* FALLTHROUGH */
 	case USB_ENDPOINT_XFER_ISOC:
 	case USB_ENDPOINT_XFER_ISOC:
-		/* iso always uses log encoding */
+		/* ISO always uses logarithmic encoding */
+		interval = min_t(u8, epd->bInterval, 16);
 		break;
 		break;
 	default:
 	default:
 		/* REVISIT we actually want to use NAK limits, hinting to the
 		/* REVISIT we actually want to use NAK limits, hinting to the
@@ -2037,9 +2035,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		goto done;
 		goto done;
 
 
 	/* Any URB not actively programmed into endpoint hardware can be
 	/* Any URB not actively programmed into endpoint hardware can be
-	 * immediately given back.  Such an URB must be at the head of its
+	 * immediately given back; that's any URB not at the head of an
 	 * endpoint queue, unless someday we get real DMA queues.  And even
 	 * endpoint queue, unless someday we get real DMA queues.  And even
-	 * then, it might not be known to the hardware...
+	 * if it's at the head, it might not be known to the hardware...
 	 *
 	 *
 	 * Otherwise abort current transfer, pending dma, etc.; urb->status
 	 * Otherwise abort current transfer, pending dma, etc.; urb->status
 	 * has already been updated.  This is a synchronous abort; it'd be
 	 * has already been updated.  This is a synchronous abort; it'd be
@@ -2078,6 +2076,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		qh->is_ready = 0;
 		qh->is_ready = 0;
 		__musb_giveback(musb, urb, 0);
 		__musb_giveback(musb, urb, 0);
 		qh->is_ready = ready;
 		qh->is_ready = ready;
+
+		/* If nothing else (usually musb_giveback) is using it
+		 * and its URB list has emptied, recycle this qh.
+		 */
+		if (ready && list_empty(&qh->hep->urb_list)) {
+			qh->hep->hcpriv = NULL;
+			list_del(&qh->ring);
+			kfree(qh);
+		}
 	} else
 	} else
 		ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 		ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 done:
 done:
@@ -2093,15 +2100,16 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
 	unsigned long		flags;
 	unsigned long		flags;
 	struct musb		*musb = hcd_to_musb(hcd);
 	struct musb		*musb = hcd_to_musb(hcd);
 	u8			is_in = epnum & USB_DIR_IN;
 	u8			is_in = epnum & USB_DIR_IN;
-	struct musb_qh		*qh = hep->hcpriv;
-	struct urb		*urb, *tmp;
+	struct musb_qh		*qh;
+	struct urb		*urb;
 	struct list_head	*sched;
 	struct list_head	*sched;
 
 
-	if (!qh)
-		return;
-
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
 
 
+	qh = hep->hcpriv;
+	if (qh == NULL)
+		goto exit;
+
 	switch (qh->type) {
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_CONTROL:
 	case USB_ENDPOINT_XFER_CONTROL:
 		sched = &musb->control;
 		sched = &musb->control;
@@ -2135,13 +2143,28 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
 
 
 		/* cleanup */
 		/* cleanup */
 		musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 		musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
-	} else
-		urb = NULL;
 
 
-	/* then just nuke all the others */
-	list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list)
-		musb_giveback(qh, urb, -ESHUTDOWN);
+		/* Then nuke all the others ... and advance the
+		 * queue on hw_ep (e.g. bulk ring) when we're done.
+		 */
+		while (!list_empty(&hep->urb_list)) {
+			urb = next_urb(qh);
+			urb->status = -ESHUTDOWN;
+			musb_advance_schedule(musb, urb, qh->hw_ep, is_in);
+		}
+	} else {
+		/* Just empty the queue; the hardware is busy with
+		 * other transfers, and since !qh->is_ready nothing
+		 * will activate any of these as it advances.
+		 */
+		while (!list_empty(&hep->urb_list))
+			__musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
 
 
+		hep->hcpriv = NULL;
+		list_del(&qh->ring);
+		kfree(qh);
+	}
+exit:
 	spin_unlock_irqrestore(&musb->lock, flags);
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 }
 
 

+ 9 - 2
drivers/usb/serial/option.c

@@ -294,7 +294,11 @@ static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
 
 
 /* Ericsson products */
 /* Ericsson products */
 #define ERICSSON_VENDOR_ID			0x0bdb
 #define ERICSSON_VENDOR_ID			0x0bdb
-#define ERICSSON_PRODUCT_F3507G			0x1900
+#define ERICSSON_PRODUCT_F3507G_1		0x1900
+#define ERICSSON_PRODUCT_F3507G_2		0x1902
+
+#define BENQ_VENDOR_ID				0x04a5
+#define BENQ_PRODUCT_H10			0x4068
 
 
 static struct usb_device_id option_ids[] = {
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -509,7 +513,10 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
-	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
+	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
+	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
+	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+	{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
 	{ } /* Terminating entry */
 	{ } /* Terminating entry */
 };
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
 MODULE_DEVICE_TABLE(usb, option_ids);

+ 2 - 2
drivers/usb/storage/unusual_devs.h

@@ -907,13 +907,13 @@ UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
 		"Genesys Logic",
 		"Genesys Logic",
 		"USB to IDE Optical",
 		"USB to IDE Optical",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
 		"Genesys Logic",
 		"Genesys Logic",
 		"USB to IDE Disk",
 		"USB to IDE Disk",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,