Re: [patch 2/2] Enable Aggressive Link Power management for AHCI controllers.

2007-10-24 Thread Jeff Garzik

Kristen Carlson Accardi wrote:

This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible 
settings for this feature are:


Setting Effect
--
min_power	ALPM is enabled, and link set to enter 
		lowest power state (SLUMBER) when idle

Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi <[EMAIL PROTECTED]>


applied, with minor changes (attached)

Please check libata-dev.git#alpm and make sure it still works as 
expected (after it mirrors out to git.kernel.org)



commit 0fdf9763a76f4cce208b7139e555019217765e81
Author: Kristen Carlson Accardi <[EMAIL PROTECTED]>
Date:   Thu Oct 25 01:33:26 2007 -0400

[libata] AHCI: add hw link power management support

This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible
settings for this feature are:

Setting Effect
--
min_power   ALPM is enabled, and link set to enter
lowest power state (SLUMBER) when idle
Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi <[EMAIL PROTECTED]>
Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>

 drivers/ata/ahci.c |  157 -
 1 file changed, 155 insertions(+), 2 deletions(-)

0fdf9763a76f4cce208b7139e555019217765e81
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 95229e7..2b4faca 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -48,6 +48,9 @@
 #define DRV_NAME   "ahci"
 #define DRV_VERSION"3.0"
 
+static int ahci_enable_alpm(struct ata_port *ap,
+   enum link_pm policy);
+static void ahci_disable_alpm(struct ata_port *ap);
 
 enum {
AHCI_PCI_BAR= 5,
@@ -98,6 +101,7 @@ enum {
HOST_CAP_SSC= (1 << 14), /* Slumber capable */
HOST_CAP_PMP= (1 << 17), /* Port Multiplier support */
HOST_CAP_CLO= (1 << 24), /* Command List Override support */
+   HOST_CAP_ALPM   = (1 << 26), /* Aggressive Link PM support */
HOST_CAP_SSS= (1 << 27), /* Staggered Spin-up */
HOST_CAP_SNTF   = (1 << 29), /* SNotification register */
HOST_CAP_NCQ= (1 << 30), /* Native Command Queueing */
@@ -154,6 +158,8 @@ enum {
  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
/* PORT_CMD bits */
+   PORT_CMD_ASP= (1 << 27), /* Aggressive Slumber/Partial */
+   PORT_CMD_ALPE   = (1 << 26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI  = (1 << 24), /* Device is ATAPI */
PORT_CMD_PMP= (1 << 17), /* PMP attached */
PORT_CMD_LIST_ON= (1 << 15), /* cmd list DMA engine running */
@@ -177,13 +183,14 @@ enum {
AHCI_HFLAG_MV_PATA  = (1 << 4), /* PATA port */
AHCI_HFLAG_NO_MSI   = (1 << 5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP   = (1 << 6), /* no PMP */
+   AHCI_HFLAG_NO_HOTPLUG   = (1 << 7), /* ignore PxSERR.DIAG.N */
 
/* ap->flags bits */
-   AHCI_FLAG_NO_HOTPLUG= (1 << 24), /* ignore PxSERR.DIAG.N */
 
AHCI_FLAG_COMMON= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+ ATA_FLAG_IPM,
AHCI_LFLAG_COMMON   = ATA_LFLAG_SKIP_D2H_BSY,
 };
 
@@ -252,6 

Re: [patch 2/2] Enable Aggressive Link Power management for AHCI controllers.

2007-10-24 Thread Jeff Garzik

Kristen Carlson Accardi wrote:

This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible 
settings for this feature are:


Setting Effect
--
min_power	ALPM is enabled, and link set to enter 
		lowest power state (SLUMBER) when idle

Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi [EMAIL PROTECTED]


applied, with minor changes (attached)

Please check libata-dev.git#alpm and make sure it still works as 
expected (after it mirrors out to git.kernel.org)



commit 0fdf9763a76f4cce208b7139e555019217765e81
Author: Kristen Carlson Accardi [EMAIL PROTECTED]
Date:   Thu Oct 25 01:33:26 2007 -0400

[libata] AHCI: add hw link power management support

This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible
settings for this feature are:

Setting Effect
--
min_power   ALPM is enabled, and link set to enter
lowest power state (SLUMBER) when idle
Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi [EMAIL PROTECTED]
Signed-off-by: Jeff Garzik [EMAIL PROTECTED]

 drivers/ata/ahci.c |  157 -
 1 file changed, 155 insertions(+), 2 deletions(-)

0fdf9763a76f4cce208b7139e555019217765e81
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 95229e7..2b4faca 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -48,6 +48,9 @@
 #define DRV_NAME   ahci
 #define DRV_VERSION3.0
 
+static int ahci_enable_alpm(struct ata_port *ap,
+   enum link_pm policy);
+static void ahci_disable_alpm(struct ata_port *ap);
 
 enum {
AHCI_PCI_BAR= 5,
@@ -98,6 +101,7 @@ enum {
HOST_CAP_SSC= (1  14), /* Slumber capable */
HOST_CAP_PMP= (1  17), /* Port Multiplier support */
HOST_CAP_CLO= (1  24), /* Command List Override support */
+   HOST_CAP_ALPM   = (1  26), /* Aggressive Link PM support */
HOST_CAP_SSS= (1  27), /* Staggered Spin-up */
HOST_CAP_SNTF   = (1  29), /* SNotification register */
HOST_CAP_NCQ= (1  30), /* Native Command Queueing */
@@ -154,6 +158,8 @@ enum {
  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
/* PORT_CMD bits */
+   PORT_CMD_ASP= (1  27), /* Aggressive Slumber/Partial */
+   PORT_CMD_ALPE   = (1  26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI  = (1  24), /* Device is ATAPI */
PORT_CMD_PMP= (1  17), /* PMP attached */
PORT_CMD_LIST_ON= (1  15), /* cmd list DMA engine running */
@@ -177,13 +183,14 @@ enum {
AHCI_HFLAG_MV_PATA  = (1  4), /* PATA port */
AHCI_HFLAG_NO_MSI   = (1  5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP   = (1  6), /* no PMP */
+   AHCI_HFLAG_NO_HOTPLUG   = (1  7), /* ignore PxSERR.DIAG.N */
 
/* ap-flags bits */
-   AHCI_FLAG_NO_HOTPLUG= (1  24), /* ignore PxSERR.DIAG.N */
 
AHCI_FLAG_COMMON= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+ ATA_FLAG_IPM,
AHCI_LFLAG_COMMON   = ATA_LFLAG_SKIP_D2H_BSY,
 };
 
@@ -252,6 +259,11 @@ static int ahci_pci_device_suspend(struct 

[patch 2/2] Enable Aggressive Link Power management for AHCI controllers.

2007-09-24 Thread Kristen Carlson Accardi
This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible 
settings for this feature are:

Setting Effect
--
min_power   ALPM is enabled, and link set to enter 
lowest power state (SLUMBER) when idle
Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi <[EMAIL PROTECTED]>

---
 drivers/ata/ahci.c |  154 -
 1 file changed, 153 insertions(+), 1 deletion(-)

Index: libata-dev/drivers/ata/ahci.c
===
--- libata-dev.orig/drivers/ata/ahci.c  2007-09-24 13:43:10.0 -0700
+++ libata-dev/drivers/ata/ahci.c   2007-09-24 13:48:59.0 -0700
@@ -48,6 +48,9 @@
 #define DRV_NAME   "ahci"
 #define DRV_VERSION"2.3"
 
+static int ahci_enable_alpm(struct ata_port *ap,
+   enum link_pm policy);
+static int ahci_disable_alpm(struct ata_port *ap);
 
 enum {
AHCI_PCI_BAR= 5,
@@ -97,6 +100,7 @@ enum {
/* HOST_CAP bits */
HOST_CAP_SSC= (1 << 14), /* Slumber capable */
HOST_CAP_CLO= (1 << 24), /* Command List Override support */
+   HOST_CAP_ALPM   = (1 << 26), /* Aggressive Link PM support */
HOST_CAP_SSS= (1 << 27), /* Staggered Spin-up */
HOST_CAP_SNTF   = (1 << 29), /* SNotification register */
HOST_CAP_NCQ= (1 << 30), /* Native Command Queueing */
@@ -152,6 +156,8 @@ enum {
  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
/* PORT_CMD bits */
+   PORT_CMD_ASP= (1 << 27), /* Aggressive Slumber/Partial */
+   PORT_CMD_ALPE   = (1 << 26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI  = (1 << 24), /* Device is ATAPI */
PORT_CMD_LIST_ON= (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
@@ -177,7 +183,7 @@ enum {
 
AHCI_FLAG_COMMON= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_ACPI_SATA,
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_IPM,
AHCI_LFLAG_COMMON   = ATA_LFLAG_SKIP_D2H_BSY,
 };
 
@@ -242,6 +248,11 @@ static int ahci_pci_device_suspend(struc
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
 
+static struct class_device_attribute *ahci_shost_attrs[] = {
+   _device_attr_link_power_management_policy,
+   NULL
+};
+
 static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name   = DRV_NAME,
@@ -259,6 +270,7 @@ static struct scsi_host_template ahci_sh
.slave_configure= ata_scsi_slave_config,
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .shost_attrs= ahci_shost_attrs,
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -286,6 +298,8 @@ static const struct ata_port_operations 
.port_suspend   = ahci_port_suspend,
.port_resume= ahci_port_resume,
 #endif
+   .enable_pm  = ahci_enable_alpm,
+   .disable_pm = ahci_disable_alpm,
 
.port_start = ahci_port_start,
.port_stop  = ahci_port_stop,
@@ -767,6 +781,130 @@ static void ahci_power_up(struct ata_por
writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+static int ahci_disable_alpm(struct ata_port *ap)
+{
+   void __iomem *port_mmio = ahci_port_base(ap);
+   u32 cmd;
+   struct ahci_port_priv *pp = ap->private_data;
+
+   /* IPM bits should be disabled by libata-core */
+   /* get the existing command bits */
+   cmd = readl(port_mmio + PORT_CMD);
+
+   /* disable ALPM and ASP */
+   cmd &= ~PORT_CMD_ASP;
+   cmd &= ~PORT_CMD_ALPE;
+
+   /* force the interface back to active */
+   cmd |= PORT_CMD_ICC_ACTIVE;
+
+   /* write out new cmd value */
+   writel(cmd, port_mmio + PORT_CMD);
+   cmd = readl(port_mmio + PORT_CMD);
+
+   /* wait 10ms to be sure we've come out 

[patch 2/2] Enable Aggressive Link Power management for AHCI controllers.

2007-09-24 Thread Kristen Carlson Accardi
This patch will set the correct bits to turn on Aggressive
Link Power Management (ALPM) for the ahci driver.  This
will cause the controller and disk to negotiate a lower
power state for the link when there is no activity (see
the AHCI 1.x spec for details).  This feature is mutually
exclusive with Hot Plug, so when ALPM is enabled, Hot Plug
is disabled.  ALPM will be enabled by default, but it is
settable via the scsi host syfs interface.  Possible 
settings for this feature are:

Setting Effect
--
min_power   ALPM is enabled, and link set to enter 
lowest power state (SLUMBER) when idle
Hot plug not allowed.

max_performance ALPM is disabled, Hot Plug is allowed

medium_powerALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle.  Hot plug not allowed.

Signed-off-by:  Kristen Carlson Accardi [EMAIL PROTECTED]

---
 drivers/ata/ahci.c |  154 -
 1 file changed, 153 insertions(+), 1 deletion(-)

Index: libata-dev/drivers/ata/ahci.c
===
--- libata-dev.orig/drivers/ata/ahci.c  2007-09-24 13:43:10.0 -0700
+++ libata-dev/drivers/ata/ahci.c   2007-09-24 13:48:59.0 -0700
@@ -48,6 +48,9 @@
 #define DRV_NAME   ahci
 #define DRV_VERSION2.3
 
+static int ahci_enable_alpm(struct ata_port *ap,
+   enum link_pm policy);
+static int ahci_disable_alpm(struct ata_port *ap);
 
 enum {
AHCI_PCI_BAR= 5,
@@ -97,6 +100,7 @@ enum {
/* HOST_CAP bits */
HOST_CAP_SSC= (1  14), /* Slumber capable */
HOST_CAP_CLO= (1  24), /* Command List Override support */
+   HOST_CAP_ALPM   = (1  26), /* Aggressive Link PM support */
HOST_CAP_SSS= (1  27), /* Staggered Spin-up */
HOST_CAP_SNTF   = (1  29), /* SNotification register */
HOST_CAP_NCQ= (1  30), /* Native Command Queueing */
@@ -152,6 +156,8 @@ enum {
  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
/* PORT_CMD bits */
+   PORT_CMD_ASP= (1  27), /* Aggressive Slumber/Partial */
+   PORT_CMD_ALPE   = (1  26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI  = (1  24), /* Device is ATAPI */
PORT_CMD_LIST_ON= (1  15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1  14), /* FIS DMA engine running */
@@ -177,7 +183,7 @@ enum {
 
AHCI_FLAG_COMMON= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_ACPI_SATA,
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_IPM,
AHCI_LFLAG_COMMON   = ATA_LFLAG_SKIP_D2H_BSY,
 };
 
@@ -242,6 +248,11 @@ static int ahci_pci_device_suspend(struc
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
 
+static struct class_device_attribute *ahci_shost_attrs[] = {
+   class_device_attr_link_power_management_policy,
+   NULL
+};
+
 static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name   = DRV_NAME,
@@ -259,6 +270,7 @@ static struct scsi_host_template ahci_sh
.slave_configure= ata_scsi_slave_config,
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .shost_attrs= ahci_shost_attrs,
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -286,6 +298,8 @@ static const struct ata_port_operations 
.port_suspend   = ahci_port_suspend,
.port_resume= ahci_port_resume,
 #endif
+   .enable_pm  = ahci_enable_alpm,
+   .disable_pm = ahci_disable_alpm,
 
.port_start = ahci_port_start,
.port_stop  = ahci_port_stop,
@@ -767,6 +781,130 @@ static void ahci_power_up(struct ata_por
writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+static int ahci_disable_alpm(struct ata_port *ap)
+{
+   void __iomem *port_mmio = ahci_port_base(ap);
+   u32 cmd;
+   struct ahci_port_priv *pp = ap-private_data;
+
+   /* IPM bits should be disabled by libata-core */
+   /* get the existing command bits */
+   cmd = readl(port_mmio + PORT_CMD);
+
+   /* disable ALPM and ASP */
+   cmd = ~PORT_CMD_ASP;
+   cmd = ~PORT_CMD_ALPE;
+
+   /* force the interface back to active */
+   cmd |= PORT_CMD_ICC_ACTIVE;
+
+   /* write out new cmd value */
+   writel(cmd, port_mmio + PORT_CMD);
+   cmd = readl(port_mmio + PORT_CMD);
+
+   /* wait 10ms to be sure we've come out of any low power state */