aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-29 15:12:34 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-29 15:12:34 -0400
commit3529a233421fc43fa7bfdf7a4317daf28348a23d (patch)
tree520558ffb70e4f4743495ad7a62d4c775c0c1ea3 /drivers/ata
parent00cda56d39f013cce60f44f1e3da19b87eba5d85 (diff)
parent31556594f913fa81d008cecfe46d7211c919a853 (diff)
Merge branch 'alpm' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'alpm' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: [libata] AHCI: add hw link power management support [libata] Link power management infrastructure
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c157
-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
5 files changed, 424 insertions, 3 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c8ab947cf359..ed9b407e42d4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -49,6 +49,9 @@
49#define DRV_NAME "ahci" 49#define DRV_NAME "ahci"
50#define DRV_VERSION "3.0" 50#define DRV_VERSION "3.0"
51 51
52static int ahci_enable_alpm(struct ata_port *ap,
53 enum link_pm policy);
54static void ahci_disable_alpm(struct ata_port *ap);
52 55
53enum { 56enum {
54 AHCI_PCI_BAR = 5, 57 AHCI_PCI_BAR = 5,
@@ -99,6 +102,7 @@ enum {
99 HOST_CAP_SSC = (1 << 14), /* Slumber capable */ 102 HOST_CAP_SSC = (1 << 14), /* Slumber capable */
100 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ 103 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
101 HOST_CAP_CLO = (1 << 24), /* Command List Override support */ 104 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
105 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
102 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ 106 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
103 HOST_CAP_SNTF = (1 << 29), /* SNotification register */ 107 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
104 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ 108 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
@@ -155,6 +159,8 @@ enum {
155 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, 159 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
156 160
157 /* PORT_CMD bits */ 161 /* PORT_CMD bits */
162 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
163 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
158 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ 164 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
159 PORT_CMD_PMP = (1 << 17), /* PMP attached */ 165 PORT_CMD_PMP = (1 << 17), /* PMP attached */
160 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ 166 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
@@ -178,13 +184,14 @@ enum {
178 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ 184 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
179 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ 185 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
180 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ 186 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
187 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
181 188
182 /* ap->flags bits */ 189 /* ap->flags bits */
183 AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */
184 190
185 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 191 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
186 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 192 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
187 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN, 193 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
194 ATA_FLAG_IPM,
188 AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, 195 AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
189}; 196};
190 197
@@ -254,6 +261,11 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
254static int ahci_pci_device_resume(struct pci_dev *pdev); 261static int ahci_pci_device_resume(struct pci_dev *pdev);
255#endif 262#endif
256 263
264static struct class_device_attribute *ahci_shost_attrs[] = {
265 &class_device_attr_link_power_management_policy,
266 NULL
267};
268
257static struct scsi_host_template ahci_sht = { 269static struct scsi_host_template ahci_sht = {
258 .module = THIS_MODULE, 270 .module = THIS_MODULE,
259 .name = DRV_NAME, 271 .name = DRV_NAME,
@@ -271,6 +283,7 @@ static struct scsi_host_template ahci_sht = {
271 .slave_configure = ata_scsi_slave_config, 283 .slave_configure = ata_scsi_slave_config,
272 .slave_destroy = ata_scsi_slave_destroy, 284 .slave_destroy = ata_scsi_slave_destroy,
273 .bios_param = ata_std_bios_param, 285 .bios_param = ata_std_bios_param,
286 .shost_attrs = ahci_shost_attrs,
274}; 287};
275 288
276static const struct ata_port_operations ahci_ops = { 289static const struct ata_port_operations ahci_ops = {
@@ -302,6 +315,8 @@ static const struct ata_port_operations ahci_ops = {
302 .port_suspend = ahci_port_suspend, 315 .port_suspend = ahci_port_suspend,
303 .port_resume = ahci_port_resume, 316 .port_resume = ahci_port_resume,
304#endif 317#endif
318 .enable_pm = ahci_enable_alpm,
319 .disable_pm = ahci_disable_alpm,
305 320
306 .port_start = ahci_port_start, 321 .port_start = ahci_port_start,
307 .port_stop = ahci_port_stop, 322 .port_stop = ahci_port_stop,
@@ -836,6 +851,130 @@ static void ahci_power_up(struct ata_port *ap)
836 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); 851 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
837} 852}
838 853
854static void ahci_disable_alpm(struct ata_port *ap)
855{
856 struct ahci_host_priv *hpriv = ap->host->private_data;
857 void __iomem *port_mmio = ahci_port_base(ap);
858 u32 cmd;
859 struct ahci_port_priv *pp = ap->private_data;
860
861 /* IPM bits should be disabled by libata-core */
862 /* get the existing command bits */
863 cmd = readl(port_mmio + PORT_CMD);
864
865 /* disable ALPM and ASP */
866 cmd &= ~PORT_CMD_ASP;
867 cmd &= ~PORT_CMD_ALPE;
868
869 /* force the interface back to active */
870 cmd |= PORT_CMD_ICC_ACTIVE;
871
872 /* write out new cmd value */
873 writel(cmd, port_mmio + PORT_CMD);
874 cmd = readl(port_mmio + PORT_CMD);
875
876 /* wait 10ms to be sure we've come out of any low power state */
877 msleep(10);
878
879 /* clear out any PhyRdy stuff from interrupt status */
880 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
881
882 /* go ahead and clean out PhyRdy Change from Serror too */
883 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
884
885 /*
886 * Clear flag to indicate that we should ignore all PhyRdy
887 * state changes
888 */
889 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
890
891 /*
892 * Enable interrupts on Phy Ready.
893 */
894 pp->intr_mask |= PORT_IRQ_PHYRDY;
895 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
896
897 /*
898 * don't change the link pm policy - we can be called
899 * just to turn of link pm temporarily
900 */
901}
902
903static int ahci_enable_alpm(struct ata_port *ap,
904 enum link_pm policy)
905{
906 struct ahci_host_priv *hpriv = ap->host->private_data;
907 void __iomem *port_mmio = ahci_port_base(ap);
908 u32 cmd;
909 struct ahci_port_priv *pp = ap->private_data;
910 u32 asp;
911
912 /* Make sure the host is capable of link power management */
913 if (!(hpriv->cap & HOST_CAP_ALPM))
914 return -EINVAL;
915
916 switch (policy) {
917 case MAX_PERFORMANCE:
918 case NOT_AVAILABLE:
919 /*
920 * if we came here with NOT_AVAILABLE,
921 * it just means this is the first time we
922 * have tried to enable - default to max performance,
923 * and let the user go to lower power modes on request.
924 */
925 ahci_disable_alpm(ap);
926 return 0;
927 case MIN_POWER:
928 /* configure HBA to enter SLUMBER */
929 asp = PORT_CMD_ASP;
930 break;
931 case MEDIUM_POWER:
932 /* configure HBA to enter PARTIAL */
933 asp = 0;
934 break;
935 default:
936 return -EINVAL;
937 }
938
939 /*
940 * Disable interrupts on Phy Ready. This keeps us from
941 * getting woken up due to spurious phy ready interrupts
942 * TBD - Hot plug should be done via polling now, is
943 * that even supported?
944 */
945 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
946 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
947
948 /*
949 * Set a flag to indicate that we should ignore all PhyRdy
950 * state changes since these can happen now whenever we
951 * change link state
952 */
953 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
954
955 /* get the existing command bits */
956 cmd = readl(port_mmio + PORT_CMD);
957
958 /*
959 * Set ASP based on Policy
960 */
961 cmd |= asp;
962
963 /*
964 * Setting this bit will instruct the HBA to aggressively
965 * enter a lower power link state when it's appropriate and
966 * based on the value set above for ASP
967 */
968 cmd |= PORT_CMD_ALPE;
969
970 /* write out new cmd value */
971 writel(cmd, port_mmio + PORT_CMD);
972 cmd = readl(port_mmio + PORT_CMD);
973
974 /* IPM bits should be set by libata-core */
975 return 0;
976}
977
839#ifdef CONFIG_PM 978#ifdef CONFIG_PM
840static void ahci_power_down(struct ata_port *ap) 979static void ahci_power_down(struct ata_port *ap)
841{ 980{
@@ -1504,6 +1643,17 @@ static void ahci_port_intr(struct ata_port *ap)
1504 if (unlikely(resetting)) 1643 if (unlikely(resetting))
1505 status &= ~PORT_IRQ_BAD_PMP; 1644 status &= ~PORT_IRQ_BAD_PMP;
1506 1645
1646 /* If we are getting PhyRdy, this is
1647 * just a power state change, we should
1648 * clear out this, plus the PhyRdy/Comm
1649 * Wake bits from Serror
1650 */
1651 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
1652 (status & PORT_IRQ_PHYRDY)) {
1653 status &= ~PORT_IRQ_PHYRDY;
1654 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
1655 }
1656
1507 if (unlikely(status & PORT_IRQ_ERROR)) { 1657 if (unlikely(status & PORT_IRQ_ERROR)) {
1508 ahci_error_intr(ap, status); 1658 ahci_error_intr(ap, status);
1509 return; 1659 return;
@@ -2151,6 +2301,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2151 ata_port_pbar_desc(ap, AHCI_PCI_BAR, 2301 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
2152 0x100 + ap->port_no * 0x80, "port"); 2302 0x100 + ap->port_no * 0x80, "port");
2153 2303
2304 /* set initial link pm policy */
2305 ap->pm_policy = NOT_AVAILABLE;
2306
2154 /* standard SATA port setup */ 2307 /* standard SATA port setup */
2155 if (hpriv->port_map & (1 << i)) 2308 if (hpriv->port_map & (1 << i))
2156 ap->ioaddr.cmd_addr = port_mmio; 2309 ap->ioaddr.cmd_addr = port_mmio;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e512903b8dbb..63035d71a61a 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
@@ -6362,6 +6547,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
6362{ 6547{
6363 int rc; 6548 int rc;
6364 6549
6550 /*
6551 * disable link pm on all ports before requesting
6552 * any pm activity
6553 */
6554 ata_lpm_enable(host);
6555
6365 rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); 6556 rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
6366 if (rc == 0) 6557 if (rc == 0)
6367 host->dev->power.power_state = mesg; 6558 host->dev->power.power_state = mesg;
@@ -6384,6 +6575,9 @@ void ata_host_resume(struct ata_host *host)
6384 ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET, 6575 ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
6385 ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); 6576 ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
6386 host->dev->power.power_state = PMSG_ON; 6577 host->dev->power.power_state = PMSG_ON;
6578
6579 /* reenable link pm */
6580 ata_lpm_disable(host);
6387} 6581}
6388#endif 6582#endif
6389 6583
@@ -6926,6 +7120,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
6926 struct ata_port *ap = host->ports[i]; 7120 struct ata_port *ap = host->ports[i];
6927 7121
6928 ata_scsi_scan_host(ap, 1); 7122 ata_scsi_scan_host(ap, 1);
7123 ata_lpm_schedule(ap, ap->pm_policy);
6929 } 7124 }
6930 7125
6931 return 0; 7126 return 0;
@@ -7322,7 +7517,6 @@ const struct ata_port_info ata_dummy_port_info = {
7322 * likely to change as new drivers are added and updated. 7517 * likely to change as new drivers are added and updated.
7323 * Do not depend on ABI/API stability. 7518 * Do not depend on ABI/API stability.
7324 */ 7519 */
7325
7326EXPORT_SYMBOL_GPL(sata_deb_timing_normal); 7520EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
7327EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); 7521EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
7328EXPORT_SYMBOL_GPL(sata_deb_timing_long); 7522EXPORT_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