summaryrefslogtreecommitdiff
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-03-09 19:36:12 +0900
committerJeff Garzik <jeff@garzik.org>2007-03-09 08:41:16 -0500
commit1aa506e437a94d520f852d39d5d6a6e7f2e01901 (patch)
treef001596d659c278ef8d78de1e11eae7b9198705c /drivers/ata
parent8ba5e4cbe444f10352756b6c7715bb26bb087680 (diff)
libata: fix ata_host_release() free order
host->ops->host_stop() might access ports. Free ports after host_stop. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f6408ca82062..3c1f8830ac8b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5685,18 +5685,22 @@ static void ata_host_release(struct device *gendev, void *res)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- if (!ap)
- continue;
-
- if (ap->ops->port_stop)
+ if (ap && ap->ops->port_stop)
ap->ops->port_stop(ap);
-
- scsi_host_put(ap->scsi_host);
}
if (host->ops->host_stop)
host->ops->host_stop(host);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap)
+ scsi_host_put(ap->scsi_host);
+
+ host->ports[i] = NULL;
+ }
+
dev_set_drvdata(gendev, NULL);
}