aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-06-07 09:15:08 -0400
committerJeff Garzik <jgarzik@redhat.com>2010-06-07 16:03:15 -0400
commit0ee719527229fa86ace8e3abccae3c2a8bbfd6db (patch)
tree7c9e76554f55af8101f38b8e3338529b66b4d275 /drivers
parent7a4f876b876afb13856a79a0402f71b9dfbe86a8 (diff)
ahci: redo stopping DMA engines on empty ports
Commit 96d60303fd (ahci: Turn off DMA engines when there's no device) implemented stopping DMA engines on empty ports but it used single sampling of status registers to determine device presence which led to disabling of DMA engines on occupied ports. Do it after all EH actions are complete using device presence state determined by EH. This avoids spurious disabling of DMA engines and simplifies the code. Signed-off-by: Tejun Heo <tj@kernel.org> Tested-by: Marc Dionne <marc.c.dionne@gmail.com> Cc: Matthew Garrett <mjg@redhat.com> Cc: Robert Hancock <hancockrwd@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libahci.c21
1 files changed, 3 insertions, 18 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 1984a6e89e84..261f86d102e8 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -541,29 +541,11 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
541 return -EINVAL; 541 return -EINVAL;
542} 542}
543 543
544static int ahci_is_device_present(void __iomem *port_mmio)
545{
546 u8 status = readl(port_mmio + PORT_TFDATA) & 0xff;
547
548 /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */
549 if (status & (ATA_BUSY | ATA_DRQ))
550 return 0;
551
552 /* Make sure PxSSTS.DET is 3h */
553 status = readl(port_mmio + PORT_SCR_STAT) & 0xf;
554 if (status != 3)
555 return 0;
556 return 1;
557}
558
559void ahci_start_engine(struct ata_port *ap) 544void ahci_start_engine(struct ata_port *ap)
560{ 545{
561 void __iomem *port_mmio = ahci_port_base(ap); 546 void __iomem *port_mmio = ahci_port_base(ap);
562 u32 tmp; 547 u32 tmp;
563 548
564 if (!ahci_is_device_present(port_mmio))
565 return;
566
567 /* start DMA */ 549 /* start DMA */
568 tmp = readl(port_mmio + PORT_CMD); 550 tmp = readl(port_mmio + PORT_CMD);
569 tmp |= PORT_CMD_START; 551 tmp |= PORT_CMD_START;
@@ -1892,6 +1874,9 @@ static void ahci_error_handler(struct ata_port *ap)
1892 } 1874 }
1893 1875
1894 sata_pmp_error_handler(ap); 1876 sata_pmp_error_handler(ap);
1877
1878 if (!ata_dev_enabled(ap->link.device))
1879 ahci_stop_engine(ap);
1895} 1880}
1896 1881
1897static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1882static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)