The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes
@ 2026-08-10 17:47 Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe Radhey Shyam Pandey
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

This series improves error handling, resource teardown, and system sleep
PM robustness in the dwc3-xilinx glue driver for ZynqMP and Versal
platforms.

Patch 1 switches probe to device_get_match_data() and adds the direct
property.h include instead of relying on of.h for that helper.

Patch 2 introduces struct dwc3_xlnx_platdata and moves ZynqMP and
Versal setup behind plat->init(). The struct also defines an exit
callback slot used by the later teardown patches.

Patch 3 fixes system suspend and resume PHY handling: suspend now
powers off the PHY before phy_exit() and propagates errors; resume
disables clocks if PHY reinitialization fails after they were enabled.

Patch 4 fixes ZynqMP init error paths. Reset handles are saved in
driver private data and fall-through error labels re-assert only the
resets already released before unwinding the PHY when init fails
partway through reset deassert or PHY setup.

Patch 5 adds dwc3_xlnx_exit_zynqmp(), wires it as the ZynqMP platform
exit callback, and calls plat->exit() from probe error paths after a
successful plat->init() and from remove()/shutdown.

Radhey Shyam Pandey (5):
  usb: dwc3: xilinx: use device_get_match_data() in probe
  usb: dwc3: xilinx: add platform data struct with init callback
  usb: dwc3: xilinx: fix system suspend and resume PHY handling
  usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths
  usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and
    remove

 drivers/usb/dwc3/dwc3-xilinx.c | 132 +++++++++++++++++++++++++--------
 1 file changed, 100 insertions(+), 32 deletions(-)


base-commit: 6b8c8af514d739d0335f5579b585e02babe8a727
-- 
2.43.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
@ 2026-08-10 17:47 ` Radhey Shyam Pandey
  2026-08-26  0:09   ` Thinh Nguyen
  2026-08-10 17:47 ` [PATCH 2/5] usb: dwc3: xilinx: add platform data struct with init callback Radhey Shyam Pandey
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

Use device_get_match_data() to obtain the platform init callback from
the OF match table instead of calling of_match_node() and dereferencing
match->data directly.

Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
---
 drivers/usb/dwc3/dwc3-xilinx.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index b832505e1b04..1a8619854d6d 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio/consumer.h>
 #include <linux/of_platform.h>
@@ -279,7 +280,6 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 	struct dwc3_xlnx		*priv_data;
 	struct device			*dev = &pdev->dev;
 	struct device_node		*np = dev->of_node;
-	const struct of_device_id	*match;
 	void __iomem			*regs;
 	int				ret;
 
@@ -291,9 +291,11 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 	if (IS_ERR(regs))
 		return dev_err_probe(dev, PTR_ERR(regs), "failed to map registers\n");
 
-	match = of_match_node(dwc3_xlnx_of_match, pdev->dev.of_node);
+	priv_data->pltfm_init = device_get_match_data(dev);
+	if (!priv_data->pltfm_init)
+		return dev_err_probe(dev, -ENODEV,
+				     "missing platform init handler\n");
 
-	priv_data->pltfm_init = match->data;
 	priv_data->regs = regs;
 	priv_data->dev = dev;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/5] usb: dwc3: xilinx: add platform data struct with init callback
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe Radhey Shyam Pandey
@ 2026-08-10 17:47 ` Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling Radhey Shyam Pandey
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

Introduce struct dwc3_xlnx_platdata and switch the OF match table to
platform data for ZynqMP and Versal. Probe calls plat->init() for
platform-specific setup.

The struct also reserves an exit callback; wiring for that follows in
subsequent patch in this series.

Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
---
 drivers/usb/dwc3/dwc3-xilinx.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 1a8619854d6d..4a04d158f872 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -42,12 +42,19 @@
 #define XLNX_USB_FPD_POWER_PRSNT		0x80
 #define FPD_POWER_PRSNT_OPTION			BIT(0)
 
+struct dwc3_xlnx;
+
+struct dwc3_xlnx_platdata {
+	int (*init)(struct dwc3_xlnx *priv_data);
+	void (*exit)(struct dwc3_xlnx *priv_data);
+};
+
 struct dwc3_xlnx {
 	int				num_clocks;
 	struct clk_bulk_data		*clks;
 	struct device			*dev;
 	void __iomem			*regs;
-	int				(*pltfm_init)(struct dwc3_xlnx *data);
+	const struct dwc3_xlnx_platdata	*plat;
 	struct phy			*usb3_phy;
 };
 
@@ -237,14 +244,22 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 	return ret;
 }
 
+static const struct dwc3_xlnx_platdata zynqmp_platdata = {
+	.init = dwc3_xlnx_init_zynqmp,
+};
+
+static const struct dwc3_xlnx_platdata versal_platdata = {
+	.init = dwc3_xlnx_init_versal,
+};
+
 static const struct of_device_id dwc3_xlnx_of_match[] = {
 	{
 		.compatible = "xlnx,zynqmp-dwc3",
-		.data = &dwc3_xlnx_init_zynqmp,
+		.data = &zynqmp_platdata,
 	},
 	{
 		.compatible = "xlnx,versal-dwc3",
-		.data = &dwc3_xlnx_init_versal,
+		.data = &versal_platdata,
 	},
 	{ /* Sentinel */ }
 };
@@ -291,8 +306,11 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 	if (IS_ERR(regs))
 		return dev_err_probe(dev, PTR_ERR(regs), "failed to map registers\n");
 
-	priv_data->pltfm_init = device_get_match_data(dev);
-	if (!priv_data->pltfm_init)
+	priv_data->plat = device_get_match_data(dev);
+	if (!priv_data->plat)
+		return dev_err_probe(dev, -ENODEV, "missing platform match data\n");
+
+	if (!priv_data->plat->init)
 		return dev_err_probe(dev, -ENODEV,
 				     "missing platform init handler\n");
 
@@ -311,7 +329,7 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = priv_data->pltfm_init(priv_data);
+	ret = priv_data->plat->init(priv_data);
 	if (ret)
 		goto err_clk_put;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 2/5] usb: dwc3: xilinx: add platform data struct with init callback Radhey Shyam Pandey
@ 2026-08-10 17:47 ` Radhey Shyam Pandey
  2026-08-26  0:12   ` Thinh Nguyen
  2026-08-10 17:47 ` [PATCH 4/5] usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths Radhey Shyam Pandey
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

System suspend and resume error paths do not handle PHY and clock
resources correctly. Suspend calls phy_exit() without first powering
off the PHY and ignores failures, while resume can leave clocks
enabled if PHY reinitialization fails.

Propagate errors to the PM core and unwind resources to ensure a
consistent state on suspend and resume failures.

Fixes: d6edcdc1ef06 ("usb: dwc3: xilinx: fix usb3 non-wakeup source resume failure")
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
---
 drivers/usb/dwc3/dwc3-xilinx.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 4a04d158f872..894f5f5e8b7a 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -403,13 +403,25 @@ static int __maybe_unused dwc3_xlnx_runtime_idle(struct device *dev)
 static int __maybe_unused dwc3_xlnx_suspend(struct device *dev)
 {
 	struct dwc3_xlnx *priv_data = dev_get_drvdata(dev);
+	int ret;
 
-	phy_exit(priv_data->usb3_phy);
+	ret = phy_power_off(priv_data->usb3_phy);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_exit(priv_data->usb3_phy);
+	if (ret < 0)
+		goto err_phy_power_on;
 
 	/* Disable the clocks */
 	clk_bulk_disable(priv_data->num_clocks, priv_data->clks);
 
 	return 0;
+
+err_phy_power_on:
+	phy_power_on(priv_data->usb3_phy);
+
+	return ret;
 }
 
 static int __maybe_unused dwc3_xlnx_resume(struct device *dev)
@@ -423,15 +435,20 @@ static int __maybe_unused dwc3_xlnx_resume(struct device *dev)
 
 	ret = phy_init(priv_data->usb3_phy);
 	if (ret < 0)
-		return ret;
+		goto err_clk_disable;
 
 	ret = phy_power_on(priv_data->usb3_phy);
 	if (ret < 0) {
 		phy_exit(priv_data->usb3_phy);
-		return ret;
+		goto err_clk_disable;
 	}
 
 	return 0;
+
+err_clk_disable:
+	clk_bulk_disable(priv_data->num_clocks, priv_data->clks);
+
+	return ret;
 }
 
 static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/5] usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
                   ` (2 preceding siblings ...)
  2026-08-10 17:47 ` [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling Radhey Shyam Pandey
@ 2026-08-10 17:47 ` Radhey Shyam Pandey
  2026-08-10 17:47 ` [PATCH 5/5] usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and remove Radhey Shyam Pandey
  2026-08-26  0:22 ` [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Thinh Nguyen
  5 siblings, 0 replies; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

If reset deassert or PHY setup fails partway through
dwc3_xlnx_init_zynqmp(), re-assert any resets that were already
released before unwinding the PHY. Use fall-through error labels so
unwind matches how far init progressed, for both USB2 and USB3 paths.

Save the ZynqMP reset handles in driver private data so later probe
teardown can re-assert released resets.

Fixes: 84770f028fab ("usb: dwc3: Add driver for Xilinx platforms")
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
---
 drivers/usb/dwc3/dwc3-xilinx.c | 49 +++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 894f5f5e8b7a..38613553937e 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -56,6 +56,10 @@ struct dwc3_xlnx {
 	void __iomem			*regs;
 	const struct dwc3_xlnx_platdata	*plat;
 	struct phy			*usb3_phy;
+	struct reset_control		*usb_crst;
+	struct reset_control		*usb_hibrst;
+	struct reset_control		*usb_apbrst;
+	bool				usb_resets_released;
 };
 
 static void dwc3_xlnx_mask_phy_rst(struct dwc3_xlnx *priv_data, bool mask)
@@ -120,7 +124,6 @@ static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data)
 static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 {
 	struct device		*dev = priv_data->dev;
-	struct reset_control	*crst, *hibrst, *apbrst;
 	struct gpio_desc	*reset_gpio;
 	int			ret = 0;
 
@@ -132,25 +135,25 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 		goto err;
 	}
 
-	crst = devm_reset_control_get_exclusive(dev, "usb_crst");
-	if (IS_ERR(crst)) {
-		ret = PTR_ERR(crst);
+	priv_data->usb_crst = devm_reset_control_get_exclusive(dev, "usb_crst");
+	if (IS_ERR(priv_data->usb_crst)) {
+		ret = PTR_ERR(priv_data->usb_crst);
 		dev_err_probe(dev, ret,
 			      "failed to get core reset signal\n");
 		goto err;
 	}
 
-	hibrst = devm_reset_control_get_exclusive(dev, "usb_hibrst");
-	if (IS_ERR(hibrst)) {
-		ret = PTR_ERR(hibrst);
+	priv_data->usb_hibrst = devm_reset_control_get_exclusive(dev, "usb_hibrst");
+	if (IS_ERR(priv_data->usb_hibrst)) {
+		ret = PTR_ERR(priv_data->usb_hibrst);
 		dev_err_probe(dev, ret,
 			      "failed to get hibernation reset signal\n");
 		goto err;
 	}
 
-	apbrst = devm_reset_control_get_exclusive(dev, "usb_apbrst");
-	if (IS_ERR(apbrst)) {
-		ret = PTR_ERR(apbrst);
+	priv_data->usb_apbrst = devm_reset_control_get_exclusive(dev, "usb_apbrst");
+	if (IS_ERR(priv_data->usb_apbrst)) {
+		ret = PTR_ERR(priv_data->usb_apbrst);
 		dev_err_probe(dev, ret,
 			      "failed to get APB reset signal\n");
 		goto err;
@@ -164,19 +167,19 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 	 * absent.
 	 */
 	if (priv_data->usb3_phy) {
-		ret = reset_control_assert(crst);
+		ret = reset_control_assert(priv_data->usb_crst);
 		if (ret < 0) {
 			dev_err(dev, "Failed to assert core reset\n");
 			goto err;
 		}
 
-		ret = reset_control_assert(hibrst);
+		ret = reset_control_assert(priv_data->usb_hibrst);
 		if (ret < 0) {
 			dev_err(dev, "Failed to assert hibernation reset\n");
 			goto err;
 		}
 
-		ret = reset_control_assert(apbrst);
+		ret = reset_control_assert(priv_data->usb_apbrst);
 		if (ret < 0) {
 			dev_err(dev, "Failed to assert APB reset\n");
 			goto err;
@@ -187,7 +190,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 	if (ret < 0)
 		goto err;
 
-	ret = reset_control_deassert(apbrst);
+	ret = reset_control_deassert(priv_data->usb_apbrst);
 	if (ret < 0) {
 		dev_err(dev, "Failed to release APB reset\n");
 		goto err_phy_exit;
@@ -203,21 +206,21 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 		writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
 	}
 
-	ret = reset_control_deassert(crst);
+	ret = reset_control_deassert(priv_data->usb_crst);
 	if (ret < 0) {
 		dev_err(dev, "Failed to release core reset\n");
-		goto err_phy_exit;
+		goto err_apbrst_assert;
 	}
 
-	ret = reset_control_deassert(hibrst);
+	ret = reset_control_deassert(priv_data->usb_hibrst);
 	if (ret < 0) {
 		dev_err(dev, "Failed to release hibernation reset\n");
-		goto err_phy_exit;
+		goto err_crst_assert;
 	}
 
 	ret = phy_power_on(priv_data->usb3_phy);
 	if (ret < 0)
-		goto err_phy_exit;
+		goto err_hibrst_assert;
 
 	/* ulpi reset via gpio-modepin or gpio-framework driver */
 	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
@@ -234,10 +237,18 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 
 	dwc3_xlnx_set_coherency(priv_data, XLNX_USB_TRAFFIC_ROUTE_CONFIG);
 
+	priv_data->usb_resets_released = true;
+
 	return 0;
 
 err_phy_power_off:
 	phy_power_off(priv_data->usb3_phy);
+err_hibrst_assert:
+	reset_control_assert(priv_data->usb_hibrst);
+err_crst_assert:
+	reset_control_assert(priv_data->usb_crst);
+err_apbrst_assert:
+	reset_control_assert(priv_data->usb_apbrst);
 err_phy_exit:
 	phy_exit(priv_data->usb3_phy);
 err:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/5] usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and remove
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
                   ` (3 preceding siblings ...)
  2026-08-10 17:47 ` [PATCH 4/5] usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths Radhey Shyam Pandey
@ 2026-08-10 17:47 ` Radhey Shyam Pandey
  2026-08-26  0:22 ` [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Thinh Nguyen
  5 siblings, 0 replies; 9+ messages in thread
From: Radhey Shyam Pandey @ 2026-08-10 17:47 UTC (permalink / raw)
  To: Thinh.Nguyen, gregkh, michal.simek, p.zabel
  Cc: linux-usb, linux-arm-kernel, linux-kernel, git,
	Radhey Shyam Pandey

Add dwc3_xlnx_exit_zynqmp() and wire it as the ZynqMP platform exit
callback. If probe steps fail after a successful plat->init(), call
plat->exit() to re-assert released resets and unwind the PHY before
disabling clocks. Call the same callback from remove() and shutdown.

Fixes: 84770f028fab ("usb: dwc3: Add driver for Xilinx platforms")
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
---
 drivers/usb/dwc3/dwc3-xilinx.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 38613553937e..0d2232741d46 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -121,6 +121,20 @@ static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data)
 	return 0;
 }
 
+static void dwc3_xlnx_exit_zynqmp(struct dwc3_xlnx *priv_data)
+{
+	phy_power_off(priv_data->usb3_phy);
+
+	if (priv_data->usb_resets_released) {
+		reset_control_assert(priv_data->usb_hibrst);
+		reset_control_assert(priv_data->usb_crst);
+		reset_control_assert(priv_data->usb_apbrst);
+		priv_data->usb_resets_released = false;
+	}
+
+	phy_exit(priv_data->usb3_phy);
+}
+
 static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 {
 	struct device		*dev = priv_data->dev;
@@ -257,6 +271,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 
 static const struct dwc3_xlnx_platdata zynqmp_platdata = {
 	.init = dwc3_xlnx_init_zynqmp,
+	.exit = dwc3_xlnx_exit_zynqmp,
 };
 
 static const struct dwc3_xlnx_platdata versal_platdata = {
@@ -346,11 +361,11 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 
 	ret = dwc3_set_swnode(dev);
 	if (ret)
-		goto err_clk_put;
+		goto err_pltfm_exit;
 
 	ret = of_platform_populate(np, NULL, NULL, dev);
 	if (ret)
-		goto err_clk_put;
+		goto err_pltfm_exit;
 
 	pm_runtime_set_active(dev);
 	ret = devm_pm_runtime_enable(dev);
@@ -367,7 +382,9 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 err_pm_set_suspended:
 	of_platform_depopulate(dev);
 	pm_runtime_set_suspended(dev);
-
+err_pltfm_exit:
+	if (priv_data->plat->exit)
+		priv_data->plat->exit(priv_data);
 err_clk_put:
 	clk_bulk_disable_unprepare(priv_data->num_clocks, priv_data->clks);
 
@@ -381,6 +398,9 @@ static void dwc3_xlnx_remove(struct platform_device *pdev)
 
 	of_platform_depopulate(dev);
 
+	if (priv_data->plat->exit)
+		priv_data->plat->exit(priv_data);
+
 	clk_bulk_disable_unprepare(priv_data->num_clocks, priv_data->clks);
 	priv_data->num_clocks = 0;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe
  2026-08-10 17:47 ` [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe Radhey Shyam Pandey
@ 2026-08-26  0:09   ` Thinh Nguyen
  0 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-08-26  0:09 UTC (permalink / raw)
  To: Radhey Shyam Pandey
  Cc: Thinh Nguyen, gregkh@linuxfoundation.org, michal.simek@amd.com,
	p.zabel@pengutronix.de, linux-usb@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, git@amd.com

On Mon, Aug 10, 2026, Radhey Shyam Pandey wrote:
> Use device_get_match_data() to obtain the platform init callback from
> the OF match table instead of calling of_match_node() and dereferencing
> match->data directly.
> 
> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
> ---
>  drivers/usb/dwc3/dwc3-xilinx.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> index b832505e1b04..1a8619854d6d 100644
> --- a/drivers/usb/dwc3/dwc3-xilinx.c
> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> @@ -12,6 +12,7 @@
>  #include <linux/clk.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
> +#include <linux/property.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/of_platform.h>
> @@ -279,7 +280,6 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
>  	struct dwc3_xlnx		*priv_data;
>  	struct device			*dev = &pdev->dev;
>  	struct device_node		*np = dev->of_node;
> -	const struct of_device_id	*match;
>  	void __iomem			*regs;
>  	int				ret;
>  
> @@ -291,9 +291,11 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
>  	if (IS_ERR(regs))
>  		return dev_err_probe(dev, PTR_ERR(regs), "failed to map registers\n");
>  
> -	match = of_match_node(dwc3_xlnx_of_match, pdev->dev.of_node);
> +	priv_data->pltfm_init = device_get_match_data(dev);
> +	if (!priv_data->pltfm_init)
> +		return dev_err_probe(dev, -ENODEV,
> +				     "missing platform init handler\n");
>  
> -	priv_data->pltfm_init = match->data;
>  	priv_data->regs = regs;
>  	priv_data->dev = dev;
>  
> -- 
> 2.43.0
> 

Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling
  2026-08-10 17:47 ` [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling Radhey Shyam Pandey
@ 2026-08-26  0:12   ` Thinh Nguyen
  0 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-08-26  0:12 UTC (permalink / raw)
  To: Radhey Shyam Pandey
  Cc: Thinh Nguyen, gregkh@linuxfoundation.org, michal.simek@amd.com,
	p.zabel@pengutronix.de, linux-usb@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, git@amd.com

On Mon, Aug 10, 2026, Radhey Shyam Pandey wrote:
> System suspend and resume error paths do not handle PHY and clock
> resources correctly. Suspend calls phy_exit() without first powering
> off the PHY and ignores failures, while resume can leave clocks
> enabled if PHY reinitialization fails.
> 
> Propagate errors to the PM core and unwind resources to ensure a
> consistent state on suspend and resume failures.
> 
> Fixes: d6edcdc1ef06 ("usb: dwc3: xilinx: fix usb3 non-wakeup source resume failure")

Does this need to be backported to stable?

BR,
Thinh

> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
> ---
>  drivers/usb/dwc3/dwc3-xilinx.c | 23 ++++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> index 4a04d158f872..894f5f5e8b7a 100644
> --- a/drivers/usb/dwc3/dwc3-xilinx.c
> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> @@ -403,13 +403,25 @@ static int __maybe_unused dwc3_xlnx_runtime_idle(struct device *dev)
>  static int __maybe_unused dwc3_xlnx_suspend(struct device *dev)
>  {
>  	struct dwc3_xlnx *priv_data = dev_get_drvdata(dev);
> +	int ret;
>  
> -	phy_exit(priv_data->usb3_phy);
> +	ret = phy_power_off(priv_data->usb3_phy);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = phy_exit(priv_data->usb3_phy);
> +	if (ret < 0)
> +		goto err_phy_power_on;
>  
>  	/* Disable the clocks */
>  	clk_bulk_disable(priv_data->num_clocks, priv_data->clks);
>  
>  	return 0;
> +
> +err_phy_power_on:
> +	phy_power_on(priv_data->usb3_phy);
> +
> +	return ret;
>  }
>  
>  static int __maybe_unused dwc3_xlnx_resume(struct device *dev)
> @@ -423,15 +435,20 @@ static int __maybe_unused dwc3_xlnx_resume(struct device *dev)
>  
>  	ret = phy_init(priv_data->usb3_phy);
>  	if (ret < 0)
> -		return ret;
> +		goto err_clk_disable;
>  
>  	ret = phy_power_on(priv_data->usb3_phy);
>  	if (ret < 0) {
>  		phy_exit(priv_data->usb3_phy);
> -		return ret;
> +		goto err_clk_disable;
>  	}
>  
>  	return 0;
> +
> +err_clk_disable:
> +	clk_bulk_disable(priv_data->num_clocks, priv_data->clks);
> +
> +	return ret;
>  }
>  
>  static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = {
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes
  2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
                   ` (4 preceding siblings ...)
  2026-08-10 17:47 ` [PATCH 5/5] usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and remove Radhey Shyam Pandey
@ 2026-08-26  0:22 ` Thinh Nguyen
  5 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-08-26  0:22 UTC (permalink / raw)
  To: Radhey Shyam Pandey
  Cc: Thinh Nguyen, gregkh@linuxfoundation.org, michal.simek@amd.com,
	p.zabel@pengutronix.de, linux-usb@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, git@amd.com

On Mon, Aug 10, 2026, Radhey Shyam Pandey wrote:
> This series improves error handling, resource teardown, and system sleep
> PM robustness in the dwc3-xilinx glue driver for ZynqMP and Versal
> platforms.
> 
> Patch 1 switches probe to device_get_match_data() and adds the direct
> property.h include instead of relying on of.h for that helper.
> 
> Patch 2 introduces struct dwc3_xlnx_platdata and moves ZynqMP and
> Versal setup behind plat->init(). The struct also defines an exit
> callback slot used by the later teardown patches.
> 
> Patch 3 fixes system suspend and resume PHY handling: suspend now
> powers off the PHY before phy_exit() and propagates errors; resume
> disables clocks if PHY reinitialization fails after they were enabled.
> 
> Patch 4 fixes ZynqMP init error paths. Reset handles are saved in
> driver private data and fall-through error labels re-assert only the
> resets already released before unwinding the PHY when init fails
> partway through reset deassert or PHY setup.
> 
> Patch 5 adds dwc3_xlnx_exit_zynqmp(), wires it as the ZynqMP platform
> exit callback, and calls plat->exit() from probe error paths after a
> successful plat->init() and from remove()/shutdown.
> 
> Radhey Shyam Pandey (5):
>   usb: dwc3: xilinx: use device_get_match_data() in probe
>   usb: dwc3: xilinx: add platform data struct with init callback
>   usb: dwc3: xilinx: fix system suspend and resume PHY handling
>   usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths
>   usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and
>     remove
> 
>  drivers/usb/dwc3/dwc3-xilinx.c | 132 +++++++++++++++++++++++++--------
>  1 file changed, 100 insertions(+), 32 deletions(-)
> 
> 
> base-commit: 6b8c8af514d739d0335f5579b585e02babe8a727
> -- 
> 2.43.0
> 

These patches look good to me, do you plan to backport the fixes? If so,
can you Cc stable and re-order them so that the fixes patches go first?
Better yet, keep the fixes and new changes in separate series.

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-26  1:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-10 17:47 [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Radhey Shyam Pandey
2026-08-10 17:47 ` [PATCH 1/5] usb: dwc3: xilinx: use device_get_match_data() in probe Radhey Shyam Pandey
2026-08-26  0:09   ` Thinh Nguyen
2026-08-10 17:47 ` [PATCH 2/5] usb: dwc3: xilinx: add platform data struct with init callback Radhey Shyam Pandey
2026-08-10 17:47 ` [PATCH 3/5] usb: dwc3: xilinx: fix system suspend and resume PHY handling Radhey Shyam Pandey
2026-08-26  0:12   ` Thinh Nguyen
2026-08-10 17:47 ` [PATCH 4/5] usb: dwc3: xilinx: re-assert resets on ZynqMP init error paths Radhey Shyam Pandey
2026-08-10 17:47 ` [PATCH 5/5] usb: dwc3: xilinx: unwind ZynqMP platform init on probe failure and remove Radhey Shyam Pandey
2026-08-26  0:22 ` [PATCH 0/5] usb: dwc3: xilinx: error handling and teardown fixes Thinh Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox