diff options
-rw-r--r-- | drivers/ata/libata-core.c | 52 |
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 | ||
6956 | static 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 | */ |
6985 | int ata_host_start(struct ata_host *host) | 6990 | int 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 | ||