diff options
Diffstat (limited to 'drivers/usb')
36 files changed, 528 insertions, 216 deletions
| diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index f5ed3d75fa5..8f5ebced5df 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/  obj-$(CONFIG_USB_SERIAL)	+= serial/  obj-$(CONFIG_USB)		+= misc/ -obj-$(CONFIG_USB_COMMON)	+= phy/ +obj-$(CONFIG_USB_OTG_UTILS)	+= phy/  obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/  obj-$(CONFIG_USB_ATM)		+= atm/ diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index a03fbc15fa9..aa491627a45 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -100,7 +100,7 @@ struct c67x00_urb_priv {  #define TD_PIDEP_OFFSET		0x04  #define TD_PIDEPMASK_PID	0xF0  #define TD_PIDEPMASK_EP		0x0F -#define TD_PORTLENMASK_DL	0x02FF +#define TD_PORTLENMASK_DL	0x03FF  #define TD_PORTLENMASK_PN	0xC000  #define TD_STATUS_OFFSET	0x07 @@ -590,7 +590,7 @@ static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,  {  	struct c67x00_td *td;  	struct c67x00_urb_priv *urbp = urb->hcpriv; -	const __u8 active_flag = 1, retry_cnt = 1; +	const __u8 active_flag = 1, retry_cnt = 3;  	__u8 cmd = 0;  	int tt = 0; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 2f45bba8561..f64fbea1cf2 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1767,7 +1767,7 @@ static int udc_start(struct ci13xxx *ci)  		goto put_transceiver;  	} -	retval = dbg_create_files(&ci->gadget.dev); +	retval = dbg_create_files(ci->dev);  	if (retval)  		goto unreg_device; @@ -1796,7 +1796,7 @@ remove_trans:  	dev_err(dev, "error = %i\n", retval);  remove_dbg: -	dbg_remove_files(&ci->gadget.dev); +	dbg_remove_files(ci->dev);  unreg_device:  	device_unregister(&ci->gadget.dev);  put_transceiver: @@ -1836,7 +1836,7 @@ static void udc_stop(struct ci13xxx *ci)  		if (ci->global_phy)  			usb_put_phy(ci->transceiver);  	} -	dbg_remove_files(&ci->gadget.dev); +	dbg_remove_files(ci->dev);  	device_unregister(&ci->gadget.dev);  	/* my kobject is dynamic, I swear! */  	memset(&ci->gadget, 0, sizeof(ci->gadget)); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5f0cb417b73..122d056d96d 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);  #define WDM_RESPONDING		7  #define WDM_SUSPENDING		8  #define WDM_RESETTING		9 +#define WDM_OVERFLOW		10  #define WDM_MAX			16 @@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb)  {  	struct wdm_device *desc = urb->context;  	int status = urb->status; +	int length = urb->actual_length;  	spin_lock(&desc->iuspin);  	clear_bit(WDM_RESPONDING, &desc->flags); @@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb)  	}  	desc->rerr = status; -	desc->reslength = urb->actual_length; -	memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); -	desc->length += desc->reslength; +	if (length + desc->length > desc->wMaxCommand) { +		/* The buffer would overflow */ +		set_bit(WDM_OVERFLOW, &desc->flags); +	} else { +		/* we may already be in overflow */ +		if (!test_bit(WDM_OVERFLOW, &desc->flags)) { +			memmove(desc->ubuf + desc->length, desc->inbuf, length); +			desc->length += length; +			desc->reslength = length; +		} +	}  skip_error:  	wake_up(&desc->wait); @@ -435,6 +445,11 @@ retry:  			rv = -ENODEV;  			goto err;  		} +		if (test_bit(WDM_OVERFLOW, &desc->flags)) { +			clear_bit(WDM_OVERFLOW, &desc->flags); +			rv = -ENOBUFS; +			goto err; +		}  		i++;  		if (file->f_flags & O_NONBLOCK) {  			if (!test_bit(WDM_READ, &desc->flags)) { @@ -478,6 +493,7 @@ retry:  			spin_unlock_irq(&desc->iuspin);  			goto retry;  		} +  		if (!desc->reslength) { /* zero length read */  			dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);  			clear_bit(WDM_READ, &desc->flags); @@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf)  	struct wdm_device *desc = wdm_find_device(intf);  	int rv; +	clear_bit(WDM_OVERFLOW, &desc->flags);  	clear_bit(WDM_RESETTING, &desc->flags);  	rv = recover_from_urb_loss(desc);  	mutex_unlock(&desc->wlock); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 999909451e3..ffa6b004a84 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -583,6 +583,7 @@ static int dwc3_remove(struct platform_device *pdev)  		break;  	} +	dwc3_free_event_buffers(dwc);  	dwc3_core_exit(dwc);  	return 0; diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b50da53e9a5..b082bec7343 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -23,8 +23,6 @@  #include <linux/usb/nop-usb-xceiv.h>  #include <linux/of.h> -#include "core.h" -  struct dwc3_exynos {  	struct platform_device	*dwc3;  	struct platform_device	*usb2_phy; diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 22f337f5721..afa05e3c9cf 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -54,8 +54,6 @@  #include <linux/usb/otg.h>  #include <linux/usb/nop-usb-xceiv.h> -#include "core.h" -  /*   * All these registers belong to OMAP's Wrapper around the   * DesignWare USB3 Core. @@ -465,20 +463,20 @@ static int dwc3_omap_remove(struct platform_device *pdev)  	return 0;  } -static const struct of_device_id of_dwc3_matach[] = { +static const struct of_device_id of_dwc3_match[] = {  	{  		"ti,dwc3",  	},  	{ },  }; -MODULE_DEVICE_TABLE(of, of_dwc3_matach); +MODULE_DEVICE_TABLE(of, of_dwc3_match);  static struct platform_driver dwc3_omap_driver = {  	.probe		= dwc3_omap_probe,  	.remove		= dwc3_omap_remove,  	.driver		= {  		.name	= "omap-dwc3", -		.of_match_table	= of_dwc3_matach, +		.of_match_table	= of_dwc3_match,  	},  }; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 7d70f44567d..e8d77689a32 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -45,8 +45,6 @@  #include <linux/usb/otg.h>  #include <linux/usb/nop-usb-xceiv.h> -#include "core.h" -  /* FIXME define these in <linux/pci_ids.h> */  #define PCI_VENDOR_ID_SYNOPSYS		0x16c3  #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3	0xabcd diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index d7da073a23f..1d139ca05ef 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -891,7 +891,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,  				DWC3_TRBCTL_CONTROL_DATA);  	} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)  			&& (dep->number == 0)) { -		u32		transfer_size; +		u32	transfer_size; +		u32	maxpacket;  		ret = usb_gadget_map_request(&dwc->gadget, &req->request,  				dep->number); @@ -902,8 +903,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,  		WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); -		transfer_size = roundup(req->request.length, -				(u32) dep->endpoint.maxpacket); +		maxpacket = dep->endpoint.maxpacket; +		transfer_size = roundup(req->request.length, maxpacket);  		dwc->ep0_bounced = true; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a04342f6cbf..82e160e96fc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2159,7 +2159,6 @@ static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)  static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)  { -	struct dwc3_gadget_ep_cmd_params params;  	struct dwc3_ep		*dep;  	int			ret;  	u32			reg; @@ -2167,8 +2166,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)  	dev_vdbg(dwc->dev, "%s\n", __func__); -	memset(¶ms, 0x00, sizeof(params)); -  	reg = dwc3_readl(dwc->regs, DWC3_DSTS);  	speed = reg & DWC3_DSTS_CONNECTSPD;  	dwc->speed = speed; diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 97a13c349cc..82fb2251135 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -35,6 +35,12 @@ mv_udc-y			:= mv_udc_core.o  obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o  obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o +# USB Functions +obj-$(CONFIG_USB_F_ACM)		+= f_acm.o +f_ss_lb-y			:= f_loopback.o f_sourcesink.o +obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o +obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o +  #  # USB gadget drivers  # @@ -74,9 +80,3 @@ obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o  obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o  obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o  obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o - -# USB Functions -obj-$(CONFIG_USB_F_ACM)		+= f_acm.o -f_ss_lb-y			:= f_loopback.o f_sourcesink.o -obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o -obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3..c0d62b27861 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1757,10 +1757,7 @@ static const struct usb_gadget_driver composite_driver_template = {  /**   * usb_composite_probe() - register a composite driver   * @driver: the driver to register - * @bind: the callback used to allocate resources that are shared across the - *	whole device, such as string IDs, and add its configurations using - *	@usb_add_config().  This may fail by returning a negative errno - *	value; it should return zero on successful initialization. + *   * Context: single threaded during gadget setup   *   * This function is used to register drivers using the composite driver diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c index f570e667a64..fa8ea4ea00c 100644 --- a/drivers/usb/gadget/f_uac1.c +++ b/drivers/usb/gadget/f_uac1.c @@ -418,6 +418,7 @@ static int audio_get_intf_req(struct usb_function *f,  	req->context = audio;  	req->complete = f_audio_complete; +	len = min_t(size_t, sizeof(value), len);  	memcpy(req->buf, &value, len);  	return len; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 8efd7555fa2..5bd930d779b 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1334,27 +1334,18 @@ static int imx_udc_start(struct usb_gadget *gadget,  		struct usb_gadget_driver *driver)  {  	struct imx_udc_struct *imx_usb; -	int retval;  	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);  	/* first hook up the driver ... */  	imx_usb->driver = driver;  	imx_usb->gadget.dev.driver = &driver->driver; -	retval = device_add(&imx_usb->gadget.dev); -	if (retval) -		goto fail; -  	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",  		__func__, driver->driver.name);  	imx_udc_enable(imx_usb);  	return 0; -fail: -	imx_usb->driver = NULL; -	imx_usb->gadget.dev.driver = NULL; -	return retval;  }  static int imx_udc_stop(struct usb_gadget *gadget, @@ -1370,8 +1361,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,  	imx_usb->gadget.dev.driver = NULL;  	imx_usb->driver = NULL; -	device_del(&imx_usb->gadget.dev); -  	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",  		__func__, driver->driver.name); @@ -1477,6 +1466,10 @@ static int __init imx_udc_probe(struct platform_device *pdev)  	imx_usb->gadget.dev.parent = &pdev->dev;  	imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; +	ret = device_add(&imx_usb->gadget.dev); +	if (retval) +		goto fail4; +  	platform_set_drvdata(pdev, imx_usb);  	usb_init_data(imx_usb); @@ -1488,9 +1481,11 @@ static int __init imx_udc_probe(struct platform_device *pdev)  	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);  	if (ret) -		goto fail4; +		goto fail5;  	return 0; +fail5: +	device_unregister(&imx_usb->gadget.dev);  fail4:  	for (i = 0; i < IMX_USB_NB_EP + 1; i++)  		free_irq(imx_usb->usbd_int[i], imx_usb); @@ -1514,6 +1509,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)  	int i;  	usb_del_gadget_udc(&imx_usb->gadget); +	device_unregister(&imx_usb->gadget.dev);  	imx_udc_disable(imx_usb);  	del_timer(&imx_usb->timer); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 06be85c2b23..f8445653577 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -62,6 +62,7 @@  #define	DRIVER_VERSION	"4 October 2004"  #define OMAP_DMA_USB_W2FC_TX0		29 +#define OMAP_DMA_USB_W2FC_RX0		26  /*   * The OMAP UDC needs _very_ early endpoint setup:  before enabling the @@ -1310,7 +1311,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)  }  static int omap_udc_start(struct usb_gadget *g, -		struct usb_gadget_driver *driver) +		struct usb_gadget_driver *driver);  static int omap_udc_stop(struct usb_gadget *g,  		struct usb_gadget_driver *driver); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 2bbcdce942d..d0f37484b6b 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1266,13 +1266,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,  	dev->gadget.dev.driver = &driver->driver;  	dev->pullup = 1; -	retval = device_add (&dev->gadget.dev); -	if (retval) { -		dev->driver = NULL; -		dev->gadget.dev.driver = NULL; -		return retval; -	} -  	/* ... then enable host detection and ep0; and we're ready  	 * for set_configuration as well as eventual disconnect.  	 */ @@ -1310,6 +1303,10 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)  	}  	del_timer_sync(&dev->timer); +	/* report disconnect; the driver is already quiesced */ +	if (driver) +		driver->disconnect(&dev->gadget); +  	/* re-init driver-visible data structures */  	udc_reinit(dev);  } @@ -1331,7 +1328,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,  	dev->gadget.dev.driver = NULL;  	dev->driver = NULL; -	device_del (&dev->gadget.dev);  	dump_state(dev);  	return 0; @@ -2146,6 +2142,13 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)  	dev->gadget.dev.parent = &pdev->dev;  	dev->gadget.dev.dma_mask = pdev->dev.dma_mask; +	retval = device_add(&dev->gadget.dev); +	if (retval) { +		dev->driver = NULL; +		dev->gadget.dev.driver = NULL; +		goto err_device_add; +	} +  	the_controller = dev;  	platform_set_drvdata(pdev, dev); @@ -2196,6 +2199,8 @@ lubbock_fail0:  	free_irq(irq, dev);  #endif   err_irq1: +	device_unregister(&dev->gadget.dev); + err_device_add:  	if (gpio_is_valid(dev->mach->gpio_pullup))  		gpio_free(dev->mach->gpio_pullup);   err_gpio_pullup: @@ -2217,10 +2222,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)  {  	struct pxa25x_udc *dev = platform_get_drvdata(pdev); -	usb_del_gadget_udc(&dev->gadget);  	if (dev->driver)  		return -EBUSY; +	usb_del_gadget_udc(&dev->gadget); +	device_unregister(&dev->gadget.dev);  	dev->pullup = 0;  	pullup(dev); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f7d25795821..2fc867652ef 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1814,11 +1814,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,  	udc->gadget.dev.driver = &driver->driver;  	dplus_pullup(udc, 1); -	retval = device_add(&udc->gadget.dev); -	if (retval) { -		dev_err(udc->dev, "device_add error %d\n", retval); -		goto fail; -	}  	if (!IS_ERR_OR_NULL(udc->transceiver)) {  		retval = otg_set_peripheral(udc->transceiver->otg,  						&udc->gadget); @@ -1876,7 +1871,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,  	udc->driver = NULL; -	device_del(&udc->gadget.dev);  	if (!IS_ERR_OR_NULL(udc->transceiver))  		return otg_set_peripheral(udc->transceiver->otg, NULL); @@ -2480,13 +2474,24 @@ static int __init pxa_udc_probe(struct platform_device *pdev)  			driver_name, udc->irq, retval);  		goto err_irq;  	} + +	retval = device_add(&udc->gadget.dev); +	if (retval) { +		dev_err(udc->dev, "device_add error %d\n", retval); +		goto err_dev_add; +	} +  	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);  	if (retval)  		goto err_add_udc;  	pxa_init_debugfs(udc); +  	return 0; +  err_add_udc: +	device_unregister(&udc->gadget.dev); +err_dev_add:  	free_irq(udc->irq, udc);  err_irq:  	iounmap(udc->regs); @@ -2507,6 +2512,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)  	int gpio = udc->mach->gpio_pullup;  	usb_del_gadget_udc(&udc->gadget); +	device_del(&udc->gadget.dev);  	usb_gadget_unregister_driver(udc->driver);  	free_irq(udc->irq, udc);  	pxa_cleanup_debugfs(udc); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index fc07b438128..08f89652533 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1668,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)  static int s3c2410_udc_start(struct usb_gadget *g,  		struct usb_gadget_driver *driver)  { -	struct s3c2410_udc *udc = to_s3c2410(g) -	int		retval; +	struct s3c2410_udc *udc = to_s3c2410(g);  	dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name); @@ -1677,22 +1676,10 @@ static int s3c2410_udc_start(struct usb_gadget *g,  	udc->driver = driver;  	udc->gadget.dev.driver = &driver->driver; -	/* Bind the driver */ -	retval = device_add(&udc->gadget.dev); -	if (retval) { -		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); -		goto register_error; -	} -  	/* Enable udc */  	s3c2410_udc_enable(udc);  	return 0; - -register_error: -	udc->driver = NULL; -	udc->gadget.dev.driver = NULL; -	return retval;  }  static int s3c2410_udc_stop(struct usb_gadget *g, @@ -1700,7 +1687,6 @@ static int s3c2410_udc_stop(struct usb_gadget *g,  {  	struct s3c2410_udc *udc = to_s3c2410(g); -	device_del(&udc->gadget.dev);  	udc->driver = NULL;  	/* Disable udc */ @@ -1842,6 +1828,13 @@ static int s3c2410_udc_probe(struct platform_device *pdev)  	udc->gadget.dev.parent = &pdev->dev;  	udc->gadget.dev.dma_mask = pdev->dev.dma_mask; +	/* Bind the driver */ +	retval = device_add(&udc->gadget.dev); +	if (retval) { +		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); +		goto err_device_add; +	} +  	the_controller = udc;  	platform_set_drvdata(pdev, udc); @@ -1930,6 +1923,8 @@ err_gpio_claim:  err_int:  	free_irq(IRQ_USBD, udc);  err_map: +	device_unregister(&udc->gadget.dev); +err_device_add:  	iounmap(base_addr);  err_mem:  	release_mem_region(rsrc_start, rsrc_len); @@ -1947,10 +1942,11 @@ static int s3c2410_udc_remove(struct platform_device *pdev)  	dev_dbg(&pdev->dev, "%s()\n", __func__); -	usb_del_gadget_udc(&udc->gadget);  	if (udc->driver)  		return -EBUSY; +	usb_del_gadget_udc(&udc->gadget); +	device_unregister(&udc->gadget.dev);  	debugfs_remove(udc->regs_info);  	if (udc_info && !udc_info->udc_command && diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/u_uac1.c index e0c5e88e03e..c7d460f4339 100644 --- a/drivers/usb/gadget/u_uac1.c +++ b/drivers/usb/gadget/u_uac1.c @@ -240,8 +240,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)  	snd = &card->playback;  	snd->filp = filp_open(fn_play, O_WRONLY, 0);  	if (IS_ERR(snd->filp)) { +		int ret = PTR_ERR(snd->filp); +  		ERROR(card, "No such PCM playback device: %s\n", fn_play);  		snd->filp = NULL; +		return ret;  	}  	pcm_file = snd->filp->private_data;  	snd->substream = pcm_file->substream; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b416a3fc995..5726cb144ab 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -748,11 +748,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		/* guard against (alleged) silicon errata */  		if (cmd & CMD_IAAD)  			ehci_dbg(ehci, "IAA with IAAD still set?\n"); -		if (ehci->async_iaa) { +		if (ehci->async_iaa)  			COUNT(ehci->stats.iaa); -			end_unlink_async(ehci); -		} else -			ehci_dbg(ehci, "IAA with nothing unlinked?\n"); +		end_unlink_async(ehci);  	}  	/* remote wakeup [4.3.1] */ diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index fd252f0cfb3..5464665f0b6 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)  		 * qtd is updated in qh_completions(). Update the QH  		 * overlay here.  		 */ -		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { +		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {  			qh->hw->hw_qtd_next = qtd->hw_next;  			qtd = NULL;  		} @@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  			else if (last_status == -EINPROGRESS && !urb->unlinked)  				continue; -			/* qh unlinked; token in overlay may be most current */ -			if (state == QH_STATE_IDLE -					&& cpu_to_hc32(ehci, qtd->qtd_dma) -						== hw->hw_current) { +			/* +			 * If this was the active qtd when the qh was unlinked +			 * and the overlay's token is active, then the overlay +			 * hasn't been written back to the qtd yet so use its +			 * token instead of the qtd's.  After the qtd is +			 * processed and removed, the overlay won't be valid +			 * any more. +			 */ +			if (state == QH_STATE_IDLE && +					qh->qtd_list.next == &qtd->qtd_list && +					(hw->hw_token & ACTIVE_BIT(ehci))) {  				token = hc32_to_cpu(ehci, hw->hw_token); +				hw->hw_token &= ~ACTIVE_BIT(ehci);  				/* An unlink may leave an incomplete  				 * async transaction in the TT buffer. @@ -1170,7 +1178,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  	struct ehci_qh		*prev;  	/* Add to the end of the list of QHs waiting for the next IAAD */ -	qh->qh_state = QH_STATE_UNLINK; +	qh->qh_state = QH_STATE_UNLINK_WAIT;  	if (ehci->async_unlink)  		ehci->async_unlink_last->unlink_next = qh;  	else @@ -1213,9 +1221,19 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)  		/* Do only the first waiting QH (nVidia bug?) */  		qh = ehci->async_unlink; -		ehci->async_iaa = qh; -		ehci->async_unlink = qh->unlink_next; -		qh->unlink_next = NULL; + +		/* +		 * Intel (?) bug: The HC can write back the overlay region +		 * even after the IAA interrupt occurs.  In self-defense, +		 * always go through two IAA cycles for each QH. +		 */ +		if (qh->qh_state == QH_STATE_UNLINK_WAIT) { +			qh->qh_state = QH_STATE_UNLINK; +		} else { +			ehci->async_iaa = qh; +			ehci->async_unlink = qh->unlink_next; +			qh->unlink_next = NULL; +		}  		/* Make sure the unlinks are all visible to the hardware */  		wmb(); diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 45b19e2c60b..05e51432dd2 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -7,11 +7,6 @@  config USB_MUSB_HDRC  	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'  	depends on USB && USB_GADGET -	select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) -	select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX) -	select TWL4030_USB if MACH_OMAP_3430SDP -	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA -	select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA  	select USB_OTG_UTILS  	help  	  Say Y here if your system has a dual role high speed USB diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 60b41cc28da..daec6e0f7e3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1624,8 +1624,6 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);  /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_SYSFS -  static ssize_t  musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)  { @@ -1742,8 +1740,6 @@ static const struct attribute_group musb_attr_group = {  	.attrs = musb_attributes,  }; -#endif	/* sysfs */ -  /* Only used to provide driver mode change events */  static void musb_irq_work(struct work_struct *data)  { @@ -1968,11 +1964,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  	if (status < 0)  		goto fail4; -#ifdef CONFIG_SYSFS  	status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);  	if (status)  		goto fail5; -#endif  	pm_runtime_put(musb->controller); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 1762354fe79..1a42a458f2c 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -51,7 +51,7 @@ struct omap2430_glue {  };  #define glue_to_musb(g)		platform_get_drvdata(g->musb) -struct omap2430_glue		*_glue; +static struct omap2430_glue	*_glue;  static struct timer_list musb_idle_timer; @@ -237,9 +237,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status)  {  	struct omap2430_glue	*glue = _glue; -	if (glue && glue_to_musb(glue)) { -		glue->status = status; -	} else { +	if (!glue) { +		pr_err("%s: musb core is not yet initialized\n", __func__); +		return; +	} +	glue->status = status; + +	if (!glue_to_musb(glue)) {  		pr_err("%s: musb core is not yet ready\n", __func__);  		return;  	} diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index e1814397ca3..2bd03d261a5 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)  	spin_lock_irqsave(&phy_lock, flags);  	phy = __usb_find_phy(&phy_list, type); -	if (IS_ERR(phy)) { +	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {  		pr_err("unable to find transceiver of type %s\n",  			usb_phy_type_string(type));  		goto err0; @@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)  	spin_lock_irqsave(&phy_lock, flags);  	phy = __usb_find_phy_dev(dev, &phy_bind_list, index); -	if (IS_ERR(phy)) { +	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {  		pr_err("unable to find transceiver\n");  		goto err0;  	} @@ -301,8 +301,12 @@ EXPORT_SYMBOL(devm_usb_put_phy);   */  void usb_put_phy(struct usb_phy *x)  { -	if (x) +	if (x) { +		struct module *owner = x->dev->driver->owner; +  		put_device(x->dev); +		module_put(owner); +	}  }  EXPORT_SYMBOL(usb_put_phy); diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c index 5323b71c352..1419ceda975 100644 --- a/drivers/usb/phy/omap-control-usb.c +++ b/drivers/usb/phy/omap-control-usb.c @@ -219,32 +219,26 @@ static int omap_control_usb_probe(struct platform_device *pdev)  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,  		"control_dev_conf"); -	control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res); -	if (!control_usb->dev_conf) { -		dev_err(&pdev->dev, "Failed to obtain io memory\n"); -		return -EADDRNOTAVAIL; -	} +	control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(control_usb->dev_conf)) +		return PTR_ERR(control_usb->dev_conf);  	if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,  			"otghs_control"); -		control_usb->otghs_control = devm_request_and_ioremap( +		control_usb->otghs_control = devm_ioremap_resource(  			&pdev->dev, res); -		if (!control_usb->otghs_control) { -			dev_err(&pdev->dev, "Failed to obtain io memory\n"); -			return -EADDRNOTAVAIL; -		} +		if (IS_ERR(control_usb->otghs_control)) +			return PTR_ERR(control_usb->otghs_control);  	}  	if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,  			"phy_power_usb"); -		control_usb->phy_power = devm_request_and_ioremap( +		control_usb->phy_power = devm_ioremap_resource(  			&pdev->dev, res); -		if (!control_usb->phy_power) { -			dev_dbg(&pdev->dev, "Failed to obtain io memory\n"); -			return -EADDRNOTAVAIL; -		} +		if (IS_ERR(control_usb->phy_power)) +			return PTR_ERR(control_usb->phy_power);  		control_usb->sys_clk = devm_clk_get(control_usb->dev,  			"sys_clkin"); diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/omap-usb3.c index fadc0c2b65b..a6e60b1e102 100644 --- a/drivers/usb/phy/omap-usb3.c +++ b/drivers/usb/phy/omap-usb3.c @@ -212,11 +212,9 @@ static int omap_usb3_probe(struct platform_device *pdev)  	}  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); -	phy->pll_ctrl_base = devm_request_and_ioremap(&pdev->dev, res); -	if (!phy->pll_ctrl_base) { -		dev_err(&pdev->dev, "ioremap of pll_ctrl failed\n"); -		return -ENOMEM; -	} +	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(phy->pll_ctrl_base)) +		return PTR_ERR(phy->pll_ctrl_base);  	phy->dev		= &pdev->dev; diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c index 6ea55373383..967101ec15f 100644 --- a/drivers/usb/phy/samsung-usbphy.c +++ b/drivers/usb/phy/samsung-usbphy.c @@ -787,11 +787,9 @@ static int samsung_usbphy_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	phy_base = devm_request_and_ioremap(dev, phy_mem); -	if (!phy_base) { -		dev_err(dev, "%s: register mapping failed\n", __func__); -		return -ENXIO; -	} +	phy_base = devm_ioremap_resource(dev, phy_mem); +	if (IS_ERR(phy_base)) +		return PTR_ERR(phy_base);  	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);  	if (!sphy) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index edc0f0dcad8..4747d1c328f 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -85,6 +85,7 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */  	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */  	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ +	{ USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */  	{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */  	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */  	{ USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ @@ -150,6 +151,25 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */  	{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */  	{ USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ +	{ USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */ +	{ USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */ +	{ USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */ +	{ USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */ +	{ USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */ +	{ USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */ +	{ USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */ +	{ USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */ +	{ USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */ +	{ USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */ +	{ USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */ +	{ USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */ +	{ USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */ +	{ USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */ +	{ USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */ +	{ USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */ +	{ USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ +	{ USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ +	{ USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */  	{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */  	{ USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */  	{ USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f7d339d8187..558adfc0500 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -341,6 +341,8 @@ static void option_instat_callback(struct urb *urb);  #define CINTERION_PRODUCT_EU3_E			0x0051  #define CINTERION_PRODUCT_EU3_P			0x0052  #define CINTERION_PRODUCT_PH8			0x0053 +#define CINTERION_PRODUCT_AH6			0x0055 +#define CINTERION_PRODUCT_PLS8			0x0060  /* Olivetti products */  #define OLIVETTI_VENDOR_ID			0x0b3c @@ -579,6 +581,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),  		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &net_intf1_blacklist }, @@ -1260,6 +1263,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, +	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) }, +	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },   	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },  	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 9b1b96f2d09..31f81c3c15e 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = {  	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) },  /* NMEA */  	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) },  /* WMC */  	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) },  /* DIAG */ +	{ USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },  	{ },  };  MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 24662547dc5..59b32b78212 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	if (is_gobi1k) {  		/* Gobi 1K USB layout: -		 * 0: serial port (doesn't respond) +		 * 0: DM/DIAG (use libqcdm from ModemManager for communication)  		 * 1: serial port (doesn't respond)  		 * 2: AT-capable modem port  		 * 3: QMI/net  		 */ -		if (ifnum == 2) +		if (ifnum == 0) { +			dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n"); +			altsetting = 1; +		} else if (ifnum == 2)  			dev_dbg(dev, "Modem port found\n");  		else  			altsetting = -1; diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 00e6c9bac8a..d643a4d4d77 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -661,7 +661,9 @@ void qt2_process_read_urb(struct urb *urb)  						 __func__);  					break;  				} -				tty_flip_buffer_push(&port->port); + +				if (port_priv->is_open) +					tty_flip_buffer_push(&port->port);  				newport = *(ch + 3); @@ -704,7 +706,8 @@ void qt2_process_read_urb(struct urb *urb)  		tty_insert_flip_string(&port->port, ch, 1);  	} -	tty_flip_buffer_push(&port->port); +	if (port_priv->is_open) +		tty_flip_buffer_push(&port->port);  }  static void qt2_write_bulk_callback(struct urb *urb) diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 7ab9046ae0e..105d900150c 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)  	return 0;  } -/* This places the HUAWEI usb dongles in multi-port mode */ -static int usb_stor_huawei_feature_init(struct us_data *us) +/* This places the HUAWEI E220 devices in multi-port mode */ +int usb_stor_huawei_e220_init(struct us_data *us)  {  	int result; @@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us)  	US_DEBUGP("Huawei mode set result is %d\n", result);  	return 0;  } - -/* - * It will send a scsi switch command called rewind' to huawei dongle. - * When the dongle receives this command at the first time, - * it will reboot immediately. After rebooted, it will ignore this command. - * So it is  unnecessary to read its response. - */ -static int usb_stor_huawei_scsi_init(struct us_data *us) -{ -	int result = 0; -	int act_len = 0; -	struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; -	char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, -			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -	bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); -	bcbw->Tag = 0; -	bcbw->DataTransferLength = 0; -	bcbw->Flags = bcbw->Lun = 0; -	bcbw->Length = sizeof(rewind_cmd); -	memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); -	memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); - -	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, -					US_BULK_CB_WRAP_LEN, &act_len); -	US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); -	return result; -} - -/* - * It tries to find the supported Huawei USB dongles. - * In Huawei, they assign the following product IDs - * for all of their mobile broadband dongles, - * including the new dongles in the future. - * So if the product ID is not included in this list, - * it means it is not Huawei's mobile broadband dongles. - */ -static int usb_stor_huawei_dongles_pid(struct us_data *us) -{ -	struct usb_interface_descriptor *idesc; -	int idProduct; - -	idesc = &us->pusb_intf->cur_altsetting->desc; -	idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct); -	/* The first port is CDROM, -	 * means the dongle in the single port mode, -	 * and a switch command is required to be sent. */ -	if (idesc && idesc->bInterfaceNumber == 0) { -		if ((idProduct == 0x1001) -			|| (idProduct == 0x1003) -			|| (idProduct == 0x1004) -			|| (idProduct >= 0x1401 && idProduct <= 0x1500) -			|| (idProduct >= 0x1505 && idProduct <= 0x1600) -			|| (idProduct >= 0x1c02 && idProduct <= 0x2202)) { -			return 1; -		} -	} -	return 0; -} - -int usb_stor_huawei_init(struct us_data *us) -{ -	int result = 0; - -	if (usb_stor_huawei_dongles_pid(us)) { -		if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446) -			result = usb_stor_huawei_scsi_init(us); -		else -			result = usb_stor_huawei_feature_init(us); -	} -	return result; -} diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 5376d4fc76f..529327fbb06 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);   * flash reader */  int usb_stor_ucr61s2b_init(struct us_data *us); -/* This places the HUAWEI usb dongles in multi-port mode */ -int usb_stor_huawei_init(struct us_data *us); +/* This places the HUAWEI E220 devices in multi-port mode */ +int usb_stor_huawei_e220_init(struct us_data *us); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 72923b56bbf..da04a074e79 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -53,6 +53,14 @@   * as opposed to devices that do something strangely or wrongly.   */ +/* In-kernel mode switching is deprecated.  Do not add new devices to + * this list for the sole purpose of switching them to a different + * mode.  Existing userspace solutions are superior. + * + * New mode switching devices should instead be added to the database + * maintained at http://www.draisberghof.de/usb_modeswitch/ + */ +  #if !defined(CONFIG_USB_STORAGE_SDDR09) && \  		!defined(CONFIG_USB_STORAGE_SDDR09_MODULE)  #define NO_SDDR09 @@ -1527,10 +1535,335 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,  /* Reported by fangxiaozhi <huananhu@huawei.com>   * This brings the HUAWEI data card devices into multi-port mode   */ -UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, +UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000, +		"HUAWEI MOBILE", +		"Mass Storage", +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		0), +UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,  		"HUAWEI MOBILE",  		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,  		0),  /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ |