diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 12:09:47 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 12:09:47 -0800 | 
| commit | 55b81e6f2795484ea8edf5805c95c007cacfa736 (patch) | |
| tree | c3724975107857fcc03b5dd649c462e4f72397be /drivers/usb/core | |
| parent | 5983faf942f260023e547f3c5f38c1033c35cc9b (diff) | |
| parent | 08e87d0d773dc9ca5faf4c3306e238ed0ea129b0 (diff) | |
| download | olio-linux-3.10-55b81e6f2795484ea8edf5805c95c007cacfa736.tar.xz olio-linux-3.10-55b81e6f2795484ea8edf5805c95c007cacfa736.zip  | |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (232 commits)
  USB: Add USB-ID for Multiplex RC serial adapter to cp210x.c
  xhci: Clean up 32-bit build warnings.
  USB: update documentation for usbmon
  usb: usb-storage doesn't support dynamic id currently, the patch disables the feature to fix an oops
  drivers/usb/class/cdc-acm.c: clear dangling pointer
  drivers/usb/dwc3/dwc3-pci.c: introduce missing kfree
  drivers/usb/host/isp1760-if.c: introduce missing kfree
  usb: option: add ZD Incorporated HSPA modem
  usb: ch9: fix up MaxStreams helper
  USB: usb-skeleton.c: cleanup open_count
  USB: usb-skeleton.c: fix open/disconnect race
  xhci: Properly handle COMP_2ND_BW_ERR
  USB: remove dead code from suspend/resume path
  USB: add quirk for another camera
  drivers: usb: wusbcore: Fix dependency for USB_WUSB
  xhci: Better debugging for critical host errors.
  xhci: Be less verbose during URB cancellation.
  xhci: Remove debugging about ring structure allocation.
  xhci: Remove debugging about toggling cycle bits.
  xhci: Remove debugging for individual transfers.
  ...
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/devio.c | 189 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 36 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 31 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 89 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 5 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 14 | 
7 files changed, 193 insertions, 175 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e3beaf229ee..3af5e2dd1d8 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -86,6 +86,7 @@ struct async {  	void __user *userbuffer;  	void __user *userurb;  	struct urb *urb; +	unsigned int mem_usage;  	int status;  	u32 secid;  	u8 bulk_addr; @@ -108,8 +109,44 @@ enum snoop_when {  #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0) -#define	MAX_USBFS_BUFFER_SIZE	16384 +/* Limit on the total amount of memory we can allocate for transfers */ +static unsigned usbfs_memory_mb = 16; +module_param(usbfs_memory_mb, uint, 0644); +MODULE_PARM_DESC(usbfs_memory_mb, +		"maximum MB allowed for usbfs buffers (0 = no limit)"); +/* Hard limit, necessary to avoid aithmetic overflow */ +#define USBFS_XFER_MAX		(UINT_MAX / 2 - 1000000) + +static atomic_t usbfs_memory_usage;	/* Total memory currently allocated */ + +/* Check whether it's okay to allocate more memory for a transfer */ +static int usbfs_increase_memory_usage(unsigned amount) +{ +	unsigned lim; + +	/* +	 * Convert usbfs_memory_mb to bytes, avoiding overflows. +	 * 0 means use the hard limit (effectively unlimited). +	 */ +	lim = ACCESS_ONCE(usbfs_memory_mb); +	if (lim == 0 || lim > (USBFS_XFER_MAX >> 20)) +		lim = USBFS_XFER_MAX; +	else +		lim <<= 20; + +	atomic_add(amount, &usbfs_memory_usage); +	if (atomic_read(&usbfs_memory_usage) <= lim) +		return 0; +	atomic_sub(amount, &usbfs_memory_usage); +	return -ENOMEM; +} + +/* Memory for a transfer is being deallocated */ +static void usbfs_decrease_memory_usage(unsigned amount) +{ +	atomic_sub(amount, &usbfs_memory_usage); +}  static int connected(struct dev_state *ps)  { @@ -249,10 +286,12 @@ static struct async *alloc_async(unsigned int numisoframes)  static void free_async(struct async *as)  {  	put_pid(as->pid); -	put_cred(as->cred); +	if (as->cred) +		put_cred(as->cred);  	kfree(as->urb->transfer_buffer);  	kfree(as->urb->setup_packet);  	usb_free_urb(as->urb); +	usbfs_decrease_memory_usage(as->mem_usage);  	kfree(as);  } @@ -792,9 +831,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)  	wLength = ctrl.wLength;		/* To suppress 64k PAGE_SIZE warning */  	if (wLength > PAGE_SIZE)  		return -EINVAL; +	ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) + +			sizeof(struct usb_ctrlrequest)); +	if (ret) +		return ret;  	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); -	if (!tbuf) -		return -ENOMEM; +	if (!tbuf) { +		ret = -ENOMEM; +		goto done; +	}  	tmo = ctrl.timeout;  	snoop(&dev->dev, "control urb: bRequestType=%02x "  		"bRequest=%02x wValue=%04x " @@ -806,8 +851,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)  	if (ctrl.bRequestType & 0x80) {  		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,  					       ctrl.wLength)) { -			free_page((unsigned long)tbuf); -			return -EINVAL; +			ret = -EINVAL; +			goto done;  		}  		pipe = usb_rcvctrlpipe(dev, 0);  		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); @@ -821,15 +866,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)  			  tbuf, max(i, 0));  		if ((i > 0) && ctrl.wLength) {  			if (copy_to_user(ctrl.data, tbuf, i)) { -				free_page((unsigned long)tbuf); -				return -EFAULT; +				ret = -EFAULT; +				goto done;  			}  		}  	} else {  		if (ctrl.wLength) {  			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { -				free_page((unsigned long)tbuf); -				return -EFAULT; +				ret = -EFAULT; +				goto done;  			}  		}  		pipe = usb_sndctrlpipe(dev, 0); @@ -843,14 +888,18 @@ static int proc_control(struct dev_state *ps, void __user *arg)  		usb_lock_device(dev);  		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);  	} -	free_page((unsigned long)tbuf);  	if (i < 0 && i != -EPIPE) {  		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "  			   "failed cmd %s rqt %u rq %u len %u ret %d\n",  			   current->comm, ctrl.bRequestType, ctrl.bRequest,  			   ctrl.wLength, i);  	} -	return i; +	ret = i; + done: +	free_page((unsigned long) tbuf); +	usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) + +			sizeof(struct usb_ctrlrequest)); +	return ret;  }  static int proc_bulk(struct dev_state *ps, void __user *arg) @@ -877,15 +926,20 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)  	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))  		return -EINVAL;  	len1 = bulk.len; -	if (len1 > MAX_USBFS_BUFFER_SIZE) +	if (len1 >= USBFS_XFER_MAX)  		return -EINVAL; -	if (!(tbuf = kmalloc(len1, GFP_KERNEL))) -		return -ENOMEM; +	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); +	if (ret) +		return ret; +	if (!(tbuf = kmalloc(len1, GFP_KERNEL))) { +		ret = -ENOMEM; +		goto done; +	}  	tmo = bulk.timeout;  	if (bulk.ep & 0x80) {  		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { -			kfree(tbuf); -			return -EINVAL; +			ret = -EINVAL; +			goto done;  		}  		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); @@ -896,15 +950,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)  		if (!i && len2) {  			if (copy_to_user(bulk.data, tbuf, len2)) { -				kfree(tbuf); -				return -EFAULT; +				ret = -EFAULT; +				goto done;  			}  		}  	} else {  		if (len1) {  			if (copy_from_user(tbuf, bulk.data, len1)) { -				kfree(tbuf); -				return -EFAULT; +				ret = -EFAULT; +				goto done;  			}  		}  		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); @@ -914,10 +968,11 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)  		usb_lock_device(dev);  		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);  	} +	ret = (i < 0 ? i : len2); + done:  	kfree(tbuf); -	if (i < 0) -		return i; -	return len2; +	usbfs_decrease_memory_usage(len1 + sizeof(struct urb)); +	return ret;  }  static int proc_resetep(struct dev_state *ps, void __user *arg) @@ -1062,7 +1117,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  {  	struct usbdevfs_iso_packet_desc *isopkt = NULL;  	struct usb_host_endpoint *ep; -	struct async *as; +	struct async *as = NULL;  	struct usb_ctrlrequest *dr = NULL;  	unsigned int u, totlen, isofrmlen;  	int ret, ifnum = -1; @@ -1095,32 +1150,30 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	}  	if (!ep)  		return -ENOENT; + +	u = 0;  	switch(uurb->type) {  	case USBDEVFS_URB_TYPE_CONTROL:  		if (!usb_endpoint_xfer_control(&ep->desc))  			return -EINVAL; -		/* min 8 byte setup packet, -		 * max 8 byte setup plus an arbitrary data stage */ -		if (uurb->buffer_length < 8 || -		    uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) +		/* min 8 byte setup packet */ +		if (uurb->buffer_length < 8)  			return -EINVAL;  		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);  		if (!dr)  			return -ENOMEM;  		if (copy_from_user(dr, uurb->buffer, 8)) { -			kfree(dr); -			return -EFAULT; +			ret = -EFAULT; +			goto error;  		}  		if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { -			kfree(dr); -			return -EINVAL; +			ret = -EINVAL; +			goto error;  		}  		ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,  				      le16_to_cpup(&dr->wIndex)); -		if (ret) { -			kfree(dr); -			return ret; -		} +		if (ret) +			goto error;  		uurb->number_of_packets = 0;  		uurb->buffer_length = le16_to_cpup(&dr->wLength);  		uurb->buffer += 8; @@ -1138,6 +1191,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			__le16_to_cpup(&dr->wValue),  			__le16_to_cpup(&dr->wIndex),  			__le16_to_cpup(&dr->wLength)); +		u = sizeof(struct usb_ctrlrequest);  		break;  	case USBDEVFS_URB_TYPE_BULK: @@ -1151,8 +1205,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			goto interrupt_urb;  		}  		uurb->number_of_packets = 0; -		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) -			return -EINVAL;  		break;  	case USBDEVFS_URB_TYPE_INTERRUPT: @@ -1160,8 +1212,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			return -EINVAL;   interrupt_urb:  		uurb->number_of_packets = 0; -		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) -			return -EINVAL;  		break;  	case USBDEVFS_URB_TYPE_ISO: @@ -1176,50 +1226,53 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))  			return -ENOMEM;  		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { -			kfree(isopkt); -			return -EFAULT; +			ret = -EFAULT; +			goto error;  		}  		for (totlen = u = 0; u < uurb->number_of_packets; u++) {  			/* arbitrary limit,  			 * sufficient for USB 2.0 high-bandwidth iso */  			if (isopkt[u].length > 8192) { -				kfree(isopkt); -				return -EINVAL; +				ret = -EINVAL; +				goto error;  			}  			totlen += isopkt[u].length;  		} -		/* 3072 * 64 microframes */ -		if (totlen > 196608) { -			kfree(isopkt); -			return -EINVAL; -		} +		u *= sizeof(struct usb_iso_packet_descriptor);  		uurb->buffer_length = totlen;  		break;  	default:  		return -EINVAL;  	} + +	if (uurb->buffer_length >= USBFS_XFER_MAX) { +		ret = -EINVAL; +		goto error; +	}  	if (uurb->buffer_length > 0 &&  			!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,  				uurb->buffer, uurb->buffer_length)) { -		kfree(isopkt); -		kfree(dr); -		return -EFAULT; +		ret = -EFAULT; +		goto error;  	}  	as = alloc_async(uurb->number_of_packets);  	if (!as) { -		kfree(isopkt); -		kfree(dr); -		return -ENOMEM; +		ret = -ENOMEM; +		goto error;  	} +	u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length; +	ret = usbfs_increase_memory_usage(u); +	if (ret) +		goto error; +	as->mem_usage = u; +  	if (uurb->buffer_length > 0) {  		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,  				GFP_KERNEL);  		if (!as->urb->transfer_buffer) { -			kfree(isopkt); -			kfree(dr); -			free_async(as); -			return -ENOMEM; +			ret = -ENOMEM; +			goto error;  		}  		/* Isochronous input data may end up being discontiguous  		 * if some of the packets are short.  Clear the buffer so @@ -1253,6 +1306,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	as->urb->transfer_buffer_length = uurb->buffer_length;  	as->urb->setup_packet = (unsigned char *)dr; +	dr = NULL;  	as->urb->start_frame = uurb->start_frame;  	as->urb->number_of_packets = uurb->number_of_packets;  	if (uurb->type == USBDEVFS_URB_TYPE_ISO || @@ -1268,6 +1322,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		totlen += isopkt[u].length;  	}  	kfree(isopkt); +	isopkt = NULL;  	as->ps = ps;  	as->userurb = arg;  	if (is_in && uurb->buffer_length > 0) @@ -1282,8 +1337,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	if (!is_in && uurb->buffer_length > 0) {  		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,  				uurb->buffer_length)) { -			free_async(as); -			return -EFAULT; +			ret = -EFAULT; +			goto error;  		}  	}  	snoop_urb(ps->dev, as->userurb, as->urb->pipe, @@ -1329,10 +1384,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		snoop_urb(ps->dev, as->userurb, as->urb->pipe,  				0, ret, COMPLETE, NULL, 0);  		async_removepending(as); -		free_async(as); -		return ret; +		goto error;  	}  	return 0; + + error: +	kfree(isopkt); +	kfree(dr); +	if (as) +		free_async(as); +	return ret;  }  static int proc_submiturb(struct dev_state *ps, void __user *arg) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 45887a0ff87..d40ff956881 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -45,10 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,  	struct usb_dynid *dynid;  	u32 idVendor = 0;  	u32 idProduct = 0; +	unsigned int bInterfaceClass = 0;  	int fields = 0;  	int retval = 0; -	fields = sscanf(buf, "%x %x", &idVendor, &idProduct); +	fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct, +					&bInterfaceClass);  	if (fields < 2)  		return -EINVAL; @@ -60,6 +62,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,  	dynid->id.idVendor = idVendor;  	dynid->id.idProduct = idProduct;  	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; +	if (fields == 3) { +		dynid->id.bInterfaceClass = (u8)bInterfaceClass; +		dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; +	}  	spin_lock(&dynids->lock);  	list_add_tail(&dynid->node, &dynids->list); @@ -1073,17 +1079,10 @@ static int usb_suspend_interface(struct usb_device *udev,  		goto done;  	driver = to_usb_driver(intf->dev.driver); -	if (driver->suspend) { -		status = driver->suspend(intf, msg); -		if (status && !PMSG_IS_AUTO(msg)) -			dev_err(&intf->dev, "%s error %d\n", -					"suspend", status); -	} else { -		/* Later we will unbind the driver and reprobe */ -		intf->needs_binding = 1; -		dev_warn(&intf->dev, "no %s for driver %s?\n", -				"suspend", driver->name); -	} +	/* at this time we know the driver supports suspend */ +	status = driver->suspend(intf, msg); +	if (status && !PMSG_IS_AUTO(msg)) +		dev_err(&intf->dev, "suspend error %d\n", status);   done:  	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); @@ -1132,16 +1131,9 @@ static int usb_resume_interface(struct usb_device *udev,  					"reset_resume", driver->name);  		}  	} else { -		if (driver->resume) { -			status = driver->resume(intf); -			if (status) -				dev_err(&intf->dev, "%s error %d\n", -						"resume", status); -		} else { -			intf->needs_binding = 1; -			dev_warn(&intf->dev, "no %s for driver %s?\n", -					"resume", driver->name); -		} +		status = driver->resume(intf); +		if (status) +			dev_err(&intf->dev, "resume error %d\n", status);  	}  done: diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index a004db35f6d..d136b8f4c8a 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -453,10 +453,6 @@ static int resume_common(struct device *dev, int event)  	pci_set_master(pci_dev); -	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); -	if (hcd->shared_hcd) -		clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags); -  	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {  		if (event != PM_EVENT_AUTO_RESUME)  			wait_for_companions(pci_dev, hcd); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 13222d352a6..eb19cba34ac 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -658,7 +658,7 @@ error:  				len > offsetof(struct usb_device_descriptor,  						bDeviceProtocol))  			((struct usb_device_descriptor *) ubuf)-> -					bDeviceProtocol = 1; +				bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT;  	}  	/* any errors get returned through the urb completion */ @@ -1168,20 +1168,6 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,  	if (urb->unlinked)  		return -EBUSY;  	urb->unlinked = status; - -	/* IRQ setup can easily be broken so that USB controllers -	 * never get completion IRQs ... maybe even the ones we need to -	 * finish unlinking the initial failed usb_set_address() -	 * or device descriptor fetch. -	 */ -	if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) { -		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  " -			"Controller is probably using the wrong IRQ.\n"); -		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); -		if (hcd->shared_hcd) -			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags); -	} -  	return 0;  }  EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb); @@ -1412,11 +1398,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,  					ret = -EAGAIN;  				else  					urb->transfer_flags |= URB_DMA_MAP_SG; -				if (n != urb->num_sgs) { -					urb->num_sgs = n; +				urb->num_mapped_sgs = n; +				if (n != urb->num_sgs)  					urb->transfer_flags |=  							URB_DMA_SG_COMBINED; -				}  			} else if (urb->sg) {  				struct scatterlist *sg = urb->sg;  				urb->transfer_dma = dma_map_page( @@ -2148,16 +2133,12 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)  	 */  	local_irq_save(flags); -	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) { +	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))  		rc = IRQ_NONE; -	} else if (hcd->driver->irq(hcd) == IRQ_NONE) { +	else if (hcd->driver->irq(hcd) == IRQ_NONE)  		rc = IRQ_NONE; -	} else { -		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); -		if (hcd->shared_hcd) -			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags); +	else  		rc = IRQ_HANDLED; -	}  	local_irq_restore(flags);  	return rc; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 79781461eec..79d339e2e70 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -84,7 +84,7 @@ struct usb_hub {  static inline int hub_is_superspeed(struct usb_device *hdev)  { -	return (hdev->descriptor.bDeviceProtocol == 3); +	return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);  }  /* Protect struct usb_device->state and ->children members @@ -1041,58 +1041,58 @@ static int hub_configure(struct usb_hub *hub,  		dev_dbg(hub_dev, "standalone hub\n");  	switch (wHubCharacteristics & HUB_CHAR_LPSM) { -		case 0x00: -			dev_dbg(hub_dev, "ganged power switching\n"); -			break; -		case 0x01: -			dev_dbg(hub_dev, "individual port power switching\n"); -			break; -		case 0x02: -		case 0x03: -			dev_dbg(hub_dev, "no power switching (usb 1.0)\n"); -			break; +	case HUB_CHAR_COMMON_LPSM: +		dev_dbg(hub_dev, "ganged power switching\n"); +		break; +	case HUB_CHAR_INDV_PORT_LPSM: +		dev_dbg(hub_dev, "individual port power switching\n"); +		break; +	case HUB_CHAR_NO_LPSM: +	case HUB_CHAR_LPSM: +		dev_dbg(hub_dev, "no power switching (usb 1.0)\n"); +		break;  	}  	switch (wHubCharacteristics & HUB_CHAR_OCPM) { -		case 0x00: -			dev_dbg(hub_dev, "global over-current protection\n"); -			break; -		case 0x08: -			dev_dbg(hub_dev, "individual port over-current protection\n"); -			break; -		case 0x10: -		case 0x18: -			dev_dbg(hub_dev, "no over-current protection\n"); -                        break; +	case HUB_CHAR_COMMON_OCPM: +		dev_dbg(hub_dev, "global over-current protection\n"); +		break; +	case HUB_CHAR_INDV_PORT_OCPM: +		dev_dbg(hub_dev, "individual port over-current protection\n"); +		break; +	case HUB_CHAR_NO_OCPM: +	case HUB_CHAR_OCPM: +		dev_dbg(hub_dev, "no over-current protection\n"); +		break;  	}  	spin_lock_init (&hub->tt.lock);  	INIT_LIST_HEAD (&hub->tt.clear_list);  	INIT_WORK(&hub->tt.clear_work, hub_tt_work);  	switch (hdev->descriptor.bDeviceProtocol) { -		case 0: -			break; -		case 1: -			dev_dbg(hub_dev, "Single TT\n"); -			hub->tt.hub = hdev; -			break; -		case 2: -			ret = usb_set_interface(hdev, 0, 1); -			if (ret == 0) { -				dev_dbg(hub_dev, "TT per port\n"); -				hub->tt.multi = 1; -			} else -				dev_err(hub_dev, "Using single TT (err %d)\n", -					ret); -			hub->tt.hub = hdev; -			break; -		case 3: -			/* USB 3.0 hubs don't have a TT */ -			break; -		default: -			dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", -				hdev->descriptor.bDeviceProtocol); -			break; +	case USB_HUB_PR_FS: +		break; +	case USB_HUB_PR_HS_SINGLE_TT: +		dev_dbg(hub_dev, "Single TT\n"); +		hub->tt.hub = hdev; +		break; +	case USB_HUB_PR_HS_MULTI_TT: +		ret = usb_set_interface(hdev, 0, 1); +		if (ret == 0) { +			dev_dbg(hub_dev, "TT per port\n"); +			hub->tt.multi = 1; +		} else +			dev_err(hub_dev, "Using single TT (err %d)\n", +				ret); +		hub->tt.hub = hdev; +		break; +	case USB_HUB_PR_SS: +		/* USB 3.0 hubs don't have a TT */ +		break; +	default: +		dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", +			hdev->descriptor.bDeviceProtocol); +		break;  	}  	/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ @@ -1360,7 +1360,6 @@ descriptor_error:  	return -ENODEV;  } -/* No BKL needed */  static int  hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)  { diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index ecf12e15a7e..4c65eb6a867 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -117,9 +117,12 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x06a3, 0x0006), .driver_info =  			USB_QUIRK_CONFIG_INTF_STRINGS }, -	/* Guillemot Webcam Hercules Dualpix Exchange*/ +	/* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */  	{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Guillemot Webcam Hercules Dualpix Exchange*/ +	{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* M-Systems Flash Disk Pioneers */  	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 3888778582c..45e8479c377 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -132,20 +132,6 @@ static inline int is_usb_device_driver(struct device_driver *drv)  			for_devices;  } -/* translate USB error codes to codes user space understands */ -static inline int usb_translate_errors(int error_code) -{ -	switch (error_code) { -	case 0: -	case -ENOMEM: -	case -ENODEV: -		return error_code; -	default: -		return -EIO; -	} -} - -  /* for labeling diagnostics */  extern const char *usbcore_name;  |