diff mbox series

[11/19] ata: libata-core: Detach a port devices on shutdown

Message ID 20230911040217.253905-12-dlemoal@kernel.org
State New
Headers show
Series Fix libata suspend/resume handling and code cleanup | expand

Commit Message

Damien Le Moal Sept. 11, 2023, 4:02 a.m. UTC
Modify ata_pci_shutdown_one() to schedule EH to unload a port devices
before freezing and thawing the port. This ensures that drives are
cleanly disabled and transitioned to standby power mode when
a PCI adapter is removed or the system is powered off.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-core.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

Comments

Hannes Reinecke Sept. 11, 2023, 6:59 a.m. UTC | #1
On 9/11/23 06:02, Damien Le Moal wrote:
> Modify ata_pci_shutdown_one() to schedule EH to unload a port devices
> before freezing and thawing the port. This ensures that drives are
> cleanly disabled and transitioned to standby power mode when
> a PCI adapter is removed or the system is powered off.
> 
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
>   drivers/ata/libata-core.c | 16 +++++++++++++++-
>   1 file changed, 15 insertions(+), 1 deletion(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
AceLan Kao Sept. 13, 2023, 1:46 a.m. UTC | #2
On Mon, Sep 11, 2023 at 01:02:09PM +0900, Damien Le Moal wrote:
> Modify ata_pci_shutdown_one() to schedule EH to unload a port devices
> before freezing and thawing the port. This ensures that drives are
> cleanly disabled and transitioned to standby power mode when
> a PCI adapter is removed or the system is powered off.
> 
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Tested-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
diff mbox series

Patch

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fafd5a82c5ea..fa70d0ef92e5 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6168,10 +6168,24 @@  EXPORT_SYMBOL_GPL(ata_pci_remove_one);
 void ata_pci_shutdown_one(struct pci_dev *pdev)
 {
 	struct ata_host *host = pci_get_drvdata(pdev);
+	struct ata_port *ap;
+	unsigned long flags;
 	int i;
 
+	/* Tell EH to disable all devices */
 	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
+		ap = host->ports[i];
+		spin_lock_irqsave(ap->lock, flags);
+		ap->pflags |= ATA_PFLAG_UNLOADING;
+		ata_port_schedule_eh(ap);
+		spin_unlock_irqrestore(ap->lock, flags);
+	}
+
+	for (i = 0; i < host->n_ports; i++) {
+		ap = host->ports[i];
+
+		/* Wait for EH to complete before freezing the port */
+		ata_port_wait_eh(ap);
 
 		ap->pflags |= ATA_PFLAG_FROZEN;