Re: [PATCH v3 13/15] ata: ahci: add FLUSH EXT and STANDBY IMMEDIATE support during shutdown

"Sascha Hauer" <[email protected]> Mon, 03 Aug 2026 21:52:50 +0000
Newsgroups org.infradead.lists.barebox
Message-ID <[email protected]>
On 2026-08-02 15:16, Luca Lauro via B4 Relay wrote:
> From: Luca Lauro <[email protected]>
>=20
> Some AHCI controllers require ATA FLUSH EXT and STANDBY IMMEDIATE to be
> issued before poweroff to ensure data integrity and proper device
> shutdown. This patch introduces ahci_port_shutdown(), which sends these
> commands using ahci_ata_nodata(), and integrates it into a new AHCI
> poweroff handler.
>=20
> Signed-off-by: Luca Lauro <[email protected]>
> ---
>  drivers/ata/ahci.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++=
++++++
>  1 file changed, 60 insertions(+)
>=20
> diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> index 2504f4d19a..a9a3f43f21 100644
> --- a/drivers/ata/ahci.c
> +++ b/drivers/ata/ahci.c
> @@ -48,6 +48,9 @@
>  #define ahci_debug(ahci, fmt, arg...) \
>  	dev_dbg(ahci->dev, fmt, ##arg)
> =20
> +#define ATA_CMD_FLUSH_EXT 0xEA
> +#define ATA_CMD_STANDBYNOW1 0xE0
> +
>  #ifndef PCI_VENDOR_ID_MARVELL_EXT
>  #define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b
>  #endif
> @@ -680,6 +683,63 @@ static int ahci_probe(struct device *dev)
>  	return ret;
>  }
> =20
> +/* Issue FLUSH EXT + STANDBY IMMEDIATE */
> +static void ahci_port_shutdown(struct ahci_port *port)
> +{
> +	if (!port->cmd_tbl || !port->cmd_slot)
> +		return;
> +
> +	if (!ahci_link_ok(port, 0))
> +		return;
> +
> +	if (ahci_ata_nodata(port, ATA_CMD_FLUSH_EXT, 0))
> +		ahci_port_info(port, "FLUSH EXT failed\n");
> +
> +	if (ahci_ata_nodata(port, ATA_CMD_STANDBYNOW1, 0))
> +		ahci_port_info(port, "STANDBY IMMEDIATE failed\n");
> +}
> +
> +/* Full poweroff sequence */
> +static void ahci_poweroff(struct poweroff_handler *handler, unsigned lon=
g flags)
> +{
> +	struct ahci_device *ahci;
> +	int i, n_ports;
> +
> +	list_for_each_entry(ahci, &ahci_devices, list) {
> +
> +		if (!ahci->mmio_base)
> +			continue;
> +
> +		/* FLUSH + STANDBY on all active ports */
> +		n_ports =3D max_t(int, ahci->n_ports, fls(ahci->port_map));
> +
> +		for (i =3D 0; i < n_ports; i++) {
> +			struct ahci_port *port =3D &ahci->ports[i];
> +
> +			if (!(ahci->port_map & (1 << i)))
> +				continue;
> +
> +			ahci_port_shutdown(port);
> +		}
> +
> +		/* (optional) shutsown controller after commands
> +		* ahci_shutdown_host(ahci);
> +		*/
> +	}
> +}
> +
> +static struct poweroff_handler ahci_po_handler =3D {
> +	.poweroff =3D ahci_poweroff,
> +	.priority =3D 200,   /* higher than gpio-poweroff */
> +};
> +
> +static int ahci_register_poweroff(void)
> +{
> +	poweroff_handler_register(&ahci_po_handler);

A poweroff handler is the thing that actually powers off the system,
i.e. the gpio-poweroff handler toggles the GPIO that cuts the power to
the system.

You are looking for something to hook into poweroff_machine() and we
currently don't have anything for this.

We might want to call shutdown_barebox() before calling
poweroff_machine(). That way you could hook into the struct
driver->remove function. That would mean though that the ahci port
shutdown would also be called before starting Linux. If you do not want
that we could introduce some flag indicating the shutdown reason
(poweroff vs. start Linux)

Sascha

--=20
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |