diff options
author | Tejun Heo <htejun@gmail.com> | 2007-03-09 05:36:12 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-03-09 08:41:16 -0500 |
commit | 1aa506e437a94d520f852d39d5d6a6e7f2e01901 (patch) | |
tree | f001596d659c278ef8d78de1e11eae7b9198705c /drivers/ata | |
parent | 8ba5e4cbe444f10352756b6c7715bb26bb087680 (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.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) | |||
5685 | for (i = 0; i < host->n_ports; i++) { | 5685 | for (i = 0; i < host->n_ports; i++) { |
5686 | struct ata_port *ap = host->ports[i]; | 5686 | struct ata_port *ap = host->ports[i]; |
5687 | 5687 | ||
5688 | if (!ap) | 5688 | if (ap && ap->ops->port_stop) |
5689 | continue; | ||
5690 | |||
5691 | if (ap->ops->port_stop) | ||
5692 | ap->ops->port_stop(ap); | 5689 | ap->ops->port_stop(ap); |
5693 | |||
5694 | scsi_host_put(ap->scsi_host); | ||
5695 | } | 5690 | } |
5696 | 5691 | ||
5697 | if (host->ops->host_stop) | 5692 | if (host->ops->host_stop) |
5698 | host->ops->host_stop(host); | 5693 | host->ops->host_stop(host); |
5699 | 5694 | ||
5695 | for (i = 0; i < host->n_ports; i++) { | ||
5696 | struct ata_port *ap = host->ports[i]; | ||
5697 | |||
5698 | if (ap) | ||
5699 | scsi_host_put(ap->scsi_host); | ||
5700 | |||
5701 | host->ports[i] = NULL; | ||
5702 | } | ||
5703 | |||
5700 | dev_set_drvdata(gendev, NULL); | 5704 | dev_set_drvdata(gendev, NULL); |
5701 | } | 5705 | } |
5702 | 5706 | ||