From 96d60303fd3336893a93565d58c4f1805a327061 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Sun, 28 Mar 2010 00:37:21 -0400 Subject: [PATCH] ahci: Turn off DMA engines when there's no device attached According to section 10.3.1 of the AHCI spec, PxCMD.ST must not be set unless there's a device attached. Following this saves us a measurable quantity of power and does not impair hotplug support. Based on a patch by Kristen Carlson Accardi. Signed-off-by: Matthew Garrett Cc: Kristen Carlson Accardi Signed-off-by: Jeff Garzik --- drivers/ata/libahci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 38e1b4e..3f586ec 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -437,11 +437,29 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) return -EINVAL; } +static int ahci_is_device_present(void __iomem *port_mmio) +{ + u8 status = readl(port_mmio + PORT_TFDATA) & 0xff; + + /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */ + if (status & (ATA_BUSY | ATA_DRQ)) + return 0; + + /* Make sure PxSSTS.DET is 3h */ + status = readl(port_mmio + PORT_SCR_STAT) & 0xf; + if (status != 3) + return 0; + return 1; +} + void ahci_start_engine(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; + if (!ahci_is_device_present(port_mmio)) + return; + /* start DMA */ tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_START; -- 1.8.2.3