diff options
author | Matthew Garrett <mjg@redhat.com> | 2010-03-28 00:37:21 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2010-05-14 17:08:01 -0400 |
commit | 96d60303fd3336893a93565d58c4f1805a327061 (patch) | |
tree | e6534dabeceb4a0a0b511c17dbffe47639fff0ac /drivers/ata/libahci.c | |
parent | 1c2a49f61785ebbcbfb481a2aab659020f0457f7 (diff) |
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 <mjg@redhat.com>
Cc: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r-- | drivers/ata/libahci.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 38e1b4e9ecf4..3f586ec84a3c 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) | |||
437 | return -EINVAL; | 437 | return -EINVAL; |
438 | } | 438 | } |
439 | 439 | ||
440 | static int ahci_is_device_present(void __iomem *port_mmio) | ||
441 | { | ||
442 | u8 status = readl(port_mmio + PORT_TFDATA) & 0xff; | ||
443 | |||
444 | /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */ | ||
445 | if (status & (ATA_BUSY | ATA_DRQ)) | ||
446 | return 0; | ||
447 | |||
448 | /* Make sure PxSSTS.DET is 3h */ | ||
449 | status = readl(port_mmio + PORT_SCR_STAT) & 0xf; | ||
450 | if (status != 3) | ||
451 | return 0; | ||
452 | return 1; | ||
453 | } | ||
454 | |||
440 | void ahci_start_engine(struct ata_port *ap) | 455 | void ahci_start_engine(struct ata_port *ap) |
441 | { | 456 | { |
442 | void __iomem *port_mmio = ahci_port_base(ap); | 457 | void __iomem *port_mmio = ahci_port_base(ap); |
443 | u32 tmp; | 458 | u32 tmp; |
444 | 459 | ||
460 | if (!ahci_is_device_present(port_mmio)) | ||
461 | return; | ||
462 | |||
445 | /* start DMA */ | 463 | /* start DMA */ |
446 | tmp = readl(port_mmio + PORT_CMD); | 464 | tmp = readl(port_mmio + PORT_CMD); |
447 | tmp |= PORT_CMD_START; | 465 | tmp |= PORT_CMD_START; |