aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fd332612d64a..81898036dbca 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6827,19 +6827,6 @@ static void ata_host_release(struct device *gendev, void *res)
6827 if (!ap) 6827 if (!ap)
6828 continue; 6828 continue;
6829 6829
6830 if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
6831 ap->ops->port_stop(ap);
6832 }
6833
6834 if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
6835 host->ops->host_stop(host);
6836
6837 for (i = 0; i < host->n_ports; i++) {
6838 struct ata_port *ap = host->ports[i];
6839
6840 if (!ap)
6841 continue;
6842
6843 if (ap->scsi_host) 6830 if (ap->scsi_host)
6844 scsi_host_put(ap->scsi_host); 6831 scsi_host_put(ap->scsi_host);
6845 6832
@@ -6966,6 +6953,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
6966 return host; 6953 return host;
6967} 6954}
6968 6955
6956static void ata_host_stop(struct device *gendev, void *res)
6957{
6958 struct ata_host *host = dev_get_drvdata(gendev);
6959 int i;
6960
6961 WARN_ON(!(host->flags & ATA_HOST_STARTED));
6962
6963 for (i = 0; i < host->n_ports; i++) {
6964 struct ata_port *ap = host->ports[i];
6965
6966 if (ap->ops->port_stop)
6967 ap->ops->port_stop(ap);
6968 }
6969
6970 if (host->ops->host_stop)
6971 host->ops->host_stop(host);
6972}
6973
6969/** 6974/**
6970 * ata_host_start - start and freeze ports of an ATA host 6975 * ata_host_start - start and freeze ports of an ATA host
6971 * @host: ATA host to start ports for 6976 * @host: ATA host to start ports for
@@ -6984,6 +6989,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
6984 */ 6989 */
6985int ata_host_start(struct ata_host *host) 6990int ata_host_start(struct ata_host *host)
6986{ 6991{
6992 int have_stop = 0;
6993 void *start_dr = NULL;
6987 int i, rc; 6994 int i, rc;
6988 6995
6989 if (host->flags & ATA_HOST_STARTED) 6996 if (host->flags & ATA_HOST_STARTED)
@@ -6995,6 +7002,22 @@ int ata_host_start(struct ata_host *host)
6995 if (!host->ops && !ata_port_is_dummy(ap)) 7002 if (!host->ops && !ata_port_is_dummy(ap))
6996 host->ops = ap->ops; 7003 host->ops = ap->ops;
6997 7004
7005 if (ap->ops->port_stop)
7006 have_stop = 1;
7007 }
7008
7009 if (host->ops->host_stop)
7010 have_stop = 1;
7011
7012 if (have_stop) {
7013 start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL);
7014 if (!start_dr)
7015 return -ENOMEM;
7016 }
7017
7018 for (i = 0; i < host->n_ports; i++) {
7019 struct ata_port *ap = host->ports[i];
7020
6998 if (ap->ops->port_start) { 7021 if (ap->ops->port_start) {
6999 rc = ap->ops->port_start(ap); 7022 rc = ap->ops->port_start(ap);
7000 if (rc) { 7023 if (rc) {
@@ -7007,6 +7030,8 @@ int ata_host_start(struct ata_host *host)
7007 ata_eh_freeze_port(ap); 7030 ata_eh_freeze_port(ap);
7008 } 7031 }
7009 7032
7033 if (start_dr)
7034 devres_add(host->dev, start_dr);
7010 host->flags |= ATA_HOST_STARTED; 7035 host->flags |= ATA_HOST_STARTED;
7011 return 0; 7036 return 0;
7012 7037
@@ -7017,6 +7042,7 @@ int ata_host_start(struct ata_host *host)
7017 if (ap->ops->port_stop) 7042 if (ap->ops->port_stop)
7018 ap->ops->port_stop(ap); 7043 ap->ops->port_stop(ap);
7019 } 7044 }
7045 devres_free(start_dr);
7020 return rc; 7046 return rc;
7021} 7047}
7022 7048