ata: sata_mv: Cleanup only the initialized ports
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Sun, 16 Feb 2014 15:29:53 +0000 (12:29 -0300)
committerTejun Heo <tj@kernel.org>
Sun, 16 Feb 2014 16:51:17 +0000 (11:51 -0500)
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
drivers/ata/sata_mv.c

index 20a7517bd3393d1a2adfcb6e4cb55afcd833e5f9..9c1a11de30441f0cc26b32a05dd91adecef68a18 100644 (file)
@@ -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]);
This page took 0.029856 seconds and 5 git commands to generate.