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

Commit bfb0e9b4 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files
I wrote:
  "USB fixes for 4.19-rc6

   Here are some small USB core and driver fixes for reported issues for
   4.19-rc6.

   The most visible is the oops fix for when the USB core is built into the
   kernel that is present in 4.18.  Turns out not many people actually do
   that so it went unnoticed for a while.  The rest is some tiny typec,
   musb, and other core fixes.

   All have been in linux-next with no reported issues."

* tag 'usb-4.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: mux: Take care of driver module reference counting
  usb: core: safely deal with the dynamic quirk lists
  usb: roles: Take care of driver module reference counting
  USB: handle NULL config in usb_find_alt_setting()
  USB: fix error handling in usb_driver_claim_interface()
  USB: remove LPM management from usb_driver_claim_interface()
  USB: usbdevfs: restore warning for nonsensical flags
  USB: usbdevfs: sanitize flags more
  Revert "usb: cdc-wdm: Fix a sleep-in-atomic-context bug in service_outstanding_interrupt()"
  usb: musb: dsps: do not disable CPPI41 irq in driver teardown
parents ccf791e5 3e3b8196
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -460,7 +460,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)

	set_bit(WDM_RESPONDING, &desc->flags);
	spin_unlock_irq(&desc->iuspin);
	rv = usb_submit_urb(desc->response, GFP_ATOMIC);
	rv = usb_submit_urb(desc->response, GFP_KERNEL);
	spin_lock_irq(&desc->iuspin);
	if (rv) {
		dev_err(&desc->intf->dev,
+12 −3
Original line number Diff line number Diff line
@@ -109,8 +109,15 @@ static void *usb_role_switch_match(struct device_connection *con, int ep,
 */
struct usb_role_switch *usb_role_switch_get(struct device *dev)
{
	return device_connection_find_match(dev, "usb-role-switch", NULL,
	struct usb_role_switch *sw;

	sw = device_connection_find_match(dev, "usb-role-switch", NULL,
					  usb_role_switch_match);

	if (!IS_ERR_OR_NULL(sw))
		WARN_ON(!try_module_get(sw->dev.parent->driver->owner));

	return sw;
}
EXPORT_SYMBOL_GPL(usb_role_switch_get);

@@ -122,8 +129,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_get);
 */
void usb_role_switch_put(struct usb_role_switch *sw)
{
	if (!IS_ERR_OR_NULL(sw))
	if (!IS_ERR_OR_NULL(sw)) {
		put_device(&sw->dev);
		module_put(sw->dev.parent->driver->owner);
	}
}
EXPORT_SYMBOL_GPL(usb_role_switch_put);

+21 −3
Original line number Diff line number Diff line
@@ -1434,10 +1434,13 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
	struct async *as = NULL;
	struct usb_ctrlrequest *dr = NULL;
	unsigned int u, totlen, isofrmlen;
	int i, ret, is_in, num_sgs = 0, ifnum = -1;
	int i, ret, num_sgs = 0, ifnum = -1;
	int number_of_packets = 0;
	unsigned int stream_id = 0;
	void *buf;
	bool is_in;
	bool allow_short = false;
	bool allow_zero = false;
	unsigned long mask =	USBDEVFS_URB_SHORT_NOT_OK |
				USBDEVFS_URB_BULK_CONTINUATION |
				USBDEVFS_URB_NO_FSBR |
@@ -1471,6 +1474,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
	u = 0;
	switch (uurb->type) {
	case USBDEVFS_URB_TYPE_CONTROL:
		if (is_in)
			allow_short = true;
		if (!usb_endpoint_xfer_control(&ep->desc))
			return -EINVAL;
		/* min 8 byte setup packet */
@@ -1511,6 +1516,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
		break;

	case USBDEVFS_URB_TYPE_BULK:
		if (!is_in)
			allow_zero = true;
		else
			allow_short = true;
		switch (usb_endpoint_type(&ep->desc)) {
		case USB_ENDPOINT_XFER_CONTROL:
		case USB_ENDPOINT_XFER_ISOC:
@@ -1531,6 +1540,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
		if (!usb_endpoint_xfer_int(&ep->desc))
			return -EINVAL;
 interrupt_urb:
		if (!is_in)
			allow_zero = true;
		else
			allow_short = true;
		break;

	case USBDEVFS_URB_TYPE_ISO:
@@ -1676,14 +1689,19 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
	u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
	if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
		u |= URB_ISO_ASAP;
	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in)
	if (allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
		u |= URB_SHORT_NOT_OK;
	if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
	if (allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET)
		u |= URB_ZERO_PACKET;
	if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
		u |= URB_NO_INTERRUPT;
	as->urb->transfer_flags = u;

	if (!allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
		dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_SHORT_NOT_OK.\n");
	if (!allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET)
		dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_ZERO_PACKET.\n");

	as->urb->transfer_buffer_length = uurb->buffer_length;
	as->urb->setup_packet = (unsigned char *)dr;
	dr = NULL;
+14 −14
Original line number Diff line number Diff line
@@ -512,7 +512,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
	struct device *dev;
	struct usb_device *udev;
	int retval = 0;
	int lpm_disable_error = -ENODEV;

	if (!iface)
		return -ENODEV;
@@ -533,16 +532,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,

	iface->condition = USB_INTERFACE_BOUND;

	/* 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
	 * runtime-PM-enabled, but only if the driver has autosuspend
	 * support.  Otherwise they are marked active, to prevent the
@@ -561,9 +550,20 @@ int usb_driver_claim_interface(struct usb_driver *driver,
	if (device_is_registered(dev))
		retval = device_bind_driver(dev);

	/* Attempt to re-enable USB3 LPM, if the disable was successful. */
	if (!lpm_disable_error)
		usb_unlocked_enable_lpm(udev);
	if (retval) {
		dev->driver = NULL;
		usb_set_intfdata(iface, NULL);
		iface->needs_remote_wakeup = 0;
		iface->condition = USB_INTERFACE_UNBOUND;

		/*
		 * Unbound interfaces are always runtime-PM-disabled
		 * and runtime-PM-suspended
		 */
		if (driver->supports_autosuspend)
			pm_runtime_disable(dev);
		pm_runtime_set_suspended(dev);
	}

	return retval;
}
+2 −1
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ static int quirks_param_set(const char *val, const struct kernel_param *kp)
	quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
			     GFP_KERNEL);
	if (!quirk_list) {
		quirk_count = 0;
		mutex_unlock(&quirk_mutex);
		return -ENOMEM;
	}
@@ -154,7 +155,7 @@ static struct kparam_string quirks_param_string = {
	.string = quirks_param,
};

module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
device_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks");

/* Lists of quirky USB devices, split in device quirks and interface quirks.
Loading