aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-20 01:42:36 -0500
committerTejun Heo <htejun@gmail.com>2006-12-03 03:56:29 -0500
commit8e16f941226f15622fbbc416a1f3d8705001a191 (patch)
tree97bf87ebff9e3e69caa0a0ebdd9ee9291c5dfac5 /drivers/ata/ahci.c
parent70e6ad0c6d1e6cb9ee3c036a85ca2561eb1fd766 (diff)
[PATCH] ahci: do not powerdown during initialization
ahci_init_controller() calls ahci_deinit_port() to make sure the controller is stopped before initializing the controller. In turn, ahci_deinit_port() invokes ahci_power_down() to power down the port. If the controller supports slumber mode, the link is put into it. Unfortunately, some devices don't implement link powersaving mode properly and show erratic behavior after link is put into slumber mode. For example, HL-DT-ST DVD-RAM GSA-H30N completely locks up on slumber transition and can only be recovered with the *REAL* hard reset - power removal and reapply. Note that this makes the first probing reset different from all others. If the above dvd-ram is hotplugged after ahci is initialized, no problem occurs because ahci is already fully initialized with phy powered up. So, this might also be the reason for other weird AHCI initial probing abnormalities. This patch moves power up/down out of port init/deinit and call them only when needed. Power down is now called only when suspending. As system suspend usually involves powering down 12v for storage devices, this shouldn't cause problem even if the attached device doesn't support slumber mode. However, in partial power management and suspend failure cases, devices might lock up after suspend attempt. I thought about removing transition to slumber mode altogether but ahci spec mandates it before HBA D3 state transition. Blacklisting such devices might be the solution. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index af3565d1fefe..f36da488a2c1 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -612,9 +612,6 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
612static void ahci_init_port(void __iomem *port_mmio, u32 cap, 612static void ahci_init_port(void __iomem *port_mmio, u32 cap,
613 dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) 613 dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
614{ 614{
615 /* power up */
616 ahci_power_up(port_mmio, cap);
617
618 /* enable FIS reception */ 615 /* enable FIS reception */
619 ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); 616 ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
620 617
@@ -640,9 +637,6 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
640 return rc; 637 return rc;
641 } 638 }
642 639
643 /* put device into slumber mode */
644 ahci_power_down(port_mmio, cap);
645
646 return 0; 640 return 0;
647} 641}
648 642
@@ -1321,7 +1315,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
1321 int rc; 1315 int rc;
1322 1316
1323 rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); 1317 rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
1324 if (rc) { 1318 if (rc == 0)
1319 ahci_power_down(port_mmio, hpriv->cap);
1320 else {
1325 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); 1321 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
1326 ahci_init_port(port_mmio, hpriv->cap, 1322 ahci_init_port(port_mmio, hpriv->cap,
1327 pp->cmd_slot_dma, pp->rx_fis_dma); 1323 pp->cmd_slot_dma, pp->rx_fis_dma);
@@ -1337,6 +1333,7 @@ static int ahci_port_resume(struct ata_port *ap)
1337 void __iomem *mmio = ap->host->mmio_base; 1333 void __iomem *mmio = ap->host->mmio_base;
1338 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1334 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
1339 1335
1336 ahci_power_up(port_mmio, hpriv->cap);
1340 ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); 1337 ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
1341 1338
1342 return 0; 1339 return 0;
@@ -1443,6 +1440,9 @@ static int ahci_port_start(struct ata_port *ap)
1443 1440
1444 ap->private_data = pp; 1441 ap->private_data = pp;
1445 1442
1443 /* power up port */
1444 ahci_power_up(port_mmio, hpriv->cap);
1445
1446 /* initialize port */ 1446 /* initialize port */
1447 ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); 1447 ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
1448 1448