[PATCH] ata: sata_mv: init and power phy per-port in port_start

Rosen Penev <[email protected]>
Newsgroups org.kernel.vger.linux-ide,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Move phy_init()/phy_power_on() out of mv_platform_probe() and into
mv_port_start(), with matching phy_power_off()/phy_exit() in
mv_port_stop().  This ties the phy lifecycle to the port lifecycle
instead of powering phys up-front in probe, and lets the generic
ata_platform_remove_one() replace the custom mv_platform_remove().

Rework mv_platform_probe() error handling to return directly now
that cleanup is handled by devres, dropping the err: label and the
now-dead hpriv->n_ports assignments in the per-port error paths.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <[email protected]>
---
 drivers/ata/sata_mv.c | 72 +++++++++++++++++--------------------------
 1 file changed, 29 insertions(+), 43 deletions(-)

diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index d260f04e6384..e811202a6873 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1670,8 +1670,10 @@ static int mv_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
 	struct mv_host_priv *hpriv = ap->host->private_data;
+	struct phy *phy = hpriv->port_phys[ap->port_no];
 	struct mv_port_priv *pp;
 	unsigned long flags;
+	int rc = -ENOMEM;
 	int tag;
 
 	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
@@ -1711,11 +1713,23 @@ static int mv_port_start(struct ata_port *ap)
 	mv_edma_cfg(ap, 0, 0);
 	spin_unlock_irqrestore(ap->lock, flags);
 
+	if (phy) {
+		rc = phy_init(phy);
+		if (rc)
+			goto out_port_free_dma_mem;
+
+		rc = phy_power_on(phy);
+		if (rc)
+			goto out_port_phy_exit;
+	}
+
 	return 0;
 
+out_port_phy_exit:
+	phy_exit(phy);
 out_port_free_dma_mem:
 	mv_port_free_dma_mem(ap);
-	return -ENOMEM;
+	return rc;
 }
 
 /**
@@ -1729,6 +1743,8 @@ static int mv_port_start(struct ata_port *ap)
  */
 static void mv_port_stop(struct ata_port *ap)
 {
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	struct phy *phy = hpriv->port_phys[ap->port_no];
 	unsigned long flags;
 
 	spin_lock_irqsave(ap->lock, flags);
@@ -1736,6 +1752,11 @@ static void mv_port_stop(struct ata_port *ap)
 	mv_enable_port_irqs(ap, 0);
 	spin_unlock_irqrestore(ap->lock, flags);
 	mv_port_free_dma_mem(ap);
+
+	if (phy) {
+		phy_power_off(phy);
+		phy_exit(phy);
+	}
 }
 
 /**
@@ -4096,26 +4117,18 @@ static int mv_platform_probe(struct platform_device *pdev)
 		char port_number[16];
 		sprintf(port_number, "%d", port);
 		hpriv->port_clks[port] = devm_clk_get_optional_enabled(&pdev->dev, port_number);
-		if (IS_ERR(hpriv->port_clks[port])) {
-			rc = PTR_ERR(hpriv->port_clks[port]);
-			hpriv->n_ports = port;
-			goto err;
-		}
+		if (IS_ERR(hpriv->port_clks[port]))
+			return PTR_ERR(hpriv->port_clks[port]);
 
 		sprintf(port_number, "port%d", port);
 		hpriv->port_phys[port] = devm_phy_optional_get(&pdev->dev,
 							       port_number);
 		if (IS_ERR(hpriv->port_phys[port])) {
 			rc = PTR_ERR(hpriv->port_phys[port]);
-			hpriv->port_phys[port] = NULL;
 			if (rc != -EPROBE_DEFER)
 				dev_warn(&pdev->dev, "error getting phy %d", rc);
-
-			/* Cleanup only the initialized ports */
-			hpriv->n_ports = port;
-			goto err;
+			return rc;
 		}
-		phy_power_on(hpriv->port_phys[port]);
 	}
 
 	/* All the ports have been initialized */
@@ -4130,7 +4143,7 @@ static int mv_platform_probe(struct platform_device *pdev)
 
 	rc = mv_create_dma_pools(hpriv, &pdev->dev);
 	if (rc)
-		goto err;
+		return rc;
 
 	/*
 	 * To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be
@@ -4144,39 +4157,12 @@ static int mv_platform_probe(struct platform_device *pdev)
 	/* initialize adapter */
 	rc = mv_init_host(host);
 	if (rc)
-		goto err;
+		return rc;
 
 	dev_info(&pdev->dev, "slots %u ports %d\n",
 		 (unsigned)MV_MAX_Q_DEPTH, host->n_ports);
 
-	rc = ata_host_activate(host, irq, mv_interrupt, IRQF_SHARED, &mv6_sht);
-	if (!rc)
-		return 0;
-
-err:
-	for (port = 0; port < hpriv->n_ports; port++)
-		phy_power_off(hpriv->port_phys[port]);
-
-	return rc;
-}
-
-/*
- *
- *      mv_platform_remove    -       unplug a platform interface
- *      @pdev: platform device
- *
- *      A platform bus SATA device has been unplugged. Perform the needed
- *      cleanup. Also called on module unload for any active devices.
- */
-static void mv_platform_remove(struct platform_device *pdev)
-{
-	struct ata_host *host = platform_get_drvdata(pdev);
-	struct mv_host_priv *hpriv = host->private_data;
-	int port;
-	ata_host_detach(host);
-
-	for (port = 0; port < host->n_ports; port++)
-		phy_power_off(hpriv->port_phys[port]);
+	return ata_host_activate(host, irq, mv_interrupt, IRQF_SHARED, &mv6_sht);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -4232,7 +4218,7 @@ MODULE_DEVICE_TABLE(of, mv_sata_dt_ids);
 
 static struct platform_driver mv_platform_driver = {
 	.probe		= mv_platform_probe,
-	.remove		= mv_platform_remove,
+	.remove		= ata_platform_remove_one,
 	.suspend	= mv_platform_suspend,
 	.resume		= mv_platform_resume,
 	.driver		= {
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.