aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c196
1 files changed, 195 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e512903b8db..63035d71a61 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);