Commit ada050c6 authored by Christophe JAILLET's avatar Christophe JAILLET Committed by Greg Kroah-Hartman
Browse files

usb: dwc2: Fix some error handling paths



dwc2_driver_probe() calls dwc2_lowlevel_hw_init() which deassert some reset
lines.
Should an error happen in dwc2_lowlevel_hw_init() after calling
reset_control_deassert() or in the probe after calling
dwc2_lowlevel_hw_init(), the reset lines remain deasserted.

Add some devm_add_action_or_reset() calls to re-assert the lines if needed.

Update the remove function accordingly.

This change is compile-tested only.

Fixes: 83f8da56 ("usb: dwc2: Add reset control to dwc2")
Signed-off-by: default avatarChristophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/r/c64537b5339342bd00f7c2152b8fc23792b9f95a.1683306479.git.christophe.jaillet@wanadoo.fr


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2f28c3c9
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -203,6 +203,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
	return ret;
}

static void dwc2_reset_control_assert(void *data)
{
	reset_control_assert(data);
}

static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
{
	int i, ret;
@@ -213,6 +218,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
				     "error getting reset control\n");

	reset_control_deassert(hsotg->reset);
	ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
				       hsotg->reset);
	if (ret)
		return ret;

	hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc");
	if (IS_ERR(hsotg->reset_ecc))
@@ -220,6 +229,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
				     "error getting reset control for ecc\n");

	reset_control_deassert(hsotg->reset_ecc);
	ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
				       hsotg->reset_ecc);
	if (ret)
		return ret;

	/*
	 * Attempt to find a generic PHY, then look for an old style
@@ -339,9 +352,6 @@ static int dwc2_driver_remove(struct platform_device *dev)
	if (hsotg->ll_hw_enabled)
		dwc2_lowlevel_hw_disable(hsotg);

	reset_control_assert(hsotg->reset);
	reset_control_assert(hsotg->reset_ecc);

	return 0;
}