diff options
Diffstat (limited to 'drivers/usb')
32 files changed, 326 insertions, 145 deletions
| diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 975d556b4787..be6331e2c276 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf)  			wb = acm->delayed_wb;  			acm->delayed_wb = NULL;  			spin_unlock_irq(&acm->write_lock); -			acm_start_wb(acm, acm->delayed_wb); +			acm_start_wb(acm, wb);  		} else {  			spin_unlock_irq(&acm->write_lock);  		} diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 18aafcb08fc8..189141ca4e05 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);  #define WDM_READ		4  #define WDM_INT_STALL		5  #define WDM_POLL_RUNNING	6 - +#define WDM_RESPONDING		7 +#define WDM_SUSPENDING		8  #define WDM_MAX			16 @@ -87,9 +88,7 @@ struct wdm_device {  	int			count;  	dma_addr_t		shandle;  	dma_addr_t		ihandle; -	struct mutex		wlock; -	struct mutex		rlock; -	struct mutex		plock; +	struct mutex		lock;  	wait_queue_head_t	wait;  	struct work_struct	rxwork;  	int			werr; @@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb)  	int status = urb->status;  	spin_lock(&desc->iuspin); +	clear_bit(WDM_RESPONDING, &desc->flags);  	if (status) {  		switch (status) {  		case -ENOENT:  			dev_dbg(&desc->intf->dev,  				"nonzero urb status received: -ENOENT"); -			break; +			goto skip_error;  		case -ECONNRESET:  			dev_dbg(&desc->intf->dev,  				"nonzero urb status received: -ECONNRESET"); -			break; +			goto skip_error;  		case -ESHUTDOWN:  			dev_dbg(&desc->intf->dev,  				"nonzero urb status received: -ESHUTDOWN"); -			break; +			goto skip_error;  		case -EPIPE:  			dev_err(&desc->intf->dev,  				"nonzero urb status received: -EPIPE\n"); @@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb)  	desc->reslength = urb->actual_length;  	memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);  	desc->length += desc->reslength; +skip_error:  	wake_up(&desc->wait);  	set_bit(WDM_READ, &desc->flags); @@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb)  	desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;  	spin_lock(&desc->iuspin);  	clear_bit(WDM_READ, &desc->flags); -	if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { +	set_bit(WDM_RESPONDING, &desc->flags); +	if (!test_bit(WDM_DISCONNECTING, &desc->flags) +		&& !test_bit(WDM_SUSPENDING, &desc->flags)) {  		rv = usb_submit_urb(desc->response, GFP_ATOMIC);  		dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",  			__func__, rv);  	}  	spin_unlock(&desc->iuspin);  	if (rv < 0) { +		clear_bit(WDM_RESPONDING, &desc->flags);  		if (rv == -EPERM)  			return;  		if (rv == -ENOMEM) { @@ -305,14 +309,38 @@ static ssize_t wdm_write  	if (we < 0)  		return -EIO; -	r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */ +	desc->outbuf = buf = kmalloc(count, GFP_KERNEL); +	if (!buf) { +		rv = -ENOMEM; +		goto outnl; +	} + +	r = copy_from_user(buf, buffer, count); +	if (r > 0) { +		kfree(buf); +		rv = -EFAULT; +		goto outnl; +	} + +	/* concurrent writes and disconnect */ +	r = mutex_lock_interruptible(&desc->lock);  	rv = -ERESTARTSYS; -	if (r) +	if (r) { +		kfree(buf);  		goto outnl; +	} + +	if (test_bit(WDM_DISCONNECTING, &desc->flags)) { +		kfree(buf); +		rv = -ENODEV; +		goto outnp; +	}  	r = usb_autopm_get_interface(desc->intf); -	if (r < 0) +	if (r < 0) { +		kfree(buf);  		goto outnp; +	}  	if (!file->f_flags && O_NONBLOCK)  		r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, @@ -320,24 +348,8 @@ static ssize_t wdm_write  	else  		if (test_bit(WDM_IN_USE, &desc->flags))  			r = -EAGAIN; -	if (r < 0) -		goto out; - -	if (test_bit(WDM_DISCONNECTING, &desc->flags)) { -		rv = -ENODEV; -		goto out; -	} - -	desc->outbuf = buf = kmalloc(count, GFP_KERNEL); -	if (!buf) { -		rv = -ENOMEM; -		goto out; -	} - -	r = copy_from_user(buf, buffer, count); -	if (r > 0) { +	if (r < 0) {  		kfree(buf); -		rv = -EFAULT;  		goto out;  	} @@ -374,7 +386,7 @@ static ssize_t wdm_write  out:  	usb_autopm_put_interface(desc->intf);  outnp: -	mutex_unlock(&desc->wlock); +	mutex_unlock(&desc->lock);  outnl:  	return rv < 0 ? rv : count;  } @@ -387,7 +399,7 @@ static ssize_t wdm_read  	struct wdm_device *desc = file->private_data; -	rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ +	rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */  	if (rv < 0)  		return -ERESTARTSYS; @@ -424,11 +436,8 @@ retry:  		spin_lock_irq(&desc->iuspin);  		if (desc->rerr) { /* read completed, error happened */ -			int t = desc->rerr;  			desc->rerr = 0;  			spin_unlock_irq(&desc->iuspin); -			dev_err(&desc->intf->dev, -				"reading had resulted in %d\n", t);  			rv = -EIO;  			goto err;  		} @@ -465,9 +474,7 @@ retry:  	rv = cntr;  err: -	mutex_unlock(&desc->rlock); -	if (rv < 0 && rv != -EAGAIN) -		dev_err(&desc->intf->dev, "wdm_read: exit error\n"); +	mutex_unlock(&desc->lock);  	return rv;  } @@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file)  	}  	intf->needs_remote_wakeup = 1; -	mutex_lock(&desc->plock); +	mutex_lock(&desc->lock);  	if (!desc->count++) {  		rv = usb_submit_urb(desc->validity, GFP_KERNEL);  		if (rv < 0) { @@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file)  	} else {  		rv = 0;  	} -	mutex_unlock(&desc->plock); +	mutex_unlock(&desc->lock);  	usb_autopm_put_interface(desc->intf);  out:  	mutex_unlock(&wdm_mutex); @@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file)  	struct wdm_device *desc = file->private_data;  	mutex_lock(&wdm_mutex); -	mutex_lock(&desc->plock); +	mutex_lock(&desc->lock);  	desc->count--; -	mutex_unlock(&desc->plock); +	mutex_unlock(&desc->lock);  	if (!desc->count) {  		dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); @@ -655,9 +662,7 @@ next_desc:  	desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);  	if (!desc)  		goto out; -	mutex_init(&desc->wlock); -	mutex_init(&desc->rlock); -	mutex_init(&desc->plock); +	mutex_init(&desc->lock);  	spin_lock_init(&desc->iuspin);  	init_waitqueue_head(&desc->wait);  	desc->wMaxCommand = maxcom; @@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf)  	/* to terminate pending flushes */  	clear_bit(WDM_IN_USE, &desc->flags);  	spin_unlock_irqrestore(&desc->iuspin, flags); -	cancel_work_sync(&desc->rxwork); +	mutex_lock(&desc->lock);  	kill_urbs(desc); +	cancel_work_sync(&desc->rxwork); +	mutex_unlock(&desc->lock);  	wake_up_all(&desc->wait);  	if (!desc->count)  		cleanup(desc);  	mutex_unlock(&wdm_mutex);  } +#ifdef CONFIG_PM  static int wdm_suspend(struct usb_interface *intf, pm_message_t message)  {  	struct wdm_device *desc = usb_get_intfdata(intf); @@ -786,22 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)  	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); -	mutex_lock(&desc->plock); -#ifdef CONFIG_PM +	/* if this is an autosuspend the caller does the locking */ +	if (!(message.event & PM_EVENT_AUTO)) +		mutex_lock(&desc->lock); +	spin_lock_irq(&desc->iuspin); +  	if ((message.event & PM_EVENT_AUTO) && -			test_bit(WDM_IN_USE, &desc->flags)) { +			(test_bit(WDM_IN_USE, &desc->flags) +			|| test_bit(WDM_RESPONDING, &desc->flags))) { +		spin_unlock_irq(&desc->iuspin);  		rv = -EBUSY;  	} else { -#endif -		cancel_work_sync(&desc->rxwork); + +		set_bit(WDM_SUSPENDING, &desc->flags); +		spin_unlock_irq(&desc->iuspin); +		/* callback submits work - order is essential */  		kill_urbs(desc); -#ifdef CONFIG_PM +		cancel_work_sync(&desc->rxwork);  	} -#endif -	mutex_unlock(&desc->plock); +	if (!(message.event & PM_EVENT_AUTO)) +		mutex_unlock(&desc->lock);  	return rv;  } +#endif  static int recover_from_urb_loss(struct wdm_device *desc)  { @@ -815,23 +831,27 @@ static int recover_from_urb_loss(struct wdm_device *desc)  	}  	return rv;  } + +#ifdef CONFIG_PM  static int wdm_resume(struct usb_interface *intf)  {  	struct wdm_device *desc = usb_get_intfdata(intf);  	int rv;  	dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); -	mutex_lock(&desc->plock); + +	clear_bit(WDM_SUSPENDING, &desc->flags);  	rv = recover_from_urb_loss(desc); -	mutex_unlock(&desc->plock); +  	return rv;  } +#endif  static int wdm_pre_reset(struct usb_interface *intf)  {  	struct wdm_device *desc = usb_get_intfdata(intf); -	mutex_lock(&desc->plock); +	mutex_lock(&desc->lock);  	return 0;  } @@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf)  	int rv;  	rv = recover_from_urb_loss(desc); -	mutex_unlock(&desc->plock); +	mutex_unlock(&desc->lock);  	return 0;  } @@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = {  	.name =		"cdc_wdm",  	.probe =	wdm_probe,  	.disconnect =	wdm_disconnect, +#ifdef CONFIG_PM  	.suspend =	wdm_suspend,  	.resume =	wdm_resume,  	.reset_resume =	wdm_resume, +#endif  	.pre_reset =	wdm_pre_reset,  	.post_reset =	wdm_post_reset,  	.id_table =	wdm_ids, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e909ff7b9094..3466fdc5bb11 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			free_async(as);  			return -ENOMEM;  		} +		/* Isochronous input data may end up being discontiguous +		 * if some of the packets are short.  Clear the buffer so +		 * that the gaps don't leak kernel data to userspace. +		 */ +		if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) +			memset(as->urb->transfer_buffer, 0, +					uurb->buffer_length);  	}  	as->urb->dev = ps->dev;  	as->urb->pipe = (uurb->type << 30) | @@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg)  	void __user *addr = as->userurb;  	unsigned int i; -	if (as->userbuffer && urb->actual_length) -		if (copy_to_user(as->userbuffer, urb->transfer_buffer, -				 urb->actual_length)) +	if (as->userbuffer && urb->actual_length) { +		if (urb->number_of_packets > 0)		/* Isochronous */ +			i = urb->transfer_buffer_length; +		else					/* Non-Isoc */ +			i = urb->actual_length; +		if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))  			goto err_out; +	}  	if (put_user(as->status, &userurb->status))  		goto err_out;  	if (put_user(urb->actual_length, &userurb->actual_length)) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 27080561a1c2..45a32dadb406 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  			if (urb->interval > (1 << 15))  				return -EINVAL;  			max = 1 << 15; +			break;  		case USB_SPEED_WIRELESS:  			if (urb->interval > 16)  				return -EINVAL; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7460cd797f45..11a3e0fa4331 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -747,7 +747,7 @@ config USB_MASS_STORAGE  	  which may be used with composite framework.  	  Say "y" to link the driver statically, or "m" to build -	  a dynamically linked module called "g_file_storage".  If unsure, +	  a dynamically linked module called "g_mass_storage".  If unsure,  	  consider File-backed Storage Gadget.  config USB_G_SERIAL diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 65a5f94cbc04..3568de210f79 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -266,7 +266,7 @@ struct usb_ep * __init usb_ep_autoconfig (  		}  #ifdef CONFIG_BLACKFIN -	} else if (gadget_is_musbhsfc(gadget) || gadget_is_musbhdrc(gadget)) { +	} else if (gadget_is_musbhdrc(gadget)) {  		if ((USB_ENDPOINT_XFER_BULK == type) ||  		    (USB_ENDPOINT_XFER_ISOC == type)) {  			if (USB_DIR_IN & desc->bEndpointAddress) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 5a3cdd08f1d0..f4911c09022e 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2910,7 +2910,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)  } -static int fsg_bind(struct usb_configuration *c, struct usb_function *f) +static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)  {  	struct fsg_dev		*fsg = fsg_from_func(f);  	struct usb_gadget	*gadget = c->cdev->gadget; @@ -2954,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  autoconf_fail:  	ERROR(fsg, "unable to autoconfigure all endpoints\n");  	rc = -ENOTSUPP; -	fsg_unbind(c, f);  	return rc;  } diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 1edbc12fff18..e511fec9f26d 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -136,6 +136,12 @@  #define	gadget_is_r8a66597(g)	0  #endif +#ifdef CONFIG_USB_S3C_HSOTG +#define gadget_is_s3c_hsotg(g)    (!strcmp("s3c-hsotg", (g)->name)) +#else +#define gadget_is_s3c_hsotg(g)    0 +#endif +  /**   * usb_gadget_controller_number - support bcdDevice id convention @@ -192,6 +198,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)  		return 0x24;  	else if (gadget_is_r8a66597(gadget))  		return 0x25; +	else if (gadget_is_s3c_hsotg(gadget)) +		return 0x26;  	return -ENOENT;  } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index e8edc640381e..1088d08c7ed8 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	 * usb_gadget_driver_{register,unregister}() must change.  	 */  	if (the_controller) { -		WARNING(dev, "ignoring %s\n", pci_name(pdev)); +		pr_warning("ignoring %s\n", pci_name(pdev));  		return -EBUSY;  	}  	if (!pdev->irq) { diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 76496f5d272c..a930d7fd7e7a 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -211,8 +211,6 @@ static int __init cdc_do_config(struct usb_configuration *c)  	ret = fsg_add(c->cdev, c, fsg_common);  	if (ret < 0)  		return ret; -	if (ret < 0) -		return ret;  	return 0;  } diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 8b45145b9136..5e13d23b5f0c 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -23,6 +23,7 @@  #include <linux/module.h>  #include <linux/interrupt.h>  #include <linux/delay.h> +#include <linux/err.h>  #include <linux/io.h>  #include <linux/platform_device.h>  #include <linux/clk.h> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 4e0c67f1f51b..b6315aa47f7a 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -12,7 +12,7 @@ fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \  ifeq ($(CONFIG_FHCI_DEBUG),y)  fhci-objs += fhci-dbg.o  endif -xhci-objs := xhci-hcd.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o +xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o  obj-$(CONFIG_USB_WHCI_HCD)	+= whci/ @@ -25,7 +25,7 @@ obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o  obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o  obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o  obj-$(CONFIG_USB_FHCI_HCD)	+= fhci.o -obj-$(CONFIG_USB_XHCI_HCD)	+= xhci.o +obj-$(CONFIG_USB_XHCI_HCD)	+= xhci-hcd.o  obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o  obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o  obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d8d6d3461d32..dc55a62859c6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -995,7 +995,7 @@ rescan:  	/* endpoints can be iso streams.  for now, we don't  	 * accelerate iso completions ... so spin a while.  	 */ -	if (qh->hw->hw_info1 == 0) { +	if (qh->hw == NULL) {  		ehci_vdbg (ehci, "iso delay\n");  		goto idle_timeout;  	} diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 39340ae00ac4..a0aaaaff2560 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)  					urb->interval);  		} -	/* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */ -	} else if (unlikely (stream->hw_info1 != 0)) { +	/* if dev->ep [epnum] is a QH, hw is set */ +	} else if (unlikely (stream->hw != NULL)) {  		ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",  			urb->dev->devpath, epnum,  			usb_pipein(urb->pipe) ? "in" : "out"); @@ -1565,13 +1565,27 @@ itd_patch(  static inline void  itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)  { -	/* always prepend ITD/SITD ... only QH tree is order-sensitive */ -	itd->itd_next = ehci->pshadow [frame]; -	itd->hw_next = ehci->periodic [frame]; -	ehci->pshadow [frame].itd = itd; +	union ehci_shadow	*prev = &ehci->pshadow[frame]; +	__hc32			*hw_p = &ehci->periodic[frame]; +	union ehci_shadow	here = *prev; +	__hc32			type = 0; + +	/* skip any iso nodes which might belong to previous microframes */ +	while (here.ptr) { +		type = Q_NEXT_TYPE(ehci, *hw_p); +		if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) +			break; +		prev = periodic_next_shadow(ehci, prev, type); +		hw_p = shadow_next_periodic(ehci, &here, type); +		here = *prev; +	} + +	itd->itd_next = here; +	itd->hw_next = *hw_p; +	prev->itd = itd;  	itd->frame = frame;  	wmb (); -	ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); +	*hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);  }  /* fit urb's itds into the selected schedule slot; activate as needed */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2d85e21ff282..b1dce96dd621 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -394,9 +394,8 @@ struct ehci_iso_sched {   * acts like a qh would, if EHCI had them for ISO.   */  struct ehci_iso_stream { -	/* first two fields match QH, but info1 == 0 */ -	__hc32			hw_next; -	__hc32			hw_info1; +	/* first field matches ehci_hq, but is NULL */ +	struct ehci_qh_hw	*hw;  	u32			refcount;  	u8			bEndpointAddress; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index bee558aed427..f71a73a93d0c 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)  /* this function must be called with interrupt disabled */  static void free_usb_address(struct r8a66597 *r8a66597, -			     struct r8a66597_device *dev) +			     struct r8a66597_device *dev, int reset)  {  	int port; @@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597,  	dev->state = USB_STATE_DEFAULT;  	r8a66597->address_map &= ~(1 << dev->address);  	dev->address = 0; -	dev_set_drvdata(&dev->udev->dev, NULL); +	/* +	 * Only when resetting USB, it is necessary to erase drvdata. When +	 * a usb device with usb hub is disconnect, "dev->udev" is already +	 * freed on usb_desconnect(). So we cannot access the data. +	 */ +	if (reset) +		dev_set_drvdata(&dev->udev->dev, NULL);  	list_del(&dev->device_list);  	kfree(dev); @@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)  	struct r8a66597_device *dev = r8a66597->root_hub[port].dev;  	disable_r8a66597_pipe_all(r8a66597, dev); -	free_usb_address(r8a66597, dev); +	free_usb_address(r8a66597, dev, 0);  	start_root_hub_sampling(r8a66597, port, 0);  } @@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597,  				spin_lock_irqsave(&r8a66597->lock, flags);  				dev = get_r8a66597_device(r8a66597, addr);  				disable_r8a66597_pipe_all(r8a66597, dev); -				free_usb_address(r8a66597, dev); +				free_usb_address(r8a66597, dev, 0);  				put_child_connect_map(r8a66597, addr);  				spin_unlock_irqrestore(&r8a66597->lock, flags);  			} @@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			rh->port |= (1 << USB_PORT_FEAT_RESET);  			disable_r8a66597_pipe_all(r8a66597, dev); -			free_usb_address(r8a66597, dev); +			free_usb_address(r8a66597, dev, 1);  			r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,  				      get_dvstctr_reg(port)); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 49f7d72f8b1b..bba9b19ed1b9 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -566,8 +566,13 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,  			if (interval < 3)  				interval = 3;  			if ((1 << interval) != 8*ep->desc.bInterval) -				dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n", -						ep->desc.bEndpointAddress, 1 << interval); +				dev_warn(&udev->dev, +						"ep %#x - rounding interval" +						" to %d microframes, " +						"ep desc says %d microframes\n", +						ep->desc.bEndpointAddress, +						1 << interval, +						8*ep->desc.bInterval);  		}  		break;  	default: diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci.c index 4cb69e0af834..492a61c2c79d 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci.c @@ -1173,6 +1173,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,  		cmd_completion = &virt_dev->cmd_completion;  		cmd_status = &virt_dev->cmd_status;  	} +	init_completion(cmd_completion);  	if (!ctx_change)  		ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 4d2952f1fb13..3adab041355a 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -202,6 +202,7 @@ static void appledisplay_work(struct work_struct *work)  static int appledisplay_probe(struct usb_interface *iface,  	const struct usb_device_id *id)  { +	struct backlight_properties props;  	struct appledisplay *pdata;  	struct usb_device *udev = interface_to_usbdev(iface);  	struct usb_host_interface *iface_desc; @@ -279,16 +280,16 @@ static int appledisplay_probe(struct usb_interface *iface,  	/* Register backlight device */  	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",  		atomic_inc_return(&count_displays) - 1); +	memset(&props, 0, sizeof(struct backlight_properties)); +	props.max_brightness = 0xff;  	pdata->bd = backlight_device_register(bl_name, NULL, pdata, -						&appledisplay_bl_data); +					      &appledisplay_bl_data, &props);  	if (IS_ERR(pdata->bd)) {  		dev_err(&iface->dev, "Backlight registration failed\n");  		retval = PTR_ERR(pdata->bd);  		goto error;  	} -	pdata->bd->props.max_brightness = 0xff; -  	/* Try to get brightness */  	brightness = appledisplay_bl_get_brightness(pdata->bd); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b4bbf8f2c238..0e8b8ab1d168 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -379,7 +379,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  				u8 devctl, u8 power)  {  	irqreturn_t handled = IRQ_NONE; -	void __iomem *mbase = musb->mregs;  	DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,  		int_usb); @@ -394,6 +393,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		if (devctl & MUSB_DEVCTL_HM) {  #ifdef CONFIG_USB_MUSB_HDRC_HCD +			void __iomem *mbase = musb->mregs; +  			switch (musb->xceiv->state) {  			case OTG_STATE_A_SUSPEND:  				/* remote wakeup?  later, GetPortStatus @@ -471,6 +472,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  #ifdef CONFIG_USB_MUSB_HDRC_HCD  	/* see manual for the order of the tests */  	if (int_usb & MUSB_INTR_SESSREQ) { +		void __iomem *mbase = musb->mregs; +  		DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));  		/* IRQ arrives from ID pin sense or (later, if VBUS power @@ -519,6 +522,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		case OTG_STATE_A_WAIT_BCON:  		case OTG_STATE_A_WAIT_VRISE:  			if (musb->vbuserr_retry) { +				void __iomem *mbase = musb->mregs; +  				musb->vbuserr_retry--;  				ignore = 1;  				devctl |= MUSB_DEVCTL_SESSION; @@ -622,6 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  	if (int_usb & MUSB_INTR_CONNECT) {  		struct usb_hcd *hcd = musb_to_hcd(musb); +		void __iomem *mbase = musb->mregs;  		handled = IRQ_HANDLED;  		musb->is_active = 1; @@ -2007,7 +2013,6 @@ bad_config:  	/* host side needs more setup */  	if (is_host_enabled(musb)) {  		struct usb_hcd	*hcd = musb_to_hcd(musb); -		u8 busctl;  		otg_set_host(musb->xceiv, &hcd->self); @@ -2018,9 +2023,9 @@ bad_config:  		/* program PHY to use external vBus if required */  		if (plat->extvbus) { -			busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); +			u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);  			busctl |= MUSB_ULPI_USE_EXTVBUS; -			musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl); +			musb_write_ulpi_buscontrol(musb->mregs, busctl);  		}  	} diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index d849fb81c131..cd9f4a9a06c6 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -469,7 +469,7 @@ struct musb_csr_regs {  struct musb_context_registers { -#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) +#ifdef CONFIG_PM  	u32 otg_sysconfig, otg_forcestandby;  #endif  	u8 power; @@ -483,7 +483,7 @@ struct musb_context_registers {  	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];  }; -#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) +#ifdef CONFIG_PM  extern void musb_platform_save_context(struct musb *musb,  		struct musb_context_registers *musb_context);  extern void musb_platform_restore_context(struct musb *musb, diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 3421cf9858b5..dec896e888db 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1689,7 +1689,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)  				dma->desired_mode = 1;  			if (rx_count < hw_ep->max_packet_sz_rx) {  				length = rx_count; -				dma->bDesiredMode = 0; +				dma->desired_mode = 0;  			} else {  				length = urb->transfer_buffer_length;  			} diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 8d8062b10e2f..fa55aacc385d 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -326,6 +326,11 @@ static inline void  musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)  	musb_writew(mbase, MUSB_RXFIFOADD, c_off);  } +static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) +{ +	musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val); +} +  static inline u8 musb_read_txfifosz(void __iomem *mbase)  {  	return musb_readb(mbase, MUSB_TXFIFOSZ); @@ -346,6 +351,11 @@ static inline u16  musb_read_rxfifoadd(void __iomem *mbase)  	return musb_readw(mbase, MUSB_RXFIFOADD);  } +static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) +{ +	return musb_readb(mbase, MUSB_ULPI_BUSCONTROL); +} +  static inline u8 musb_read_configdata(void __iomem *mbase)  {  	musb_writeb(mbase, MUSB_INDEX, 0); @@ -510,20 +520,33 @@ static inline void  musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)  {  } +static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) +{ +} +  static inline u8 musb_read_txfifosz(void __iomem *mbase)  { +	return 0;  }  static inline u16 musb_read_txfifoadd(void __iomem *mbase)  { +	return 0;  }  static inline u8 musb_read_rxfifosz(void __iomem *mbase)  { +	return 0;  }  static inline u16  musb_read_rxfifoadd(void __iomem *mbase)  { +	return 0; +} + +static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) +{ +	return 0;  }  static inline u8 musb_read_configdata(void __iomem *mbase) @@ -577,22 +600,27 @@ static inline void  musb_write_txhubport(void __iomem *mbase, u8 epnum,  static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)  { +	return 0;  }  static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)  { +	return 0;  }  static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)  { +	return 0;  }  static inline u8  musb_read_txfunaddr(void __iomem *mbase, u8 epnum)  { +	return 0;  }  static inline u8  musb_read_txhubaddr(void __iomem *mbase, u8 epnum)  { +	return 0;  }  static inline void  musb_read_txhubport(void __iomem *mbase, u8 epnum) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index c78b255e3f83..a0ecb42cb33a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -474,14 +474,14 @@ config USB_SERIAL_OTI6858  config USB_SERIAL_QCAUX  	tristate "USB Qualcomm Auxiliary Serial Port Driver" -	---help--- +	help  	  Say Y here if you want to use the auxiliary serial ports provided  	  by many modems based on Qualcomm chipsets.  These ports often use  	  a proprietary protocol called DM and cannot be used for AT- or  	  PPP-based communication.  	  To compile this driver as a module, choose M here: the -	  module will be called moto_modem.  If unsure, choose N. +	  module will be called qcaux.  If unsure, choose N.  config USB_SERIAL_QUALCOMM  	tristate "USB Qualcomm Serial modem" diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index b22ac3258523..f347da2ef00a 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -181,6 +181,7 @@ static int usb_console_setup(struct console *co, char *options)  	/* The console is special in terms of closing the device so  	 * indicate this port is now acting as a system console. */  	port->console = 1; +	port->port.console = 1;  	mutex_unlock(&serial->disc_mutex);  	return retval; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 507382b0a9ed..ec9b0449ccf6 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -313,11 +313,6 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,  		return -EPROTO;  	} -	/* Single data value */ -	result = usb_control_msg(serial->dev, -			usb_sndctrlpipe(serial->dev, 0), -			request, REQTYPE_HOST_TO_DEVICE, data[0], -			0, NULL, 0, 300);  	return 0;  } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6af0dfa5f5ac..1d7c4fac02e8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -91,7 +91,7 @@ struct ftdi_private {  	unsigned long tx_outstanding_bytes;  	unsigned long tx_outstanding_urbs;  	unsigned short max_packet_size; -	struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() */ +	struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */  };  /* struct ftdi_sio_quirk is used by devices requiring special attention. */ @@ -658,6 +658,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },  	{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },  	{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, +	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, @@ -1272,8 +1273,8 @@ check_and_exit:  	     (priv->flags & ASYNC_SPD_MASK)) ||  	    (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&  	     (old_priv.custom_divisor != priv->custom_divisor))) { -		mutex_unlock(&priv->cfg_lock);  		change_speed(tty, port); +		mutex_unlock(&priv->cfg_lock);  	}  	else  		mutex_unlock(&priv->cfg_lock); @@ -2264,9 +2265,11 @@ static void ftdi_set_termios(struct tty_struct *tty,  		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);  	} else {  		/* set the baudrate determined before */ +		mutex_lock(&priv->cfg_lock);  		if (change_speed(tty, port))  			dev_err(&port->dev, "%s urb failed to set baudrate\n",  				__func__); +		mutex_unlock(&priv->cfg_lock);  		/* Ensure RTS and DTR are raised when baudrate changed from 0 */  		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)  			set_mctrl(port, TIOCM_DTR | TIOCM_RTS); diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 0727e198503e..75482cbc3998 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -501,6 +501,13 @@  #define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */  /* + * Contec products (http://www.contec.com) + * Submitted by Daniel Sangorrin + */ +#define CONTEC_VID		0x06CE	/* Vendor ID */ +#define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */ + +/*   * Definitions for B&B Electronics products.   */  #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */ diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 89fac36684c5..f804acb138ec 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -130,7 +130,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port  	spin_unlock_irqrestore(&port->lock, flags);  	/* if we have a bulk endpoint, start reading from it */ -	if (serial->num_bulk_in) { +	if (port->bulk_in_size) {  		/* Start reading from the device */  		usb_fill_bulk_urb(port->read_urb, serial->dev,  				   usb_rcvbulkpipe(serial->dev, @@ -159,10 +159,10 @@ static void generic_cleanup(struct usb_serial_port *port)  	dbg("%s - port %d", __func__, port->number);  	if (serial->dev) { -		/* shutdown any bulk reads that might be going on */ -		if (serial->num_bulk_out) +		/* shutdown any bulk transfers that might be going on */ +		if (port->bulk_out_size)  			usb_kill_urb(port->write_urb); -		if (serial->num_bulk_in) +		if (port->bulk_in_size)  			usb_kill_urb(port->read_urb);  	}  } @@ -333,15 +333,15 @@ int usb_serial_generic_write(struct tty_struct *tty,  	dbg("%s - port %d", __func__, port->number); +	/* only do something if we have a bulk out endpoint */ +	if (!port->bulk_out_size) +		return -ENODEV; +  	if (count == 0) {  		dbg("%s - write request of 0 bytes", __func__);  		return 0;  	} -	/* only do something if we have a bulk out endpoint */ -	if (!serial->num_bulk_out) -		return 0; -  	if (serial->type->max_in_flight_urbs)  		return usb_serial_multi_urb_write(tty, port,  						  buf, count); @@ -364,14 +364,19 @@ int usb_serial_generic_write_room(struct tty_struct *tty)  	int room = 0;  	dbg("%s - port %d", __func__, port->number); + +	if (!port->bulk_out_size) +		return 0; +  	spin_lock_irqsave(&port->lock, flags);  	if (serial->type->max_in_flight_urbs) {  		if (port->urbs_in_flight < serial->type->max_in_flight_urbs)  			room = port->bulk_out_size *  				(serial->type->max_in_flight_urbs -  				 port->urbs_in_flight); -	} else if (serial->num_bulk_out) +	} else {  		room = kfifo_avail(&port->write_fifo); +	}  	spin_unlock_irqrestore(&port->lock, flags);  	dbg("%s - returns %d", __func__, room); @@ -382,15 +387,18 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data;  	struct usb_serial *serial = port->serial; -	int chars = 0;  	unsigned long flags; +	int chars;  	dbg("%s - port %d", __func__, port->number); +	if (!port->bulk_out_size) +		return 0; +  	spin_lock_irqsave(&port->lock, flags);  	if (serial->type->max_in_flight_urbs)  		chars = port->tx_bytes_flight; -	else if (serial->num_bulk_out) +	else  		chars = kfifo_len(&port->write_fifo);  	spin_unlock_irqrestore(&port->lock, flags); @@ -415,11 +423,13 @@ void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port,  			   ((serial->type->read_bulk_callback) ?  			     serial->type->read_bulk_callback :  			     usb_serial_generic_read_bulk_callback), port); +  	result = usb_submit_urb(urb, mem_flags); -	if (result) +	if (result && result != -EPERM) {  		dev_err(&port->dev,  			"%s - failed resubmitting read urb, error %d\n",  							__func__, result); +	}  }  EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb); @@ -498,23 +508,18 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)  		if (port->urbs_in_flight < 0)  			port->urbs_in_flight = 0;  		spin_unlock_irqrestore(&port->lock, flags); - -		if (status) { -			dbg("%s - nonzero multi-urb write bulk status " -				"received: %d", __func__, status); -			return; -		}  	} else {  		port->write_urb_busy = 0; -		if (status) { -			dbg("%s - nonzero multi-urb write bulk status " -				"received: %d", __func__, status); +		if (status)  			kfifo_reset_out(&port->write_fifo); -		} else +		else  			usb_serial_generic_write_start(port);  	} +	if (status) +		dbg("%s - non-zero urb status: %d", __func__, status); +  	usb_serial_port_softint(port);  }  EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 847b805d63a3..950cb311ca94 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,7 +288,9 @@ static int  option_resume(struct usb_serial *serial);  #define QUALCOMM_VENDOR_ID			0x05C6 -#define MAXON_VENDOR_ID				0x16d8 +#define CMOTECH_VENDOR_ID			0x16d8 +#define CMOTECH_PRODUCT_6008			0x6008 +#define CMOTECH_PRODUCT_6280			0x6280  #define TELIT_VENDOR_ID				0x1bc7  #define TELIT_PRODUCT_UC864E			0x1003 @@ -309,6 +311,7 @@ static int  option_resume(struct usb_serial *serial);  #define DLINK_VENDOR_ID				0x1186  #define DLINK_PRODUCT_DWM_652			0x3e04  #define DLINK_PRODUCT_DWM_652_U5		0xce16 +#define DLINK_PRODUCT_DWM_652_U5A		0xce1e  #define QISDA_VENDOR_ID				0x1da5  #define QISDA_PRODUCT_H21_4512			0x4512 @@ -332,6 +335,24 @@ static int  option_resume(struct usb_serial *serial);  #define ALCATEL_VENDOR_ID			0x1bbb  #define ALCATEL_PRODUCT_X060S			0x0000 +#define PIRELLI_VENDOR_ID			0x1266 +#define PIRELLI_PRODUCT_C100_1			0x1002 +#define PIRELLI_PRODUCT_C100_2			0x1003 +#define PIRELLI_PRODUCT_1004			0x1004 +#define PIRELLI_PRODUCT_1005			0x1005 +#define PIRELLI_PRODUCT_1006			0x1006 +#define PIRELLI_PRODUCT_1007			0x1007 +#define PIRELLI_PRODUCT_1008			0x1008 +#define PIRELLI_PRODUCT_1009			0x1009 +#define PIRELLI_PRODUCT_100A			0x100a +#define PIRELLI_PRODUCT_100B			0x100b +#define PIRELLI_PRODUCT_100C			0x100c +#define PIRELLI_PRODUCT_100D			0x100d +#define PIRELLI_PRODUCT_100E			0x100e +#define PIRELLI_PRODUCT_100F			0x100f +#define PIRELLI_PRODUCT_1011			0x1011 +#define PIRELLI_PRODUCT_1012			0x1012 +  /* Airplus products */  #define AIRPLUS_VENDOR_ID			0x1011  #define AIRPLUS_PRODUCT_MCD650			0x3198 @@ -547,7 +568,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },  	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */  	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ -	{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ +	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ +	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ @@ -659,6 +681,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },  	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },  	{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ +	{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5A) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, @@ -666,7 +689,6 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },  	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */  	{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, -	{ USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },  	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },  	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, @@ -675,6 +697,24 @@ static const struct usb_device_id option_ids[] = {    	  .driver_info = (kernel_ulong_t)&four_g_w14_blacklist    	},  	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, +	/* Pirelli  */ +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) }, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) }, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) }, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) }, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, +	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, +  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); @@ -798,12 +838,19 @@ static int option_probe(struct usb_serial *serial,  			const struct usb_device_id *id)  {  	struct option_intf_private *data; +  	/* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */  	if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&  		serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&  		serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)  		return -ENODEV; +	/* Bandrich modem and AT command interface is 0xff */ +	if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID || +		serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) && +		serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) +		return -ENODEV; +  	data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL);  	if (!data)  		return -ENOMEM; diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 310ff6ec6567..53a2d5a935a2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -47,6 +47,35 @@ static const struct usb_device_id id_table[] = {  	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */  	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */  	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */ +	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */ +	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */ +	{USB_DEVICE(0x05c6, 0x9224)},	/* Sony Gobi 2000 QDL device (N0279, VU730) */ +	{USB_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */ +	{USB_DEVICE(0x05c6, 0x9244)},	/* Samsung Gobi 2000 QDL device (VL176) */ +	{USB_DEVICE(0x05c6, 0x9245)},	/* Samsung Gobi 2000 Modem device (VL176) */ +	{USB_DEVICE(0x03f0, 0x241d)},	/* HP Gobi 2000 QDL device (VP412) */ +	{USB_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */ +	{USB_DEVICE(0x05c6, 0x9214)},	/* Acer Gobi 2000 QDL device (VP413) */ +	{USB_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */ +	{USB_DEVICE(0x05c6, 0x9264)},	/* Asus Gobi 2000 QDL device (VR305) */ +	{USB_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */ +	{USB_DEVICE(0x05c6, 0x9234)},	/* Top Global Gobi 2000 QDL device (VR306) */ +	{USB_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */ +	{USB_DEVICE(0x05c6, 0x9274)},	/* iRex Technologies Gobi 2000 QDL device (VR307) */ +	{USB_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */ +	{USB_DEVICE(0x1199, 0x9000)},	/* Sierra Wireless Gobi 2000 QDL device (VT773) */ +	{USB_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9004)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9005)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9006)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9007)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9008)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ +	{USB_DEVICE(0x16d8, 0x8001)},	/* CMDTech Gobi 2000 QDL device (VU922) */ +	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */  	{ }				/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 98b549b1cab2..ccf1dbbb87ef 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -374,6 +374,15 @@ UNUSUAL_DEV(  0x04ce, 0x0002, 0x0074, 0x0074,  		US_SC_DEVICE, US_PR_DEVICE, NULL,  		US_FL_FIX_INQUIRY), +/* Reported by Ondrej Zary <linux@rainbow-software.org> + * The device reports one sector more and breaks when that sector is accessed + */ +UNUSUAL_DEV(  0x04ce, 0x0002, 0x026c, 0x026c, +		"ScanLogic", +		"SL11R-IDE", +		US_SC_DEVICE, US_PR_DEVICE, NULL, +		US_FL_FIX_CAPACITY), +  /* Reported by Kriston Fincher <kriston@airmail.net>   * Patch submitted by Sean Millichamp <sean@bruenor.org>   * This is to support the Panasonic PalmCam PV-SD4090 @@ -1380,20 +1389,6 @@ UNUSUAL_DEV(  0x0f19, 0x0105, 0x0100, 0x0100,  		US_SC_DEVICE, US_PR_DEVICE, NULL,  		US_FL_IGNORE_RESIDUE ), -/* Jeremy Katz <katzj@redhat.com>: - * The Blackberry Pearl can run in two modes; a usb-storage only mode - * and a mode that allows access via mass storage and to its database. - * The berry_charge module will set the device to dual mode and thus we - * should ignore its native mode if that module is built - */ -#ifdef CONFIG_USB_BERRY_CHARGE -UNUSUAL_DEV(  0x0fca, 0x0006, 0x0001, 0x0001, -		"RIM", -		"Blackberry Pearl", -		US_SC_DEVICE, US_PR_DEVICE, NULL, -		US_FL_IGNORE_DEVICE ), -#endif -  /* Reported by Michael Stattmann <michael@stattmann.com> */  UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,  		"Sony Ericsson", | 
