Move ahci platform shutdown function to libahci as preparation to add shutdown handler for PCIe AHCI. Signed-off-by: Hanna Hawa <hhhawa@xxxxxxxxxx> --- drivers/ata/ahci.h | 1 + drivers/ata/libahci.c | 33 +++++++++++++++++++++++++++++++++ drivers/ata/libahci_platform.c | 20 +------------------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 3dbf398c92ea..df84dfdf9037 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -418,6 +418,7 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv, int ahci_reset_em(struct ata_host *host); void ahci_print_info(struct ata_host *host, const char *scc_s); int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht); +void ahci_common_shutdown(struct ata_host *host); void ahci_error_handler(struct ata_port *ap); u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index bff369d9a1a7..f5dd5d66c442 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2602,6 +2602,39 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht) } EXPORT_SYMBOL_GPL(ahci_host_activate); +/** + * ahci_common_shutdown - Disable interrupts and stop DMA for host ports + * @host: target ATA host + * + * This common function is called during system shutdown and performs the + * minimal deconfiguration required to ensure that an ahci host cannot corrupt + * or otherwise interfere with a new kernel being started with kexec. + */ +void ahci_common_shutdown(struct ata_host *host) +{ + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->mmio; + int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + /* Disable port interrupts */ + if (ap->ops->freeze) + ap->ops->freeze(ap); + + /* Stop the port DMA engines */ + if (ap->ops->port_stop) + ap->ops->port_stop(ap); + } + + /* Disable and clear host interrupts */ + writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT); +} +EXPORT_SYMBOL_GPL(ahci_common_shutdown); + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Common AHCI SATA low-level routines"); MODULE_LICENSE("GPL"); diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 8befce036af8..dd2bfa3986f8 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -680,26 +680,8 @@ static void ahci_host_stop(struct ata_host *host) void ahci_platform_shutdown(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); - struct ahci_host_priv *hpriv = host->private_data; - void __iomem *mmio = hpriv->mmio; - int i; - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - /* Disable port interrupts */ - if (ap->ops->freeze) - ap->ops->freeze(ap); - /* Stop the port DMA engines */ - if (ap->ops->port_stop) - ap->ops->port_stop(ap); - } - - /* Disable and clear host interrupts */ - writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT); + ahci_common_shutdown(host); } EXPORT_SYMBOL_GPL(ahci_platform_shutdown); -- 2.17.1