* [patch 1/4] Store interrupt value
[not found] <20070705194909.337398431@intel.com>
@ 2007-07-05 20:05 ` Kristen Carlson Accardi
2007-08-01 8:18 ` Tejun Heo
2007-08-01 14:01 ` Jeff Garzik
2007-07-05 20:05 ` [patch 2/4] Expose Power Management Policy option to users Kristen Carlson Accardi
` (2 subsequent siblings)
3 siblings, 2 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-05 20:05 UTC (permalink / raw)
To: jeff
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi, Kristen Carlson Accardi
Use a stored value for which interrupts to enable. Changing this allows
us to selectively turn off certain interrupts later and have them
stay off.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c
+++ 2.6-git/drivers/ata/ahci.c
@@ -211,6 +211,7 @@ struct ahci_port_priv {
unsigned int ncq_saw_d2h:1;
unsigned int ncq_saw_dmas:1;
unsigned int ncq_saw_sdb:1;
+ u32 intr_mask; /* interrupts to enable */
};
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -1408,6 +1409,7 @@ static void ahci_thaw(struct ata_port *a
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
+ struct ahci_port_priv *pp = ap->private_data;
/* clear IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
@@ -1415,7 +1417,7 @@ static void ahci_thaw(struct ata_port *a
writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
/* turn IRQ back on */
- writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
static void ahci_error_handler(struct ata_port *ap)
@@ -1571,6 +1573,12 @@ static int ahci_port_start(struct ata_po
pp->cmd_tbl = mem;
pp->cmd_tbl_dma = mem_dma;
+ /*
+ * Save off initial list of interrupts to be enabled.
+ * This could be changed later
+ */
+ pp->intr_mask = DEF_PORT_IRQ;
+
ap->private_data = pp;
/* power up port */
--
^ permalink raw reply [flat|nested] 43+ messages in thread
* [patch 2/4] Expose Power Management Policy option to users
[not found] <20070705194909.337398431@intel.com>
2007-07-05 20:05 ` [patch 1/4] Store interrupt value Kristen Carlson Accardi
@ 2007-07-05 20:05 ` Kristen Carlson Accardi
2007-07-09 19:36 ` Pavel Machek
2007-07-30 16:32 ` Jeff Garzik
2007-07-05 20:05 ` [patch 3/4] Enable link power management for ata drivers Kristen Carlson Accardi
2007-07-05 20:05 ` [patch 4/4] Enable Aggressive Link Power management for AHCI controllers Kristen Carlson Accardi
3 siblings, 2 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-05 20:05 UTC (permalink / raw)
To: jeff
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi, Kristen Carlson Accardi
This patch will modify the scsi subsystem to allow
users to set a power management policy for the link.
The scsi subsystem will create a new sysfs file for each
host in /sys/class/scsi_host called "link_power_management_policy".
This file can have 3 possible values:
Value Meaning
-------------------------------------------------------------------
min_power User wishes the link to conserve power as much as
possible, even at the cost of some performance
max_performance User wants priority to be on performance, not power
savings
medium_power User wants power savings, with less performance cost
than min_power (but less power savings as well).
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/scsi/hosts.c
===================================================================
--- 2.6-git.orig/drivers/scsi/hosts.c
+++ 2.6-git/drivers/scsi/hosts.c
@@ -54,6 +54,25 @@ static struct class shost_class = {
};
/**
+ * scsi_host_set_link_pm - Change the link power management policy
+ * @shost: scsi host to change the policy of.
+ * @policy: policy to change to.
+ *
+ * Returns zero if successful or an error if the requested
+ * transition is illegal.
+ **/
+int scsi_host_set_link_pm(struct Scsi_Host *shost,
+ enum scsi_host_link_pm policy)
+{
+ struct scsi_host_template *sht = shost->hostt;
+ if (sht->set_link_pm_policy)
+ sht->set_link_pm_policy(shost, policy);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_host_set_link_pm);
+
+/**
* scsi_host_set_state - Take the given host through the host
* state model.
* @shost: scsi host to change the state of.
Index: 2.6-git/drivers/scsi/scsi_sysfs.c
===================================================================
--- 2.6-git.orig/drivers/scsi/scsi_sysfs.c
+++ 2.6-git/drivers/scsi/scsi_sysfs.c
@@ -189,6 +189,74 @@ show_shost_state(struct class_device *cl
static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+static const struct {
+ enum scsi_host_link_pm value;
+ char *name;
+} shost_link_pm_policy[] = {
+ { SHOST_NOT_AVAILABLE, "max_performance" },
+ { SHOST_MIN_POWER, "min_power" },
+ { SHOST_MAX_PERFORMANCE, "max_performance" },
+ { SHOST_MEDIUM_POWER, "medium_power" },
+};
+
+const char *scsi_host_link_pm_policy(enum scsi_host_link_pm policy)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(shost_link_pm_policy); i++) {
+ if (shost_link_pm_policy[i].value == policy) {
+ name = shost_link_pm_policy[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
+static ssize_t store_link_pm_policy(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ enum scsi_host_link_pm policy = 0;
+ int i;
+
+ /*
+ * we are skipping array location 0 on purpose - this
+ * is because a value of SHOST_NOT_AVAILABLE is displayed
+ * to the user as max_performance, but when the user
+ * writes "max_performance", they actually want the
+ * value to match SHOST_MAX_PERFORMANCE.
+ */
+ for (i = 1; i < ARRAY_SIZE(shost_link_pm_policy); i++) {
+ const int len = strlen(shost_link_pm_policy[i].name);
+ if (strncmp(shost_link_pm_policy[i].name, buf, len) == 0 &&
+ buf[len] == '\n') {
+ policy = shost_link_pm_policy[i].value;
+ break;
+ }
+ }
+ if (!policy)
+ return -EINVAL;
+
+ if (scsi_host_set_link_pm(shost, policy))
+ return -EINVAL;
+ return count;
+}
+static ssize_t
+show_link_pm_policy(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ const char *policy =
+ scsi_host_link_pm_policy(shost->shost_link_pm_policy);
+
+ if (!policy)
+ return -EINVAL;
+
+ return snprintf(buf, 23, "%s\n", policy);
+}
+static CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+ show_link_pm_policy, store_link_pm_policy);
+
shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -207,6 +275,7 @@ static struct class_device_attribute *sc
&class_device_attr_proc_name,
&class_device_attr_scan,
&class_device_attr_state,
+ &class_device_attr_link_power_management_policy,
NULL
};
Index: 2.6-git/include/scsi/scsi_host.h
===================================================================
--- 2.6-git.orig/include/scsi/scsi_host.h
+++ 2.6-git/include/scsi/scsi_host.h
@@ -42,6 +42,16 @@ enum scsi_eh_timer_return {
EH_RESET_TIMER,
};
+/*
+ * shost pm policy: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions)
+ */
+enum scsi_host_link_pm {
+ SHOST_NOT_AVAILABLE,
+ SHOST_MIN_POWER,
+ SHOST_MAX_PERFORMANCE,
+ SHOST_MEDIUM_POWER,
+};
struct scsi_host_template {
struct module *module;
@@ -345,6 +355,12 @@ struct scsi_host_template {
int (*suspend)(struct scsi_device *, pm_message_t state);
/*
+ * link power management support
+ */
+ int (*set_link_pm_policy)(struct Scsi_Host *, enum scsi_host_link_pm);
+ enum scsi_host_link_pm default_link_pm_policy;
+
+ /*
* Name of proc directory
*/
char *proc_name;
@@ -642,6 +658,7 @@ struct Scsi_Host {
enum scsi_host_state shost_state;
+ enum scsi_host_link_pm shost_link_pm_policy;
/* ldm bits */
struct device shost_gendev;
@@ -749,4 +766,5 @@ extern struct Scsi_Host *scsi_register(s
extern void scsi_unregister(struct Scsi_Host *);
extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
+extern int scsi_host_set_link_pm(struct Scsi_Host *, enum scsi_host_link_pm);
#endif /* _SCSI_SCSI_HOST_H */
Index: 2.6-git/Documentation/scsi/link_power_management_policy.txt
===================================================================
--- /dev/null
+++ 2.6-git/Documentation/scsi/link_power_management_policy.txt
@@ -0,0 +1,19 @@
+This parameter allows the user to set the link (interface) power management.
+There are 3 possible options:
+
+Value Effect
+----------------------------------------------------------------------------
+min_power Tell the controller to try to make the link use the
+ least possible power when possible. This may
+ sacrifice some performance due to increased latency
+ when coming out of lower power states.
+
+max_performance Generally, this means no power management. Tell
+ the controller to have performance be a priority
+ over power management.
+
+medium_power Tell the controller to enter a lower power state
+ when possible, but do not enter the lowest power
+ state, thus improving latency over min_power setting.
+
+
--
^ permalink raw reply [flat|nested] 43+ messages in thread
* [patch 3/4] Enable link power management for ata drivers
[not found] <20070705194909.337398431@intel.com>
2007-07-05 20:05 ` [patch 1/4] Store interrupt value Kristen Carlson Accardi
2007-07-05 20:05 ` [patch 2/4] Expose Power Management Policy option to users Kristen Carlson Accardi
@ 2007-07-05 20:05 ` Kristen Carlson Accardi
2007-07-05 22:33 ` Andrew Morton
2007-08-01 8:27 ` Tejun Heo
2007-07-05 20:05 ` [patch 4/4] Enable Aggressive Link Power management for AHCI controllers Kristen Carlson Accardi
3 siblings, 2 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-05 20:05 UTC (permalink / raw)
To: jeff
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi, Kristen Carlson Accardi
libata drivers can define a function (enable_pm) that will
perform hardware specific actions to enable whatever power
management policy the user set up from the scsi sysfs
interface if the driver supports it. This power management
policy will be activated after all disks have been
enumerated and intialized. Drivers should also define
disable_pm, which will turn off link power management, but
not change link power management policy.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c
+++ 2.6-git/drivers/ata/libata-scsi.c
@@ -2905,6 +2905,51 @@ void ata_scsi_simulate(struct ata_device
}
}
+int ata_scsi_set_link_pm_policy(struct Scsi_Host *shost,
+ enum scsi_host_link_pm policy)
+{
+ struct ata_port *ap = ata_shost_to_port(shost);
+ int rc = -EINVAL;
+ int i;
+
+ /*
+ * make sure no broken devices are on this port,
+ * and that all devices support interface power
+ * management
+ */
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+
+ /* only check drives which exist */
+ if (!ata_dev_enabled(dev))
+ continue;
+
+ /*
+ * do we need to handle the case where we've hotplugged
+ * a broken drive (since hotplug and ALPM are mutually
+ * exclusive) ?
+ *
+ * If so, if we detect a broken drive on a port with
+ * alpm already enabled, then we should reset the policy
+ * to off for the entire port.
+ */
+ if ((dev->horkage & ATA_HORKAGE_ALPM) ||
+ !(dev->flags & ATA_DFLAG_IPM)) {
+ ata_dev_printk(dev, KERN_ERR,
+ "Unable to set Link PM policy\n");
+ ap->pm_policy = SHOST_MAX_PERFORMANCE;
+ }
+ }
+
+ if (ap->ops->enable_pm)
+ rc = ap->ops->enable_pm(ap, policy);
+
+ if (!rc)
+ shost->shost_link_pm_policy = ap->pm_policy;
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ata_scsi_set_link_pm_policy);
+
int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
{
int i, rc;
@@ -2927,7 +2972,7 @@ int ata_scsi_add_hosts(struct ata_host *
shost->max_lun = 1;
shost->max_channel = 1;
shost->max_cmd_len = 16;
-
+ shost->shost_link_pm_policy = ap->pm_policy;
rc = scsi_add_host(ap->scsi_host, ap->host->dev);
if (rc)
goto err_add;
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h
+++ 2.6-git/include/linux/libata.h
@@ -136,6 +136,7 @@ enum {
ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+ ATA_DFLAG_IPM = (1 << 6), /* device supports interface PM */
ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
@@ -298,6 +299,7 @@ enum {
ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */
+ ATA_HORKAGE_ALPM = (1 << 4), /* ALPM problems */
};
enum hsm_task_states {
@@ -546,6 +548,7 @@ struct ata_port {
pm_message_t pm_mesg;
int *pm_result;
+ enum scsi_host_link_pm pm_policy;
void *private_data;
@@ -605,7 +608,8 @@ struct ata_port_operations {
int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
int (*port_resume) (struct ata_port *ap);
-
+ int (*enable_pm) (struct ata_port *ap, enum scsi_host_link_pm policy);
+ int (*disable_pm) (struct ata_port *ap);
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@@ -811,7 +815,7 @@ extern int ata_cable_40wire(struct ata_p
extern int ata_cable_80wire(struct ata_port *ap);
extern int ata_cable_sata(struct ata_port *ap);
extern int ata_cable_unknown(struct ata_port *ap);
-
+extern int ata_scsi_set_link_pm_policy(struct Scsi_Host *shost, enum scsi_host_link_pm);
/*
* Timing helpers
*/
Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c
+++ 2.6-git/drivers/ata/libata-core.c
@@ -2021,6 +2021,9 @@ int ata_dev_configure(struct ata_device
if (dev->flags & ATA_DFLAG_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+ if (ata_id_has_hipm(dev->id) || ata_id_has_dipm(dev->id))
+ dev->flags |= ATA_DFLAG_IPM;
+
if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
/* Let the user know. We don't want to disallow opens for
rescue purposes, or in case the vendor is just a blithering
@@ -2046,6 +2049,13 @@ int ata_dev_configure(struct ata_device
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
+ if (ata_device_blacklisted(dev) & ATA_HORKAGE_ALPM) {
+ dev->horkage |= ATA_HORKAGE_ALPM;
+
+ /* reset link pm_policy for this port to no pm */
+ ap->pm_policy = SHOST_MAX_PERFORMANCE;
+ }
+
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -5807,6 +5817,28 @@ int ata_flush_cache(struct ata_device *d
return 0;
}
+static void ata_host_disable_link_pm(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ if (ap->ops->disable_pm)
+ ap->ops->disable_pm(ap);
+ }
+}
+
+static void ata_host_enable_link_pm(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ ata_scsi_set_link_pm_policy(ap->scsi_host,
+ ap->pm_policy);
+ }
+}
+
#ifdef CONFIG_PM
static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
unsigned int action, unsigned int ehi_flags,
@@ -5874,6 +5906,12 @@ int ata_host_suspend(struct ata_host *ho
{
int rc;
+ /*
+ * disable link pm on all ports before requesting
+ * any pm activity
+ */
+ ata_host_disable_link_pm(host);
+
rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
if (rc == 0)
host->dev->power.power_state = mesg;
@@ -5896,6 +5934,9 @@ void ata_host_resume(struct ata_host *ho
ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host->dev->power.power_state = PMSG_ON;
+
+ /* reenable link pm */
+ ata_host_enable_link_pm(host);
}
#endif
@@ -6385,6 +6426,8 @@ int ata_host_register(struct ata_host *h
struct ata_port *ap = host->ports[i];
ata_scsi_scan_host(ap);
+ ata_scsi_set_link_pm_policy(ap->scsi_host,
+ ap->pm_policy);
}
return 0;
Index: 2.6-git/include/linux/ata.h
===================================================================
--- 2.6-git.orig/include/linux/ata.h
+++ 2.6-git/include/linux/ata.h
@@ -321,6 +321,8 @@ struct ata_taskfile {
((u64) (id)[(n) + 0]) )
#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
+#define ata_id_has_hipm(id) ((id)[76] & (1 << 9))
+#define ata_id_has_dipm(id) ((id)[78] & (1 << 3))
static inline unsigned int ata_id_major_version(const u16 *id)
{
--
^ permalink raw reply [flat|nested] 43+ messages in thread
* [patch 4/4] Enable Aggressive Link Power management for AHCI controllers.
[not found] <20070705194909.337398431@intel.com>
` (2 preceding siblings ...)
2007-07-05 20:05 ` [patch 3/4] Enable link power management for ata drivers Kristen Carlson Accardi
@ 2007-07-05 20:05 ` Kristen Carlson Accardi
3 siblings, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-05 20:05 UTC (permalink / raw)
To: jeff
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi, 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_power ALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle. Hot plug not allowed.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c
+++ 2.6-git/drivers/ata/ahci.c
@@ -48,6 +48,9 @@
#define DRV_NAME "ahci"
#define DRV_VERSION "2.2"
+static int ahci_enable_alpm(struct ata_port *ap,
+ enum scsi_host_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_NCQ = (1 << 30), /* Native Command Queueing */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
@@ -151,6 +155,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 */
@@ -171,6 +177,7 @@ enum {
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
+ AHCI_FLAG_NO_HOTPLUG = (1 << 29), /* ignore PxSERR.DIAG.N */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -253,6 +260,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,
+ .set_link_pm_policy = ata_scsi_set_link_pm_policy,
};
static const struct ata_port_operations ahci_ops = {
@@ -284,6 +292,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,
@@ -719,6 +729,156 @@ 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, scontrol;
+ struct ahci_port_priv *pp = ap->private_data;
+
+ /*
+ * disable Interface Power Management State Transitions
+ * This is accomplished by setting bits 8:11 of the
+ * SATA Control register
+ */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol |= (0x3 << 8);
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+ /* 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 */
+ msleep(10);
+
+ /* clear out any PhyRdy stuff from interrupt status */
+ writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
+
+ /* go ahead and clean out PhyRdy Change from Serror too */
+ ahci_scr_write(ap, SCR_ERROR, (1 << 16));
+
+ /*
+ * Clear flag to indicate that we should ignore all PhyRdy
+ * state changes
+ */
+ ap->flags &= ~AHCI_FLAG_NO_HOTPLUG;
+
+ /*
+ * Enable interrupts on Phy Ready.
+ */
+ pp->intr_mask |= PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * don't change the link pm policy - we can be called
+ * just to turn of link pm temporarily
+ */
+ return 0;
+}
+
+static int ahci_enable_alpm(struct ata_port *ap,
+ enum scsi_host_link_pm policy)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 cmd, scontrol, sstatus;
+ struct ahci_port_priv *pp = ap->private_data;
+ u32 asp;
+
+ /* Make sure the host is capable of link power management */
+ if (!(hpriv->cap & HOST_CAP_ALPM)) {
+ ap->pm_policy = SHOST_NOT_AVAILABLE;
+ return -EINVAL;
+ }
+
+ /* make sure we have a device attached */
+ sstatus = readl(port_mmio + PORT_SCR_STAT);
+ if (!(sstatus & 0xf00)) {
+ ap->pm_policy = SHOST_NOT_AVAILABLE;
+ return -EINVAL;
+ }
+
+ switch (policy) {
+ case SHOST_MAX_PERFORMANCE:
+ case SHOST_NOT_AVAILABLE:
+ /*
+ * if we came here with SHOST_NOT_AVAILABLE,
+ * it just means this is the first time we
+ * have tried to enable - default to max performance,
+ * and let the user go to lower power modes on request.
+ */
+ ahci_disable_alpm(ap);
+ ap->pm_policy = SHOST_MAX_PERFORMANCE;
+ return 0;
+ case SHOST_MIN_POWER:
+ /* configure HBA to enter SLUMBER */
+ asp = PORT_CMD_ASP;
+ break;
+ case SHOST_MEDIUM_POWER:
+ /* configure HBA to enter PARTIAL */
+ asp = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ap->pm_policy = policy;
+
+ /*
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready interrupts
+ * TBD - Hot plug should be done via polling now, is
+ * that even supported?
+ */
+ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * Set a flag to indicate that we should ignore all PhyRdy
+ * state changes since these can happen now whenever we
+ * change link state
+ */
+ ap->flags |= AHCI_FLAG_NO_HOTPLUG;
+
+ /* get the existing command bits */
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /*
+ * enable Interface Power Management State Transitions
+ * This is accomplished by clearing bits 8:11 of the
+ * SATA Control register
+ */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol &= ~(0x3 << 8);
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+ /*
+ * Set ASP based on Policy
+ */
+ cmd |= asp;
+
+ /*
+ * Setting this bit will instruct the HBA to aggressively
+ * enter a lower power link state when it's appropriate and
+ * based on the value set above for ASP
+ */
+ cmd |= PORT_CMD_ALPE;
+
+ /* write out new cmd value */
+ writel(cmd, port_mmio + PORT_CMD);
+ cmd = readl(port_mmio + PORT_CMD);
+ return 0;
+}
+
#ifdef CONFIG_PM
static void ahci_power_down(struct ata_port *ap)
{
@@ -1244,6 +1404,10 @@ static void ahci_host_intr(struct ata_po
status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT);
+ if ((ap->flags & AHCI_FLAG_NO_HOTPLUG) &&
+ (status & PORT_IRQ_PHYRDY))
+ status &= ~PORT_IRQ_PHYRDY;
+
if (unlikely(status & PORT_IRQ_ERROR)) {
ahci_error_intr(ap, status);
return;
@@ -1759,6 +1923,7 @@ static int ahci_init_one(struct pci_dev
ap->ioaddr.cmd_addr = port_mmio;
ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
+ ap->pm_policy = SHOST_NOT_AVAILABLE;
} else
host->ports[i]->ops = &ata_dummy_port_ops;
}
--
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 20:05 ` [patch 3/4] Enable link power management for ata drivers Kristen Carlson Accardi
@ 2007-07-05 22:33 ` Andrew Morton
2007-07-05 22:37 ` Andrew Morton
2007-07-06 0:00 ` Jeff Garzik
2007-08-01 8:27 ` Tejun Heo
1 sibling, 2 replies; 43+ messages in thread
From: Andrew Morton @ 2007-07-05 22:33 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: jeff, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi
On Thu, 5 Jul 2007 13:05:30 -0700
Kristen Carlson Accardi <kristen.c.accardi@intel.com> wrote:
> + ATA_DFLAG_IPM = (1 << 6), /* device supports interface PM */
> ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
I had to bump this to (1<<7), so we've run out.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 22:33 ` Andrew Morton
@ 2007-07-05 22:37 ` Andrew Morton
2007-07-06 0:01 ` Jeff Garzik
2007-07-06 0:02 ` Jeff Garzik
2007-07-06 0:00 ` Jeff Garzik
1 sibling, 2 replies; 43+ messages in thread
From: Andrew Morton @ 2007-07-05 22:37 UTC (permalink / raw)
To: Kristen Carlson Accardi, jeff, linux-kernel, linux-ide,
James.Bottomley, edwintorok, axboe, linux-scsi
On Thu, 5 Jul 2007 15:33:34 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:
> On Thu, 5 Jul 2007 13:05:30 -0700
> Kristen Carlson Accardi <kristen.c.accardi@intel.com> wrote:
>
> > + ATA_DFLAG_IPM = (1 << 6), /* device supports interface PM */
> > ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
>
> I had to bump this to (1<<7), so we've run out.
err, no, we've more than run out because you AN patches took the last one.
I guess we can bump ATA_DFLAG_CFG_MASK up to 12, like this?
--- a/include/linux/libata.h~ata-ahci-alpm-enable-link-power-management-for-ata-drivers
+++ a/include/linux/libata.h
@@ -140,11 +140,12 @@ enum {
ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
ATA_DFLAG_AN = (1 << 7), /* device supports Async notification */
- ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
+ ATA_DFLAG_IPM = (1 << 8), /* device supports interface PM */
+ ATA_DFLAG_CFG_MASK = (1 << 12) - 1,
- ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
- ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */
- ATA_DFLAG_SPUNDOWN = (1 << 10), /* XXX: for spindown_compat */
+ ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */
+ ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
+ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
ATA_DFLAG_DETACH = (1 << 16),
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 22:33 ` Andrew Morton
2007-07-05 22:37 ` Andrew Morton
@ 2007-07-06 0:00 ` Jeff Garzik
1 sibling, 0 replies; 43+ messages in thread
From: Jeff Garzik @ 2007-07-06 0:00 UTC (permalink / raw)
To: Andrew Morton
Cc: Kristen Carlson Accardi, linux-kernel, linux-ide, James.Bottomley,
edwintorok, axboe, linux-scsi
Andrew Morton wrote:
> On Thu, 5 Jul 2007 13:05:30 -0700
> Kristen Carlson Accardi <kristen.c.accardi@intel.com> wrote:
>
>> + ATA_DFLAG_IPM = (1 << 6), /* device supports interface PM */
>> ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
>
> I had to bump this to (1<<7), so we've run out.
You can shuffle the numbers a bit, as long as the masks (*_MASK) stay
correct for their purpose
Jeff
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 22:37 ` Andrew Morton
@ 2007-07-06 0:01 ` Jeff Garzik
2007-07-06 0:02 ` Jeff Garzik
1 sibling, 0 replies; 43+ messages in thread
From: Jeff Garzik @ 2007-07-06 0:01 UTC (permalink / raw)
To: Andrew Morton
Cc: Kristen Carlson Accardi, linux-kernel, linux-ide, James.Bottomley,
edwintorok, axboe, linux-scsi
Andrew Morton wrote:
> I guess we can bump ATA_DFLAG_CFG_MASK up to 12, like this?
Yep
Jeff
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 22:37 ` Andrew Morton
2007-07-06 0:01 ` Jeff Garzik
@ 2007-07-06 0:02 ` Jeff Garzik
2007-07-06 0:17 ` Andrew Morton
1 sibling, 1 reply; 43+ messages in thread
From: Jeff Garzik @ 2007-07-06 0:02 UTC (permalink / raw)
To: Andrew Morton
Cc: Kristen Carlson Accardi, linux-kernel, linux-ide, James.Bottomley,
edwintorok, axboe, linux-scsi
May I assume that I may delete the patches from Kristen, and assume that
you will resend an updated version of her AN and ALPM patches to me?
Jeff
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-06 0:02 ` Jeff Garzik
@ 2007-07-06 0:17 ` Andrew Morton
0 siblings, 0 replies; 43+ messages in thread
From: Andrew Morton @ 2007-07-06 0:17 UTC (permalink / raw)
To: Jeff Garzik
Cc: Kristen Carlson Accardi, linux-kernel, linux-ide, James.Bottomley,
edwintorok, axboe, linux-scsi
On Thu, 05 Jul 2007 20:02:08 -0400
Jeff Garzik <jeff@garzik.org> wrote:
> May I assume that I may delete the patches from Kristen, and assume that
> you will resend an updated version of her AN and ALPM patches to me?
>
Sure. But I have a sneaking feeling that Kristen sneaks sneaky fixes into
her patches without telling me, so I won't be 100% confident about their
uptodateness (hint).
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-05 20:05 ` [patch 2/4] Expose Power Management Policy option to users Kristen Carlson Accardi
@ 2007-07-09 19:36 ` Pavel Machek
2007-07-11 16:51 ` Kristen Carlson Accardi
2007-07-30 16:32 ` Jeff Garzik
1 sibling, 1 reply; 43+ messages in thread
From: Pavel Machek @ 2007-07-09 19:36 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
Hi!
> This patch will modify the scsi subsystem to allow
> users to set a power management policy for the link.
>
> The scsi subsystem will create a new sysfs file for each
> host in /sys/class/scsi_host called "link_power_management_policy".
> This file can have 3 possible values:
>
> Value Meaning
> -------------------------------------------------------------------
> min_power User wishes the link to conserve power as much as
> possible, even at the cost of some performance
>
> max_performance User wants priority to be on performance, not power
> savings
>
> medium_power User wants power savings, with less performance cost
> than min_power (but less power savings as well).
Has that anything to do with HIPM vs. DIPM?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-09 19:36 ` Pavel Machek
@ 2007-07-11 16:51 ` Kristen Carlson Accardi
0 siblings, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-11 16:51 UTC (permalink / raw)
To: Pavel Machek
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
On Mon, 9 Jul 2007 19:36:04 +0000
Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
> > This patch will modify the scsi subsystem to allow
> > users to set a power management policy for the link.
> >
> > The scsi subsystem will create a new sysfs file for each
> > host in /sys/class/scsi_host called "link_power_management_policy".
> > This file can have 3 possible values:
> >
> > Value Meaning
> > -------------------------------------------------------------------
> > min_power User wishes the link to conserve power as much as
> > possible, even at the cost of some performance
> >
> > max_performance User wants priority to be on performance, not power
> > savings
> >
> > medium_power User wants power savings, with less performance cost
> > than min_power (but less power savings as well).
>
> Has that anything to do with HIPM vs. DIPM?
>
> Pavel
Hi Pavel,
I'm not sure I'm understanding your question, but if you mean the different
levels of power savings you would get, no. With ALPM you have the option of
instructing the link to either go into slumber or partial mode when it
determines the link is quiet. Slumber uses less power, but has more latency
to come out of. So, for a SATA device, setting the link_power_managment
file to "medium_power" will set up the link to only go into Partial mode,
which has less power savings (about half by my informal measurement), but
less latency, and therefore less of a performance hit.
Hopefully this answers your question.
Kristen
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-05 20:05 ` [patch 2/4] Expose Power Management Policy option to users Kristen Carlson Accardi
2007-07-09 19:36 ` Pavel Machek
@ 2007-07-30 16:32 ` Jeff Garzik
2007-07-31 6:27 ` Tejun Heo
1 sibling, 1 reply; 43+ messages in thread
From: Jeff Garzik @ 2007-07-30 16:32 UTC (permalink / raw)
To: Kristen Carlson Accardi, James.Bottomley, linux-scsi
Cc: akpm, linux-kernel, linux-ide, edwintorok, axboe
Kristen Carlson Accardi wrote:
> @@ -42,6 +42,16 @@ enum scsi_eh_timer_return {
> EH_RESET_TIMER,
> };
>
> +/*
> + * shost pm policy: If you alter this, you also need to alter scsi_sysfs.c
> + * (for the ascii descriptions)
> + */
> +enum scsi_host_link_pm {
> + SHOST_NOT_AVAILABLE,
> + SHOST_MIN_POWER,
> + SHOST_MAX_PERFORMANCE,
> + SHOST_MEDIUM_POWER,
> +};
>
> struct scsi_host_template {
> struct module *module;
> @@ -345,6 +355,12 @@ struct scsi_host_template {
> int (*suspend)(struct scsi_device *, pm_message_t state);
>
> /*
> + * link power management support
> + */
> + int (*set_link_pm_policy)(struct Scsi_Host *, enum scsi_host_link_pm);
> + enum scsi_host_link_pm default_link_pm_policy;
> +
> + /*
> * Name of proc directory
> */
> char *proc_name;
> @@ -642,6 +658,7 @@ struct Scsi_Host {
>
>
> enum scsi_host_state shost_state;
> + enum scsi_host_link_pm shost_link_pm_policy;
>
> /* ldm bits */
> struct device shost_gendev;
Any chance the SCSI peeps could ACK this, and then let me include it in
the ALPM patchset in the libata tree?
Jeff
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-30 16:32 ` Jeff Garzik
@ 2007-07-31 6:27 ` Tejun Heo
2007-07-31 14:16 ` Arjan van de Ven
` (2 more replies)
0 siblings, 3 replies; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 6:27 UTC (permalink / raw)
To: Jeff Garzik
Cc: Kristen Carlson Accardi, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
Jeff Garzik wrote:
> Any chance the SCSI peeps could ACK this, and then let me include it in
> the ALPM patchset in the libata tree?
ATA link PS is pretty complex with HIPM, DIPM and AHCI ALPM. I'm not
sure whether this three level knob would be sufficient. It might be
good enough if we're gonna develop extensive in-kernel black/white list
specifying which method works on which combination but my gut tells me
that it's best left to userland (probably in the form of per-notebook PS
profile).
Adding to the fun, there are quite a few broken devices out there which
act weirdly when link PS actions are taken.
Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
'cool down' period before entering PS state which unnecessarily hampers
performance and might increase chance of device malfunction.
So, mild NACK from me.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 6:27 ` Tejun Heo
@ 2007-07-31 14:16 ` Arjan van de Ven
2007-07-31 14:45 ` Tejun Heo
2007-07-31 14:58 ` Tejun Heo
2007-07-31 14:18 ` James Bottomley
2007-07-31 16:30 ` Kristen Carlson Accardi
2 siblings, 2 replies; 43+ messages in thread
From: Arjan van de Ven @ 2007-07-31 14:16 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
On Tue, 2007-07-31 at 15:27 +0900, Tejun Heo wrote:
> Jeff Garzik wrote:
> > Any chance the SCSI peeps could ACK this, and then let me include it in
> > the ALPM patchset in the libata tree?
>
> ATA link PS is pretty complex with HIPM, DIPM and AHCI ALPM. I'm not
> sure whether this three level knob would be sufficient.
adding more levels later is easy.
> It might be
> good enough if we're gonna develop extensive in-kernel black/white list
> specifying which method works on which combination but my gut tells me
> that it's best left to userland (probably in the form of per-notebook PS
> profile).
either sucks. AHCI ALPM ought to work if it's supported; it's what other
operating systems also use...
>
> Adding to the fun, there are quite a few broken devices out there which
> act weirdly when link PS actions are taken.
do you have any specific examples that act funny with the patch in
question here? (the patch tries to be careful, previous patches weren't
always so please test this patch before claiming the concept as a whole
is broken)
>
> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
> 'cool down' period before entering PS state
that's a chipset implementation decision.... not part of the
spec/technology per se.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 6:27 ` Tejun Heo
2007-07-31 14:16 ` Arjan van de Ven
@ 2007-07-31 14:18 ` James Bottomley
2007-08-01 16:53 ` Matthew Wilcox
2007-07-31 16:30 ` Kristen Carlson Accardi
2 siblings, 1 reply; 43+ messages in thread
From: James Bottomley @ 2007-07-31 14:18 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, Kristen Carlson Accardi, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Tue, 2007-07-31 at 15:27 +0900, Tejun Heo wrote:
> Jeff Garzik wrote:
> > Any chance the SCSI peeps could ACK this, and then let me include it in
> > the ALPM patchset in the libata tree?
>
> ATA link PS is pretty complex with HIPM, DIPM and AHCI ALPM. I'm not
> sure whether this three level knob would be sufficient. It might be
> good enough if we're gonna develop extensive in-kernel black/white list
> specifying which method works on which combination but my gut tells me
> that it's best left to userland (probably in the form of per-notebook PS
> profile).
>
> Adding to the fun, there are quite a few broken devices out there which
> act weirdly when link PS actions are taken.
>
> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
> 'cool down' period before entering PS state which unnecessarily hampers
> performance and might increase chance of device malfunction.
>
> So, mild NACK from me.
The other comment is that power saving seems to be a property of the
transport rather than the host. If you do it in the transport classes,
then you can expose all the knobs the actual transport possesses (which
is, unfortunately, none for quite a few SCSI transports).
James
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 14:16 ` Arjan van de Ven
@ 2007-07-31 14:45 ` Tejun Heo
2007-07-31 16:15 ` Arjan van de Ven
2007-07-31 16:18 ` Kristen Carlson Accardi
2007-07-31 14:58 ` Tejun Heo
1 sibling, 2 replies; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 14:45 UTC (permalink / raw)
To: Arjan van de Ven
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
Arjan van de Ven wrote:
> On Tue, 2007-07-31 at 15:27 +0900, Tejun Heo wrote:
>> Jeff Garzik wrote:
>>> Any chance the SCSI peeps could ACK this, and then let me include it in
>>> the ALPM patchset in the libata tree?
>> ATA link PS is pretty complex with HIPM, DIPM and AHCI ALPM. I'm not
>> sure whether this three level knob would be sufficient.
>
> adding more levels later is easy.
Dunno whether they would be linear levels and putting HIPM, DIPM, ALPM
selection into SCSI sysfs knob doesn't look so appealing.
>> It might be
>> good enough if we're gonna develop extensive in-kernel black/white list
>> specifying which method works on which combination but my gut tells me
>> that it's best left to userland (probably in the form of per-notebook PS
>> profile).
>
> either sucks. AHCI ALPM ought to work if it's supported; it's what other
> operating systems also use...
>> Adding to the fun, there are quite a few broken devices out there which
>> act weirdly when link PS actions are taken.
>
> do you have any specific examples that act funny with the patch in
> question here? (the patch tries to be careful, previous patches weren't
> always so please test this patch before claiming the concept as a whole
> is broken)
They were hardware problems. I don't think any amount of proper
implementation can fix them. I have one DVD RAM somewhere in my pile of
hardware which locks up solidly if any link PS mode is used and had a
report of a HDD which had problem with link PS. Can't remember the
details tho. Also, IIRC one of my wendies spins down on SLUMBER.
>> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
>> 'cool down' period before entering PS state
>
> that's a chipset implementation decision.... not part of the
> spec/technology per se.
That's actually something AHCI spec specifically states. From section
8.3.1.3.
When PxCMD.ALPE is set to ‘1’, if the HBA recognizes that there are no
commands to process, the HBA shall initiate a transition to Partial or
Slumber interface power management state based upon the setting of
PxCMD.ASP. The HBA recognizes no commands to transmit as either:
• PxSACT is set to 0h, and the HBA updates PxCI from a non-zero
value to 0h.
• PxCI is set to 0h, and a Set Device Bits FIS is received that
updates PxSACT from a non-zero value to 0h.
Have no idea why it's specified this way. Adding 100ms or 1s cool down
time wouldn't burn noticeably more power. Maybe AHCI expects the host
driver to queue commands even for non-NCQ drives but libata currently
doesn't do that.
Anyways, I don't really think this attribute belongs to SCSI sysfs
hierarchy. There currently isn't any alternative but sysfs is part of
userland visible interface and putting something into SCSI sysfs
hierarchy just because libata doesn't have one doesn't look like a good
idea.
sysfs isn't far from being detached from kobject and driver model. I
think it would be best to wait a bit and build proper libata sysfs
hierarchy which won't have to be changed later when libata departs from
SCSI. Well, it isn't really a good way but IMHO it's better than
sticking ATA power saving node into SCSI sysfs hierarchy.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 14:16 ` Arjan van de Ven
2007-07-31 14:45 ` Tejun Heo
@ 2007-07-31 14:58 ` Tejun Heo
1 sibling, 0 replies; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 14:58 UTC (permalink / raw)
To: Arjan van de Ven
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
Arjan van de Ven wrote:
> either sucks. AHCI ALPM ought to work if it's supported; it's what other
> operating systems also use...
A question. Does the other OS enable ALPM without checking against
white/black list? Or is it enabled only on certain configurations -
e.g. specific notebooks, etc?
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 14:45 ` Tejun Heo
@ 2007-07-31 16:15 ` Arjan van de Ven
2007-07-31 18:29 ` Tejun Heo
2007-07-31 16:18 ` Kristen Carlson Accardi
1 sibling, 1 reply; 43+ messages in thread
From: Arjan van de Ven @ 2007-07-31 16:15 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
> They were hardware problems. I don't think any amount of proper
> implementation can fix them. I have one DVD RAM somewhere in my pile of
> hardware which locks up solidly if any link PS mode is used and had a
and the AHCI ALPM code decides to use power savings on this device? if
so, please give us the idents so that we can add it to the blacklist as
the first entry... (or can buy it to check it in detail first)
--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 14:45 ` Tejun Heo
2007-07-31 16:15 ` Arjan van de Ven
@ 2007-07-31 16:18 ` Kristen Carlson Accardi
2007-07-31 17:48 ` Tejun Heo
1 sibling, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-31 16:18 UTC (permalink / raw)
To: Tejun Heo
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Tue, 31 Jul 2007 23:45:25 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Anyways, I don't really think this attribute belongs to SCSI sysfs
> hierarchy. There currently isn't any alternative but sysfs is part of
> userland visible interface and putting something into SCSI sysfs
> hierarchy just because libata doesn't have one doesn't look like a good
> idea.
>
> sysfs isn't far from being detached from kobject and driver model. I
> think it would be best to wait a bit and build proper libata sysfs
> hierarchy which won't have to be changed later when libata departs from
> SCSI. Well, it isn't really a good way but IMHO it's better than
> sticking ATA power saving node into SCSI sysfs hierarchy.
"Wait a bit" could be a very long time. Who is working on building this
new libata sysfs support now? If the answer is "no one", which I think it
may be, do you want to hold up a feature that actually helps many people
for possibly 6 months or more just because we have to go through scsi
right now for our sysfs interface? on top of that, the last mail I
got from James on this subject indicated that if we kept our granularity
large with the power savings levels, SCSI can actually take advantage of
this as well. Sure, we may have to tweak things around later, but isn't
this what we do routinely? Holding up valuable features from the kernel
because things aren't perfect yet seems really broken.
As far as your complaints about broken hardware go, keep in mind that
the patch set does provide a method of adding these disks to a blacklist,
so I don't see that as a problem. And, the default for this feature is
"off", and user space would have to explicitly enable it.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 6:27 ` Tejun Heo
2007-07-31 14:16 ` Arjan van de Ven
2007-07-31 14:18 ` James Bottomley
@ 2007-07-31 16:30 ` Kristen Carlson Accardi
2007-07-31 18:02 ` Tejun Heo
2 siblings, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-31 16:30 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
On Tue, 31 Jul 2007 15:27:34 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Jeff Garzik wrote:
> > Any chance the SCSI peeps could ACK this, and then let me include it in
> > the ALPM patchset in the libata tree?
>
> ATA link PS is pretty complex with HIPM, DIPM and AHCI ALPM. I'm not
> sure whether this three level knob would be sufficient. It might be
> good enough if we're gonna develop extensive in-kernel black/white list
> specifying which method works on which combination but my gut tells me
> that it's best left to userland (probably in the form of per-notebook PS
> profile).
I think what you are saying is that you'd like a way to use your HIPM
and DIPM without ALPM on the AHCI driver. Fine - it's really easy
to add these levels later - if they don't make sense at the sysfs interface
we can add module params to specify the definition of "min_power" as
being performed via HIPM and DIPM instead of ALPM - although as of yet we
have no evidence what so ever that this method actually adds value over
ALPM.
>
> Adding to the fun, there are quite a few broken devices out there which
> act weirdly when link PS actions are taken.
OK - this is why I added the blacklist for this feature.
>
> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
> 'cool down' period before entering PS state which unnecessarily hampers
> performance and might increase chance of device malfunction.
"might increase"? How about some actual examples of where you've shown
this to be a problem? I can assert that I think ALPM is a good idea,
because I've never had a report of it causing problems. Windows has
been using this feature for a very long time - and you have to admit that
they have a pretty large market share. Nobody is complaining about ALPM
increasing device malfunction, so unless you have proof it seems insane
to nak due to this.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 16:18 ` Kristen Carlson Accardi
@ 2007-07-31 17:48 ` Tejun Heo
2007-07-31 20:24 ` Kristen Carlson Accardi
0 siblings, 1 reply; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 17:48 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
Hello, Kristen.
Kristen Carlson Accardi wrote:
> On Tue, 31 Jul 2007 23:45:25 +0900
> Tejun Heo <htejun@gmail.com> wrote:
>
>> Anyways, I don't really think this attribute belongs to SCSI sysfs
>> hierarchy. There currently isn't any alternative but sysfs is part of
>> userland visible interface and putting something into SCSI sysfs
>> hierarchy just because libata doesn't have one doesn't look like a good
>> idea.
>>
>> sysfs isn't far from being detached from kobject and driver model. I
>> think it would be best to wait a bit and build proper libata sysfs
>> hierarchy which won't have to be changed later when libata departs from
>> SCSI. Well, it isn't really a good way but IMHO it's better than
>> sticking ATA power saving node into SCSI sysfs hierarchy.
>
> "Wait a bit" could be a very long time. Who is working on building this
> new libata sysfs support now?
I happen to be working on sysfs these days and guess why I started
working on sysfs. :-)
Disassociating sysfs from driver model is probably one or two patchsets
away. It could have happened earlier but I wanted to pace things a bit
so that the changes receive some testing through release cycles. Check
how many sysfs related changes went through .23-rc1 merge window and
expect about the same influx during the next cycle; with some luck, it
can be complete before .24-rc1 window.
> If the answer is "no one", which I think it
> may be, do you want to hold up a feature that actually helps many people
> for possibly 6 months or more just because we have to go through scsi
> right now for our sysfs interface?
I don't necessarily want to but delaying it might be the right thing to
do. Anyways, if we're going to do an interim solution, I don't think
mainline SCSI sysfs hierarchy is the right place. Do it with module
parameter which carries large "to be deprecated sign" or maintain out of
tree patches.
> on top of that, the last mail I
> got from James on this subject indicated that if we kept our granularity
> large with the power savings levels, SCSI can actually take advantage of
> this as well. Sure, we may have to tweak things around later, but isn't
> this what we do routinely? Holding up valuable features from the kernel
> because things aren't perfect yet seems really broken.
>
> As far as your complaints about broken hardware go, keep in mind that
> the patch set does provide a method of adding these disks to a blacklist,
> so I don't see that as a problem. And, the default for this feature is
> "off", and user space would have to explicitly enable it.
This is gonna be a bit long. Please be patient.
Due to the generosity of the ATA committee, we have, by default, at
least two ways to achieve link PS - HIPS and DIPS. I dunno why but
someone thought we needed two. And then, ahci people thought automatic
HIPS would be nice, which I fully agree, and added ALPM. Unfortunately,
they mandated ALPM to kick in the moment command engine becomes idle, so
most current implementations suffer unnecessary performance hit when
ALPM is active.
We have this crazy number of combinations. HIPS, DIPS,
not-so-hot-looking ALPM and probably some number of broken devices which
may be happy with some method but not with others. Some might be happy
with PARTIAL but vomit on SLUMBER. I might be being too pessimistic but
my last two years in IDE/ATA land taught me to be pessimistic about
hardware quality. Heck, I bet you some of non-intel ahci
implementations which claim to support ALPM will crap themselves when
actually told to do so.
If we're gonna do this like NCQ and gonna put knowledge about all the
combinations into the driver. The suggested interface is good enough.
Heck, we probably don't even need three levels. On and off should be
enough if things are done right as link PS doesn't have to incur
noticeable performance degradation. But to do that, we'll need to test
a lot of combinations and it's gonna be much harder than NCQ (some ahci
implementations don't seem to actually enter PS mode when instructed to
do so via SControl but turning off the controller saves a lot of power.
Maybe ALPM works better on such cases) and the blacklist will probably
be longer.
The alternate way is to export flexible interface to userland and let
userland decide and if we're gonna do that. SCSI sysfs just isn't the
place.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 16:30 ` Kristen Carlson Accardi
@ 2007-07-31 18:02 ` Tejun Heo
2007-07-31 19:58 ` Kristen Carlson Accardi
0 siblings, 1 reply; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 18:02 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
Kristen Carlson Accardi wrote:
> I think what you are saying is that you'd like a way to use your HIPM
> and DIPM without ALPM on the AHCI driver. Fine - it's really easy
> to add these levels later - if they don't make sense at the sysfs interface
> we can add module params to specify the definition of "min_power" as
> being performed via HIPM and DIPM instead of ALPM - although as of yet we
> have no evidence what so ever that this method actually adds value over
> ALPM.
I don't really care whose PS implementation goes in. Believe me. I try
to stay away from that. I don't even like my previous implementation.
ALPM has unnecessary performance penalty && is not applicable to
non-ahci controller. Have you tested ALPM on non-intel ahcis? There
are a lot out there these days.
I don't think the interface you're suggesting is a good one. Do you?
>> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
>> 'cool down' period before entering PS state which unnecessarily hampers
>> performance and might increase chance of device malfunction.
>
> "might increase"? How about some actual examples of where you've shown
> this to be a problem?
I wouldn't have used "might" if I had actual examples. Well, feel free
to disregard anything following the "might". I just feel uneasy about
jumping back and forth between PS and active states between consecutive
commands.
> I can assert that I think ALPM is a good idea,
> because I've never had a report of it causing problems. Windows has
> been using this feature for a very long time - and you have to admit that
> they have a pretty large market share. Nobody is complaining about ALPM
> increasing device malfunction, so unless you have proof it seems insane
> to nak due to this.
Is ALPM enabled by default? How do they deal with the performance
degradation?
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 16:15 ` Arjan van de Ven
@ 2007-07-31 18:29 ` Tejun Heo
2007-08-01 9:23 ` Tejun Heo
0 siblings, 1 reply; 43+ messages in thread
From: Tejun Heo @ 2007-07-31 18:29 UTC (permalink / raw)
To: Arjan van de Ven
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
Arjan van de Ven wrote:
>> They were hardware problems. I don't think any amount of proper
>> implementation can fix them. I have one DVD RAM somewhere in my pile of
>> hardware which locks up solidly if any link PS mode is used and had a
>
> and the AHCI ALPM code decides to use power savings on this device? if
> so, please give us the idents so that we can add it to the blacklist as
> the first entry... (or can buy it to check it in detail first)
Yeap, lemme check.
It's "TSSTcorpCD/DVDW SH-S183A" with firmware revision "SB01". Wanna
check ID capability bits but 'hdparm -I /dev/sr0' is still broken and
it's already past 3 am here. I'll report back tomorrow.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 18:02 ` Tejun Heo
@ 2007-07-31 19:58 ` Kristen Carlson Accardi
2007-08-01 3:24 ` Tejun Heo
0 siblings, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-31 19:58 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
On Wed, 01 Aug 2007 03:02:55 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Kristen Carlson Accardi wrote:
> > I think what you are saying is that you'd like a way to use your HIPM
> > and DIPM without ALPM on the AHCI driver. Fine - it's really easy
> > to add these levels later - if they don't make sense at the sysfs interface
> > we can add module params to specify the definition of "min_power" as
> > being performed via HIPM and DIPM instead of ALPM - although as of yet we
> > have no evidence what so ever that this method actually adds value over
> > ALPM.
>
> I don't really care whose PS implementation goes in. Believe me. I try
> to stay away from that. I don't even like my previous implementation.
>
> ALPM has unnecessary performance penalty && is not applicable to
> non-ahci controller. Have you tested ALPM on non-intel ahcis? There
> are a lot out there these days.
I have not personally, however there has been a lot of testing of this
hardware feature both on other OS and for this particular implementation
by the powertop community, which is composed of community members running
all sorts of hardware. So far I've not received any bug reports
wrt non-intel AHCI. As I mentioned several times, the default for ALPM
is to be off anyway.
>
> I don't think the interface you're suggesting is a good one. Do you?
I think if it's applicable to SCSI at all it is fine. If it is not, then
I think we need to make do with the interface we are given. I do not think
we should hold up a feature for libata sysfs integration.
>
> >> Also, I generally don't think AHCI ALPM is a good idea. It doesn't have
> >> 'cool down' period before entering PS state which unnecessarily hampers
> >> performance and might increase chance of device malfunction.
> >
> > "might increase"? How about some actual examples of where you've shown
> > this to be a problem?
>
> I wouldn't have used "might" if I had actual examples. Well, feel free
> to disregard anything following the "might". I just feel uneasy about
> jumping back and forth between PS and active states between consecutive
> commands.
I want us to be careful about spreading a lot of unease without data to
back it up.
>
> > I can assert that I think ALPM is a good idea,
> > because I've never had a report of it causing problems. Windows has
> > been using this feature for a very long time - and you have to admit that
> > they have a pretty large market share. Nobody is complaining about ALPM
> > increasing device malfunction, so unless you have proof it seems insane
> > to nak due to this.
>
> Is ALPM enabled by default? How do they deal with the performance
> degradation?
I believe so, but I'm obviously not privvy to their implementation details.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 17:48 ` Tejun Heo
@ 2007-07-31 20:24 ` Kristen Carlson Accardi
2007-08-01 3:20 ` Tejun Heo
0 siblings, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-07-31 20:24 UTC (permalink / raw)
To: Tejun Heo
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Wed, 01 Aug 2007 02:48:42 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Hello, Kristen.
>
> Kristen Carlson Accardi wrote:
> > On Tue, 31 Jul 2007 23:45:25 +0900
> > Tejun Heo <htejun@gmail.com> wrote:
> >
> >> Anyways, I don't really think this attribute belongs to SCSI sysfs
> >> hierarchy. There currently isn't any alternative but sysfs is part of
> >> userland visible interface and putting something into SCSI sysfs
> >> hierarchy just because libata doesn't have one doesn't look like a good
> >> idea.
> >>
> >> sysfs isn't far from being detached from kobject and driver model. I
> >> think it would be best to wait a bit and build proper libata sysfs
> >> hierarchy which won't have to be changed later when libata departs from
> >> SCSI. Well, it isn't really a good way but IMHO it's better than
> >> sticking ATA power saving node into SCSI sysfs hierarchy.
> >
> > "Wait a bit" could be a very long time. Who is working on building this
> > new libata sysfs support now?
>
> I happen to be working on sysfs these days and guess why I started
> working on sysfs. :-)
>
> Disassociating sysfs from driver model is probably one or two patchsets
> away. It could have happened earlier but I wanted to pace things a bit
> so that the changes receive some testing through release cycles. Check
> how many sysfs related changes went through .23-rc1 merge window and
> expect about the same influx during the next cycle; with some luck, it
> can be complete before .24-rc1 window.
So at current rate of development and kernel release schedule, the best
possible scenario is still 6 months away - whereas this patchset is already
tested and ready for merging now.
>
> > If the answer is "no one", which I think it
> > may be, do you want to hold up a feature that actually helps many people
> > for possibly 6 months or more just because we have to go through scsi
> > right now for our sysfs interface?
>
> I don't necessarily want to but delaying it might be the right thing to
> do. Anyways, if we're going to do an interim solution, I don't think
> mainline SCSI sysfs hierarchy is the right place. Do it with module
> parameter which carries large "to be deprecated sign" or maintain out of
> tree patches.
Out of tree patches don't work. Nobody tests them. A module parameter
will not work - we need to be able to expose the sysfs interface so that
users may chose to turn the feature off and on at will - mainly according
to their usage. For example, at boot time - you want ALPM off to maximize
performance. Lets say when you are plugged into the wall socket, you leave
it off, but then when you go on battery power you would want to enable it.
>
> > on top of that, the last mail I
> > got from James on this subject indicated that if we kept our granularity
> > large with the power savings levels, SCSI can actually take advantage of
> > this as well. Sure, we may have to tweak things around later, but isn't
> > this what we do routinely? Holding up valuable features from the kernel
> > because things aren't perfect yet seems really broken.
> >
> > As far as your complaints about broken hardware go, keep in mind that
> > the patch set does provide a method of adding these disks to a blacklist,
> > so I don't see that as a problem. And, the default for this feature is
> > "off", and user space would have to explicitly enable it.
>
> This is gonna be a bit long. Please be patient.
>
> Due to the generosity of the ATA committee, we have, by default, at
> least two ways to achieve link PS - HIPS and DIPS. I dunno why but
> someone thought we needed two. And then, ahci people thought automatic
They thought we needed two because sometimes the device knows when it
will be idle faster than the host can. this is why ALPM can determine
idleness faster than any software algorithm on the host cpu can. You
can use ALPM without having HIPM. You can also use it without having
DIPM.
> HIPS would be nice, which I fully agree, and added ALPM. Unfortunately,
> they mandated ALPM to kick in the moment command engine becomes idle, so
> most current implementations suffer unnecessary performance hit when
> ALPM is active.
"unnecessary" is subjective and at the moment, untrue. You
have to make performance/power tradeoffs with anything, whether it's
CPU or your AHCI controller. It's the current cost of getting out of these
sleep states even if you aren't using ALPM but just doing HIPM or DIPM
manually. But, this is why it's so critical to allow the user to
control when ALPM is enabled dynamically - which this patchset does.
The medium power setting is provided for users who wish to not go to
SLUMBER and get the higher latency cost but still have some power savings.
>
> We have this crazy number of combinations. HIPS, DIPS,
> not-so-hot-looking ALPM and probably some number of broken devices which
> may be happy with some method but not with others. Some might be happy
> with PARTIAL but vomit on SLUMBER. I might be being too pessimistic but
> my last two years in IDE/ATA land taught me to be pessimistic about
> hardware quality. Heck, I bet you some of non-intel ahci
> implementations which claim to support ALPM will crap themselves when
> actually told to do so.
>
> If we're gonna do this like NCQ and gonna put knowledge about all the
> combinations into the driver. The suggested interface is good enough.
> Heck, we probably don't even need three levels. On and off should be
> enough if things are done right as link PS doesn't have to incur
> noticeable performance degradation. But to do that, we'll need to test
> a lot of combinations and it's gonna be much harder than NCQ (some ahci
> implementations don't seem to actually enter PS mode when instructed to
> do so via SControl but turning off the controller saves a lot of power.
> Maybe ALPM works better on such cases) and the blacklist will probably
> be longer.
I understand you are being cautious based on your prior experience, but
again we still have no data to show that we are going to have a lot of
problems. Perhaps we should proceed optimistically and deal with problems
when they actually occur rather than block something on a bet.
>
> The alternate way is to export flexible interface to userland and let
> userland decide and if we're gonna do that. SCSI sysfs just isn't the
> place.
How about a patch? I'd love to have a flexible interface to userland,
it was my goal to provide this with the sysfs files. The requirement
is that the users be able to turn ALPM off and on dynamically, and to
be able to chose the power savings level you want - i.e. SLUMBER vs.
PARTIAL - perferrably not using those terms since users really shouldn't
need to know AHCI terminology just to chose a power management level.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 20:24 ` Kristen Carlson Accardi
@ 2007-08-01 3:20 ` Tejun Heo
0 siblings, 0 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-01 3:20 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
Kristen Carlson Accardi wrote:
> So at current rate of development and kernel release schedule, the best
> possible scenario is still 6 months away - whereas this patchset is already
> tested and ready for merging now.
The best possible scenario is .24-rc1 merge window with or without
waiting. With waiting, the best possible scenario is harder to achieve tho.
> Out of tree patches don't work. Nobody tests them. A module parameter
> will not work - we need to be able to expose the sysfs interface so that
> users may chose to turn the feature off and on at will - mainly according
> to their usage. For example, at boot time - you want ALPM off to maximize
> performance. Lets say when you are plugged into the wall socket, you leave
> it off, but then when you go on battery power you would want to enable it.
You can turn on and off dynamically using a module parameter. Although
it's not a pretty interface, it should work as an interim solution if we
absolutely must merge ALPM now.
>> Due to the generosity of the ATA committee, we have, by default, at
>> least two ways to achieve link PS - HIPS and DIPS. I dunno why but
>> someone thought we needed two. And then, ahci people thought automatic
>
> They thought we needed two because sometimes the device knows when it
> will be idle faster than the host can. this is why ALPM can determine
> idleness faster than any software algorithm on the host cpu can. You
> can use ALPM without having HIPM. You can also use it without having
> DIPM.
I see. I get that one way is better than another in some way. I'm just
not convinced whether the advantage is substantial enough to justify the
complexity.
>> HIPS would be nice, which I fully agree, and added ALPM. Unfortunately,
>> they mandated ALPM to kick in the moment command engine becomes idle, so
>> most current implementations suffer unnecessary performance hit when
>> ALPM is active.
>
> "unnecessary" is subjective and at the moment, untrue. You
> have to make performance/power tradeoffs with anything, whether it's
> CPU or your AHCI controller. It's the current cost of getting out of these
> sleep states even if you aren't using ALPM but just doing HIPM or DIPM
> manually.
Having short cool-down time would remove most of performance degradation
and I'm pretty sure power consumption would stay about the same.
> But, this is why it's so critical to allow the user to
> control when ALPM is enabled dynamically - which this patchset does.
> The medium power setting is provided for users who wish to not go to
> SLUMBER and get the higher latency cost but still have some power savings.
Note that PARTIAL also incurs noticeable performance degradation.
> I understand you are being cautious based on your prior experience, but
> again we still have no data to show that we are going to have a lot of
> problems. Perhaps we should proceed optimistically and deal with problems
> when they actually occur rather than block something on a bet.
I would agree with you, merge it and see the fireworks in -mm if it
didn't involve user visible API. We have an API decision to make here
and it hasn't been sufficiently considered yet.
>> The alternate way is to export flexible interface to userland and let
>> userland decide and if we're gonna do that. SCSI sysfs just isn't the
>> place.
>
> How about a patch? I'd love to have a flexible interface to userland,
> it was my goal to provide this with the sysfs files. The requirement
> is that the users be able to turn ALPM off and on dynamically, and to
> be able to chose the power savings level you want - i.e. SLUMBER vs.
> PARTIAL - perferrably not using those terms since users really shouldn't
> need to know AHCI terminology just to chose a power management level.
As I wrote before, which level of interface to export to userland is
related with where to put the knowledge about working and broken
combinations. Unfortunately, we don't have data to support one way or
the other at the moment. All I'm saying is that we should be cautious
before introducing user-land visible interface which lives in SCSI sysfs
as it's unknown whether it would fit the reality or not.
Sorry that I don't have an alternative patch now, but something which
can relieve the situation is being worked on, so let's give it some time
and see how things turn out. Things have to wait till the next -rc1
window anyway.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 19:58 ` Kristen Carlson Accardi
@ 2007-08-01 3:24 ` Tejun Heo
2007-08-01 15:52 ` Kristen Carlson Accardi
2007-08-01 21:07 ` Kristen Carlson Accardi
0 siblings, 2 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-01 3:24 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
Kristen Carlson Accardi wrote:
>> I don't think the interface you're suggesting is a good one. Do you?
>
> I think if it's applicable to SCSI at all it is fine. If it is not, then
> I think we need to make do with the interface we are given. I do not think
> we should hold up a feature for libata sysfs integration.
Well, I guess we'll have to agree to disagree here and leave the
decision to James and Jeff.
>>> I can assert that I think ALPM is a good idea,
>>> because I've never had a report of it causing problems. Windows has
>>> been using this feature for a very long time - and you have to admit that
>>> they have a pretty large market share. Nobody is complaining about ALPM
>>> increasing device malfunction, so unless you have proof it seems insane
>>> to nak due to this.
>> Is ALPM enabled by default? How do they deal with the performance
>> degradation?
>
> I believe so, but I'm obviously not privvy to their implementation details.
It would be *really* great if we can find more about how they do it.
How and when it's enabled and on which systems. Is it possible to find
this out?
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 1/4] Store interrupt value
2007-07-05 20:05 ` [patch 1/4] Store interrupt value Kristen Carlson Accardi
@ 2007-08-01 8:18 ` Tejun Heo
2007-08-01 14:01 ` Jeff Garzik
1 sibling, 0 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-01 8:18 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
Kristen Carlson Accardi wrote:
> Use a stored value for which interrupts to enable. Changing this allows
> us to selectively turn off certain interrupts later and have them
> stay off.
>
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Acked-by: Tejun Heo <htejun@gmail.com>
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-07-05 20:05 ` [patch 3/4] Enable link power management for ata drivers Kristen Carlson Accardi
2007-07-05 22:33 ` Andrew Morton
@ 2007-08-01 8:27 ` Tejun Heo
2007-08-01 9:45 ` edwintorok
2007-08-01 21:11 ` Kristen Carlson Accardi
1 sibling, 2 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-01 8:27 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
Kristen Carlson Accardi wrote:
> libata drivers can define a function (enable_pm) that will
> perform hardware specific actions to enable whatever power
> management policy the user set up from the scsi sysfs
> interface if the driver supports it. This power management
> policy will be activated after all disks have been
> enumerated and intialized. Drivers should also define
> disable_pm, which will turn off link power management, but
> not change link power management policy.
>
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Please update the patch against the current libata-dev#upstream and
there are several lines where tab follows space and git-applymbox isn't
happy about it. Those lines are in other patches too.
> +int ata_scsi_set_link_pm_policy(struct Scsi_Host *shost,
> + enum scsi_host_link_pm policy)
> +{
> + struct ata_port *ap = ata_shost_to_port(shost);
> + int rc = -EINVAL;
> + int i;
> +
> + /*
> + * make sure no broken devices are on this port,
> + * and that all devices support interface power
> + * management
> + */
> + for (i = 0; i < ATA_MAX_DEVICES; i++) {
> + struct ata_device *dev = &ap->device[i];
> +
> + /* only check drives which exist */
> + if (!ata_dev_enabled(dev))
> + continue;
> +
> + /*
> + * do we need to handle the case where we've hotplugged
> + * a broken drive (since hotplug and ALPM are mutually
> + * exclusive) ?
> + *
> + * If so, if we detect a broken drive on a port with
> + * alpm already enabled, then we should reset the policy
> + * to off for the entire port.
> + */
> + if ((dev->horkage & ATA_HORKAGE_ALPM) ||
> + !(dev->flags & ATA_DFLAG_IPM)) {
> + ata_dev_printk(dev, KERN_ERR,
> + "Unable to set Link PM policy\n");
> + ap->pm_policy = SHOST_MAX_PERFORMANCE;
> + }
> + }
> +
> + if (ap->ops->enable_pm)
> + rc = ap->ops->enable_pm(ap, policy);
> +
> + if (!rc)
> + shost->shost_link_pm_policy = ap->pm_policy;
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(ata_scsi_set_link_pm_policy);
This function is directly called from SCSI sysfs write, right? You
can't do this without synchronizing with EH. The best way is to define
an EH action and ask EH to transit between powersave states.
> @@ -2021,6 +2021,9 @@ int ata_dev_configure(struct ata_device
> if (dev->flags & ATA_DFLAG_LBA48)
> dev->max_sectors = ATA_MAX_SECTORS_LBA48;
>
> + if (ata_id_has_hipm(dev->id) || ata_id_has_dipm(dev->id))
> + dev->flags |= ATA_DFLAG_IPM;
Is it safe to use ALPM on a device which only claims to support DIPM?
> @@ -2046,6 +2049,13 @@ int ata_dev_configure(struct ata_device
> dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
> dev->max_sectors);
>
> + if (ata_device_blacklisted(dev) & ATA_HORKAGE_ALPM) {
> + dev->horkage |= ATA_HORKAGE_ALPM;
I think this should be ATA_HORKAGE_IPM.
> @@ -6385,6 +6426,8 @@ int ata_host_register(struct ata_host *h
> struct ata_port *ap = host->ports[i];
>
> ata_scsi_scan_host(ap);
> + ata_scsi_set_link_pm_policy(ap->scsi_host,
> + ap->pm_policy);
Again, this should be done from EH.
> @@ -321,6 +321,8 @@ struct ata_taskfile {
> ((u64) (id)[(n) + 0]) )
>
> #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
> +#define ata_id_has_hipm(id) ((id)[76] & (1 << 9))
> +#define ata_id_has_dipm(id) ((id)[78] & (1 << 3))
We probably need !0xffff test here.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 18:29 ` Tejun Heo
@ 2007-08-01 9:23 ` Tejun Heo
2007-08-01 16:31 ` Kristen Carlson Accardi
2007-08-01 21:16 ` Kristen Carlson Accardi
0 siblings, 2 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-01 9:23 UTC (permalink / raw)
To: Arjan van de Ven
Cc: Jeff Garzik, Kristen Carlson Accardi, James.Bottomley, linux-scsi,
akpm, linux-kernel, linux-ide, edwintorok, axboe
Tejun Heo wrote:
> Arjan van de Ven wrote:
>>> They were hardware problems. I don't think any amount of proper
>>> implementation can fix them. I have one DVD RAM somewhere in my pile of
>>> hardware which locks up solidly if any link PS mode is used and had a
>> and the AHCI ALPM code decides to use power savings on this device? if
>> so, please give us the idents so that we can add it to the blacklist as
>> the first entry... (or can buy it to check it in detail first)
>
> Yeap, lemme check.
>
> It's "TSSTcorpCD/DVDW SH-S183A" with firmware revision "SB01". Wanna
> check ID capability bits but 'hdparm -I /dev/sr0' is still broken and
> it's already past 3 am here. I'll report back tomorrow.
Oops, that was the wrong one. Locking up one was HL-DT-STDVD-RAM
GSA-H30N and it correctly reports that it doesn't support IPM. Here
are some test results.
Controller is ICH9.
00:1f.2 SATA controller [Class 0106]: Intel Corporation Unknown device [8086:2922] (rev 02)
====
1. HL-DT-STDVD-RAM GSA-H30N
ATAPI CD-ROM, with removable media
Model Number: HL-DT-STDVD-RAM GSA-H30N
Serial Number:
Firmware Revision: 1.00
Standards:
Likely used CD-ROM ATAPI-1
Configuration:
DRQ response: 50us.
Packet size: 12 bytes
Capabilities:
LBA, IORDY(can be disabled)
DMA: sdma0 sdma1 sdma2 mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 *udma5
Cycle time: min=120ns recommended=120ns
PIO: pio0 pio1 pio2 pio3 pio4
Cycle time: no flow control=120ns IORDY flow control=120
This device doesn't claim to support HIPM nor DIPM.
# echo min_power > link_power_management_policy
[ 752.761751] ata1.00: Unable to set Link PM policy
[ 784.510218] ata1.00: exception Emask 0x50 SAct 0x0 SErr 0xd0800 action 0x6 frozen
[ 784.530266] ata1.00: cmd a0/00:00:00:00:20/00:00:00:00:00/a0 tag 0 cdb 0x43 data 12 in
[ 784.530270] res 40/00:03:00:00:20/00:00:00:00:00/a0 Emask 0x54 (ATA bus error)
[ 784.571175] ata1: hard resetting port
[ 790.489486] ata1: port is slow to respond, please be patient (Status 0x80)
[ 794.594247] ata1: COMRESET failed (errno=-16)
[ 794.611174] ata1: hard resetting port
[ 800.541562] ata1: port is slow to respond, please be patient (Status 0x80)
[ 804.646316] ata1: COMRESET failed (errno=-16)
[ 804.663284] ata1: hard resetting port
[ 810.593623] ata1: port is slow to respond, please be patient (Status 0x80)
[ 839.654644] ata1: COMRESET failed (errno=-16)
[ 839.672576] ata1: limiting SATA link speed to 1.5 Gbps
[ 839.691024] ata1: hard resetting port
[ 844.726659] ata1: COMRESET failed (errno=-16)
[ 844.744064] ata1: reset failed, giving up
[ 844.761614] ata1.00: disabled
[ 844.761639] ata1: EH complete
The device doesn't respond till power is physically removed and
restored. It seems something in ahci_disable_alpm() path upsets the
device.
2. TSSTcorpCD/DVDW SH-S183A
ATAPI CD-ROM, with removable media
Model Number: TSSTcorpCD/DVDW SH-S183A
Serial Number:
Firmware Revision: SB01
Standards:
Likely used CD-ROM ATAPI-1
Configuration:
DRQ response: 50us.
Packet size: 12 bytes
Capabilities:
LBA, IORDY(can be disabled)
DMA: mdma0 mdma1 mdma2 udma0 udma1 *udma2
Cycle time: min=120ns recommended=120ns
PIO: pio0 pio1 pio2 pio3 pio4
Cycle time: no flow control=120ns IORDY flow control=120ns
Commands/features:
Enabled Supported:
* SATA-I signaling speed (1.5Gb/s)
* Host-initiated interface power management
* Phy event counters
Device-initiated interface power management
unknown 78[5]
* Software settings preservation
This one claims to support HIPS.
# echo min_power > link_power_management_policy
[ 1301.917248] ata1.00: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0x2
[ 1301.938338] ata1.00: irq_stat 0x40000001
[ 1301.956955] ata1.00: cmd a0/00:00:00:00:20/00:00:00:00:00/a0 tag 0 cdb 0x43 data 12 in
[ 1301.956959] res 51/20:03:00:00:00/00:00:00:00:00/a0 Emask 0x10 (ATA bus error)
[ 1304.189565] ata1: soft resetting port
[ 1304.207745] ata1: SATA link down (SStatus 611 SControl 300)
[ 1304.228076] ata1: failed to recover some devices, retrying in 5 secs
[ 1309.245599] ata1: hard resetting port
[ 1314.773227] ata1: port is slow to respond, please be patient (Status 0x80)
[ 1319.269677] ata1: COMRESET failed (errno=-16)
[ 1319.289639] ata1: hard resetting port
[ 1319.781285] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
[ 1320.115569] ata1.00: configured for UDMA/33
[ 1320.134780] ata1: EH complete
And hotplug works fine after EH is done with itself. Dunno why.
3. PLEXTOR DVDR PX-716A
ATAPI CD-ROM, with removable media
Model Number: PLEXTOR DVDR PX-716A
Serial Number: 127377
Firmware Revision: 1.09
Standards:
Likely used CD-ROM ATAPI-1
Configuration:
DRQ response: 50us.
Packet size: 12 bytes
Capabilities:
LBA, IORDY(can be disabled)
DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 *udma4
Cycle time: min=120ns recommended=120ns
PIO: pio0 pio1 pio2 pio3 pio4
Cycle time: no flow control=120ns IORDY flow control=120ns
HW reset results:
CBLID- below Vih
Device num = 0
# echo min_power > link_power_management_policy
[ 2102.655765] ata1.00: Unable to set Link PM policy
[ 2104.505926] ata1.00: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0x2
[ 2104.527256] ata1.00: irq_stat 0x40000001
[ 2104.545868] ata1.00: cmd a0/00:00:00:00:20/00:00:00:00:00/a0 tag 0 cdb 0x43 data 12 in
[ 2104.545870] res 51/24:03:00:00:20/00:00:00:00:00/a0 Emask 0x10 (ATA bus error)
[ 2106.810252] ata1: soft resetting port
[ 2106.828106] ata1: SATA link down (SStatus 611 SControl 300)
[ 2106.847957] ata1: failed to recover some devices, retrying in 5 secs
[ 2111.870285] ata1: hard resetting port
[ 2117.401917] ata1: port is slow to respond, please be patient (Status 0x80)
[ 2121.902365] ata1: COMRESET failed (errno=-16)
[ 2121.920313] ata1: hard resetting port
[ 2122.413973] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
[ 2122.795507] ata1.00: configured for UDMA/66
[ 2122.813234] ata1: EH complete
4. Harddisks
All the harddisks I have behave themselves. Impressive.
====
In all cases, hotplug works well even after ALPM is configured. Have
no idea why. It might be that PARTIAL/SLUMBER mode didn't kick in or
ICH9 has some magic feature to detect PHY status changes even in PS
mode (wishful thinking).
Will repeat the test with ICH7 when I get some time. Anyone up for
testing JMB and VIA?
With some massging to ahci_disable_alpm(), I think it can be fairly
safe on this chipset at least.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-08-01 8:27 ` Tejun Heo
@ 2007-08-01 9:45 ` edwintorok
2007-08-01 21:11 ` Kristen Carlson Accardi
1 sibling, 0 replies; 43+ messages in thread
From: edwintorok @ 2007-08-01 9:45 UTC (permalink / raw)
To: Tejun Heo
Cc: Kristen Carlson Accardi, jeff, akpm, linux-kernel, linux-ide,
James.Bottomley, axboe, linux-scsi
On 8/1/07, Tejun Heo <htejun@gmail.com> wrote:
> >
> > + if (ata_id_has_hipm(dev->id) || ata_id_has_dipm(dev->id))
> > + dev->flags |= ATA_DFLAG_IPM;
>
> Is it safe to use ALPM on a device which only claims to support DIPM?
I have tested on a Dell Inspiron 6400, it has ICH7-M (82801GBM) chipset.
The harddisk claims to support only DIPM, and the ALPM patches work with it.
Kristen said either DIPM or HIPM will work with ALPM accord to the
spec, see this email:
http://www.bughost.org/pipermail/power/2007-June/000691.html
--Edwin
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 1/4] Store interrupt value
2007-07-05 20:05 ` [patch 1/4] Store interrupt value Kristen Carlson Accardi
2007-08-01 8:18 ` Tejun Heo
@ 2007-08-01 14:01 ` Jeff Garzik
2007-08-01 21:18 ` Kristen Carlson Accardi
1 sibling, 1 reply; 43+ messages in thread
From: Jeff Garzik @ 2007-08-01 14:01 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi
Kristen Carlson Accardi wrote:
> Use a stored value for which interrupts to enable. Changing this allows
> us to selectively turn off certain interrupts later and have them
> stay off.
>
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
ACK. Regenerate against current kernel and I'll apply immediately
(tried to do so just now)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 3:24 ` Tejun Heo
@ 2007-08-01 15:52 ` Kristen Carlson Accardi
2007-08-01 21:07 ` Kristen Carlson Accardi
1 sibling, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 15:52 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
On Wed, 01 Aug 2007 12:24:44 +0900
Tejun Heo <htejun@gmail.com> wrote:
> It would be *really* great if we can find more about how they do it.
> How and when it's enabled and on which systems. Is it possible to find
> this out?
No - it's really not a good idea for us to go and ask other OS's how they
implement things in this level of detail.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 9:23 ` Tejun Heo
@ 2007-08-01 16:31 ` Kristen Carlson Accardi
2007-08-01 21:16 ` Kristen Carlson Accardi
1 sibling, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 16:31 UTC (permalink / raw)
To: Tejun Heo
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Wed, 01 Aug 2007 18:23:21 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Tejun Heo wrote:
> > Arjan van de Ven wrote:
> >>> They were hardware problems. I don't think any amount of proper
> >>> implementation can fix them. I have one DVD RAM somewhere in my pile of
> >>> hardware which locks up solidly if any link PS mode is used and had a
> >> and the AHCI ALPM code decides to use power savings on this device? if
> >> so, please give us the idents so that we can add it to the blacklist as
> >> the first entry... (or can buy it to check it in detail first)
> >
> > Yeap, lemme check.
> >
> > It's "TSSTcorpCD/DVDW SH-S183A" with firmware revision "SB01". Wanna
> > check ID capability bits but 'hdparm -I /dev/sr0' is still broken and
> > it's already past 3 am here. I'll report back tomorrow.
>
> Oops, that was the wrong one. Locking up one was HL-DT-STDVD-RAM
> GSA-H30N and it correctly reports that it doesn't support IPM. Here
> are some test results.
>
> Controller is ICH9.
>
> 00:1f.2 SATA controller [Class 0106]: Intel Corporation Unknown device [8086:2922] (rev 02)
>
> ====
>
> 1. HL-DT-STDVD-RAM GSA-H30N
>
> ATAPI CD-ROM, with removable media
> Model Number: HL-DT-STDVD-RAM GSA-H30N
> Serial Number:
> Firmware Revision: 1.00
> Standards:
> Likely used CD-ROM ATAPI-1
> Configuration:
> DRQ response: 50us.
> Packet size: 12 bytes
> Capabilities:
> LBA, IORDY(can be disabled)
> DMA: sdma0 sdma1 sdma2 mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 *udma5
> Cycle time: min=120ns recommended=120ns
> PIO: pio0 pio1 pio2 pio3 pio4
> Cycle time: no flow control=120ns IORDY flow control=120
>
> This device doesn't claim to support HIPM nor DIPM.
Are you sure you are using the latest version of the patch? This seems
like a bug, if the device doesn't support HIPM or DIPM it shouldn't attempt
to use ALPM. There was a check for this put into the patch on about the
second or third version - maybe I'm not doing it right.
(from the patch located here:
http://www.kernel.org/pub/linux/kernel/people/kristen/patches/SATA/alpm/libata-enable-pm
if (ata_id_has_hipm(dev->id) || ata_id_has_dipm(dev->id))
+ dev->flags |= ATA_DFLAG_IPM;
+
<snip>
>
> 2. TSSTcorpCD/DVDW SH-S183A
>
> ATAPI CD-ROM, with removable media
> Model Number: TSSTcorpCD/DVDW SH-S183A
> Serial Number:
> Firmware Revision: SB01
> Standards:
> Likely used CD-ROM ATAPI-1
> Configuration:
> DRQ response: 50us.
> Packet size: 12 bytes
> Capabilities:
> LBA, IORDY(can be disabled)
> DMA: mdma0 mdma1 mdma2 udma0 udma1 *udma2
> Cycle time: min=120ns recommended=120ns
> PIO: pio0 pio1 pio2 pio3 pio4
> Cycle time: no flow control=120ns IORDY flow control=120ns
> Commands/features:
> Enabled Supported:
> * SATA-I signaling speed (1.5Gb/s)
> * Host-initiated interface power management
> * Phy event counters
> Device-initiated interface power management
> unknown 78[5]
> * Software settings preservation
>
> This one claims to support HIPS.
>
> # echo min_power > link_power_management_policy
> [ 1301.917248] ata1.00: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0x2
> [ 1301.938338] ata1.00: irq_stat 0x40000001
> [ 1301.956955] ata1.00: cmd a0/00:00:00:00:20/00:00:00:00:00/a0 tag 0 cdb 0x43 data 12 in
> [ 1301.956959] res 51/20:03:00:00:00/00:00:00:00:00/a0 Emask 0x10 (ATA bus error)
> [ 1304.189565] ata1: soft resetting port
> [ 1304.207745] ata1: SATA link down (SStatus 611 SControl 300)
> [ 1304.228076] ata1: failed to recover some devices, retrying in 5 secs
> [ 1309.245599] ata1: hard resetting port
> [ 1314.773227] ata1: port is slow to respond, please be patient (Status 0x80)
> [ 1319.269677] ata1: COMRESET failed (errno=-16)
> [ 1319.289639] ata1: hard resetting port
> [ 1319.781285] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
> [ 1320.115569] ata1.00: configured for UDMA/33
> [ 1320.134780] ata1: EH complete
>
> And hotplug works fine after EH is done with itself. Dunno why.
It works because after EH you've reset the port, and when you reset the
port you turn off ipm (note the value of SControl). I left this the way
it was without attempting to renable link pm after a reset because I figured
if there was something bad happening and we needed to reset we should leave
ipm off.
As far as the failure you are seeing goes - this may not actually be a
hardware problem but just a case of us not understanding which bits we
need to clear out of the Interrupt status register once we enable
ALPM. The value of SErr indicates that this device has gotten PhyRdy -
which is normal for power state changes, and the interrupt status indicates
that a d2h FIS was received which is also normal - the TFES bit seems to be
set - it may be that we need to modify the interrupt code to not only ignore
PhyRdy when ALPM is enabled, but also clear out bit 0 - this is definitely
something we can try. But, meanwhile, please make sure you are testing
with the latest version of the patches.
>
> 3. PLEXTOR DVDR PX-716A
>
> ATAPI CD-ROM, with removable media
> Model Number: PLEXTOR DVDR PX-716A
> Serial Number: 127377
> Firmware Revision: 1.09
> Standards:
> Likely used CD-ROM ATAPI-1
> Configuration:
> DRQ response: 50us.
> Packet size: 12 bytes
> Capabilities:
> LBA, IORDY(can be disabled)
> DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 *udma4
> Cycle time: min=120ns recommended=120ns
> PIO: pio0 pio1 pio2 pio3 pio4
> Cycle time: no flow control=120ns IORDY flow control=120ns
> HW reset results:
> CBLID- below Vih
> Device num = 0
>
> # echo min_power > link_power_management_policy
> [ 2102.655765] ata1.00: Unable to set Link PM policy
> [ 2104.505926] ata1.00: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0x2
> [ 2104.527256] ata1.00: irq_stat 0x40000001
> [ 2104.545868] ata1.00: cmd a0/00:00:00:00:20/00:00:00:00:00/a0 tag 0 cdb 0x43 data 12 in
> [ 2104.545870] res 51/24:03:00:00:20/00:00:00:00:00/a0 Emask 0x10 (ATA bus error)
> [ 2106.810252] ata1: soft resetting port
> [ 2106.828106] ata1: SATA link down (SStatus 611 SControl 300)
> [ 2106.847957] ata1: failed to recover some devices, retrying in 5 secs
> [ 2111.870285] ata1: hard resetting port
> [ 2117.401917] ata1: port is slow to respond, please be patient (Status 0x80)
> [ 2121.902365] ata1: COMRESET failed (errno=-16)
> [ 2121.920313] ata1: hard resetting port
> [ 2122.413973] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
> [ 2122.795507] ata1.00: configured for UDMA/66
> [ 2122.813234] ata1: EH complete
this looks like the same issue as above.
>
> 4. Harddisks
>
> All the harddisks I have behave themselves. Impressive.
>
> ====
>
> In all cases, hotplug works well even after ALPM is configured. Have
> no idea why. It might be that PARTIAL/SLUMBER mode didn't kick in or
> ICH9 has some magic feature to detect PHY status changes even in PS
> mode (wishful thinking).
Make sure you are using the latest version of the patches - and that
the devices are not resetting themselves for some reason. I don't see
how hotplug can work if we are indeed ignoring PhyRdy.
> With some massging to ahci_disable_alpm(), I think it can be fairly
> safe on this chipset at least.
Not sure what part of disable_alpm you think is broken here - I see
the issue to be more likely in the interrupt handler. I'll
regenerate the patches today against the latest kernel and you
should rerun your tests just to make sure we aren't trying to fix
something that's already been fixed.
Thanks,
Kristen
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-07-31 14:18 ` James Bottomley
@ 2007-08-01 16:53 ` Matthew Wilcox
2007-08-01 17:06 ` James Bottomley
0 siblings, 1 reply; 43+ messages in thread
From: Matthew Wilcox @ 2007-08-01 16:53 UTC (permalink / raw)
To: James Bottomley
Cc: Tejun Heo, Jeff Garzik, Kristen Carlson Accardi, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Tue, Jul 31, 2007 at 09:18:08AM -0500, James Bottomley wrote:
> The other comment is that power saving seems to be a property of the
> transport rather than the host. If you do it in the transport classes,
> then you can expose all the knobs the actual transport possesses (which
> is, unfortunately, none for quite a few SCSI transports).
Would it save any power to negotiate down to, say, FAST-20 for the SPI
transport? Or to negotiate narrow instead of wide, so fewer cables have
to be powered?
--
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours. We can't possibly take such
a retrograde step."
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 16:53 ` Matthew Wilcox
@ 2007-08-01 17:06 ` James Bottomley
0 siblings, 0 replies; 43+ messages in thread
From: James Bottomley @ 2007-08-01 17:06 UTC (permalink / raw)
To: Matthew Wilcox
Cc: Tejun Heo, Jeff Garzik, Kristen Carlson Accardi, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Wed, 2007-08-01 at 10:53 -0600, Matthew Wilcox wrote:
> On Tue, Jul 31, 2007 at 09:18:08AM -0500, James Bottomley wrote:
> > The other comment is that power saving seems to be a property of the
> > transport rather than the host. If you do it in the transport classes,
> > then you can expose all the knobs the actual transport possesses (which
> > is, unfortunately, none for quite a few SCSI transports).
>
> Would it save any power to negotiate down to, say, FAST-20 for the SPI
> transport? Or to negotiate narrow instead of wide, so fewer cables have
> to be powered?
Mechanically, I don't believe so. I'm not sure I can find any reports
on it; however, I believe the power wastage SPI comes from the
transcievers and terminators. There's the passive power from simply
powering the resistive bus and then the RMS power from sending commands
over an impedance circuit. simple physics on a 5v bus tells me that the
former is likely to be far greater than the latter. Finally, if you
think about what the bus is doing during signalling, the power drain is
independent of the frequency so I think the faster you squirt your data,
the lower the energy drain (hence high speed busses are actually lower
energy than low speed ones if the number of bits you have to transfer
remains constant).
James
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 3:24 ` Tejun Heo
2007-08-01 15:52 ` Kristen Carlson Accardi
@ 2007-08-01 21:07 ` Kristen Carlson Accardi
1 sibling, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 21:07 UTC (permalink / raw)
To: Tejun Heo
Cc: Jeff Garzik, James.Bottomley, linux-scsi, akpm, linux-kernel,
linux-ide, edwintorok, axboe
On Wed, 01 Aug 2007 12:24:44 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Kristen Carlson Accardi wrote:
> >> I don't think the interface you're suggesting is a good one. Do you?
> >
> > I think if it's applicable to SCSI at all it is fine. If it is not, then
> > I think we need to make do with the interface we are given. I do not think
> > we should hold up a feature for libata sysfs integration.
>
> Well, I guess we'll have to agree to disagree here and leave the
> decision to James and Jeff.
A compromise to avoiding having this in SCSI is to use the
shost_attrs array in the scsi host template. This will not change the way
the interface will look, it will just remove any link power management
stuff from the scsi subsystem directly and have it be an ATA only attribute.
I did go ahead and leave the Documentation file in the scsi directory
because that is where the attribute winds up being visible to the user.
Here's the patch, and this series is also available at
http://www.kernel.org/pub/linux/kernel/people/kristen/patches/SATA/alpm:
Enable link power management for ata drivers
libata drivers can define a function (enable_pm) that will
perform hardware specific actions to enable whatever power
management policy the user set up from the scsi sysfs
interface if the driver supports it. This power management
policy will be activated after all disks have been
enumerated and intialized. Drivers should also define
disable_pm, which will turn off link power management, but
not change link power management policy.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c
+++ 2.6-git/drivers/ata/libata-scsi.c
@@ -110,6 +110,78 @@ static struct scsi_transport_template at
.user_scan = ata_scsi_user_scan,
};
+static const struct {
+ enum link_pm value;
+ char *name;
+} link_pm_policy[] = {
+ { NOT_AVAILABLE, "max_performance" },
+ { MIN_POWER, "min_power" },
+ { MAX_PERFORMANCE, "max_performance" },
+ { MEDIUM_POWER, "medium_power" },
+};
+
+const char *ata_scsi_link_pm_policy(enum link_pm policy)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++) {
+ if (link_pm_policy[i].value == policy) {
+ name = link_pm_policy[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
+static ssize_t store_link_pm_policy(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ enum link_pm policy = 0;
+ int i;
+
+ /*
+ * we are skipping array location 0 on purpose - this
+ * is because a value of NOT_AVAILABLE is displayed
+ * to the user as max_performance, but when the user
+ * writes "max_performance", they actually want the
+ * value to match MAX_PERFORMANCE.
+ */
+ for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
+ const int len = strlen(link_pm_policy[i].name);
+ if (strncmp(link_pm_policy[i].name, buf, len) == 0 &&
+ buf[len] == '\n') {
+ policy = link_pm_policy[i].value;
+ break;
+ }
+ }
+ if (!policy)
+ return -EINVAL;
+
+ if (ata_scsi_set_link_pm_policy(ap, policy))
+ return -EINVAL;
+ return count;
+}
+
+static ssize_t
+show_link_pm_policy(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ const char *policy =
+ ata_scsi_link_pm_policy(ap->pm_policy);
+
+ if (!policy)
+ return -EINVAL;
+
+ return snprintf(buf, 23, "%s\n", policy);
+}
+CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+ show_link_pm_policy, store_link_pm_policy);
+EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
+
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
@@ -2904,6 +2976,47 @@ void ata_scsi_simulate(struct ata_device
}
}
+int ata_scsi_set_link_pm_policy(struct ata_port *ap,
+ enum link_pm policy)
+{
+ int rc = -EINVAL;
+ int i;
+
+ /*
+ * make sure no broken devices are on this port,
+ * and that all devices support interface power
+ * management
+ */
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+
+ /* only check drives which exist */
+ if (!ata_dev_enabled(dev))
+ continue;
+
+ /*
+ * do we need to handle the case where we've hotplugged
+ * a broken drive (since hotplug and ALPM are mutually
+ * exclusive) ?
+ *
+ * If so, if we detect a broken drive on a port with
+ * alpm already enabled, then we should reset the policy
+ * to off for the entire port.
+ */
+ if ((dev->horkage & ATA_HORKAGE_IPM) ||
+ !(dev->flags & ATA_DFLAG_IPM)) {
+ ata_dev_printk(dev, KERN_ERR,
+ "Unable to set Link PM policy\n");
+ ap->pm_policy = MAX_PERFORMANCE;
+ }
+ }
+
+ if (ap->ops->enable_pm)
+ rc = ap->ops->enable_pm(ap, policy);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ata_scsi_set_link_pm_policy);
+
int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
{
int i, rc;
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h
+++ 2.6-git/include/linux/libata.h
@@ -139,7 +139,8 @@ enum {
ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
- ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
+ ATA_DFLAG_IPM = (1 << 7), /* device supports IPM */
+ ATA_DFLAG_CFG_MASK = (1 << 12) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */
@@ -303,6 +304,7 @@ enum {
ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */
+ ATA_HORKAGE_IPM = (1 << 4), /* LPM problems */
};
enum hsm_task_states {
@@ -341,6 +343,18 @@ typedef int (*ata_reset_fn_t)(struct ata
unsigned long deadline);
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
+/*
+ * host pm policy: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions)
+ */
+enum link_pm {
+ NOT_AVAILABLE,
+ MIN_POWER,
+ MAX_PERFORMANCE,
+ MEDIUM_POWER,
+};
+extern struct class_device_attribute class_device_attr_link_power_management_policy;
+
struct ata_ioports {
void __iomem *cmd_addr;
void __iomem *data_addr;
@@ -567,6 +581,7 @@ struct ata_port {
pm_message_t pm_mesg;
int *pm_result;
+ enum link_pm pm_policy;
struct timer_list fastdrain_timer;
unsigned long fastdrain_cnt;
@@ -632,7 +647,8 @@ struct ata_port_operations {
int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
int (*port_resume) (struct ata_port *ap);
-
+ int (*enable_pm) (struct ata_port *ap, enum link_pm policy);
+ int (*disable_pm) (struct ata_port *ap);
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@@ -839,7 +855,7 @@ extern int ata_cable_40wire(struct ata_p
extern int ata_cable_80wire(struct ata_port *ap);
extern int ata_cable_sata(struct ata_port *ap);
extern int ata_cable_unknown(struct ata_port *ap);
-
+extern int ata_scsi_set_link_pm_policy(struct ata_port *ap, enum link_pm);
/*
* Timing helpers
*/
@@ -868,7 +884,6 @@ enum {
ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
};
-
#ifdef CONFIG_PCI
struct pci_bits {
unsigned int reg; /* PCI config register to read */
Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c
+++ 2.6-git/drivers/ata/libata-core.c
@@ -1993,6 +1993,9 @@ int ata_dev_configure(struct ata_device
if (dev->flags & ATA_DFLAG_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+ if (ata_id_has_hipm(dev->id) || ata_id_has_dipm(dev->id))
+ dev->flags |= ATA_DFLAG_IPM;
+
if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
/* Let the user know. We don't want to disallow opens for
rescue purposes, or in case the vendor is just a blithering
@@ -2018,6 +2021,13 @@ int ata_dev_configure(struct ata_device
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
+ if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
+ dev->horkage |= ATA_HORKAGE_IPM;
+
+ /* reset link pm_policy for this port to no pm */
+ ap->pm_policy = MAX_PERFORMANCE;
+ }
+
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -5872,6 +5882,27 @@ int ata_flush_cache(struct ata_device *d
return 0;
}
+static void ata_host_disable_link_pm(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ if (ap->ops->disable_pm)
+ ap->ops->disable_pm(ap);
+ }
+}
+
+static void ata_host_enable_link_pm(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ ata_scsi_set_link_pm_policy(ap, ap->pm_policy);
+ }
+}
+
#ifdef CONFIG_PM
static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
unsigned int action, unsigned int ehi_flags,
@@ -5939,6 +5970,12 @@ int ata_host_suspend(struct ata_host *ho
{
int rc;
+ /*
+ * disable link pm on all ports before requesting
+ * any pm activity
+ */
+ ata_host_disable_link_pm(host);
+
rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
if (rc == 0)
host->dev->power.power_state = mesg;
@@ -5961,6 +5998,9 @@ void ata_host_resume(struct ata_host *ho
ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host->dev->power.power_state = PMSG_ON;
+
+ /* reenable link pm */
+ ata_host_enable_link_pm(host);
}
#endif
@@ -6457,6 +6497,7 @@ int ata_host_register(struct ata_host *h
struct ata_port *ap = host->ports[i];
ata_scsi_scan_host(ap, 1);
+ ata_scsi_set_link_pm_policy(ap, ap->pm_policy);
}
return 0;
Index: 2.6-git/include/linux/ata.h
===================================================================
--- 2.6-git.orig/include/linux/ata.h
+++ 2.6-git/include/linux/ata.h
@@ -355,6 +355,12 @@ struct ata_taskfile {
((u64) (id)[(n) + 0]) )
#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
+#define ata_id_has_hipm(id) \
+ ( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
+ ((id)[76] & (1 << 9)) )
+#define ata_id_has_dipm(id) \
+ ( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
+ ((id)[78] & (1 << 3)) )
static inline unsigned int ata_id_major_version(const u16 *id)
{
Index: 2.6-git/Documentation/scsi/link_power_management_policy.txt
===================================================================
--- /dev/null
+++ 2.6-git/Documentation/scsi/link_power_management_policy.txt
@@ -0,0 +1,19 @@
+This parameter allows the user to set the link (interface) power management.
+There are 3 possible options:
+
+Value Effect
+----------------------------------------------------------------------------
+min_power Tell the controller to try to make the link use the
+ least possible power when possible. This may
+ sacrifice some performance due to increased latency
+ when coming out of lower power states.
+
+max_performance Generally, this means no power management. Tell
+ the controller to have performance be a priority
+ over power management.
+
+medium_power Tell the controller to enter a lower power state
+ when possible, but do not enter the lowest power
+ state, thus improving latency over min_power setting.
+
+
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-08-01 8:27 ` Tejun Heo
2007-08-01 9:45 ` edwintorok
@ 2007-08-01 21:11 ` Kristen Carlson Accardi
2007-08-02 5:27 ` Tejun Heo
1 sibling, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 21:11 UTC (permalink / raw)
To: Tejun Heo
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
On Wed, 01 Aug 2007 17:27:39 +0900
Tejun Heo <htejun@gmail.com> wrote:
> Kristen Carlson Accardi wrote:
<snippy>
> Is it safe to use ALPM on a device which only claims to support DIPM?
Yes - I doubled checked this with the AHCI people - and of course you
have Edvin's testing to prove it does fine.
> I think this should be ATA_HORKAGE_IPM.
OK - I changed it.
> > @@ -321,6 +321,8 @@ struct ata_taskfile {
> > ((u64) (id)[(n) + 0]) )
> >
> > #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
> > +#define ata_id_has_hipm(id) ((id)[76] & (1 << 9))
> > +#define ata_id_has_dipm(id) ((id)[78] & (1 << 3))
>
> We probably need !0xffff test here.
Thanks, I fixed that too.
As far as moving the enable/disable_pm calls to EH - can you take
a look at the other patch I sent which implements the shost_attrs
to see if I still need to do this? I really don't know much about
the EH stuff - can you explain why we need to use it to set the
link pm?
thanks for your review,
Kristen
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 9:23 ` Tejun Heo
2007-08-01 16:31 ` Kristen Carlson Accardi
@ 2007-08-01 21:16 ` Kristen Carlson Accardi
2007-08-09 16:10 ` Kristen Carlson Accardi
1 sibling, 1 reply; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 21:16 UTC (permalink / raw)
To: Tejun Heo
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
I was able to duplicate Tejun's problem on an ATAPI device I had here.
this updated patch fixed my problem. These devices are just setting
PhyReady (N) and CommWake (W) in Serror on power state changes, ignoring
them seems to be fine, and fixed the problem for me.
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_power ALPM is enabled, and link set to enter
second lowest power state (PARTIAL) when
idle. Hot plug not allowed.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c
+++ 2.6-git/drivers/ata/ahci.c
@@ -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,
@@ -98,6 +101,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 */
@@ -153,6 +157,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 */
@@ -244,6 +250,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,
@@ -261,6 +272,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 = {
@@ -292,6 +304,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,
@@ -778,6 +792,156 @@ 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, scontrol;
+ struct ahci_port_priv *pp = ap->private_data;
+
+ /*
+ * disable Interface Power Management State Transitions
+ * This is accomplished by setting bits 8:11 of the
+ * SATA Control register
+ */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol |= (0x3 << 8);
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+ /* 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 */
+ msleep(10);
+
+ /* clear out any PhyRdy stuff from interrupt status */
+ writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
+
+ /* go ahead and clean out PhyRdy Change from Serror too */
+ ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+
+ /*
+ * Clear flag to indicate that we should ignore all PhyRdy
+ * state changes
+ */
+ ap->flags &= ~AHCI_FLAG_NO_HOTPLUG;
+
+ /*
+ * Enable interrupts on Phy Ready.
+ */
+ pp->intr_mask |= PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * don't change the link pm policy - we can be called
+ * just to turn of link pm temporarily
+ */
+ return 0;
+}
+
+static int ahci_enable_alpm(struct ata_port *ap,
+ enum link_pm policy)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 cmd, scontrol, sstatus;
+ struct ahci_port_priv *pp = ap->private_data;
+ u32 asp;
+
+ /* Make sure the host is capable of link power management */
+ if (!(hpriv->cap & HOST_CAP_ALPM)) {
+ ap->pm_policy = NOT_AVAILABLE;
+ return -EINVAL;
+ }
+
+ /* make sure we have a device attached */
+ sstatus = readl(port_mmio + PORT_SCR_STAT);
+ if (!(sstatus & 0xf00)) {
+ ap->pm_policy = NOT_AVAILABLE;
+ return -EINVAL;
+ }
+
+ switch (policy) {
+ case MAX_PERFORMANCE:
+ case NOT_AVAILABLE:
+ /*
+ * if we came here with NOT_AVAILABLE,
+ * it just means this is the first time we
+ * have tried to enable - default to max performance,
+ * and let the user go to lower power modes on request.
+ */
+ ahci_disable_alpm(ap);
+ ap->pm_policy = MAX_PERFORMANCE;
+ return 0;
+ case MIN_POWER:
+ /* configure HBA to enter SLUMBER */
+ asp = PORT_CMD_ASP;
+ break;
+ case MEDIUM_POWER:
+ /* configure HBA to enter PARTIAL */
+ asp = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ap->pm_policy = policy;
+
+ /*
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready interrupts
+ * TBD - Hot plug should be done via polling now, is
+ * that even supported?
+ */
+ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * Set a flag to indicate that we should ignore all PhyRdy
+ * state changes since these can happen now whenever we
+ * change link state
+ */
+ ap->flags |= AHCI_FLAG_NO_HOTPLUG;
+
+ /* get the existing command bits */
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /*
+ * enable Interface Power Management State Transitions
+ * This is accomplished by clearing bits 8:11 of the
+ * SATA Control register
+ */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol &= ~(0x3 << 8);
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+ /*
+ * Set ASP based on Policy
+ */
+ cmd |= asp;
+
+ /*
+ * Setting this bit will instruct the HBA to aggressively
+ * enter a lower power link state when it's appropriate and
+ * based on the value set above for ASP
+ */
+ cmd |= PORT_CMD_ALPE;
+
+ /* write out new cmd value */
+ writel(cmd, port_mmio + PORT_CMD);
+ cmd = readl(port_mmio + PORT_CMD);
+ return 0;
+}
+
#ifdef CONFIG_PM
static void ahci_power_down(struct ata_port *ap)
{
@@ -1355,6 +1519,17 @@ static void ahci_port_intr(struct ata_po
status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT);
+ /* If we are getting PhyRdy, this is
+ * just a power state change, we should
+ * clear out this, plus the PhyRdy/Comm
+ * Wake bits from Serror
+ */
+ if ((ap->flags & AHCI_FLAG_NO_HOTPLUG) &&
+ (status & PORT_IRQ_PHYRDY)) {
+ status &= ~PORT_IRQ_PHYRDY;
+ ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+ }
+
if (unlikely(status & PORT_IRQ_ERROR)) {
ahci_error_intr(ap, status);
return;
@@ -1861,6 +2036,9 @@ static int ahci_init_one(struct pci_dev
struct ata_port *ap = host->ports[i];
void __iomem *port_mmio = ahci_port_base(ap);
+ /* set initial link pm policy */
+ ap->pm_policy = NOT_AVAILABLE;
+
/* standard SATA port setup */
if (hpriv->port_map & (1 << i))
ap->ioaddr.cmd_addr = port_mmio;
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 1/4] Store interrupt value
2007-08-01 14:01 ` Jeff Garzik
@ 2007-08-01 21:18 ` Kristen Carlson Accardi
0 siblings, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-01 21:18 UTC (permalink / raw)
To: Jeff Garzik
Cc: akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok, axboe,
linux-scsi
Store interrupt value
Use a stored value for which interrupts to enable. Changing this allows
us to selectively turn off certain interrupts later and have them
stay off.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c
+++ 2.6-git/drivers/ata/ahci.c
@@ -175,6 +175,7 @@ enum {
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */
+ AHCI_FLAG_NO_HOTPLUG = (1 << 31), /* ignore PxSERR.DIAG.N */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -215,6 +216,7 @@ struct ahci_port_priv {
unsigned int ncq_saw_d2h:1;
unsigned int ncq_saw_dmas:1;
unsigned int ncq_saw_sdb:1;
+ u32 intr_mask; /* interrupts to enable */
};
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
@@ -1518,6 +1520,7 @@ static void ahci_thaw(struct ata_port *a
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
+ struct ahci_port_priv *pp = ap->private_data;
/* clear IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
@@ -1525,7 +1528,7 @@ static void ahci_thaw(struct ata_port *a
writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
/* turn IRQ back on */
- writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
static void ahci_error_handler(struct ata_port *ap)
@@ -1679,6 +1682,12 @@ static int ahci_port_start(struct ata_po
pp->cmd_tbl = mem;
pp->cmd_tbl_dma = mem_dma;
+ /*
+ * Save off initial list of interrupts to be enabled.
+ * This could be changed later
+ */
+ pp->intr_mask = DEF_PORT_IRQ;
+
ap->private_data = pp;
/* engage engines, captain */
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 3/4] Enable link power management for ata drivers
2007-08-01 21:11 ` Kristen Carlson Accardi
@ 2007-08-02 5:27 ` Tejun Heo
0 siblings, 0 replies; 43+ messages in thread
From: Tejun Heo @ 2007-08-02 5:27 UTC (permalink / raw)
To: Kristen Carlson Accardi
Cc: jeff, akpm, linux-kernel, linux-ide, James.Bottomley, edwintorok,
axboe, linux-scsi
Kristen Carlson Accardi wrote:
> On Wed, 01 Aug 2007 17:27:39 +0900
> Tejun Heo <htejun@gmail.com> wrote:
>
>> Kristen Carlson Accardi wrote:
> <snippy>
>> Is it safe to use ALPM on a device which only claims to support DIPM?
>
> Yes - I doubled checked this with the AHCI people - and of course you
> have Edvin's testing to prove it does fine.
Alright.
> As far as moving the enable/disable_pm calls to EH - can you take
> a look at the other patch I sent which implements the shost_attrs
> to see if I still need to do this? I really don't know much about
> the EH stuff - can you explain why we need to use it to set the
> link pm?
Unfortunately, yes, you still need to. Only two threads of execution
(one is not a real thread tho) are allowed to access a libata port -
command execution and EH, and the two are mutually exclusive. Invoking
something from the outside is done by doing the following.
1. recording what to do in ehi->[dev_]action, ap->pflags or dev->flags
2. schedule EH by calling either ata_port_schedule_eh(),
ata_port_abort() or ata_port_freeze(). The first one waits for the
currently in-flight commands to finish before entering EH. The second
one aborts all in-flight commands and enters EH. The third one aborts
all commands and freezes the port and enters EH.
3. wait for EH to finish by calling ata_port_wait_eh().
This achieves correct synchronization and other EH functionalities can
be easily used. e.g. Resuming requires resetting the bus and
revalidating the attached devices, so the resume handler can just
request such actions together. For link PS, I think it would probably
be a good idea to revalidate after mode change to make sure the device
works in the new mode. If revalidation fails, it can reset and back off.
EH is done in three large steps - autopsy, report and recover. To
implement an action, the 'recover' stage needs to be extended. It
basically comes down to hooking the enable/disable functions into the
right places in ata_eh_recover(). Unconditionally disabling link PS
prior to reset and enabling it back again before revalidation would be a
pretty good choice, but haven't thought about it too hard so take it
with a grain of salt.
I'm not sure whether it would be necessary now but it would be nice to
have a proper recovery logic later. e.g. If more than certain number of
ATA bus occurs in certain mount of time, disable link PS. This kind of
logic is used during autopsy to determine whether stepping down
link/transfer speed is needed. Please take a look at
ata_eh_speed_down(). It might be enough to piggy back on
ata_eh_speed_down() tho such that the first step of speeding down is
turning off link PS.
Hope the brief introduction to libata-EH-hacking helps.
--
tejun
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [patch 2/4] Expose Power Management Policy option to users
2007-08-01 21:16 ` Kristen Carlson Accardi
@ 2007-08-09 16:10 ` Kristen Carlson Accardi
0 siblings, 0 replies; 43+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-09 16:10 UTC (permalink / raw)
To: Tejun Heo
Cc: Arjan van de Ven, Jeff Garzik, James.Bottomley, linux-scsi, akpm,
linux-kernel, linux-ide, edwintorok, axboe
On Wed, 1 Aug 2007 14:16:51 -0700
Kristen Carlson Accardi <kristen.c.accardi@intel.com> wrote:
> I was able to duplicate Tejun's problem on an ATAPI device I had here.
> this updated patch fixed my problem. These devices are just setting
> PhyReady (N) and CommWake (W) in Serror on power state changes, ignoring
> them seems to be fine, and fixed the problem for me.
Hi Tejun,
Were you able to test out this patch and see if it solved your ATAPI
device/ALPM issues?
Thanks,
Kristen
>
>
> 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_power ALPM is enabled, and link set to enter
> second lowest power state (PARTIAL) when
> idle. Hot plug not allowed.
>
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
>
> Index: 2.6-git/drivers/ata/ahci.c
> ===================================================================
> --- 2.6-git.orig/drivers/ata/ahci.c
> +++ 2.6-git/drivers/ata/ahci.c
> @@ -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,
> @@ -98,6 +101,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 */
> @@ -153,6 +157,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 */
> @@ -244,6 +250,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,
> @@ -261,6 +272,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 = {
> @@ -292,6 +304,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,
> @@ -778,6 +792,156 @@ 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, scontrol;
> + struct ahci_port_priv *pp = ap->private_data;
> +
> + /*
> + * disable Interface Power Management State Transitions
> + * This is accomplished by setting bits 8:11 of the
> + * SATA Control register
> + */
> + scontrol = readl(port_mmio + PORT_SCR_CTL);
> + scontrol |= (0x3 << 8);
> + writel(scontrol, port_mmio + PORT_SCR_CTL);
> +
> + /* 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 */
> + msleep(10);
> +
> + /* clear out any PhyRdy stuff from interrupt status */
> + writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
> +
> + /* go ahead and clean out PhyRdy Change from Serror too */
> + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
> +
> + /*
> + * Clear flag to indicate that we should ignore all PhyRdy
> + * state changes
> + */
> + ap->flags &= ~AHCI_FLAG_NO_HOTPLUG;
> +
> + /*
> + * Enable interrupts on Phy Ready.
> + */
> + pp->intr_mask |= PORT_IRQ_PHYRDY;
> + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
> +
> + /*
> + * don't change the link pm policy - we can be called
> + * just to turn of link pm temporarily
> + */
> + return 0;
> +}
> +
> +static int ahci_enable_alpm(struct ata_port *ap,
> + enum link_pm policy)
> +{
> + struct ahci_host_priv *hpriv = ap->host->private_data;
> + void __iomem *port_mmio = ahci_port_base(ap);
> + u32 cmd, scontrol, sstatus;
> + struct ahci_port_priv *pp = ap->private_data;
> + u32 asp;
> +
> + /* Make sure the host is capable of link power management */
> + if (!(hpriv->cap & HOST_CAP_ALPM)) {
> + ap->pm_policy = NOT_AVAILABLE;
> + return -EINVAL;
> + }
> +
> + /* make sure we have a device attached */
> + sstatus = readl(port_mmio + PORT_SCR_STAT);
> + if (!(sstatus & 0xf00)) {
> + ap->pm_policy = NOT_AVAILABLE;
> + return -EINVAL;
> + }
> +
> + switch (policy) {
> + case MAX_PERFORMANCE:
> + case NOT_AVAILABLE:
> + /*
> + * if we came here with NOT_AVAILABLE,
> + * it just means this is the first time we
> + * have tried to enable - default to max performance,
> + * and let the user go to lower power modes on request.
> + */
> + ahci_disable_alpm(ap);
> + ap->pm_policy = MAX_PERFORMANCE;
> + return 0;
> + case MIN_POWER:
> + /* configure HBA to enter SLUMBER */
> + asp = PORT_CMD_ASP;
> + break;
> + case MEDIUM_POWER:
> + /* configure HBA to enter PARTIAL */
> + asp = 0;
> + break;
> + default:
> + return -EINVAL;
> + }
> + ap->pm_policy = policy;
> +
> + /*
> + * Disable interrupts on Phy Ready. This keeps us from
> + * getting woken up due to spurious phy ready interrupts
> + * TBD - Hot plug should be done via polling now, is
> + * that even supported?
> + */
> + pp->intr_mask &= ~PORT_IRQ_PHYRDY;
> + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
> +
> + /*
> + * Set a flag to indicate that we should ignore all PhyRdy
> + * state changes since these can happen now whenever we
> + * change link state
> + */
> + ap->flags |= AHCI_FLAG_NO_HOTPLUG;
> +
> + /* get the existing command bits */
> + cmd = readl(port_mmio + PORT_CMD);
> +
> + /*
> + * enable Interface Power Management State Transitions
> + * This is accomplished by clearing bits 8:11 of the
> + * SATA Control register
> + */
> + scontrol = readl(port_mmio + PORT_SCR_CTL);
> + scontrol &= ~(0x3 << 8);
> + writel(scontrol, port_mmio + PORT_SCR_CTL);
> +
> + /*
> + * Set ASP based on Policy
> + */
> + cmd |= asp;
> +
> + /*
> + * Setting this bit will instruct the HBA to aggressively
> + * enter a lower power link state when it's appropriate and
> + * based on the value set above for ASP
> + */
> + cmd |= PORT_CMD_ALPE;
> +
> + /* write out new cmd value */
> + writel(cmd, port_mmio + PORT_CMD);
> + cmd = readl(port_mmio + PORT_CMD);
> + return 0;
> +}
> +
> #ifdef CONFIG_PM
> static void ahci_power_down(struct ata_port *ap)
> {
> @@ -1355,6 +1519,17 @@ static void ahci_port_intr(struct ata_po
> status = readl(port_mmio + PORT_IRQ_STAT);
> writel(status, port_mmio + PORT_IRQ_STAT);
>
> + /* If we are getting PhyRdy, this is
> + * just a power state change, we should
> + * clear out this, plus the PhyRdy/Comm
> + * Wake bits from Serror
> + */
> + if ((ap->flags & AHCI_FLAG_NO_HOTPLUG) &&
> + (status & PORT_IRQ_PHYRDY)) {
> + status &= ~PORT_IRQ_PHYRDY;
> + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
> + }
> +
> if (unlikely(status & PORT_IRQ_ERROR)) {
> ahci_error_intr(ap, status);
> return;
> @@ -1861,6 +2036,9 @@ static int ahci_init_one(struct pci_dev
> struct ata_port *ap = host->ports[i];
> void __iomem *port_mmio = ahci_port_base(ap);
>
> + /* set initial link pm policy */
> + ap->pm_policy = NOT_AVAILABLE;
> +
> /* standard SATA port setup */
> if (hpriv->port_map & (1 << i))
> ap->ioaddr.cmd_addr = port_mmio;
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2007-08-09 16:10 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20070705194909.337398431@intel.com>
2007-07-05 20:05 ` [patch 1/4] Store interrupt value Kristen Carlson Accardi
2007-08-01 8:18 ` Tejun Heo
2007-08-01 14:01 ` Jeff Garzik
2007-08-01 21:18 ` Kristen Carlson Accardi
2007-07-05 20:05 ` [patch 2/4] Expose Power Management Policy option to users Kristen Carlson Accardi
2007-07-09 19:36 ` Pavel Machek
2007-07-11 16:51 ` Kristen Carlson Accardi
2007-07-30 16:32 ` Jeff Garzik
2007-07-31 6:27 ` Tejun Heo
2007-07-31 14:16 ` Arjan van de Ven
2007-07-31 14:45 ` Tejun Heo
2007-07-31 16:15 ` Arjan van de Ven
2007-07-31 18:29 ` Tejun Heo
2007-08-01 9:23 ` Tejun Heo
2007-08-01 16:31 ` Kristen Carlson Accardi
2007-08-01 21:16 ` Kristen Carlson Accardi
2007-08-09 16:10 ` Kristen Carlson Accardi
2007-07-31 16:18 ` Kristen Carlson Accardi
2007-07-31 17:48 ` Tejun Heo
2007-07-31 20:24 ` Kristen Carlson Accardi
2007-08-01 3:20 ` Tejun Heo
2007-07-31 14:58 ` Tejun Heo
2007-07-31 14:18 ` James Bottomley
2007-08-01 16:53 ` Matthew Wilcox
2007-08-01 17:06 ` James Bottomley
2007-07-31 16:30 ` Kristen Carlson Accardi
2007-07-31 18:02 ` Tejun Heo
2007-07-31 19:58 ` Kristen Carlson Accardi
2007-08-01 3:24 ` Tejun Heo
2007-08-01 15:52 ` Kristen Carlson Accardi
2007-08-01 21:07 ` Kristen Carlson Accardi
2007-07-05 20:05 ` [patch 3/4] Enable link power management for ata drivers Kristen Carlson Accardi
2007-07-05 22:33 ` Andrew Morton
2007-07-05 22:37 ` Andrew Morton
2007-07-06 0:01 ` Jeff Garzik
2007-07-06 0:02 ` Jeff Garzik
2007-07-06 0:17 ` Andrew Morton
2007-07-06 0:00 ` Jeff Garzik
2007-08-01 8:27 ` Tejun Heo
2007-08-01 9:45 ` edwintorok
2007-08-01 21:11 ` Kristen Carlson Accardi
2007-08-02 5:27 ` Tejun Heo
2007-07-05 20:05 ` [patch 4/4] Enable Aggressive Link Power management for AHCI controllers Kristen Carlson Accardi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).