Commit 78ac16d4 authored by Kyle Tso's avatar Kyle Tso Committed by Wentao Guan
Browse files

usb: dwc3: core: Defer the probe until USB power supply ready

stable inclusion
from stable-v6.6.76
commit 876b1bf63b6f40107d3d5e685127f4b9ba1469fd
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBW08Q

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=876b1bf63b6f40107d3d5e685127f4b9ba1469fd



--------------------------------

commit 66e0ea341a2a78d14336117f19763bd9be26d45d upstream.

Currently, DWC3 driver attempts to acquire the USB power supply only
once during the probe. If the USB power supply is not ready at that
time, the driver simply ignores the failure and continues the probe,
leading to permanent non-functioning of the gadget vbus_draw callback.

Address this problem by delaying the dwc3 driver initialization until
the USB power supply is registered.

Fixes: 6f0764b5 ("usb: dwc3: add a power supply for current control")
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarKyle Tso <kyletso@google.com>
Acked-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20250115044548.2701138-1-kyletso@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 876b1bf63b6f40107d3d5e685127f4b9ba1469fd)
Signed-off-by: default avatarWentao Guan <guanwentao@uniontech.com>
parent 14b8c057
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -1505,8 +1505,6 @@ static void dwc3_get_properties(struct dwc3 *dwc)
	u8			tx_thr_num_pkt_prd = 0;
	u8			tx_max_burst_prd = 0;
	u8			tx_fifo_resize_max_num;
	const char		*usb_psy_name;
	int			ret;

	/* default to highest possible threshold */
	lpm_nyet_threshold = 0xf;
@@ -1541,13 +1539,6 @@ static void dwc3_get_properties(struct dwc3 *dwc)

	dwc->sys_wakeup = device_may_wakeup(dwc->sysdev);

	ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name);
	if (ret >= 0) {
		dwc->usb_psy = power_supply_get_by_name(usb_psy_name);
		if (!dwc->usb_psy)
			dev_err(dev, "couldn't get usb power supply\n");
	}

	dwc->has_lpm_erratum = device_property_read_bool(dev,
				"snps,has-lpm-erratum");
	device_property_read_u8(dev, "snps,lpm-nyet-threshold",
@@ -1887,6 +1878,23 @@ static int dwc3_get_clocks(struct dwc3 *dwc)
	return 0;
}

static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc)
{
	struct power_supply *usb_psy;
	const char *usb_psy_name;
	int ret;

	ret = device_property_read_string(dwc->dev, "usb-psy-name", &usb_psy_name);
	if (ret < 0)
		return NULL;

	usb_psy = power_supply_get_by_name(usb_psy_name);
	if (!usb_psy)
		return ERR_PTR(-EPROBE_DEFER);

	return usb_psy;
}

static int dwc3_probe(struct platform_device *pdev)
{
	struct device		*dev = &pdev->dev;
@@ -1940,6 +1948,10 @@ static int dwc3_probe(struct platform_device *pdev)

	dwc3_get_properties(dwc);

	dwc->usb_psy = dwc3_get_usb_power_supply(dwc);
	if (IS_ERR(dwc->usb_psy))
		return dev_err_probe(dev, PTR_ERR(dwc->usb_psy), "couldn't get usb power supply\n");

	dwc->reset = devm_reset_control_array_get_optional_shared(dev);
	if (IS_ERR(dwc->reset)) {
		ret = PTR_ERR(dwc->reset);