aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>2014-02-16 12:29:53 -0300
committerTejun Heo <tj@kernel.org>2014-02-16 11:51:17 -0500
commit8ad116e649b21a42e3cccfb3c1b8d5ea52ba19e5 (patch)
treec5a69d0a235864821b6ad4d46c9a280b72f95e7f
parent9f9c47f00ce99329b1a82e2ac4f70f0fe3db549c (diff)
ata: sata_mv: Cleanup only the initialized ports
When an error occurs in the port initialization loop, currently the driver tries to cleanup all the ports. This results in a NULL pointer dereference if the ports were only partially initialized. Fix this by updating only the number of initialized ports (either with failure or successfully), before jumping to the error path and looping over that number in the cleanup loop. Cc: Andrew Lunn <andrew@lunn.ch> Reported-by: Mikael Pettersson <mikpelinux@gmail.com> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--drivers/ata/sata_mv.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 20a7517bd33..9c1a11de304 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4104,7 +4104,6 @@ static int mv_platform_probe(struct platform_device *pdev)
if (!hpriv->port_phys)
return -ENOMEM;
host->private_data = hpriv;
- hpriv->n_ports = n_ports;
hpriv->board_idx = chip_soc;
host->iomap = NULL;
@@ -4132,11 +4131,17 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->port_phys[port] = NULL;
if ((rc != -EPROBE_DEFER) && (rc != -ENODEV))
dev_warn(&pdev->dev, "error getting phy");
+
+ /* Cleanup only the initialized ports */
+ hpriv->n_ports = port;
goto err;
} else
phy_power_on(hpriv->port_phys[port]);
}
+ /* All the ports have been initialized */
+ hpriv->n_ports = n_ports;
+
/*
* (Re-)program MBUS remapping windows if we are asked to.
*/
@@ -4174,7 +4179,7 @@ err:
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
- for (port = 0; port < n_ports; port++) {
+ for (port = 0; port < hpriv->n_ports; port++) {
if (!IS_ERR(hpriv->port_clks[port])) {
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);