Commit e4c26faa authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB/Thunderbolt fixes from Greg KH:
 "Here are some small USB and Thunderbolt driver fixes for 5.9-rc5.

  Nothing huge, just a number of bugfixes and new device ids for
  problems reported:

   - new USB serial driver ids

   - bug fixes for syzbot reported problems

   - typec driver fixes

   - thunderbolt driver fixes

   - revert of reported broken commit

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

* tag 'usb-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: intel_pmc_mux: Do not configure SBU and HSL Orientation in Alternate modes
  usb: typec: intel_pmc_mux: Do not configure Altmode HPD High
  usb: core: fix slab-out-of-bounds Read in read_descriptors
  Revert "usb: dwc3: meson-g12a: fix shared reset control use"
  usb: typec: ucsi: acpi: Check the _DEP dependencies
  usb: typec: intel_pmc_mux: Un-register the USB role switch
  usb: Fix out of sync data toggle if a configured device is reconfigured
  USB: serial: option: support dynamic Quectel USB compositions
  USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules
  thunderbolt: Use maximum USB3 link rate when reclaiming if link is not up
  thunderbolt: Disable ports that are not implemented
  USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
parents 6c7247f6 a29c0adb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -684,6 +684,7 @@ static int tb_init_port(struct tb_port *port)
		if (res == -ENODEV) {
			tb_dbg(port->sw->tb, " Port %d: not implemented\n",
			       port->port);
			port->disabled = true;
			return 0;
		}
		return res;
+1 −1
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ struct tb_switch {
 * @cap_adap: Offset of the adapter specific capability (%0 if not present)
 * @cap_usb4: Offset to the USB4 port capability (%0 if not present)
 * @port: Port number on switch
 * @disabled: Disabled by eeprom
 * @disabled: Disabled by eeprom or enabled but not implemented
 * @bonded: true if the port is bonded (two lanes combined as one)
 * @dual_link_port: If the switch is connected using two ports, points
 *		    to the other port.
+10 −2
Original line number Diff line number Diff line
@@ -951,10 +951,18 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
	int ret, max_rate, allocate_up, allocate_down;

	ret = usb4_usb3_port_actual_link_rate(tunnel->src_port);
	if (ret <= 0) {
		tb_tunnel_warn(tunnel, "tunnel is not up\n");
	if (ret < 0) {
		tb_tunnel_warn(tunnel, "failed to read actual link rate\n");
		return;
	} else if (!ret) {
		/* Use maximum link rate if the link valid is not set */
		ret = usb4_usb3_port_max_link_rate(tunnel->src_port);
		if (ret < 0) {
			tb_tunnel_warn(tunnel, "failed to read maximum link rate\n");
			return;
		}
	}

	/*
	 * 90% of the max rate can be allocated for isochronous
	 * transfers.
+42 −49
Original line number Diff line number Diff line
@@ -1205,6 +1205,34 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
	}
}

/*
 * usb_disable_device_endpoints -- Disable all endpoints for a device
 * @dev: the device whose endpoints are being disabled
 * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
 */
static void usb_disable_device_endpoints(struct usb_device *dev, int skip_ep0)
{
	struct usb_hcd *hcd = bus_to_hcd(dev->bus);
	int i;

	if (hcd->driver->check_bandwidth) {
		/* First pass: Cancel URBs, leave endpoint pointers intact. */
		for (i = skip_ep0; i < 16; ++i) {
			usb_disable_endpoint(dev, i, false);
			usb_disable_endpoint(dev, i + USB_DIR_IN, false);
		}
		/* Remove endpoints from the host controller internal state */
		mutex_lock(hcd->bandwidth_mutex);
		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
		mutex_unlock(hcd->bandwidth_mutex);
	}
	/* Second pass: remove endpoint pointers */
	for (i = skip_ep0; i < 16; ++i) {
		usb_disable_endpoint(dev, i, true);
		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
	}
}

/**
 * usb_disable_device - Disable all the endpoints for a USB device
 * @dev: the device whose endpoints are being disabled
@@ -1218,7 +1246,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
	int i;
	struct usb_hcd *hcd = bus_to_hcd(dev->bus);

	/* getting rid of interfaces will disconnect
	 * any drivers bound to them (a key side effect)
@@ -1264,22 +1291,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)

	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
		skip_ep0 ? "non-ep0" : "all");
	if (hcd->driver->check_bandwidth) {
		/* First pass: Cancel URBs, leave endpoint pointers intact. */
		for (i = skip_ep0; i < 16; ++i) {
			usb_disable_endpoint(dev, i, false);
			usb_disable_endpoint(dev, i + USB_DIR_IN, false);
		}
		/* Remove endpoints from the host controller internal state */
		mutex_lock(hcd->bandwidth_mutex);
		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
		mutex_unlock(hcd->bandwidth_mutex);
		/* Second pass: remove endpoint pointers */
	}
	for (i = skip_ep0; i < 16; ++i) {
		usb_disable_endpoint(dev, i, true);
		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
	}

	usb_disable_device_endpoints(dev, skip_ep0);
}

/**
@@ -1522,6 +1535,9 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
 * The caller must own the device lock.
 *
 * Return: Zero on success, else a negative error code.
 *
 * If this routine fails the device will probably be in an unusable state
 * with endpoints disabled, and interfaces only partially enabled.
 */
int usb_reset_configuration(struct usb_device *dev)
{
@@ -1537,10 +1553,7 @@ int usb_reset_configuration(struct usb_device *dev)
	 * calls during probe() are fine
	 */

	for (i = 1; i < 16; ++i) {
		usb_disable_endpoint(dev, i, true);
		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
	}
	usb_disable_device_endpoints(dev, 1); /* skip ep0*/

	config = dev->actconfig;
	retval = 0;
@@ -1553,34 +1566,10 @@ int usb_reset_configuration(struct usb_device *dev)
		mutex_unlock(hcd->bandwidth_mutex);
		return -ENOMEM;
	}
	/* Make sure we have enough bandwidth for each alternate setting 0 */
	for (i = 0; i < config->desc.bNumInterfaces; i++) {
		struct usb_interface *intf = config->interface[i];
		struct usb_host_interface *alt;

		alt = usb_altnum_to_altsetting(intf, 0);
		if (!alt)
			alt = &intf->altsetting[0];
		if (alt != intf->cur_altsetting)
			retval = usb_hcd_alloc_bandwidth(dev, NULL,
					intf->cur_altsetting, alt);
		if (retval < 0)
			break;
	}
	/* If not, reinstate the old alternate settings */
	/* xHCI adds all endpoints in usb_hcd_alloc_bandwidth */
	retval = usb_hcd_alloc_bandwidth(dev, config, NULL, NULL);
	if (retval < 0) {
reset_old_alts:
		for (i--; i >= 0; i--) {
			struct usb_interface *intf = config->interface[i];
			struct usb_host_interface *alt;

			alt = usb_altnum_to_altsetting(intf, 0);
			if (!alt)
				alt = &intf->altsetting[0];
			if (alt != intf->cur_altsetting)
				usb_hcd_alloc_bandwidth(dev, NULL,
						alt, intf->cur_altsetting);
		}
		usb_enable_lpm(dev);
		mutex_unlock(hcd->bandwidth_mutex);
		return retval;
@@ -1589,8 +1578,12 @@ reset_old_alts:
			USB_REQ_SET_CONFIGURATION, 0,
			config->desc.bConfigurationValue, 0,
			NULL, 0, USB_CTRL_SET_TIMEOUT);
	if (retval < 0)
		goto reset_old_alts;
	if (retval < 0) {
		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
		usb_enable_lpm(dev);
		mutex_unlock(hcd->bandwidth_mutex);
		return retval;
	}
	mutex_unlock(hcd->bandwidth_mutex);

	/* re-init hc/hcd interface/endpoint state */
+5 −0
Original line number Diff line number Diff line
@@ -889,7 +889,11 @@ read_descriptors(struct file *filp, struct kobject *kobj,
	size_t srclen, n;
	int cfgno;
	void *src;
	int retval;

	retval = usb_lock_device_interruptible(udev);
	if (retval < 0)
		return -EINTR;
	/* The binary attribute begins with the device descriptor.
	 * Following that are the raw descriptor entries for all the
	 * configurations (config plus subsidiary descriptors).
@@ -914,6 +918,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
			off -= srclen;
		}
	}
	usb_unlock_device(udev);
	return count - nleft;
}

Loading