Re: [patch 2/2] Enable Aggressive Link Power management for AHCI controllers.
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.
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.
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.
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 */