diff options
author | Tejun Heo <htejun@gmail.com> | 2007-03-09 11:36:12 +0100 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-03-09 14:41:16 +0100 |
commit | 1aa506e437a94d520f852d39d5d6a6e7f2e01901 (patch) | |
tree | f001596d659c278ef8d78de1e11eae7b9198705c /drivers/ata | |
parent | sata_nv: revert use of notifiers for now (diff) | |
download | linux-1aa506e437a94d520f852d39d5d6a6e7f2e01901.tar.xz linux-1aa506e437a94d520f852d39d5d6a6e7f2e01901.zip |
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.c | 16 |
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); } |