From: Matthew Garrett Date: Sun, 28 Mar 2010 04:37:21 +0000 (-0400) Subject: ahci: Turn off DMA engines when there's no device attached X-Git-Tag: v2.6.35-rc1~481^2~38 X-Git-Url: http://ftp.safe.ca/?p=safe%2Fjmp%2Flinux-2.6;a=commitdiff_plain;h=96d60303fd 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 --- 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;