diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/buffer.c | 3 | ||||
| -rw-r--r-- | drivers/usb/core/devio.c | 11 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 40 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 16 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 10 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 48 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 1 | 
7 files changed, 74 insertions, 55 deletions
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 2741566ee4f2..98e39f91723a 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -122,6 +122,9 @@ void *hcd_buffer_alloc(  	struct usb_hcd		*hcd = bus_to_hcd(bus);  	int			i; +	if (size == 0) +		return NULL; +  	/* some USB hosts just use PIO */  	if (!IS_ENABLED(CONFIG_HAS_DMA) ||  	    (!bus->controller->dma_mask && diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 52c4461dfccd..e9f5043a2167 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -216,7 +216,7 @@ static void usbdev_vm_close(struct vm_area_struct *vma)  	dec_usb_memory_use_count(usbm, &usbm->vma_use_count);  } -struct vm_operations_struct usbdev_vm_ops = { +static struct vm_operations_struct usbdev_vm_ops = {  	.open = usbdev_vm_open,  	.close = usbdev_vm_close  }; @@ -1316,10 +1316,11 @@ static int proc_getdriver(struct usb_dev_state *ps, void __user *arg)  static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg)  { -	struct usbdevfs_connectinfo ci = { -		.devnum = ps->dev->devnum, -		.slow = ps->dev->speed == USB_SPEED_LOW -	}; +	struct usbdevfs_connectinfo ci; + +	memset(&ci, 0, sizeof(ci)); +	ci.devnum = ps->dev->devnum; +	ci.slow = ps->dev->speed == USB_SPEED_LOW;  	if (copy_to_user(arg, &ci, sizeof(ci)))  		return -EFAULT; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2057d91d8336..dadd1e8dfe09 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -284,7 +284,7 @@ static int usb_probe_interface(struct device *dev)  	struct usb_device *udev = interface_to_usbdev(intf);  	const struct usb_device_id *id;  	int error = -ENODEV; -	int lpm_disable_error; +	int lpm_disable_error = -ENODEV;  	dev_dbg(dev, "%s\n", __func__); @@ -336,12 +336,14 @@ static int usb_probe_interface(struct device *dev)  	 * setting during probe, that should also be fine.  usb_set_interface()  	 * will attempt to disable LPM, and fail if it can't disable it.  	 */ -	lpm_disable_error = usb_unlocked_disable_lpm(udev); -	if (lpm_disable_error && driver->disable_hub_initiated_lpm) { -		dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.", -				__func__, driver->name); -		error = lpm_disable_error; -		goto err; +	if (driver->disable_hub_initiated_lpm) { +		lpm_disable_error = usb_unlocked_disable_lpm(udev); +		if (lpm_disable_error) { +			dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.", +					__func__, driver->name); +			error = lpm_disable_error; +			goto err; +		}  	}  	/* Carry out a deferred switch to altsetting 0 */ @@ -391,7 +393,8 @@ static int usb_unbind_interface(struct device *dev)  	struct usb_interface *intf = to_usb_interface(dev);  	struct usb_host_endpoint *ep, **eps = NULL;  	struct usb_device *udev; -	int i, j, error, r, lpm_disable_error; +	int i, j, error, r; +	int lpm_disable_error = -ENODEV;  	intf->condition = USB_INTERFACE_UNBINDING; @@ -399,12 +402,13 @@ static int usb_unbind_interface(struct device *dev)  	udev = interface_to_usbdev(intf);  	error = usb_autoresume_device(udev); -	/* Hub-initiated LPM policy may change, so attempt to disable LPM until +	/* If hub-initiated LPM policy may change, attempt to disable LPM until  	 * the driver is unbound.  If LPM isn't disabled, that's fine because it  	 * wouldn't be enabled unless all the bound interfaces supported  	 * hub-initiated LPM.  	 */ -	lpm_disable_error = usb_unlocked_disable_lpm(udev); +	if (driver->disable_hub_initiated_lpm) +		lpm_disable_error = usb_unlocked_disable_lpm(udev);  	/*  	 * Terminate all URBs for this interface unless the driver @@ -505,7 +509,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,  	struct device *dev;  	struct usb_device *udev;  	int retval = 0; -	int lpm_disable_error; +	int lpm_disable_error = -ENODEV;  	if (!iface)  		return -ENODEV; @@ -526,12 +530,14 @@ int usb_driver_claim_interface(struct usb_driver *driver,  	iface->condition = USB_INTERFACE_BOUND; -	/* Disable LPM until this driver is bound. */ -	lpm_disable_error = usb_unlocked_disable_lpm(udev); -	if (lpm_disable_error && driver->disable_hub_initiated_lpm) { -		dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.", -				__func__, driver->name); -		return -ENOMEM; +	/* See the comment about disabling LPM in usb_probe_interface(). */ +	if (driver->disable_hub_initiated_lpm) { +		lpm_disable_error = usb_unlocked_disable_lpm(udev); +		if (lpm_disable_error) { +			dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.", +					__func__, driver->name); +			return -ENOMEM; +		}  	}  	/* Claimed interfaces are initially inactive (suspended) and diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 2ca2cef7f681..34b837ae1ed7 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -994,7 +994,7 @@ static void usb_bus_init (struct usb_bus *bus)  	bus->bandwidth_allocated = 0;  	bus->bandwidth_int_reqs  = 0;  	bus->bandwidth_isoc_reqs = 0; -	mutex_init(&bus->usb_address0_mutex); +	mutex_init(&bus->devnum_next_mutex);  }  /*-------------------------------------------------------------------------*/ @@ -1118,6 +1118,7 @@ static int register_root_hub(struct usb_hcd *hcd)  		/* Did the HC die before the root hub was registered? */  		if (HCD_DEAD(hcd))  			usb_hc_died (hcd);	/* This time clean up */ +		usb_dev->dev.of_node = parent_dev->of_node;  	}  	mutex_unlock(&usb_bus_idr_lock); @@ -2521,6 +2522,14 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,  		return NULL;  	}  	if (primary_hcd == NULL) { +		hcd->address0_mutex = kmalloc(sizeof(*hcd->address0_mutex), +				GFP_KERNEL); +		if (!hcd->address0_mutex) { +			kfree(hcd); +			dev_dbg(dev, "hcd address0 mutex alloc failed\n"); +			return NULL; +		} +		mutex_init(hcd->address0_mutex);  		hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),  				GFP_KERNEL);  		if (!hcd->bandwidth_mutex) { @@ -2532,6 +2541,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,  		dev_set_drvdata(dev, hcd);  	} else {  		mutex_lock(&usb_port_peer_mutex); +		hcd->address0_mutex = primary_hcd->address0_mutex;  		hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;  		hcd->primary_hcd = primary_hcd;  		primary_hcd->primary_hcd = primary_hcd; @@ -2598,8 +2608,10 @@ static void hcd_release(struct kref *kref)  	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);  	mutex_lock(&usb_port_peer_mutex); -	if (usb_hcd_is_primary_hcd(hcd)) +	if (usb_hcd_is_primary_hcd(hcd)) { +		kfree(hcd->address0_mutex);  		kfree(hcd->bandwidth_mutex); +	}  	if (hcd->shared_hcd) {  		struct usb_hcd *peer = hcd->shared_hcd; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 38cc4bae0a82..bee13517676f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -104,6 +104,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev);  static inline char *portspeed(struct usb_hub *hub, int portstatus)  { +	if (hub_is_superspeedplus(hub->hdev)) +		return "10.0 Gb/s";  	if (hub_is_superspeed(hub->hdev))  		return "5.0 Gb/s";  	if (portstatus & USB_PORT_STAT_HIGH_SPEED) @@ -2080,7 +2082,7 @@ static void choose_devnum(struct usb_device *udev)  	struct usb_bus	*bus = udev->bus;  	/* be safe when more hub events are proceed in parallel */ -	mutex_lock(&bus->usb_address0_mutex); +	mutex_lock(&bus->devnum_next_mutex);  	if (udev->wusb) {  		devnum = udev->portnum + 1;  		BUG_ON(test_bit(devnum, bus->devmap.devicemap)); @@ -2098,7 +2100,7 @@ static void choose_devnum(struct usb_device *udev)  		set_bit(devnum, bus->devmap.devicemap);  		udev->devnum = devnum;  	} -	mutex_unlock(&bus->usb_address0_mutex); +	mutex_unlock(&bus->devnum_next_mutex);  }  static void release_devnum(struct usb_device *udev) @@ -4364,7 +4366,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,  	if (oldspeed == USB_SPEED_LOW)  		delay = HUB_LONG_RESET_TIME; -	mutex_lock(&hdev->bus->usb_address0_mutex); +	mutex_lock(hcd->address0_mutex);  	/* Reset the device; full speed may morph to high speed */  	/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ @@ -4650,7 +4652,7 @@ fail:  		hub_port_disable(hub, port1, 0);  		update_devnum(udev, devnum);	/* for disconnect processing */  	} -	mutex_unlock(&hdev->bus->usb_address0_mutex); +	mutex_unlock(hcd->address0_mutex);  	return retval;  } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 8e641b5893ed..ea681f157368 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -302,9 +302,10 @@ static void sg_complete(struct urb *urb)  		 */  		spin_unlock(&io->lock);  		for (i = 0, found = 0; i < io->entries; i++) { -			if (!io->urbs[i] || !io->urbs[i]->dev) +			if (!io->urbs[i])  				continue;  			if (found) { +				usb_block_urb(io->urbs[i]);  				retval = usb_unlink_urb(io->urbs[i]);  				if (retval != -EINPROGRESS &&  				    retval != -ENODEV && @@ -515,12 +516,10 @@ void usb_sg_wait(struct usb_sg_request *io)  		int retval;  		io->urbs[i]->dev = io->dev; -		retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); - -		/* after we submit, let completions or cancellations fire; -		 * we handshake using io->status. -		 */  		spin_unlock_irq(&io->lock); + +		retval = usb_submit_urb(io->urbs[i], GFP_NOIO); +  		switch (retval) {  			/* maybe we retrying will recover */  		case -ENXIO:	/* hc didn't queue this one */ @@ -578,31 +577,28 @@ EXPORT_SYMBOL_GPL(usb_sg_wait);  void usb_sg_cancel(struct usb_sg_request *io)  {  	unsigned long flags; +	int i, retval;  	spin_lock_irqsave(&io->lock, flags); +	if (io->status) { +		spin_unlock_irqrestore(&io->lock, flags); +		return; +	} +	/* shut everything down */ +	io->status = -ECONNRESET; +	spin_unlock_irqrestore(&io->lock, flags); -	/* shut everything down, if it didn't already */ -	if (!io->status) { -		int i; - -		io->status = -ECONNRESET; -		spin_unlock(&io->lock); -		for (i = 0; i < io->entries; i++) { -			int retval; +	for (i = io->entries - 1; i >= 0; --i) { +		usb_block_urb(io->urbs[i]); -			if (!io->urbs[i]->dev) -				continue; -			retval = usb_unlink_urb(io->urbs[i]); -			if (retval != -EINPROGRESS -					&& retval != -ENODEV -					&& retval != -EBUSY -					&& retval != -EIDRM) -				dev_warn(&io->dev->dev, "%s, unlink --> %d\n", -					__func__, retval); -		} -		spin_lock(&io->lock); +		retval = usb_unlink_urb(io->urbs[i]); +		if (retval != -EINPROGRESS +		    && retval != -ENODEV +		    && retval != -EBUSY +		    && retval != -EIDRM) +			dev_warn(&io->dev->dev, "%s, unlink --> %d\n", +				 __func__, retval);  	} -	spin_unlock_irqrestore(&io->lock, flags);  }  EXPORT_SYMBOL_GPL(usb_sg_cancel); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 479187c32571..5e80697ef952 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -466,7 +466,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,  		dev->route = 0;  		dev->dev.parent = bus->controller; -		dev->dev.of_node = bus->controller->of_node;  		dev_set_name(&dev->dev, "usb%d", bus->busnum);  		root_hub = 1;  	} else {  | 
