Commit 809be620 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB driver fixes from Greg KH:
 "Here are a bunch of small USB driver fixes for 6.8-rc3. Included in
  here are:

   - new usb-serial driver ids

   - new dwc3 driver id added

   - typec driver change revert

   - ncm gadget driver endian bugfix

   - xhci bugfixes for a number of reported issues

   - usb hub bugfix for alternate settings

   - ulpi driver debugfs memory leak fix

   - chipidea driver bugfix

   - usb gadget driver fixes

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

* tag 'usb-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (24 commits)
  USB: serial: option: add Fibocom FM101-GL variant
  USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
  USB: serial: cp210x: add ID for IMST iM871A-USB
  usb: typec: tcpm: fix the PD disabled case
  usb: ucsi_acpi: Quirk to ack a connector change ack cmd
  usb: ucsi_acpi: Fix command completion handling
  usb: ucsi: Add missing ppm_lock
  usb: ulpi: Fix debugfs directory leak
  Revert "usb: typec: tcpm: fix cc role at port reset"
  usb: gadget: pch_udc: fix an Excess kernel-doc warning
  usb: f_mass_storage: forbid async queue when shutdown happen
  USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
  usb: chipidea: core: handle power lost in workqueue
  usb: dwc3: gadget: Fix NULL pointer dereference in dwc3_gadget_suspend
  usb: dwc3: pci: add support for the Intel Arrow Lake-H
  usb: core: Prevent null pointer dereference in update_port_device_state
  xhci: handle isoc Babble and Buffer Overrun events properly
  xhci: process isoc TD properly when there was a transaction error mid TD.
  xhci: fix off by one check when adding a secondary interrupter.
  xhci: fix possible null pointer dereference at secondary interrupter removal
  ...
parents bdda52cc ad834c7c
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -448,7 +448,7 @@ Function-specific configfs interface
The function name to use when creating the function directory is "ncm".
The NCM function provides these attributes in its function directory:

	===============   ==================================================
	======================= ==================================================
	ifname			network device interface name associated with this
				function instance
	qmult			queue length multiplier for high and super speed
@@ -457,8 +457,8 @@ The NCM function provides these attributes in its function directory:
	dev_addr		MAC address of device's end of this
				Ethernet over USB link
	max_segment_size	Segment size required for P2P connections. This
			  will set MTU to (max_segment_size - 14 bytes)
	===============   ==================================================
				will set MTU to 14 bytes
	======================= ==================================================

and after creating the functions/ncm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
+2 −0
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ struct hw_bank {
 * @enabled_otg_timer_bits: bits of enabled otg timers
 * @next_otg_timer: next nearest enabled timer to be expired
 * @work: work for role changing
 * @power_lost_work: work for power lost handling
 * @wq: workqueue thread
 * @qh_pool: allocation pool for queue heads
 * @td_pool: allocation pool for transfer descriptors
@@ -226,6 +227,7 @@ struct ci_hdrc {
	enum otg_fsm_timer		next_otg_timer;
	struct usb_role_switch		*role_switch;
	struct work_struct		work;
	struct work_struct		power_lost_work;
	struct workqueue_struct		*wq;

	struct dma_pool			*qh_pool;
+24 −20
Original line number Diff line number Diff line
@@ -856,6 +856,27 @@ static int ci_extcon_register(struct ci_hdrc *ci)
	return 0;
}

static void ci_power_lost_work(struct work_struct *work)
{
	struct ci_hdrc *ci = container_of(work, struct ci_hdrc, power_lost_work);
	enum ci_role role;

	disable_irq_nosync(ci->irq);
	pm_runtime_get_sync(ci->dev);
	if (!ci_otg_is_fsm_mode(ci)) {
		role = ci_get_role(ci);

		if (ci->role != role) {
			ci_handle_id_switch(ci);
		} else if (role == CI_ROLE_GADGET) {
			if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV))
				usb_gadget_vbus_connect(&ci->gadget);
		}
	}
	pm_runtime_put_sync(ci->dev);
	enable_irq(ci->irq);
}

static DEFINE_IDA(ci_ida);

struct platform_device *ci_hdrc_add_device(struct device *dev,
@@ -1045,6 +1066,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)

	spin_lock_init(&ci->lock);
	mutex_init(&ci->mutex);
	INIT_WORK(&ci->power_lost_work, ci_power_lost_work);

	ci->dev = dev;
	ci->platdata = dev_get_platdata(dev);
	ci->imx28_write_fix = !!(ci->platdata->flags &
@@ -1396,25 +1419,6 @@ static int ci_suspend(struct device *dev)
	return 0;
}

static void ci_handle_power_lost(struct ci_hdrc *ci)
{
	enum ci_role role;

	disable_irq_nosync(ci->irq);
	if (!ci_otg_is_fsm_mode(ci)) {
		role = ci_get_role(ci);

		if (ci->role != role) {
			ci_handle_id_switch(ci);
		} else if (role == CI_ROLE_GADGET) {
			if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV))
				usb_gadget_vbus_connect(&ci->gadget);
		}
	}

	enable_irq(ci->irq);
}

static int ci_resume(struct device *dev)
{
	struct ci_hdrc *ci = dev_get_drvdata(dev);
@@ -1446,7 +1450,7 @@ static int ci_resume(struct device *dev)
		ci_role(ci)->resume(ci, power_lost);

	if (power_lost)
		ci_handle_power_lost(ci);
		queue_work(system_freezable_wq, &ci->power_lost_work);

	if (ci->supports_runtime_pm) {
		pm_runtime_disable(dev);
+1 −1
Original line number Diff line number Diff line
@@ -301,7 +301,7 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
		return ret;
	}

	root = debugfs_create_dir(dev_name(dev), ulpi_root);
	root = debugfs_create_dir(dev_name(&ulpi->dev), ulpi_root);
	debugfs_create_file("regs", 0444, root, ulpi, &ulpi_regs_fops);

	dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n",
+32 −14
Original line number Diff line number Diff line
@@ -2053,11 +2053,21 @@ static void update_port_device_state(struct usb_device *udev)

	if (udev->parent) {
		hub = usb_hub_to_struct_hub(udev->parent);

		/*
		 * The Link Layer Validation System Driver (lvstest)
		 * has a test step to unbind the hub before running the
		 * rest of the procedure. This triggers hub_disconnect
		 * which will set the hub's maxchild to 0, further
		 * resulting in usb_hub_to_struct_hub returning NULL.
		 */
		if (hub) {
			port_dev = hub->ports[udev->portnum - 1];
			WRITE_ONCE(port_dev->state, udev->state);
			sysfs_notify_dirent(port_dev->state_kn);
		}
	}
}

static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
@@ -2388,6 +2398,13 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
			}
		} else if (desc->bLength == sizeof
				(struct usb_otg_descriptor)) {
			/*
			 * We are operating on a legacy OTP device
			 * These should be told that they are operating
			 * on the wrong port if we have another port that does
			 * support HNP
			 */
			if (bus->otg_port != 0) {
				/* Set a_alt_hnp_support for legacy otg device */
				err = usb_control_msg(udev,
					usb_sndctrlpipe(udev, 0),
@@ -2401,6 +2418,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
						err);
			}
		}
	}
#endif
	return err;
}
Loading