diff options
author | Thierry Reding <treding@nvidia.com> | 2020-03-19 11:52:13 +0100 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2020-03-19 14:00:05 +0100 |
commit | e78fdbad1e902f422a7a0452cce8378d2652f219 (patch) | |
tree | 43e31763ea49d61dc5e32c033b4214c070229f4f /drivers/phy/tegra/xusb-tegra186.c | |
parent | phy: tegra: Fix regulator leak (diff) | |
download | linux-e78fdbad1e902f422a7a0452cce8378d2652f219.tar.xz linux-e78fdbad1e902f422a7a0452cce8378d2652f219.zip |
phy: tegra: Don't use device-managed API to allocate ports
The device-managed allocation API doesn't work well with the life-cycle
of device objects. Since ports have device objects allocated within, it
can lead to situations where these devices need to stay around until
after their parent pad controller has been unbound from its driver. The
device-managed memory allocated for the port objects will, however, get
freed when the pad controller unbinds from the driver. This can cause
use-after-free errors down the road.
Note that the device is deleted as part of the driver unbind operation,
so there isn't much that can be done with it after that point, but the
memory still needs to stay around to ensure none of the references are
invalidated.
One situation where this arises is when a VBUS supply is associated with
a USB 2 or 3 port. When that supply is released using regulator_put() an
SRCU call will queue the release of the device link connecting the port
and the regulator after a grace period. This means that the regulator is
going to keep on to the last reference of the port device even after the
pad controller driver was unbound (which is when the memory backing the
port device is freed).
Fix this by allocating port objects using non-device-managed memory. Add
release callbacks for these objects so that their memory gets freed when
the last reference goes away. This decouples the port devices' lifetime
from the "active" lifetime of the pad controller (i.e. the time during
which the pad controller driver owns the device).
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/phy/tegra/xusb-tegra186.c')
-rw-r--r-- | drivers/phy/tegra/xusb-tegra186.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c index 973df722b93d..5d64f69b39a9 100644 --- a/drivers/phy/tegra/xusb-tegra186.c +++ b/drivers/phy/tegra/xusb-tegra186.c @@ -615,6 +615,7 @@ tegra186_usb2_port_map(struct tegra_xusb_port *port) } static const struct tegra_xusb_port_ops tegra186_usb2_port_ops = { + .release = tegra_xusb_usb2_port_release, .remove = tegra_xusb_usb2_port_remove, .enable = tegra186_usb2_port_enable, .disable = tegra186_usb2_port_disable, @@ -675,6 +676,7 @@ tegra186_usb3_port_map(struct tegra_xusb_port *port) } static const struct tegra_xusb_port_ops tegra186_usb3_port_ops = { + .release = tegra_xusb_usb3_port_release, .remove = tegra_xusb_usb3_port_remove, .enable = tegra186_usb3_port_enable, .disable = tegra186_usb3_port_disable, |