aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristen Carlson Accardi <kristen.c.accardi@intel.com>2007-10-25 00:58:59 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-29 11:00:35 -0400
commitca77329fb713b7fea6a307068e0dd0248e7aa640 (patch)
tree6a1b987f489d7c3f0bbe81647b4ee2b0216afe8a
parentab6fc95f609b372a19e18ea689986846ab1ba29c (diff)
[libata] Link power management infrastructure
Device Initiated Power Management, which is defined in SATA 2.5 can be enabled for disks which support it. This patch enables DIPM when the user sets the link power management policy to "min_power". Additionally, libata drivers can define a function (enable_pm) that will perform hardware specific actions to enable whatever power management policy the user set up for Host Initiated Power management (HIPM). 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. Documentation/scsi/link_power_management_policy.txt has additional information. Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--Documentation/scsi/link_power_management_policy.txt19
-rw-r--r--drivers/ata/libata-core.c196
-rw-r--r--drivers/ata/libata-eh.c4
-rw-r--r--drivers/ata/libata-scsi.c68
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--include/linux/ata.h21
-rw-r--r--include/linux/libata.h21
7 files changed, 329 insertions, 2 deletions
diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.txt
new file mode 100644
index 000000000000..d18993d01884
--- /dev/null
+++ b/Documentation/scsi/link_power_management_policy.txt
@@ -0,0 +1,19 @@
1This parameter allows the user to set the link (interface) power management.
2There are 3 possible options:
3
4Value Effect
5----------------------------------------------------------------------------
6min_power Tell the controller to try to make the link use the
7 least possible power when possible. This may
8 sacrifice some performance due to increased latency
9 when coming out of lower power states.
10
11max_performance Generally, this means no power management. Tell
12 the controller to have performance be a priority
13 over power management.
14
15medium_power Tell the controller to enter a lower power state
16 when possible, but do not enter the lowest power
17 state, thus improving latency over min_power setting.
18
19
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3891cdc6bd3d..513babe6a143 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -620,6 +620,177 @@ void ata_dev_disable(struct ata_device *dev)
620 } 620 }
621} 621}
622 622
623static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
624{
625 struct ata_link *link = dev->link;
626 struct ata_port *ap = link->ap;
627 u32 scontrol;
628 unsigned int err_mask;
629 int rc;
630
631 /*
632 * disallow DIPM for drivers which haven't set
633 * ATA_FLAG_IPM. This is because when DIPM is enabled,
634 * phy ready will be set in the interrupt status on
635 * state changes, which will cause some drivers to
636 * think there are errors - additionally drivers will
637 * need to disable hot plug.
638 */
639 if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) {
640 ap->pm_policy = NOT_AVAILABLE;
641 return -EINVAL;
642 }
643
644 /*
645 * For DIPM, we will only enable it for the
646 * min_power setting.
647 *
648 * Why? Because Disks are too stupid to know that
649 * If the host rejects a request to go to SLUMBER
650 * they should retry at PARTIAL, and instead it
651 * just would give up. So, for medium_power to
652 * work at all, we need to only allow HIPM.
653 */
654 rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
655 if (rc)
656 return rc;
657
658 switch (policy) {
659 case MIN_POWER:
660 /* no restrictions on IPM transitions */
661 scontrol &= ~(0x3 << 8);
662 rc = sata_scr_write(link, SCR_CONTROL, scontrol);
663 if (rc)
664 return rc;
665
666 /* enable DIPM */
667 if (dev->flags & ATA_DFLAG_DIPM)
668 err_mask = ata_dev_set_feature(dev,
669 SETFEATURES_SATA_ENABLE, SATA_DIPM);
670 break;
671 case MEDIUM_POWER:
672 /* allow IPM to PARTIAL */
673 scontrol &= ~(0x1 << 8);
674 scontrol |= (0x2 << 8);
675 rc = sata_scr_write(link, SCR_CONTROL, scontrol);
676 if (rc)
677 return rc;
678
679 /* disable DIPM */
680 if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM))
681 err_mask = ata_dev_set_feature(dev,
682 SETFEATURES_SATA_DISABLE, SATA_DIPM);
683 break;
684 case NOT_AVAILABLE:
685 case MAX_PERFORMANCE:
686 /* disable all IPM transitions */
687 scontrol |= (0x3 << 8);
688 rc = sata_scr_write(link, SCR_CONTROL, scontrol);
689 if (rc)
690 return rc;
691
692 /* disable DIPM */
693 if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM))
694 err_mask = ata_dev_set_feature(dev,
695 SETFEATURES_SATA_DISABLE, SATA_DIPM);
696 break;
697 }
698
699 /* FIXME: handle SET FEATURES failure */
700 (void) err_mask;
701
702 return 0;
703}
704
705/**
706 * ata_dev_enable_pm - enable SATA interface power management
707 * @device - device to enable ipm for
708 * @policy - the link power management policy
709 *
710 * Enable SATA Interface power management. This will enable
711 * Device Interface Power Management (DIPM) for min_power
712 * policy, and then call driver specific callbacks for
713 * enabling Host Initiated Power management.
714 *
715 * Locking: Caller.
716 * Returns: -EINVAL if IPM is not supported, 0 otherwise.
717 */
718void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
719{
720 int rc = 0;
721 struct ata_port *ap = dev->link->ap;
722
723 /* set HIPM first, then DIPM */
724 if (ap->ops->enable_pm)
725 rc = ap->ops->enable_pm(ap, policy);
726 if (rc)
727 goto enable_pm_out;
728 rc = ata_dev_set_dipm(dev, policy);
729
730enable_pm_out:
731 if (rc)
732 ap->pm_policy = MAX_PERFORMANCE;
733 else
734 ap->pm_policy = policy;
735 return /* rc */; /* hopefully we can use 'rc' eventually */
736}
737
738/**
739 * ata_dev_disable_pm - disable SATA interface power management
740 * @device - device to enable ipm for
741 *
742 * Disable SATA Interface power management. This will disable
743 * Device Interface Power Management (DIPM) without changing
744 * policy, call driver specific callbacks for disabling Host
745 * Initiated Power management.
746 *
747 * Locking: Caller.
748 * Returns: void
749 */
750static void ata_dev_disable_pm(struct ata_device *dev)
751{
752 struct ata_port *ap = dev->link->ap;
753
754 ata_dev_set_dipm(dev, MAX_PERFORMANCE);
755 if (ap->ops->disable_pm)
756 ap->ops->disable_pm(ap);
757}
758
759void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
760{
761 ap->pm_policy = policy;
762 ap->link.eh_info.action |= ATA_EHI_LPM;
763 ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
764 ata_port_schedule_eh(ap);
765}
766
767static void ata_lpm_enable(struct ata_host *host)
768{
769 struct ata_link *link;
770 struct ata_port *ap;
771 struct ata_device *dev;
772 int i;
773
774 for (i = 0; i < host->n_ports; i++) {
775 ap = host->ports[i];
776 ata_port_for_each_link(link, ap) {
777 ata_link_for_each_dev(dev, link)
778 ata_dev_disable_pm(dev);
779 }
780 }
781}
782
783static void ata_lpm_disable(struct ata_host *host)
784{
785 int i;
786
787 for (i = 0; i < host->n_ports; i++) {
788 struct ata_port *ap = host->ports[i];
789 ata_lpm_schedule(ap, ap->pm_policy);
790 }
791}
792
793
623/** 794/**
624 * ata_devchk - PATA device presence detection 795 * ata_devchk - PATA device presence detection
625 * @ap: ATA channel to examine 796 * @ap: ATA channel to examine
@@ -2101,6 +2272,13 @@ int ata_dev_configure(struct ata_device *dev)
2101 if (dev->flags & ATA_DFLAG_LBA48) 2272 if (dev->flags & ATA_DFLAG_LBA48)
2102 dev->max_sectors = ATA_MAX_SECTORS_LBA48; 2273 dev->max_sectors = ATA_MAX_SECTORS_LBA48;
2103 2274
2275 if (!(dev->horkage & ATA_HORKAGE_IPM)) {
2276 if (ata_id_has_hipm(dev->id))
2277 dev->flags |= ATA_DFLAG_HIPM;
2278 if (ata_id_has_dipm(dev->id))
2279 dev->flags |= ATA_DFLAG_DIPM;
2280 }
2281
2104 if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { 2282 if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
2105 /* Let the user know. We don't want to disallow opens for 2283 /* Let the user know. We don't want to disallow opens for
2106 rescue purposes, or in case the vendor is just a blithering 2284 rescue purposes, or in case the vendor is just a blithering
@@ -2126,6 +2304,13 @@ int ata_dev_configure(struct ata_device *dev)
2126 dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, 2304 dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
2127 dev->max_sectors); 2305 dev->max_sectors);
2128 2306
2307 if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
2308 dev->horkage |= ATA_HORKAGE_IPM;
2309
2310 /* reset link pm_policy for this port to no pm */
2311 ap->pm_policy = MAX_PERFORMANCE;
2312 }
2313
2129 if (ap->ops->dev_config) 2314 if (ap->ops->dev_config)
2130 ap->ops->dev_config(dev); 2315 ap->ops->dev_config(dev);
2131 2316
@@ -6361,6 +6546,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
6361{ 6546{
6362 int rc; 6547 int rc;
6363 6548
6549 /*
6550 * disable link pm on all ports before requesting
6551 * any pm activity
6552 */
6553 ata_lpm_enable(host);
6554
6364 rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); 6555 rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
6365 if (rc == 0) 6556 if (rc == 0)
6366 host->dev->power.power_state = mesg; 6557 host->dev->power.power_state = mesg;
@@ -6383,6 +6574,9 @@ void ata_host_resume(struct ata_host *host)
6383 ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET, 6574 ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
6384 ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); 6575 ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
6385 host->dev->power.power_state = PMSG_ON; 6576 host->dev->power.power_state = PMSG_ON;
6577
6578 /* reenable link pm */
6579 ata_lpm_disable(host);
6386} 6580}
6387#endif 6581#endif
6388 6582
@@ -6925,6 +7119,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
6925 struct ata_port *ap = host->ports[i]; 7119 struct ata_port *ap = host->ports[i];
6926 7120
6927 ata_scsi_scan_host(ap, 1); 7121 ata_scsi_scan_host(ap, 1);
7122 ata_lpm_schedule(ap, ap->pm_policy);
6928 } 7123 }
6929 7124
6930 return 0; 7125 return 0;
@@ -7321,7 +7516,6 @@ const struct ata_port_info ata_dummy_port_info = {
7321 * likely to change as new drivers are added and updated. 7516 * likely to change as new drivers are added and updated.
7322 * Do not depend on ABI/API stability. 7517 * Do not depend on ABI/API stability.
7323 */ 7518 */
7324
7325EXPORT_SYMBOL_GPL(sata_deb_timing_normal); 7519EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
7326EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); 7520EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
7327EXPORT_SYMBOL_GPL(sata_deb_timing_long); 7521EXPORT_SYMBOL_GPL(sata_deb_timing_long);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ec55d63cf20e..fefea7470e51 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2628,6 +2628,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2628 ehc->i.flags &= ~ATA_EHI_SETMODE; 2628 ehc->i.flags &= ~ATA_EHI_SETMODE;
2629 } 2629 }
2630 2630
2631 if (ehc->i.action & ATA_EHI_LPM)
2632 ata_link_for_each_dev(dev, link)
2633 ata_dev_enable_pm(dev, ap->pm_policy);
2634
2631 /* this link is okay now */ 2635 /* this link is okay now */
2632 ehc->i.flags = 0; 2636 ehc->i.flags = 0;
2633 continue; 2637 continue;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f752eddc19ed..93bd36c19690 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -110,6 +110,74 @@ static struct scsi_transport_template ata_scsi_transport_template = {
110}; 110};
111 111
112 112
113static const struct {
114 enum link_pm value;
115 const char *name;
116} link_pm_policy[] = {
117 { NOT_AVAILABLE, "max_performance" },
118 { MIN_POWER, "min_power" },
119 { MAX_PERFORMANCE, "max_performance" },
120 { MEDIUM_POWER, "medium_power" },
121};
122
123const char *ata_scsi_lpm_get(enum link_pm policy)
124{
125 int i;
126
127 for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++)
128 if (link_pm_policy[i].value == policy)
129 return link_pm_policy[i].name;
130
131 return NULL;
132}
133
134static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
135 const char *buf, size_t count)
136{
137 struct Scsi_Host *shost = class_to_shost(class_dev);
138 struct ata_port *ap = ata_shost_to_port(shost);
139 enum link_pm policy = 0;
140 int i;
141
142 /*
143 * we are skipping array location 0 on purpose - this
144 * is because a value of NOT_AVAILABLE is displayed
145 * to the user as max_performance, but when the user
146 * writes "max_performance", they actually want the
147 * value to match MAX_PERFORMANCE.
148 */
149 for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
150 const int len = strlen(link_pm_policy[i].name);
151 if (strncmp(link_pm_policy[i].name, buf, len) == 0 &&
152 buf[len] == '\n') {
153 policy = link_pm_policy[i].value;
154 break;
155 }
156 }
157 if (!policy)
158 return -EINVAL;
159
160 ata_lpm_schedule(ap, policy);
161 return count;
162}
163
164static ssize_t
165ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
166{
167 struct Scsi_Host *shost = class_to_shost(class_dev);
168 struct ata_port *ap = ata_shost_to_port(shost);
169 const char *policy =
170 ata_scsi_lpm_get(ap->pm_policy);
171
172 if (!policy)
173 return -EINVAL;
174
175 return snprintf(buf, 23, "%s\n", policy);
176}
177CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
178 ata_scsi_lpm_show, ata_scsi_lpm_put);
179EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
180
113static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, 181static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
114 void (*done)(struct scsi_cmnd *)) 182 void (*done)(struct scsi_cmnd *))
115{ 183{
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 90df58a3edc9..0e6cf3a484dc 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -101,6 +101,8 @@ extern int sata_link_init_spd(struct ata_link *link);
101extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); 101extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
102extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); 102extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
103extern struct ata_port *ata_port_alloc(struct ata_host *host); 103extern struct ata_port *ata_port_alloc(struct ata_host *host);
104extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
105extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
104 106
105/* libata-acpi.c */ 107/* libata-acpi.c */
106#ifdef CONFIG_ATA_ACPI 108#ifdef CONFIG_ATA_ACPI
diff --git a/include/linux/ata.h b/include/linux/ata.h
index e21c002c3a4a..128dc7ad4901 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -236,6 +236,7 @@ enum {
236 236
237 /* SETFEATURE Sector counts for SATA features */ 237 /* SETFEATURE Sector counts for SATA features */
238 SATA_AN = 0x05, /* Asynchronous Notification */ 238 SATA_AN = 0x05, /* Asynchronous Notification */
239 SATA_DIPM = 0x03, /* Device Initiated Power Management */
239 240
240 /* ATAPI stuff */ 241 /* ATAPI stuff */
241 ATAPI_PKT_DMA = (1 << 0), 242 ATAPI_PKT_DMA = (1 << 0),
@@ -378,6 +379,26 @@ struct ata_taskfile {
378 379
379#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20) 380#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
380 381
382static inline bool ata_id_has_hipm(const u16 *id)
383{
384 u16 val = id[76];
385
386 if (val == 0 || val == 0xffff)
387 return false;
388
389 return val & (1 << 9);
390}
391
392static inline bool ata_id_has_dipm(const u16 *id)
393{
394 u16 val = id[78];
395
396 if (val == 0 || val == 0xffff)
397 return false;
398
399 return val & (1 << 3);
400}
401
381static inline int ata_id_has_fua(const u16 *id) 402static inline int ata_id_has_fua(const u16 *id)
382{ 403{
383 if ((id[84] & 0xC000) != 0x4000) 404 if ((id[84] & 0xC000) != 0x4000)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 439d40f86c55..147ccc40c8af 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -133,6 +133,8 @@ enum {
133 ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ 133 ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
134 ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ 134 ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
135 ATA_DFLAG_AN = (1 << 7), /* AN configured */ 135 ATA_DFLAG_AN = (1 << 7), /* AN configured */
136 ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */
137 ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */
136 ATA_DFLAG_CFG_MASK = (1 << 12) - 1, 138 ATA_DFLAG_CFG_MASK = (1 << 12) - 1,
137 139
138 ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */ 140 ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */
@@ -186,6 +188,7 @@ enum {
186 ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ 188 ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
187 ATA_FLAG_AN = (1 << 18), /* controller supports AN */ 189 ATA_FLAG_AN = (1 << 18), /* controller supports AN */
188 ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */ 190 ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
191 ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
189 192
190 /* The following flag belongs to ap->pflags but is kept in 193 /* The following flag belongs to ap->pflags but is kept in
191 * ap->flags because it's referenced in many LLDs and will be 194 * ap->flags because it's referenced in many LLDs and will be
@@ -302,6 +305,7 @@ enum {
302 ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ 305 ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */
303 ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ 306 ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
304 ATA_EHI_QUIET = (1 << 3), /* be quiet */ 307 ATA_EHI_QUIET = (1 << 3), /* be quiet */
308 ATA_EHI_LPM = (1 << 4), /* link power management action */
305 309
306 ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */ 310 ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */
307 ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */ 311 ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */
@@ -333,6 +337,7 @@ enum {
333 ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ 337 ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */
334 ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */ 338 ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */
335 ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ 339 ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */
340 ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */
336 341
337 /* DMA mask for user DMA control: User visible values; DO NOT 342 /* DMA mask for user DMA control: User visible values; DO NOT
338 renumber */ 343 renumber */
@@ -378,6 +383,18 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes,
378 unsigned long deadline); 383 unsigned long deadline);
379typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes); 384typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
380 385
386/*
387 * host pm policy: If you alter this, you also need to alter libata-scsi.c
388 * (for the ascii descriptions)
389 */
390enum link_pm {
391 NOT_AVAILABLE,
392 MIN_POWER,
393 MAX_PERFORMANCE,
394 MEDIUM_POWER,
395};
396extern struct class_device_attribute class_device_attr_link_power_management_policy;
397
381struct ata_ioports { 398struct ata_ioports {
382 void __iomem *cmd_addr; 399 void __iomem *cmd_addr;
383 void __iomem *data_addr; 400 void __iomem *data_addr;
@@ -624,6 +641,7 @@ struct ata_port {
624 641
625 pm_message_t pm_mesg; 642 pm_message_t pm_mesg;
626 int *pm_result; 643 int *pm_result;
644 enum link_pm pm_policy;
627 645
628 struct timer_list fastdrain_timer; 646 struct timer_list fastdrain_timer;
629 unsigned long fastdrain_cnt; 647 unsigned long fastdrain_cnt;
@@ -691,7 +709,8 @@ struct ata_port_operations {
691 709
692 int (*port_suspend) (struct ata_port *ap, pm_message_t mesg); 710 int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
693 int (*port_resume) (struct ata_port *ap); 711 int (*port_resume) (struct ata_port *ap);
694 712 int (*enable_pm) (struct ata_port *ap, enum link_pm policy);
713 void (*disable_pm) (struct ata_port *ap);
695 int (*port_start) (struct ata_port *ap); 714 int (*port_start) (struct ata_port *ap);
696 void (*port_stop) (struct ata_port *ap); 715 void (*port_stop) (struct ata_port *ap);
697 716