Matthias Brugger 5534a2
From: Prabhakar Kushwaha <pkushwaha@marvell.com>
Matthias Brugger 5534a2
Date: Sat, 25 Jan 2020 03:37:29 +0000
Matthias Brugger 5534a2
Subject: ata: ahci: Add shutdown to freeze hardware resources of ahci
Matthias Brugger 5534a2
Git-commit: 10a663a1b15134a5a714aa515e11425a44d4fdf7
Matthias Brugger 5534a2
Patch-mainline: v5.6-rc1
Matthias Brugger 5534a2
References: bsc#1164388
Matthias Brugger 5534a2
Matthias Brugger 5534a2
device_shutdown() called from reboot or power_shutdown expect
Matthias Brugger 5534a2
all devices to be shutdown. Same is true for even ahci pci driver.
Matthias Brugger 5534a2
As no ahci shutdown function is implemented, the ata subsystem
Matthias Brugger 5534a2
always remains alive with DMA & interrupt support. File system
Matthias Brugger 5534a2
related calls should not be honored after device_shutdown().
Matthias Brugger 5534a2
Matthias Brugger 5534a2
So defining ahci pci driver shutdown to freeze hardware (mask
Matthias Brugger 5534a2
interrupt, stop DMA engine and free DMA resources).
Matthias Brugger 5534a2
Matthias Brugger 5534a2
Signed-off-by: Prabhakar Kushwaha <pkushwaha@marvell.com>
Matthias Brugger 5534a2
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Matthias Brugger 5534a2
Signed-off-by: Matthias Brugger <mbrugger@suse.com>
Matthias Brugger 5534a2
---
Matthias Brugger 5534a2
 drivers/ata/ahci.c        |  7 +++++++
Matthias Brugger 5534a2
 drivers/ata/libata-core.c | 21 +++++++++++++++++++++
Matthias Brugger 5534a2
 include/linux/libata.h    |  1 +
Matthias Brugger 5534a2
 3 files changed, 29 insertions(+)
Matthias Brugger 5534a2
Matthias Brugger 5534a2
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
Matthias Brugger 5534a2
index 4bfd1b14b390..11ea1aff40db 100644
Matthias Brugger 5534a2
--- a/drivers/ata/ahci.c
Matthias Brugger 5534a2
+++ b/drivers/ata/ahci.c
Matthias Brugger 5534a2
@@ -81,6 +81,7 @@ enum board_ids {
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Matthias Brugger 5534a2
 static void ahci_remove_one(struct pci_dev *dev);
Matthias Brugger 5534a2
+static void ahci_shutdown_one(struct pci_dev *dev);
Matthias Brugger 5534a2
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Matthias Brugger 5534a2
 				 unsigned long deadline);
Matthias Brugger 5534a2
 static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
Matthias Brugger 5534a2
@@ -606,6 +607,7 @@ static struct pci_driver ahci_pci_driver = {
Matthias Brugger 5534a2
 	.id_table		= ahci_pci_tbl,
Matthias Brugger 5534a2
 	.probe			= ahci_init_one,
Matthias Brugger 5534a2
 	.remove			= ahci_remove_one,
Matthias Brugger 5534a2
+	.shutdown		= ahci_shutdown_one,
Matthias Brugger 5534a2
 	.driver = {
Matthias Brugger 5534a2
 		.pm		= &ahci_pci_pm_ops,
Matthias Brugger 5534a2
 	},
Matthias Brugger 5534a2
@@ -1877,6 +1879,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Matthias Brugger 5534a2
 	return 0;
Matthias Brugger 5534a2
 }
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
+static void ahci_shutdown_one(struct pci_dev *pdev)
Matthias Brugger 5534a2
+{
Matthias Brugger 5534a2
+	ata_pci_shutdown_one(pdev);
Matthias Brugger 5534a2
+}
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
 static void ahci_remove_one(struct pci_dev *pdev)
Matthias Brugger 5534a2
 {
Matthias Brugger 5534a2
 	pm_runtime_get_noresume(&pdev->dev);
Matthias Brugger 5534a2
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
Matthias Brugger 5534a2
index 6f4ab5c5b52d..42c8728f6117 100644
Matthias Brugger 5534a2
--- a/drivers/ata/libata-core.c
Matthias Brugger 5534a2
+++ b/drivers/ata/libata-core.c
Matthias Brugger 5534a2
@@ -6767,6 +6767,26 @@ void ata_pci_remove_one(struct pci_dev *pdev)
Matthias Brugger 5534a2
 	ata_host_detach(host);
Matthias Brugger 5534a2
 }
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
+void ata_pci_shutdown_one(struct pci_dev *pdev)
Matthias Brugger 5534a2
+{
Matthias Brugger 5534a2
+	struct ata_host *host = pci_get_drvdata(pdev);
Matthias Brugger 5534a2
+	int i;
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
+	for (i = 0; i < host->n_ports; i++) {
Matthias Brugger 5534a2
+		struct ata_port *ap = host->ports[i];
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
+		ap->pflags |= ATA_PFLAG_FROZEN;
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
+		/* Disable port interrupts */
Matthias Brugger 5534a2
+		if (ap->ops->freeze)
Matthias Brugger 5534a2
+			ap->ops->freeze(ap);
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
+		/* Stop the port DMA engines */
Matthias Brugger 5534a2
+		if (ap->ops->port_stop)
Matthias Brugger 5534a2
+			ap->ops->port_stop(ap);
Matthias Brugger 5534a2
+	}
Matthias Brugger 5534a2
+}
Matthias Brugger 5534a2
+
Matthias Brugger 5534a2
 /* move to PCI subsystem */
Matthias Brugger 5534a2
 int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
Matthias Brugger 5534a2
 {
Matthias Brugger 5534a2
@@ -7387,6 +7407,7 @@ EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
 #ifdef CONFIG_PCI
Matthias Brugger 5534a2
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
Matthias Brugger 5534a2
+EXPORT_SYMBOL_GPL(ata_pci_shutdown_one);
Matthias Brugger 5534a2
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
Matthias Brugger 5534a2
 #ifdef CONFIG_PM
Matthias Brugger 5534a2
 EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
Matthias Brugger 5534a2
diff --git a/include/linux/libata.h b/include/linux/libata.h
Matthias Brugger 5534a2
index 2dbde119721d..bff539918d82 100644
Matthias Brugger 5534a2
--- a/include/linux/libata.h
Matthias Brugger 5534a2
+++ b/include/linux/libata.h
Matthias Brugger 5534a2
@@ -1221,6 +1221,7 @@ struct pci_bits {
Matthias Brugger 5534a2
 };
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
 extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
Matthias Brugger 5534a2
+extern void ata_pci_shutdown_one(struct pci_dev *pdev);
Matthias Brugger 5534a2
 extern void ata_pci_remove_one(struct pci_dev *pdev);
Matthias Brugger 5534a2
 
Matthias Brugger 5534a2
 #ifdef CONFIG_PM
Matthias Brugger 5534a2
-- 
Matthias Brugger 5534a2
2.25.0
Matthias Brugger 5534a2