diff options
Diffstat (limited to 'drivers/usb')
76 files changed, 819 insertions, 387 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-acm.c b/drivers/usb/class/cdc-acm.c index 8ac25adf31b..387dc6c8ad2 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -593,7 +593,6 @@ static void acm_port_destruct(struct tty_port *port)  	dev_dbg(&acm->control->dev, "%s\n", __func__); -	tty_unregister_device(acm_tty_driver, acm->minor);  	acm_release_minor(acm);  	usb_put_intf(acm->control);  	kfree(acm->country_codes); @@ -977,6 +976,8 @@ static int acm_probe(struct usb_interface *intf,  	int num_rx_buf;  	int i;  	int combined_interfaces = 0; +	struct device *tty_dev; +	int rv = -ENOMEM;  	/* normal quirks */  	quirks = (unsigned long)id->driver_info; @@ -1339,11 +1340,24 @@ skip_countries:  	usb_set_intfdata(data_interface, acm);  	usb_get_intf(control_interface); -	tty_port_register_device(&acm->port, acm_tty_driver, minor, +	tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,  			&control_interface->dev); +	if (IS_ERR(tty_dev)) { +		rv = PTR_ERR(tty_dev); +		goto alloc_fail8; +	}  	return 0; +alloc_fail8: +	if (acm->country_codes) { +		device_remove_file(&acm->control->dev, +				&dev_attr_wCountryCodes); +		device_remove_file(&acm->control->dev, +				&dev_attr_iCountryCodeRelDate); +	} +	device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);  alloc_fail7: +	usb_set_intfdata(intf, NULL);  	for (i = 0; i < ACM_NW; i++)  		usb_free_urb(acm->wb[i].urb);  alloc_fail6: @@ -1359,7 +1373,7 @@ alloc_fail2:  	acm_release_minor(acm);  	kfree(acm);  alloc_fail: -	return -ENOMEM; +	return rv;  }  static void stop_data_traffic(struct acm *acm) @@ -1411,6 +1425,8 @@ static void acm_disconnect(struct usb_interface *intf)  	stop_data_traffic(acm); +	tty_unregister_device(acm_tty_driver, acm->minor); +  	usb_free_urb(acm->ctrlurb);  	for (i = 0; i < ACM_NW; i++)  		usb_free_urb(acm->wb[i].urb); 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/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 622b4a48e73..2b487d4797b 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -173,6 +173,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	struct hc_driver	*driver;  	struct usb_hcd		*hcd;  	int			retval; +	int			hcd_irq = 0;  	if (usb_disabled())  		return -ENODEV; @@ -187,15 +188,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  		return -ENODEV;  	dev->current_state = PCI_D0; -	/* The xHCI driver supports MSI and MSI-X, -	 * so don't fail if the BIOS doesn't provide a legacy IRQ. +	/* +	 * The xHCI driver has its own irq management +	 * make sure irq setup is not touched for xhci in generic hcd code  	 */ -	if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) { -		dev_err(&dev->dev, -			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n", -			pci_name(dev)); -		retval = -ENODEV; -		goto disable_pci; +	if ((driver->flags & HCD_MASK) != HCD_USB3) { +		if (!dev->irq) { +			dev_err(&dev->dev, +			"Found HC with no IRQ. Check BIOS/PCI %s setup!\n", +				pci_name(dev)); +			retval = -ENODEV; +			goto disable_pci; +		} +		hcd_irq = dev->irq;  	}  	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev)); @@ -245,7 +250,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	pci_set_master(dev); -	retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); +	retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);  	if (retval != 0)  		goto unmap_registers;  	set_hs_companion(dev, hcd); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 99b34a30354..f9ec44cbb82 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)  }  EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +	if (!hcd->driver->find_raw_port_number) +		return port1; + +	return hcd->driver->find_raw_port_number(hcd, port1); +} +  static int usb_hcd_request_irqs(struct usb_hcd *hcd,  		unsigned int irqnum, unsigned long irqflags)  { diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 797f9d51473..65d4e55552c 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev)  {  	struct usb_port *port_dev = to_usb_port(dev); -	dev_pm_qos_hide_flags(dev);  	kfree(port_dev);  } diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad3f75..255c14464bf 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@  #include <linux/kernel.h>  #include <linux/acpi.h>  #include <linux/pci.h> +#include <linux/usb/hcd.h>  #include <acpi/acpi_bus.h>  #include "usb.h" @@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  		 * connected to.  		 */  		if (!udev->parent) { -			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), +			struct usb_hcd *hcd = bus_to_hcd(udev->bus); +			int raw_port_num; + +			raw_port_num = usb_hcd_find_raw_port_number(hcd,  				port_num); +			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), +				raw_port_num);  			if (!*handle)  				return -ENODEV;  		} else { 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/Kconfig b/drivers/usb/gadget/Kconfig index 5a0c541daf8..c7525b1cad7 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -145,6 +145,7 @@ config USB_LPC32XX  	tristate "LPC32XX USB Peripheral Controller"  	depends on ARCH_LPC32XX  	select USB_ISP1301 +	select USB_OTG_UTILS  	help  	   This option selects the USB device controller in the LPC32xx SoC. 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_rndis.c b/drivers/usb/gadget/f_rndis.c index 71beeb83355..cc9c49c57c8 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -447,14 +447,13 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)  static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)  {  	struct f_rndis			*rndis = req->context; -	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;  	int				status;  	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */  //	spin_lock(&dev->lock);  	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);  	if (status < 0) -		ERROR(cdev, "RNDIS command error %d, %d/%d\n", +		pr_err("RNDIS command error %d, %d/%d\n",  			status, req->actual, req->length);  //	spin_unlock(&dev->lock);  } 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/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 3953dd4d718..3b343b23e4b 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -357,7 +357,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)  		goto error;  	gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; -	for (i = func_num; --i; ) { +	for (i = func_num; i--; ) {  		ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);  		if (unlikely(ret < 0)) {  			while (++i < func_num) @@ -413,7 +413,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)  		gether_cleanup();  	gfs_ether_setup = false; -	for (i = func_num; --i; ) +	for (i = func_num; i--; )  		if (ffs_tab[i].ffs_data)  			functionfs_unbind(ffs_tab[i].ffs_data); 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/net2272.c b/drivers/usb/gadget/net2272.c index d226058e3b8..32524b63195 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -59,7 +59,7 @@ static const char * const ep_name[] = {  };  #define DMA_ADDR_INVALID	(~(dma_addr_t)0) -#ifdef CONFIG_USB_GADGET_NET2272_DMA +#ifdef CONFIG_USB_NET2272_DMA  /*   * use_dma: the NET2272 can use an external DMA controller.   * Note that since there is no generic DMA api, some functions, @@ -1495,6 +1495,13 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)  	for (i = 0; i < 4; ++i)  		net2272_dequeue_all(&dev->ep[i]); +	/* report disconnect; the driver is already quiesced */ +	if (driver) { +		spin_unlock(&dev->lock); +		driver->disconnect(&dev->gadget); +		spin_lock(&dev->lock); +	} +  	net2272_usb_reinit(dev);  } diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index a1b650e1133..3bd0f992fb4 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1924,7 +1924,6 @@ static int net2280_start(struct usb_gadget *_gadget,  err_func:  	device_remove_file (&dev->pdev->dev, &dev_attr_function);  err_unbind: -	driver->unbind (&dev->gadget);  	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	return retval; @@ -1946,6 +1945,13 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)  	for (i = 0; i < 7; i++)  		nuke (&dev->ep [i]); +	/* report disconnect; the driver is already quiesced */ +	if (driver) { +		spin_unlock(&dev->lock); +		driver->disconnect(&dev->gadget); +		spin_lock(&dev->lock); +	} +  	usb_reinit (dev);  } 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_serial.c b/drivers/usb/gadget/u_serial.c index c5034d9c946..b369292d4b9 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -136,7 +136,7 @@ static struct portmaster {  	pr_debug(fmt, ##arg)  #endif /* pr_vdebug */  #else -#ifndef pr_vdebig +#ifndef pr_vdebug  #define pr_vdebug(fmt, arg...) \  	({ if (0) pr_debug(fmt, ##arg); })  #endif /* pr_vdebug */ 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/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2a9cd369f71..f8f62c3ed65 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -216,7 +216,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)  	usb_gadget_disconnect(udc->gadget);  	udc->driver->disconnect(udc->gadget);  	udc->driver->unbind(udc->gadget); -	usb_gadget_udc_stop(udc->gadget, udc->driver); +	usb_gadget_udc_stop(udc->gadget, NULL);  	udc->driver = NULL;  	udc->dev.driver = NULL; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b416a3fc995..416a6dce5e1 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)  static void end_unlink_async(struct ehci_hcd *ehci);  static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci);  static void ehci_work(struct ehci_hcd *ehci);  static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);  static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -748,11 +749,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-hub.c b/drivers/usb/host/ehci-hub.c index 4d3b294f203..7d06e77f6c4 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)  	ehci->rh_state = EHCI_RH_SUSPENDED;  	end_unlink_async(ehci); -	unlink_empty_async(ehci); +	unlink_empty_async_suspended(ehci);  	ehci_handle_intr_unlinks(ehci);  	end_free_itds(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index fd252f0cfb3..23d13690428 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(); @@ -1298,6 +1316,19 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  	}  } +/* The root hub is suspended; unlink all the async QHs */ +static void unlink_empty_async_suspended(struct ehci_hcd *ehci) +{ +	struct ehci_qh		*qh; + +	while (ehci->async->qh_next.qh) { +		qh = ehci->async->qh_next.qh; +		WARN_ON(!list_empty(&qh->qtd_list)); +		single_unlink_async(ehci, qh); +	} +	start_iaa_cycle(ehci, false); +} +  /* makes sure the async qh will become idle */  /* caller must own ehci->lock */ diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b476daf49f6..010f686d888 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1214,6 +1214,7 @@ itd_urb_transaction (  		memset (itd, 0, sizeof *itd);  		itd->itd_dma = itd_dma; +		itd->frame = 9999;		/* an invalid value */  		list_add (&itd->itd_list, &sched->td_list);  	}  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -1915,6 +1916,7 @@ sitd_urb_transaction (  		memset (sitd, 0, sizeof *sitd);  		sitd->sitd_dma = sitd_dma; +		sitd->frame = 9999;		/* an invalid value */  		list_add (&sitd->sitd_list, &iso_sched->td_list);  	} diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0..c3fa1305f83 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)  	 * (a) SMP races against real IAA firing and retriggering, and  	 * (b) clean HC shutdown, when IAA watchdog was pending.  	 */ -	if (ehci->async_iaa) { +	if (1) {  		u32 cmd, status;  		/* If we get here, IAA is *REALLY* late.  It's barely diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ffbe3a..6dc238c592b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,   * is attached to (or the roothub port its ancestor hub is attached to).  All we   * know is the index of that port under either the USB 2.0 or the USB 3.0   * roothub, but that doesn't give us the real index into the HW port status - * registers.  Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed.  Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index.   */  static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,  		struct usb_device *udev)  {  	struct usb_device *top_dev; -	unsigned int num_similar_speed_ports; -	unsigned int faked_port_num; -	int i; +	struct usb_hcd *hcd; + +	if (udev->speed == USB_SPEED_SUPER) +		hcd = xhci->shared_hcd; +	else +		hcd = xhci->main_hcd;  	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;  			top_dev = top_dev->parent)  		/* Found device below root hub */; -	faked_port_num = top_dev->portnum; -	for (i = 0, num_similar_speed_ports = 0; -			i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { -		u8 port_speed = xhci->port_array[i]; - -		/* -		 * Skip ports that don't have known speeds, or have duplicate -		 * Extended Capabilities port speed entries. -		 */ -		if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) -			continue; -		/* -		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and -		 * 1.1 ports are under the USB 2.0 hub.  If the port speed -		 * matches the device speed, it's a similar speed port. -		 */ -		if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER)) -			num_similar_speed_ports++; -		if (num_similar_speed_ports == faked_port_num) -			/* Roothub ports are numbered from 1 to N */ -			return i+1; -	} -	return 0; +	return	xhci_find_raw_port_number(hcd, top_dev->portnum);  }  /* Setup an xHCI virtual device for a Set Address command */ diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0ec17..1a30c380043 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {  	.set_usb2_hw_lpm =	xhci_set_usb2_hardware_lpm,  	.enable_usb3_lpm_timeout =	xhci_enable_usb3_lpm_timeout,  	.disable_usb3_lpm_timeout =	xhci_disable_usb3_lpm_timeout, +	.find_raw_port_number =	xhci_find_raw_port_number,  };  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 88287546530..1969c001b3f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,  	max_ports = HCS_MAX_PORTS(xhci->hcs_params1);  	if ((port_id <= 0) || (port_id > max_ports)) {  		xhci_warn(xhci, "Invalid port id %d\n", port_id); -		bogus_port_status = true; -		goto cleanup; +		inc_deq(xhci, xhci->event_ring); +		return;  	}  	/* Figure out which usb_hcd this port is attached to:  	 * is it a USB 3.0 port or a USB 2.0/1.1 port?  	 */  	major_revision = xhci->port_array[port_id - 1]; + +	/* Find the right roothub. */ +	hcd = xhci_to_hcd(xhci); +	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) +		hcd = xhci->shared_hcd; +  	if (major_revision == 0) {  		xhci_warn(xhci, "Event for port %u not in "  				"Extended Capabilities, ignoring.\n", @@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,  	 * into the index into the ports on the correct split roothub, and the  	 * correct bus_state structure.  	 */ -	/* Find the right roothub. */ -	hcd = xhci_to_hcd(xhci); -	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) -		hcd = xhci->shared_hcd;  	bus_state = &xhci->bus_state[hcd_index(hcd)];  	if (hcd->speed == HCD_USB3)  		port_array = xhci->usb3_ports; @@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,  		if (event_trb != ep_ring->dequeue &&  				event_trb != td->last_trb)  			td->urb->actual_length = -				td->urb->transfer_buffer_length -				- TRB_LEN(le32_to_cpu(event->transfer_len)); +				td->urb->transfer_buffer_length - +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  		else  			td->urb->actual_length = 0; @@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,  		/* Maybe the event was for the data stage? */  			td->urb->actual_length =  				td->urb->transfer_buffer_length - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  			xhci_dbg(xhci, "Waiting for status "  					"stage event\n");  			return 0; @@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,  	/* handle completion code */  	switch (trb_comp_code) {  	case COMP_SUCCESS: -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {  			frame->status = 0;  			break;  		} @@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,  				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));  		}  		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - -			TRB_LEN(le32_to_cpu(event->transfer_len)); +			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  		if (trb_comp_code != COMP_STOP_INVAL) {  			frame->actual_length = len; @@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  	case COMP_SUCCESS:  		/* Double check that the HW transferred everything. */  		if (event_trb != td->last_trb || -				TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { +		    EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {  			xhci_warn(xhci, "WARN Successful completion "  					"on short TX\n");  			if (td->urb->transfer_flags & URB_SHORT_NOT_OK) @@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  				"%d bytes untransferred\n",  				td->urb->ep->desc.bEndpointAddress,  				td->urb->transfer_buffer_length, -				TRB_LEN(le32_to_cpu(event->transfer_len))); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));  	/* Fast path - was this the last TRB in the TD for this URB? */  	if (event_trb == td->last_trb) { -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {  			td->urb->actual_length =  				td->urb->transfer_buffer_length - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  			if (td->urb->transfer_buffer_length <  					td->urb->actual_length) {  				xhci_warn(xhci, "HC gave bad length "  						"of %d bytes left\n", -					  TRB_LEN(le32_to_cpu(event->transfer_len))); +					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));  				td->urb->actual_length = 0;  				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)  					*status = -EREMOTEIO; @@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  		if (trb_comp_code != COMP_STOP_INVAL)  			td->urb->actual_length +=  				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  	}  	return finish_td(xhci, td, event_trb, event, ep, status, false); @@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,  	 * transfer type  	 */  	case COMP_SUCCESS: -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)  			break;  		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)  			trb_comp_code = COMP_SHORT_TX; @@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,  		 * TD list.  		 */  		if (list_empty(&ep_ring->td_list)) { -			xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " -					"with no TDs queued?\n", -				  TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), -				  ep_index); -			xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", -				 (le32_to_cpu(event->flags) & -				  TRB_TYPE_BITMASK)>>10); -			xhci_print_trb_offsets(xhci, (union xhci_trb *) event); +			/* +			 * A stopped endpoint may generate an extra completion +			 * event if the device was suspended.  Don't print +			 * warnings. +			 */ +			if (!(trb_comp_code == COMP_STOP || +						trb_comp_code == COMP_STOP_INVAL)) { +				xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", +						TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), +						ep_index); +				xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", +						(le32_to_cpu(event->flags) & +						 TRB_TYPE_BITMASK)>>10); +				xhci_print_trb_offsets(xhci, (union xhci_trb *) event); +			}  			if (ep->skip) {  				ep->skip = false;  				xhci_dbg(xhci, "td_list is empty while skip " diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f1f01a834ba..53b8f89a0b1 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)  	 * generate interrupts.  Don't even try to enable MSI.  	 */  	if (xhci->quirks & XHCI_BROKEN_MSI) -		return 0; +		goto legacy_irq;  	/* unregister the legacy interrupt */  	if (hcd->irq) @@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)  		return -EINVAL;  	} + legacy_irq:  	/* fall back to legacy interrupt*/  	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,  			hcd->irq_descr, hcd); @@ -3778,6 +3779,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)  	return 0;  } +/* + * Transfer the port index into real index in the HW port status + * registers. Caculate offset between the port's PORTSC register + * and port status base. Divide the number of per port register + * to get the real index. The raw port number bases 1. + */ +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +	struct xhci_hcd *xhci = hcd_to_xhci(hcd); +	__le32 __iomem *base_addr = &xhci->op_regs->port_status_base; +	__le32 __iomem *addr; +	int raw_port; + +	if (hcd->speed != HCD_USB3) +		addr = xhci->usb2_ports[port1 - 1]; +	else +		addr = xhci->usb3_ports[port1 - 1]; + +	raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; +	return raw_port; +} +  #ifdef CONFIG_USB_SUSPEND  /* BESL to HIRD Encoding array for USB2 LPM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f791bd0aee6..63582719e0f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -206,8 +206,8 @@ struct xhci_op_regs {  /* bits 12:31 are reserved (and should be preserved on writes). */  /* IMAN - Interrupt Management Register */ -#define IMAN_IP		(1 << 1) -#define IMAN_IE		(1 << 0) +#define IMAN_IE		(1 << 1) +#define IMAN_IP		(1 << 0)  /* USBSTS - USB status - status bitmasks */  /* HC not running - set to 1 when run/stop bit is cleared. */ @@ -972,6 +972,10 @@ struct xhci_transfer_event {  	__le32	flags;  }; +/* Transfer event TRB length bit mask */ +/* bits 0:23 */ +#define	EVENT_TRB_LEN(p)		((p) & 0xffffff) +  /** Transfer Event bit fields **/  #define	TRB_TO_EP_ID(p)	(((p) >> 16) & 0x1f) @@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,  int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,  		char *buf, u16 wLength);  int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);  #ifdef CONFIG_PM  int xhci_bus_suspend(struct usb_hcd *hcd); 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/da8xx.c b/drivers/usb/musb/da8xx.c index 7c71769d71f..41613a2b35e 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)  		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);  		int err; -		err = musb->int_usb & USB_INTR_VBUSERROR; +		err = musb->int_usb & MUSB_INTR_VBUSERROR;  		if (err) {  			/*  			 * The Mentor core doesn't debounce VBUS as needed 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/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index be18537c5f1..83eddedcd9b 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -141,7 +141,9 @@ static inline void map_dma_buffer(struct musb_request *request,  static inline void unmap_dma_buffer(struct musb_request *request,  				struct musb *musb)  { -	if (!is_buffer_mapped(request)) +	struct musb_ep *musb_ep = request->ep; + +	if (!is_buffer_mapped(request) || !musb_ep->dma)  		return;  	if (request->request.dma == DMA_ADDR_INVALID) { @@ -195,7 +197,10 @@ __acquires(ep->musb->lock)  	ep->busy = 1;  	spin_unlock(&musb->lock); -	unmap_dma_buffer(req, musb); + +	if (!dma_mapping_error(&musb->g.dev, request->dma)) +		unmap_dma_buffer(req, musb); +  	if (request->status == 0)  		dev_dbg(musb->controller, "%s done request %p,  %d/%d\n",  				ep->end_point.name, request, 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/Kconfig b/drivers/usb/phy/Kconfig index 65217a59006..90549382eba 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -38,6 +38,7 @@ config USB_ISP1301  	tristate "NXP ISP1301 USB transceiver support"  	depends on USB || USB_GADGET  	depends on I2C +	select USB_OTG_UTILS  	help  	  Say Y here to add support for the NXP ISP1301 USB transceiver driver.  	  This chip is typically used as USB transceiver for USB host, gadget 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/ark3116.c b/drivers/usb/serial/ark3116.c index cbd904b8fba..4775f8209e5 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial)  }  struct ark3116_private { -	wait_queue_head_t       delta_msr_wait;  	struct async_icount	icount;  	int			irda;	/* 1 for irda device */ @@ -146,7 +145,6 @@ static int ark3116_port_probe(struct usb_serial_port *port)  	if (!priv)  		return -ENOMEM; -	init_waitqueue_head(&priv->delta_msr_wait);  	mutex_init(&priv->hw_lock);  	spin_lock_init(&priv->status_lock); @@ -456,10 +454,14 @@ static int ark3116_ioctl(struct tty_struct *tty,  	case TIOCMIWAIT:  		for (;;) {  			struct async_icount prev = priv->icount; -			interruptible_sleep_on(&priv->delta_msr_wait); +			interruptible_sleep_on(&port->delta_msr_wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			if ((prev.rng == priv->icount.rng) &&  			    (prev.dsr == priv->icount.dsr) &&  			    (prev.dcd == priv->icount.dcd) && @@ -580,7 +582,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)  			priv->icount.dcd++;  		if (msr & UART_MSR_TERI)  			priv->icount.rng++; -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  	}  } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d255f66e708..07d4650a32a 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  struct ch341_private {  	spinlock_t lock; /* access lock */ -	wait_queue_head_t delta_msr_wait; /* wait queue for modem status */  	unsigned baud_rate; /* set baud rate */  	u8 line_control; /* set line control value RTS/DTR */  	u8 line_status; /* active status of modem control inputs */ @@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	priv->baud_rate = DEFAULT_BAUD_RATE;  	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; @@ -298,7 +296,7 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)  		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);  	spin_unlock_irqrestore(&priv->lock, flags);  	ch341_set_handshake(port->serial->dev, priv->line_control); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  }  static void ch341_close(struct usb_serial_port *port) @@ -491,7 +489,7 @@ static void ch341_read_int_callback(struct urb *urb)  			tty_kref_put(tty);  		} -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  	}  exit: @@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (!multi_change) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		multi_change = priv->multi_status_change; 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/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 8efa19d0e9f..ba7352e4187 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -111,7 +111,6 @@ struct cypress_private {  	int baud_rate;			   /* stores current baud rate in  					      integer form */  	int isthrottled;		   /* if throttled, discard reads */ -	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */  	char prev_status, diff_status;	   /* used for TIOCMIWAIT */  	/* we pass a pointer to this as the argument sent to  	   cypress_set_termios old_termios */ @@ -449,7 +448,6 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)  		kfree(priv);  		return -ENOMEM;  	} -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_reset_configuration(serial->dev); @@ -868,12 +866,16 @@ static int cypress_ioctl(struct tty_struct *tty,  	switch (cmd) {  	/* This code comes from drivers/char/serial.c and ftdi_sio.c */  	case TIOCMIWAIT: -		while (priv != NULL) { -			interruptible_sleep_on(&priv->delta_msr_wait); +		for (;;) { +			interruptible_sleep_on(&port->delta_msr_wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; -			else { + +			if (port->serial->disconnected) +				return -EIO; + +			{  				char diff = priv->diff_status;  				if (diff == 0)  					return -EIO; /* no change => error */ @@ -1187,7 +1189,7 @@ static void cypress_read_int_callback(struct urb *urb)  	if (priv->current_status != priv->prev_status) {  		priv->diff_status |= priv->current_status ^  			priv->prev_status; -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  		priv->prev_status = priv->current_status;  	}  	spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index b1b2dc64b50..a172ad5c5ce 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  struct f81232_private {  	spinlock_t lock; -	wait_queue_head_t delta_msr_wait;  	u8 line_control;  	u8 line_status;  }; @@ -111,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -256,11 +255,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -322,7 +324,6 @@ static int f81232_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index edd162df49c..9886180e45f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -69,9 +69,7 @@ struct ftdi_private {  	int flags;		/* some ASYNC_xxxx flags are supported */  	unsigned long last_dtr_rts;	/* saved modem control outputs */  	struct async_icount	icount; -	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */  	char prev_status;        /* Used for TIOCMIWAIT */ -	bool dev_gone;        /* Used to abort TIOCMIWAIT */  	char transmit_empty;	/* If transmitter is empty or not */  	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface  				   (0 for FT232/245) */ @@ -642,6 +640,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },  	{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },  	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, +	{ USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, @@ -1691,10 +1690,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  	kref_init(&priv->kref);  	mutex_init(&priv->cfg_lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	priv->flags = ASYNC_LOW_LATENCY; -	priv->dev_gone = false;  	if (quirk && quirk->port_probe)  		quirk->port_probe(priv); @@ -1840,8 +1837,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)  {  	struct ftdi_private *priv = usb_get_serial_port_data(port); -	priv->dev_gone = true; -	wake_up_interruptible_all(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	remove_sysfs_attrs(port); @@ -1989,7 +1985,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,  		if (diff_status & FTDI_RS0_RLSD)  			priv->icount.dcd++; -		wake_up_interruptible_all(&priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  		priv->prev_status = status;  	} @@ -2440,11 +2436,15 @@ static int ftdi_ioctl(struct tty_struct *tty,  	 */  	case TIOCMIWAIT:  		cprev = priv->icount; -		while (!priv->dev_gone) { -			interruptible_sleep_on(&priv->delta_msr_wait); +		for (;;) { +			interruptible_sleep_on(&port->delta_msr_wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			cnow = priv->icount;  			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||  			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || @@ -2454,8 +2454,6 @@ static int ftdi_ioctl(struct tty_struct *tty,  			}  			cprev = cnow;  		} -		return -EIO; -		break;  	case TIOCSERGETLSR:  		return get_lsr_info(port, (struct serial_struct __user *)arg);  		break; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9d359e189a6..e79861eeed4 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -584,6 +584,13 @@  #define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */  /* + * Mitsubishi Electric Corp. (http://www.meau.com) + * Submitted by Konstantin Holoborodko + */ +#define MITSUBISHI_VID		0x06D3 +#define MITSUBISHI_FXUSB_PID	0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */ + +/*   * Definitions for B&B Electronics products.   */  #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 1a07b12ef34..81caf5623ee 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -956,10 +956,7 @@ static void garmin_close(struct usb_serial_port *port)  	if (!serial)  		return; -	mutex_lock(&port->serial->disc_mutex); - -	if (!port->serial->disconnected) -		garmin_clear(garmin_data_p); +	garmin_clear(garmin_data_p);  	/* shutdown our urbs */  	usb_kill_urb(port->read_urb); @@ -968,8 +965,6 @@ static void garmin_close(struct usb_serial_port *port)  	/* keep reset state so we know that we must start a new session */  	if (garmin_data_p->state != STATE_RESET)  		garmin_data_p->state = STATE_DISCONNECTED; - -	mutex_unlock(&port->serial->disc_mutex);  } diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b00e5cbf741..efd8b978128 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -110,7 +110,6 @@ struct edgeport_port {  	wait_queue_head_t	wait_chase;		/* for handling sleeping while waiting for chase to finish */  	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */  	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */ -	wait_queue_head_t	delta_msr_wait;		/* for handling sleeping while waiting for msr change to happen */  	struct async_icount	icount;  	struct usb_serial_port	*port;			/* loop back to the owner of this object */ @@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* initialize our wait queues */  	init_waitqueue_head(&edge_port->wait_open);  	init_waitqueue_head(&edge_port->wait_chase); -	init_waitqueue_head(&edge_port->delta_msr_wait);  	init_waitqueue_head(&edge_port->wait_command);  	/* initialize our icount structure */ @@ -1669,13 +1667,17 @@ static int edge_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);  		cprev = edge_port->icount;  		while (1) { -			prepare_to_wait(&edge_port->delta_msr_wait, +			prepare_to_wait(&port->delta_msr_wait,  						&wait, TASK_INTERRUPTIBLE);  			schedule(); -			finish_wait(&edge_port->delta_msr_wait, &wait); +			finish_wait(&port->delta_msr_wait, &wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			cnow = edge_port->icount;  			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&  			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) @@ -2051,7 +2053,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)  			icount->dcd++;  		if (newMsr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->delta_msr_wait);  	}  	/* Save the new modem status */ diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index c23776679f7..7777172206d 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -87,9 +87,6 @@ struct edgeport_port {  	int close_pending;  	int lsr_event;  	struct async_icount	icount; -	wait_queue_head_t	delta_msr_wait;	/* for handling sleeping while -						   waiting for msr change to -						   happen */  	struct edgeport_serial	*edge_serial;  	struct usb_serial_port	*port;  	__u8 bUartMode;		/* Port type, 0: RS232, etc. */ @@ -1459,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)  			icount->dcd++;  		if (msr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->delta_msr_wait);  	}  	/* Save the new modem status */ @@ -1754,7 +1751,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	dev = port->serial->dev;  	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); -	init_waitqueue_head(&edge_port->delta_msr_wait);  	/* turn off loopback */  	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0); @@ -2434,10 +2430,14 @@ static int edge_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);  		cprev = edge_port->icount;  		while (1) { -			interruptible_sleep_on(&edge_port->delta_msr_wait); +			interruptible_sleep_on(&port->delta_msr_wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			cnow = edge_port->icount;  			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&  			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) @@ -2649,6 +2649,7 @@ static struct usb_serial_driver edgeport_2port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, +	.get_icount		= edge_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a64d420f687..06d5a60be2c 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -114,8 +114,6 @@ struct mct_u232_private {  	unsigned char	     last_msr;      /* Modem Status Register */  	unsigned int	     rx_flags;      /* Throttling flags */  	struct async_icount  icount; -	wait_queue_head_t    msr_wait;	/* for handling sleeping while waiting -						for msr change to happen */  };  #define THROTTLED		0x01 @@ -409,7 +407,6 @@ static int mct_u232_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->msr_wait);  	usb_set_serial_port_data(port, priv); @@ -601,7 +598,7 @@ static void mct_u232_read_int_callback(struct urb *urb)  		tty_kref_put(tty);  	}  #endif -	wake_up_interruptible(&priv->msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	spin_unlock_irqrestore(&priv->lock, flags);  exit:  	retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -810,13 +807,17 @@ static int  mct_u232_ioctl(struct tty_struct *tty,  		cprev = mct_u232_port->icount;  		spin_unlock_irqrestore(&mct_u232_port->lock, flags);  		for ( ; ; ) { -			prepare_to_wait(&mct_u232_port->msr_wait, +			prepare_to_wait(&port->delta_msr_wait,  					&wait, TASK_INTERRUPTIBLE);  			schedule(); -			finish_wait(&mct_u232_port->msr_wait, &wait); +			finish_wait(&port->delta_msr_wait, &wait);  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			spin_lock_irqsave(&mct_u232_port->lock, flags);  			cnow = mct_u232_port->icount;  			spin_unlock_irqrestore(&mct_u232_port->lock, flags); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 809fb329eca..b8051fa6191 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -219,7 +219,6 @@ struct moschip_port {  	char open;  	char open_ports;  	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */ -	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */  	int delta_msr_cond;  	struct async_icount icount;  	struct usb_serial_port *port;	/* loop back to the owner of this object */ @@ -423,6 +422,9 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)  			icount->rng++;  			smp_wmb();  		} + +		mos7840_port->delta_msr_cond = 1; +		wake_up_interruptible(&port->port->delta_msr_wait);  	}  } @@ -1127,7 +1129,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* initialize our wait queues */  	init_waitqueue_head(&mos7840_port->wait_chase); -	init_waitqueue_head(&mos7840_port->delta_msr_wait);  	/* initialize our icount structure */  	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); @@ -2017,8 +2018,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,  			mos7840_port->read_urb_busy = false;  		}  	} -	wake_up(&mos7840_port->delta_msr_wait); -	mos7840_port->delta_msr_cond = 1;  	dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,  		mos7840_port->shadowLCR);  } @@ -2219,13 +2218,18 @@ static int mos7840_ioctl(struct tty_struct *tty,  		while (1) {  			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */  			mos7840_port->delta_msr_cond = 0; -			wait_event_interruptible(mos7840_port->delta_msr_wait, -						 (mos7840_port-> +			wait_event_interruptible(port->delta_msr_wait, +						 (port->serial->disconnected || +						  mos7840_port->  						  delta_msr_cond == 1));  			/* see if a signal did it */  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			cnow = mos7840_port->icount;  			smp_rmb();  			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 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/oti6858.c b/drivers/usb/serial/oti6858.c index a958fd41b5b..87c71ccfee8 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -188,7 +188,6 @@ struct oti6858_private {  	u8 setup_done;  	struct delayed_work delayed_setup_work; -	wait_queue_head_t intr_wait;  	struct usb_serial_port *port;   /* USB port with which associated */  }; @@ -339,7 +338,6 @@ static int oti6858_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->intr_wait);  	priv->port = port;  	INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);  	INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); @@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		wait_event_interruptible(priv->intr_wait, +		wait_event_interruptible(port->delta_msr_wait, +					port->serial->disconnected ||  					priv->status.pin_state != prev);  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->status.pin_state & PIN_MASK;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -763,7 +765,7 @@ static void oti6858_read_int_callback(struct urb *urb)  		if (!priv->transient) {  			if (xs->pin_state != priv->status.pin_state) -				wake_up_interruptible(&priv->intr_wait); +				wake_up_interruptible(&port->delta_msr_wait);  			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);  		} diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 54adc9125e5..3b10018d89a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -139,7 +139,6 @@ struct pl2303_serial_private {  struct pl2303_private {  	spinlock_t lock; -	wait_queue_head_t delta_msr_wait;  	u8 line_control;  	u8 line_status;  }; @@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -607,11 +605,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -719,7 +720,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,  	spin_unlock_irqrestore(&priv->lock, flags);  	if (priv->line_status & UART_BREAK_ERROR)  		usb_serial_handle_break(port); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	tty = tty_port_tty_get(&port->port);  	if (!tty) @@ -783,7 +784,7 @@ static void pl2303_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	if (!urb->actual_length)  		return; 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..75f125ddb0c 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -128,7 +128,6 @@ struct qt2_port_private {  	u8          shadowLSR;  	u8          shadowMSR; -	wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */  	struct async_icount icount;  	struct usb_serial_port *port; @@ -506,8 +505,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		wait_event_interruptible(priv->delta_msr_wait, -					 ((priv->icount.rng != prev.rng) || +		wait_event_interruptible(port->delta_msr_wait, +					 (port->serial->disconnected || +					  (priv->icount.rng != prev.rng) ||  					  (priv->icount.dsr != prev.dsr) ||  					  (priv->icount.dcd != prev.dcd) ||  					  (priv->icount.cts != prev.cts))); @@ -515,6 +515,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		cur = priv->icount;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -661,7 +664,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 +709,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) @@ -824,7 +830,6 @@ static int qt2_port_probe(struct usb_serial_port *port)  	spin_lock_init(&port_priv->lock);  	spin_lock_init(&port_priv->urb_lock); -	init_waitqueue_head(&port_priv->delta_msr_wait);  	port_priv->port = port;  	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -967,7 +972,7 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)  		if (newMSR & UART_MSR_TERI)  			port_priv->icount.rng++; -		wake_up_interruptible(&port_priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  	}  } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 91ff8e3bddb..549ef68ff5f 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -149,7 +149,6 @@ enum spcp8x5_type {  struct spcp8x5_private {  	spinlock_t 	lock;  	enum spcp8x5_type	type; -	wait_queue_head_t	delta_msr_wait;  	u8 			line_control;  	u8 			line_status;  }; @@ -179,7 +178,6 @@ static int spcp8x5_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	priv->type = type;  	usb_set_serial_port_data(port , priv); @@ -475,7 +473,7 @@ static void spcp8x5_process_read_urb(struct urb *urb)  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags);  	/* wake up the wait for termios */ -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -526,12 +524,15 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,  	while (1) {  		/* wake up in bulk read */ -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index b57cf841c5b..4b2a19757b4 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -61,7 +61,6 @@ struct ssu100_port_private {  	spinlock_t status_lock;  	u8 shadowLSR;  	u8 shadowMSR; -	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */  	struct async_icount icount;  }; @@ -355,8 +354,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->status_lock, flags);  	while (1) { -		wait_event_interruptible(priv->delta_msr_wait, -					 ((priv->icount.rng != prev.rng) || +		wait_event_interruptible(port->delta_msr_wait, +					 (port->serial->disconnected || +					  (priv->icount.rng != prev.rng) ||  					  (priv->icount.dsr != prev.dsr) ||  					  (priv->icount.dcd != prev.dcd) ||  					  (priv->icount.cts != prev.cts))); @@ -364,6 +364,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->status_lock, flags);  		cur = priv->icount;  		spin_unlock_irqrestore(&priv->status_lock, flags); @@ -445,7 +448,6 @@ static int ssu100_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->status_lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -537,7 +539,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)  			priv->icount.dcd++;  		if (msr & UART_MSR_TERI)  			priv->icount.rng++; -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->delta_msr_wait);  	}  } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 39cb9b807c3..73deb029fc0 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -74,7 +74,6 @@ struct ti_port {  	int			tp_flags;  	int			tp_closing_wait;/* in .01 secs */  	struct async_icount	tp_icount; -	wait_queue_head_t	tp_msr_wait;	/* wait for msr change */  	wait_queue_head_t	tp_write_wait;  	struct ti_device	*tp_tdev;  	struct usb_serial_port	*tp_port; @@ -432,7 +431,6 @@ static int ti_port_probe(struct usb_serial_port *port)  	else  		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;  	tport->tp_closing_wait = closing_wait; -	init_waitqueue_head(&tport->tp_msr_wait);  	init_waitqueue_head(&tport->tp_write_wait);  	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {  		kfree(tport); @@ -784,9 +782,13 @@ static int ti_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);  		cprev = tport->tp_icount;  		while (1) { -			interruptible_sleep_on(&tport->tp_msr_wait); +			interruptible_sleep_on(&port->delta_msr_wait);  			if (signal_pending(current))  				return -ERESTARTSYS; + +			if (port->serial->disconnected) +				return -EIO; +  			cnow = tport->tp_icount;  			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&  			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) @@ -1392,7 +1394,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  			icount->dcd++;  		if (msr & TI_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&tport->tp_msr_wait); +		wake_up_interruptible(&tport->tp_port->delta_msr_wait);  		spin_unlock_irqrestore(&tport->tp_lock, flags);  	} diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a19ed74d770..5d9b178484f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -151,6 +151,7 @@ static void destroy_serial(struct kref *kref)  		}  	} +	usb_put_intf(serial->interface);  	usb_put_dev(serial->dev);  	kfree(serial);  } @@ -620,7 +621,7 @@ static struct usb_serial *create_serial(struct usb_device *dev,  	}  	serial->dev = usb_get_dev(dev);  	serial->type = driver; -	serial->interface = interface; +	serial->interface = usb_get_intf(interface);  	kref_init(&serial->kref);  	mutex_init(&serial->disc_mutex);  	serial->minor = SERIAL_TTY_NO_MINOR; @@ -902,6 +903,7 @@ static int usb_serial_probe(struct usb_interface *interface,  		port->port.ops = &serial_port_ops;  		port->serial = serial;  		spin_lock_init(&port->lock); +		init_waitqueue_head(&port->delta_msr_wait);  		/* Keep this for private driver use for the moment but  		   should probably go away */  		INIT_WORK(&port->work, usb_serial_port_work); 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..1799335288b 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 @@ -488,6 +496,13 @@ UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */ +UNUSUAL_DEV(  0x04e8, 0x5136, 0x0000, 0x9999, +		"Samsung", +		"YP-Z3", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_MAX_SECTORS_64), +  /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.   * Device uses standards-violating 32-byte Bulk Command Block Wrappers and   * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. @@ -1527,10 +1542,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) */  |