eth_phy_of_to_plat() claims the PHY reset GPIO with gpio_request_by_name() and the PHY reset control with reset_get_by_index(), but nothing releases either when the device is removed. When retrying a wedged PHY, any follow-up probes fail because the reset GPIO is already claimed.
Add a pre_remove hook that frees both. Signed-off-by: Graeme Smecher <[email protected]> Acked-by: Michal Simek <[email protected]> --- This patch was 4/4 of the zynq_gem resource leak series up to v3. As Michal Simek requested, it is now sent separately so that it can go through the net tree; the zynq_gem patches continue as their own v4. Tested on QEMU (xilinx-zynq-a9, xilinx_zynq_virt), with a PHY that has reset-gpios and a (syscon-reset) resets property: after repeated unbind/bind of the ethernet controller, the eth-phy device probes again. Without this patch, the next probe fails because the reset GPIO is still claimed. Changes in v4: - Split out of the zynq_gem series; no code changes - Rebased onto current main - Add Acked-by from Michal Simek - Link to v3: https://lore.kernel.org/r/[email protected] Changes in v3: - Rebased onto the eth-phy reset control support; also release the reset control with reset_free(). Use per-feature DM_GPIO/DM_RESET guards, and reword the subject accordingly --- drivers/net/eth-phy-uclass.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c index a13e2fc7c50a239bdea4aaeb6d77496cc86b3575..7ac1876f846abbddd23117db235a535eb96d234b 100644 --- a/drivers/net/eth-phy-uclass.c +++ b/drivers/net/eth-phy-uclass.c @@ -191,11 +191,25 @@ static int eth_phy_pre_probe(struct udevice *dev) return 0; } +static int eth_phy_pre_remove(struct udevice *dev) +{ + struct eth_phy_device_priv *uc_priv = dev_get_uclass_priv(dev); + + if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&uc_priv->reset_gpio)) + dm_gpio_free(dev, &uc_priv->reset_gpio); + + if (CONFIG_IS_ENABLED(DM_RESET) && reset_valid(&uc_priv->reset_ctrl)) + reset_free(&uc_priv->reset_ctrl); + + return 0; +} + UCLASS_DRIVER(eth_phy_generic) = { .id = UCLASS_ETH_PHY, .name = "eth_phy_generic", .per_device_auto = sizeof(struct eth_phy_device_priv), .pre_probe = eth_phy_pre_probe, + .pre_remove = eth_phy_pre_remove, }; U_BOOT_DRIVER(eth_phy_generic_drv) = { --- base-commit: 709a97a05df66e394f40d249105d0baade46f107 change-id: 20261106-eth-phy-release-reset-0e959156e2c8 Best regards, -- Graeme Smecher <[email protected]>
