]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
authorRadhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Fri, 17 Jul 2026 18:25:26 +0000 (23:55 +0530)
committerDamien Le Moal <dlemoal@kernel.org>
Sat, 18 Jul 2026 01:37:02 +0000 (10:37 +0900)
On phy_init() failure the error path fallsthrough to disable_rsts, which
deasserts the controller reset and then enters disable_phys calling
phy_power_off() on PHYs that were never powered on. That corrupts the PHY
power_count and triggers an extra runtime PM put.

Use a separate exit_phys path that unwinds with phy_exit() only and falls
through to disable_clks while the controller remains in reset.  Reserve
phy_power_off() for the phy_power_on() failure path only, and skip
masked-out ports in both unwind loops.

On phy_power_on() failure re-assert the controller reset before disabling
clocks and regulators, matching the teardown order used by
ahci_platform_enable_resources() and ahci_platform_disable_resources().

Fixes: 26c8404e162b ("ata: ahci_ceva: fix error handling for Xilinx GT PHY support")
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
drivers/ata/ahci_ceva.c

index 2d6a08c23d6ad5d1d11a7de7fbe2968201d6095a..2961e53288f429da003960a9482f47d87c650c63 100644 (file)
@@ -211,7 +211,7 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
 
                rc = phy_init(hpriv->phys[i]);
                if (rc)
-                       goto disable_rsts;
+                       goto exit_phys;
        }
 
        /* De-assert the controller reset */
@@ -230,14 +230,24 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
 
        return 0;
 
-disable_rsts:
-       ahci_platform_deassert_rsts(hpriv);
-
 disable_phys:
        while (--i >= 0) {
+               if (ahci_ignore_port(hpriv, i))
+                       continue;
+
                phy_power_off(hpriv->phys[i]);
                phy_exit(hpriv->phys[i]);
        }
+       ahci_platform_assert_rsts(hpriv);
+       goto disable_clks;
+
+exit_phys:
+       while (--i >= 0) {
+               if (ahci_ignore_port(hpriv, i))
+                       continue;
+
+               phy_exit(hpriv->phys[i]);
+       }
 
 disable_clks:
        ahci_platform_disable_clks(hpriv);