Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf3bd966 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB fixes from Greg KH:
 "Here are some small USB fixes for a bunch of warnings/errors that the
  syzbot has been finding with it's new-found ability to stress-test the
  USB layer.

  All of these are tiny, but fix real issues, and are marked for stable
  as well. All of these have had lots of testing in linux-next as well"

* tag 'usb-5.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: w1 ds2490: Fix bug caused by improper use of altsetting array
  USB: yurex: Fix protection fault after device removal
  usb: usbip: fix isoc packet num validation in get_pipe
  USB: core: Fix bug caused by duplicate interface PM usage counter
  USB: dummy-hcd: Fix failure to give back unlinked URBs
  USB: core: Fix unterminated string returned by usb_string()
parents fea27bc7 c114944d
Loading
Loading
Loading
Loading
+9 −5
Original line number Original line Diff line number Diff line
@@ -370,11 +370,15 @@ autosuspend the interface's device. When the usage counter is = 0
then the interface is considered to be idle, and the kernel may
then the interface is considered to be idle, and the kernel may
autosuspend the device.
autosuspend the device.


Drivers need not be concerned about balancing changes to the usage
Drivers must be careful to balance their overall changes to the usage
counter; the USB core will undo any remaining "get"s when a driver
counter.  Unbalanced "get"s will remain in effect when a driver is
is unbound from its interface.  As a corollary, drivers must not call
unbound from its interface, preventing the device from going into
any of the ``usb_autopm_*`` functions after their ``disconnect``
runtime suspend should the interface be bound to a driver again.  On
routine has returned.
the other hand, drivers are allowed to achieve this balance by calling
the ``usb_autopm_*`` functions even after their ``disconnect`` routine
has returned -- say from within a work-queue routine -- provided they
retain an active reference to the interface (via ``usb_get_intf`` and
``usb_put_intf``).


Drivers using the async routines are responsible for their own
Drivers using the async routines are responsible for their own
synchronization and mutual exclusion.
synchronization and mutual exclusion.
+0 −13
Original line number Original line Diff line number Diff line
@@ -473,11 +473,6 @@ static int usb_unbind_interface(struct device *dev)
		pm_runtime_disable(dev);
		pm_runtime_disable(dev);
	pm_runtime_set_suspended(dev);
	pm_runtime_set_suspended(dev);


	/* Undo any residual pm_autopm_get_interface_* calls */
	for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r)
		usb_autopm_put_interface_no_suspend(intf);
	atomic_set(&intf->pm_usage_cnt, 0);

	if (!error)
	if (!error)
		usb_autosuspend_device(udev);
		usb_autosuspend_device(udev);


@@ -1633,7 +1628,6 @@ void usb_autopm_put_interface(struct usb_interface *intf)
	int			status;
	int			status;


	usb_mark_last_busy(udev);
	usb_mark_last_busy(udev);
	atomic_dec(&intf->pm_usage_cnt);
	status = pm_runtime_put_sync(&intf->dev);
	status = pm_runtime_put_sync(&intf->dev);
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
			__func__, atomic_read(&intf->dev.power.usage_count),
			__func__, atomic_read(&intf->dev.power.usage_count),
@@ -1662,7 +1656,6 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
	int			status;
	int			status;


	usb_mark_last_busy(udev);
	usb_mark_last_busy(udev);
	atomic_dec(&intf->pm_usage_cnt);
	status = pm_runtime_put(&intf->dev);
	status = pm_runtime_put(&intf->dev);
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
			__func__, atomic_read(&intf->dev.power.usage_count),
			__func__, atomic_read(&intf->dev.power.usage_count),
@@ -1684,7 +1677,6 @@ void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
	struct usb_device	*udev = interface_to_usbdev(intf);
	struct usb_device	*udev = interface_to_usbdev(intf);


	usb_mark_last_busy(udev);
	usb_mark_last_busy(udev);
	atomic_dec(&intf->pm_usage_cnt);
	pm_runtime_put_noidle(&intf->dev);
	pm_runtime_put_noidle(&intf->dev);
}
}
EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
@@ -1715,8 +1707,6 @@ int usb_autopm_get_interface(struct usb_interface *intf)
	status = pm_runtime_get_sync(&intf->dev);
	status = pm_runtime_get_sync(&intf->dev);
	if (status < 0)
	if (status < 0)
		pm_runtime_put_sync(&intf->dev);
		pm_runtime_put_sync(&intf->dev);
	else
		atomic_inc(&intf->pm_usage_cnt);
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
			__func__, atomic_read(&intf->dev.power.usage_count),
			__func__, atomic_read(&intf->dev.power.usage_count),
			status);
			status);
@@ -1750,8 +1740,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
	status = pm_runtime_get(&intf->dev);
	status = pm_runtime_get(&intf->dev);
	if (status < 0 && status != -EINPROGRESS)
	if (status < 0 && status != -EINPROGRESS)
		pm_runtime_put_noidle(&intf->dev);
		pm_runtime_put_noidle(&intf->dev);
	else
		atomic_inc(&intf->pm_usage_cnt);
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
			__func__, atomic_read(&intf->dev.power.usage_count),
			__func__, atomic_read(&intf->dev.power.usage_count),
			status);
			status);
@@ -1775,7 +1763,6 @@ void usb_autopm_get_interface_no_resume(struct usb_interface *intf)
	struct usb_device	*udev = interface_to_usbdev(intf);
	struct usb_device	*udev = interface_to_usbdev(intf);


	usb_mark_last_busy(udev);
	usb_mark_last_busy(udev);
	atomic_inc(&intf->pm_usage_cnt);
	pm_runtime_get_noresume(&intf->dev);
	pm_runtime_get_noresume(&intf->dev);
}
}
EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
+3 −1
Original line number Original line Diff line number Diff line
@@ -820,9 +820,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)


	if (dev->state == USB_STATE_SUSPENDED)
	if (dev->state == USB_STATE_SUSPENDED)
		return -EHOSTUNREACH;
		return -EHOSTUNREACH;
	if (size <= 0 || !buf || !index)
	if (size <= 0 || !buf)
		return -EINVAL;
		return -EINVAL;
	buf[0] = 0;
	buf[0] = 0;
	if (index <= 0 || index >= 256)
		return -EINVAL;
	tbuf = kmalloc(256, GFP_NOIO);
	tbuf = kmalloc(256, GFP_NOIO);
	if (!tbuf)
	if (!tbuf)
		return -ENOMEM;
		return -ENOMEM;
+15 −4
Original line number Original line Diff line number Diff line
@@ -979,8 +979,18 @@ static int dummy_udc_start(struct usb_gadget *g,
	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
	struct dummy		*dum = dum_hcd->dum;
	struct dummy		*dum = dum_hcd->dum;


	if (driver->max_speed == USB_SPEED_UNKNOWN)
	switch (g->speed) {
	/* All the speeds we support */
	case USB_SPEED_LOW:
	case USB_SPEED_FULL:
	case USB_SPEED_HIGH:
	case USB_SPEED_SUPER:
		break;
	default:
		dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n",
				driver->max_speed);
		return -EINVAL;
		return -EINVAL;
	}


	/*
	/*
	 * SLAVE side init ... the layer above hardware, which
	 * SLAVE side init ... the layer above hardware, which
@@ -1784,9 +1794,10 @@ static void dummy_timer(struct timer_list *t)
		/* Bus speed is 500000 bytes/ms, so use a little less */
		/* Bus speed is 500000 bytes/ms, so use a little less */
		total = 490000;
		total = 490000;
		break;
		break;
	default:
	default:	/* Can't happen */
		dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
		dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
		return;
		total = 0;
		break;
	}
	}


	/* FIXME if HZ != 1000 this will probably misbehave ... */
	/* FIXME if HZ != 1000 this will probably misbehave ... */
@@ -1828,7 +1839,7 @@ static void dummy_timer(struct timer_list *t)


		/* Used up this frame's bandwidth? */
		/* Used up this frame's bandwidth? */
		if (total <= 0)
		if (total <= 0)
			break;
			continue;


		/* find the gadget's ep for this request (if configured) */
		/* find the gadget's ep for this request (if configured) */
		address = usb_pipeendpoint (urb->pipe);
		address = usb_pipeendpoint (urb->pipe);
+1 −0
Original line number Original line Diff line number Diff line
@@ -314,6 +314,7 @@ static void yurex_disconnect(struct usb_interface *interface)
	usb_deregister_dev(interface, &yurex_class);
	usb_deregister_dev(interface, &yurex_class);


	/* prevent more I/O from starting */
	/* prevent more I/O from starting */
	usb_poison_urb(dev->urb);
	mutex_lock(&dev->io_mutex);
	mutex_lock(&dev->io_mutex);
	dev->interface = NULL;
	dev->interface = NULL;
	mutex_unlock(&dev->io_mutex);
	mutex_unlock(&dev->io_mutex);
Loading