phy: tegra: Fix regulator leak
Devices are created for each port of the XUSB pad controller. Each USB 2 and USB 3 port can potentially have an associated VBUS power supply that needs to be removed when the device is removed. Since port devices never bind to a driver, the driver core will not get to perform the cleanup of device-managed resources that usually happens on driver unbind. Now, the driver core will also perform device-managed resource cleanup for driver-less devices when they are released. However, when a device link is created between the regulator and the port device, as part of regulator_get(), the regulator takes a reference to the port device and prevents it from being released unless regulator_put() is called, which will never happen. Avoid this by using the non-device-managed API and manually releasing the regulator reference when the port is unregistered. Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
@@ -554,6 +554,9 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
|
||||
usb_remove_phy(&port->usb_phy);
|
||||
}
|
||||
|
||||
if (port->ops->remove)
|
||||
port->ops->remove(port);
|
||||
|
||||
device_unregister(&port->dev);
|
||||
}
|
||||
|
||||
@@ -734,7 +737,7 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
|
||||
}
|
||||
}
|
||||
|
||||
usb2->supply = devm_regulator_get(&port->dev, "vbus");
|
||||
usb2->supply = regulator_get(&port->dev, "vbus");
|
||||
return PTR_ERR_OR_ZERO(usb2->supply);
|
||||
}
|
||||
|
||||
@@ -784,6 +787,13 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void tegra_xusb_usb2_port_remove(struct tegra_xusb_port *port)
|
||||
{
|
||||
struct tegra_xusb_usb2_port *usb2 = to_usb2_port(port);
|
||||
|
||||
regulator_put(usb2->supply);
|
||||
}
|
||||
|
||||
static int tegra_xusb_ulpi_port_parse_dt(struct tegra_xusb_ulpi_port *ulpi)
|
||||
{
|
||||
struct tegra_xusb_port *port = &ulpi->base;
|
||||
@@ -912,7 +922,7 @@ static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
usb3->supply = devm_regulator_get(&port->dev, "vbus");
|
||||
usb3->supply = regulator_get(&port->dev, "vbus");
|
||||
return PTR_ERR_OR_ZERO(usb3->supply);
|
||||
}
|
||||
|
||||
@@ -963,6 +973,13 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void tegra_xusb_usb3_port_remove(struct tegra_xusb_port *port)
|
||||
{
|
||||
struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
|
||||
|
||||
regulator_put(usb3->supply);
|
||||
}
|
||||
|
||||
static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl)
|
||||
{
|
||||
struct tegra_xusb_port *port, *tmp;
|
||||
|
Reference in New Issue
Block a user