Commit 0dc1f314 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB fixes from Greg KH:
 "Here are some small USB driver fixes for some reported issues. These
  contain:

   - typec driver fixes

   - dwc3 driver fixes

   - xhci driver fixes

   - renesas controller fixes

   - gadget driver fixes

   - a new USB quirk added

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

* tag 'usb-6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: ucsi: Fix NULL pointer access
  usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader
  usb: xhci: Fix host controllers "dying" after suspend and resume
  usb: dwc3: Set SUSPENDENABLE soon after phy init
  usb: hub: lack of clearing xHC resources
  usb: renesas_usbhs: Flush the notify_hotplug_work
  usb: renesas_usbhs: Use devm_usb_get_phy()
  usb: renesas_usbhs: Call clk_put()
  usb: dwc3: gadget: Prevent irq storm when TH re-executes
  usb: gadget: Check bmAttributes only if configuration is valid
  xhci: Restrict USB4 tunnel detection for USB3 devices to Intel hosts
  usb: xhci: Enable the TRB overfetch quirk on VIA VL805
  usb: gadget: Fix setting self-powered state on suspend
  usb: typec: ucsi: increase timeout for PPM reset operations
  acpi: typec: ucsi: Introduce a ->poll_cci method
  usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality
  usb: gadget: Set self-powered based on MaxPower and bmAttributes
  usb: gadget: u_ether: Set is_suspend flag if remote wakeup fails
  usb: atm: cxacru: fix a flaw in existing endpoint checks
parents 51b38f3c b13abcb7
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -1131,7 +1131,10 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
	struct cxacru_data *instance;
	struct usb_device *usb_dev = interface_to_usbdev(intf);
	struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
	struct usb_endpoint_descriptor *in, *out;
	static const u8 ep_addrs[] = {
		CXACRU_EP_CMD + USB_DIR_IN,
		CXACRU_EP_CMD + USB_DIR_OUT,
		0};
	int ret;

	/* instance init */
@@ -1179,13 +1182,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
	}

	if (usb_endpoint_xfer_int(&cmd_ep->desc))
		ret = usb_find_common_endpoints(intf->cur_altsetting,
						NULL, NULL, &in, &out);
		ret = usb_check_int_endpoints(intf, ep_addrs);
	else
		ret = usb_find_common_endpoints(intf->cur_altsetting,
						&in, &out, NULL, NULL);
		ret = usb_check_bulk_endpoints(intf, ep_addrs);

	if (ret) {
	if (!ret) {
		usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n");
		ret = -ENODEV;
		goto fail;
+33 −0
Original line number Diff line number Diff line
@@ -6065,6 +6065,36 @@ void usb_hub_cleanup(void)
	usb_deregister(&hub_driver);
} /* usb_hub_cleanup() */

/**
 * hub_hc_release_resources - clear resources used by host controller
 * @udev: pointer to device being released
 *
 * Context: task context, might sleep
 *
 * Function releases the host controller resources in correct order before
 * making any operation on resuming usb device. The host controller resources
 * allocated for devices in tree should be released starting from the last
 * usb device in tree toward the root hub. This function is used only during
 * resuming device when usb device require reinitialization – that is, when
 * flag udev->reset_resume is set.
 *
 * This call is synchronous, and may not be used in an interrupt context.
 */
static void hub_hc_release_resources(struct usb_device *udev)
{
	struct usb_hub *hub = usb_hub_to_struct_hub(udev);
	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
	int i;

	/* Release up resources for all children before this device */
	for (i = 0; i < udev->maxchild; i++)
		if (hub->ports[i]->child)
			hub_hc_release_resources(hub->ports[i]->child);

	if (hcd->driver->reset_device)
		hcd->driver->reset_device(hcd, udev);
}

/**
 * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device
 * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
@@ -6129,6 +6159,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
	bos = udev->bos;
	udev->bos = NULL;

	if (udev->reset_resume)
		hub_hc_release_resources(udev);

	mutex_lock(hcd->address0_mutex);

	for (i = 0; i < PORT_INIT_TRIES; ++i) {
+4 −0
Original line number Diff line number Diff line
@@ -341,6 +341,10 @@ static const struct usb_device_id usb_quirk_list[] = {
	{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
	  USB_QUIRK_STRING_FETCH_255 },

	/* Prolific Single-LUN Mass Storage Card Reader */
	{ USB_DEVICE(0x067b, 0x2731), .driver_info = USB_QUIRK_DELAY_INIT |
	  USB_QUIRK_NO_LPM },

	/* Saitek Cyborg Gold Joystick */
	{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },
+48 −37
Original line number Diff line number Diff line
@@ -131,11 +131,24 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
	}
}

void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
{
	unsigned int hw_mode;
	u32 reg;

	reg = dwc3_readl(dwc->regs, DWC3_GCTL);

	 /*
	  * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE and
	  * GUSB2PHYCFG.SUSPHY should be cleared during mode switching,
	  * and they can be set after core initialization.
	  */
	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && !ignore_susphy) {
		if (DWC3_GCTL_PRTCAP(reg) != mode)
			dwc3_enable_susphy(dwc, false);
	}

	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
	reg |= DWC3_GCTL_PRTCAPDIR(mode);
	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
@@ -216,7 +229,7 @@ static void __dwc3_set_mode(struct work_struct *work)

	spin_lock_irqsave(&dwc->lock, flags);

	dwc3_set_prtcap(dwc, desired_dr_role);
	dwc3_set_prtcap(dwc, desired_dr_role, false);

	spin_unlock_irqrestore(&dwc->lock, flags);

@@ -658,16 +671,7 @@ static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index)
	 */
	reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;

	/*
	 * Above DWC_usb3.0 1.94a, it is recommended to set
	 * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
	 * So default value will be '0' when the core is reset. Application
	 * needs to set it to '1' after the core initialization is completed.
	 *
	 * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
	 * cleared after power-on reset, and it can be set after core
	 * initialization.
	 */
	/* Ensure the GUSB3PIPECTL.SUSPENDENABLE is cleared prior to phy init. */
	reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;

	if (dwc->u2ss_inp3_quirk)
@@ -747,15 +751,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index)
		break;
	}

	/*
	 * Above DWC_usb3.0 1.94a, it is recommended to set
	 * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
	 * So default value will be '0' when the core is reset. Application
	 * needs to set it to '1' after the core initialization is completed.
	 *
	 * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
	 * after power-on reset, and it can be set after core initialization.
	 */
	/* Ensure the GUSB2PHYCFG.SUSPHY is cleared prior to phy init. */
	reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;

	if (dwc->dis_enblslpm_quirk)
@@ -830,6 +826,25 @@ static int dwc3_phy_init(struct dwc3 *dwc)
			goto err_exit_usb3_phy;
	}

	/*
	 * Above DWC_usb3.0 1.94a, it is recommended to set
	 * DWC3_GUSB3PIPECTL_SUSPHY and DWC3_GUSB2PHYCFG_SUSPHY to '0' during
	 * coreConsultant configuration. So default value will be '0' when the
	 * core is reset. Application needs to set it to '1' after the core
	 * initialization is completed.
	 *
	 * Certain phy requires to be in P0 power state during initialization.
	 * Make sure GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY are clear
	 * prior to phy init to maintain in the P0 state.
	 *
	 * After phy initialization, some phy operations can only be executed
	 * while in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and
	 * GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid
	 * blocking phy ops.
	 */
	if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
		dwc3_enable_susphy(dwc, true);

	return 0;

err_exit_usb3_phy:
@@ -1588,7 +1603,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)

	switch (dwc->dr_mode) {
	case USB_DR_MODE_PERIPHERAL:
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, false);

		if (dwc->usb2_phy)
			otg_set_vbus(dwc->usb2_phy->otg, false);
@@ -1600,7 +1615,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
			return dev_err_probe(dev, ret, "failed to initialize gadget\n");
		break;
	case USB_DR_MODE_HOST:
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, false);

		if (dwc->usb2_phy)
			otg_set_vbus(dwc->usb2_phy->otg, true);
@@ -1645,7 +1660,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
	}

	/* de-assert DRVVBUS for HOST and OTG mode */
	dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
	dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true);
}

static void dwc3_get_software_properties(struct dwc3 *dwc)
@@ -1835,8 +1850,6 @@ static void dwc3_get_properties(struct dwc3 *dwc)
	dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd;
	dwc->tx_max_burst_prd = tx_max_burst_prd;

	dwc->imod_interval = 0;

	dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
}

@@ -1854,21 +1867,19 @@ static void dwc3_check_params(struct dwc3 *dwc)
	unsigned int hwparam_gen =
		DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3);

	/* Check for proper value of imod_interval */
	if (dwc->imod_interval && !dwc3_has_imod(dwc)) {
		dev_warn(dwc->dev, "Interrupt moderation not supported\n");
		dwc->imod_interval = 0;
	}

	/*
	 * Enable IMOD for all supporting controllers.
	 *
	 * Particularly, DWC_usb3 v3.00a must enable this feature for
	 * the following reason:
	 *
	 * Workaround for STAR 9000961433 which affects only version
	 * 3.00a of the DWC_usb3 core. This prevents the controller
	 * interrupt from being masked while handling events. IMOD
	 * allows us to work around this issue. Enable it for the
	 * affected version.
	 */
	if (!dwc->imod_interval &&
	    DWC3_VER_IS(DWC3, 300A))
	if (dwc3_has_imod((dwc)))
		dwc->imod_interval = 1;

	/* Check the maximum_speed parameter */
@@ -2457,7 +2468,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
		if (ret)
			return ret;

		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true);
		dwc3_gadget_resume(dwc);
		break;
	case DWC3_GCTL_PRTCAP_HOST:
@@ -2465,7 +2476,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
			ret = dwc3_core_init_for_resume(dwc);
			if (ret)
				return ret;
			dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
			dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, true);
			break;
		}
		/* Restore GUSB2PHYCFG bits that were modified in suspend */
@@ -2494,7 +2505,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
		if (ret)
			return ret;

		dwc3_set_prtcap(dwc, dwc->current_dr_role);
		dwc3_set_prtcap(dwc, dwc->current_dr_role, true);

		dwc3_otg_init(dwc);
		if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
+1 −1
Original line number Diff line number Diff line
@@ -1558,7 +1558,7 @@ struct dwc3_gadget_ep_cmd_params {
#define DWC3_HAS_OTG			BIT(3)

/* prototypes */
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode);
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy);
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type);

Loading