aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNate Watterson <nwatters@codeaurora.org>2017-07-20 15:26:24 -0400
committerTejun Heo <tj@kernel.org>2017-08-04 16:34:14 -0400
commit8eede5bc4ef04281fbba7ddfe157052d0e76075d (patch)
tree87c88cf41e67e8168c4fd7c965d7ec323bb76e67
parentafbd39a42e2d777852a2809298fd4e71b1e5abf7 (diff)
ata: ahci_platform: Add shutdown handler
The newly introduced ahci_platform_shutdown() method is called during system shutdown to disable host controller DMA and interrupts in order to avoid potentially corrupting or otherwise interfering with a new kernel being started with kexec. Signed-off-by: Nate Watterson <nwatters@codeaurora.org> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--drivers/ata/ahci_platform.c1
-rw-r--r--drivers/ata/libahci_platform.c34
-rw-r--r--include/linux/ahci_platform.h2
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 62a04c8fb5c9..99f9a895a459 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -93,6 +93,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
93static struct platform_driver ahci_driver = { 93static struct platform_driver ahci_driver = {
94 .probe = ahci_probe, 94 .probe = ahci_probe,
95 .remove = ata_platform_remove_one, 95 .remove = ata_platform_remove_one,
96 .shutdown = ahci_platform_shutdown,
96 .driver = { 97 .driver = {
97 .name = DRV_NAME, 98 .name = DRV_NAME,
98 .of_match_table = ahci_of_match, 99 .of_match_table = ahci_of_match,
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index cd2eab6aa92e..a270a1173c8c 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -602,6 +602,40 @@ static void ahci_host_stop(struct ata_host *host)
602 ahci_platform_disable_resources(hpriv); 602 ahci_platform_disable_resources(hpriv);
603} 603}
604 604
605/**
606 * ahci_platform_shutdown - Disable interrupts and stop DMA for host ports
607 * @dev: platform device pointer for the host
608 *
609 * This function is called during system shutdown and performs the minimal
610 * deconfiguration required to ensure that an ahci_platform host cannot
611 * corrupt or otherwise interfere with a new kernel being started with kexec.
612 */
613void ahci_platform_shutdown(struct platform_device *pdev)
614{
615 struct ata_host *host = platform_get_drvdata(pdev);
616 struct ahci_host_priv *hpriv = host->private_data;
617 void __iomem *mmio = hpriv->mmio;
618 int i;
619
620 for (i = 0; i < host->n_ports; i++) {
621 struct ata_port *ap = host->ports[i];
622
623 /* Disable port interrupts */
624 if (ap->ops->freeze)
625 ap->ops->freeze(ap);
626
627 /* Stop the port DMA engines */
628 if (ap->ops->port_stop)
629 ap->ops->port_stop(ap);
630 }
631
632 /* Disable and clear host interrupts */
633 writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL);
634 readl(mmio + HOST_CTL); /* flush */
635 writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT);
636}
637EXPORT_SYMBOL_GPL(ahci_platform_shutdown);
638
605#ifdef CONFIG_PM_SLEEP 639#ifdef CONFIG_PM_SLEEP
606/** 640/**
607 * ahci_platform_suspend_host - Suspend an ahci-platform host 641 * ahci_platform_suspend_host - Suspend an ahci-platform host
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index a270f25ee7c7..1b0a17b22cd3 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -36,6 +36,8 @@ int ahci_platform_init_host(struct platform_device *pdev,
36 const struct ata_port_info *pi_template, 36 const struct ata_port_info *pi_template,
37 struct scsi_host_template *sht); 37 struct scsi_host_template *sht);
38 38
39void ahci_platform_shutdown(struct platform_device *pdev);
40
39int ahci_platform_suspend_host(struct device *dev); 41int ahci_platform_suspend_host(struct device *dev);
40int ahci_platform_resume_host(struct device *dev); 42int ahci_platform_resume_host(struct device *dev);
41int ahci_platform_suspend(struct device *dev); 43int ahci_platform_suspend(struct device *dev);