summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-09-03 18:06:02 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-09-03 18:06:02 -0400
commit7b01463e51f6849d0787b24d06a62efcb243dd44 (patch)
treec084f9b5290fe4b6f279e711c0ada7be9dca8b32 /drivers/acpi/sleep.c
parenta1b5fd8fa29fb2359f398ef17a706449d94de80d (diff)
parent726fb6b4f2a82a14a906f39bdabac4863b87c01a (diff)
Merge branch 'pm-sleep'
* pm-sleep: ACPI / PM: Check low power idle constraints for debug only PM / s2idle: Rename platform operations structure PM / s2idle: Rename ->enter_freeze to ->enter_s2idle PM / s2idle: Rename freeze_state enum and related items PM / s2idle: Rename PM_SUSPEND_FREEZE to PM_SUSPEND_TO_IDLE ACPI / PM: Prefer suspend-to-idle over S3 on some systems platform/x86: intel-hid: Wake up Dell Latitude 7275 from suspend-to-idle PM / suspend: Define pr_fmt() in suspend.c PM / suspend: Use mem_sleep_labels[] strings in messages PM / sleep: Put pm_test under CONFIG_PM_SLEEP_DEBUG PM / sleep: Check pm_wakeup_pending() in __device_suspend_noirq() PM / core: Add error argument to dpm_show_time() PM / core: Split dpm_suspend_noirq() and dpm_resume_noirq() PM / s2idle: Rearrange the main suspend-to-idle loop PM / timekeeping: Print debug messages when requested PM / sleep: Mark suspend/hibernation start and finish PM / sleep: Do not print debug messages by default PM / suspend: Export pm_suspend_target_state
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r--drivers/acpi/sleep.c202
1 files changed, 188 insertions, 14 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index fa8243c5c062..09460d9f9208 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -669,6 +669,7 @@ static const struct acpi_device_id lps0_device_ids[] = {
669 669
670#define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66" 670#define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
671 671
672#define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1
672#define ACPI_LPS0_SCREEN_OFF 3 673#define ACPI_LPS0_SCREEN_OFF 3
673#define ACPI_LPS0_SCREEN_ON 4 674#define ACPI_LPS0_SCREEN_ON 4
674#define ACPI_LPS0_ENTRY 5 675#define ACPI_LPS0_ENTRY 5
@@ -680,6 +681,166 @@ static acpi_handle lps0_device_handle;
680static guid_t lps0_dsm_guid; 681static guid_t lps0_dsm_guid;
681static char lps0_dsm_func_mask; 682static char lps0_dsm_func_mask;
682 683
684/* Device constraint entry structure */
685struct lpi_device_info {
686 char *name;
687 int enabled;
688 union acpi_object *package;
689};
690
691/* Constraint package structure */
692struct lpi_device_constraint {
693 int uid;
694 int min_dstate;
695 int function_states;
696};
697
698struct lpi_constraints {
699 acpi_handle handle;
700 int min_dstate;
701};
702
703static struct lpi_constraints *lpi_constraints_table;
704static int lpi_constraints_table_size;
705
706static void lpi_device_get_constraints(void)
707{
708 union acpi_object *out_obj;
709 int i;
710
711 out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
712 1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
713 NULL, ACPI_TYPE_PACKAGE);
714
715 acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
716 out_obj ? "successful" : "failed");
717
718 if (!out_obj)
719 return;
720
721 lpi_constraints_table = kcalloc(out_obj->package.count,
722 sizeof(*lpi_constraints_table),
723 GFP_KERNEL);
724 if (!lpi_constraints_table)
725 goto free_acpi_buffer;
726
727 acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n");
728
729 for (i = 0; i < out_obj->package.count; i++) {
730 struct lpi_constraints *constraint;
731 acpi_status status;
732 union acpi_object *package = &out_obj->package.elements[i];
733 struct lpi_device_info info = { };
734 int package_count = 0, j;
735
736 if (!package)
737 continue;
738
739 for (j = 0; j < package->package.count; ++j) {
740 union acpi_object *element =
741 &(package->package.elements[j]);
742
743 switch (element->type) {
744 case ACPI_TYPE_INTEGER:
745 info.enabled = element->integer.value;
746 break;
747 case ACPI_TYPE_STRING:
748 info.name = element->string.pointer;
749 break;
750 case ACPI_TYPE_PACKAGE:
751 package_count = element->package.count;
752 info.package = element->package.elements;
753 break;
754 }
755 }
756
757 if (!info.enabled || !info.package || !info.name)
758 continue;
759
760 constraint = &lpi_constraints_table[lpi_constraints_table_size];
761
762 status = acpi_get_handle(NULL, info.name, &constraint->handle);
763 if (ACPI_FAILURE(status))
764 continue;
765
766 acpi_handle_debug(lps0_device_handle,
767 "index:%d Name:%s\n", i, info.name);
768
769 constraint->min_dstate = -1;
770
771 for (j = 0; j < package_count; ++j) {
772 union acpi_object *info_obj = &info.package[j];
773 union acpi_object *cnstr_pkg;
774 union acpi_object *obj;
775 struct lpi_device_constraint dev_info;
776
777 switch (info_obj->type) {
778 case ACPI_TYPE_INTEGER:
779 /* version */
780 break;
781 case ACPI_TYPE_PACKAGE:
782 if (info_obj->package.count < 2)
783 break;
784
785 cnstr_pkg = info_obj->package.elements;
786 obj = &cnstr_pkg[0];
787 dev_info.uid = obj->integer.value;
788 obj = &cnstr_pkg[1];
789 dev_info.min_dstate = obj->integer.value;
790
791 acpi_handle_debug(lps0_device_handle,
792 "uid:%d min_dstate:%s\n",
793 dev_info.uid,
794 acpi_power_state_string(dev_info.min_dstate));
795
796 constraint->min_dstate = dev_info.min_dstate;
797 break;
798 }
799 }
800
801 if (constraint->min_dstate < 0) {
802 acpi_handle_debug(lps0_device_handle,
803 "Incomplete constraint defined\n");
804 continue;
805 }
806
807 lpi_constraints_table_size++;
808 }
809
810 acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
811
812free_acpi_buffer:
813 ACPI_FREE(out_obj);
814}
815
816static void lpi_check_constraints(void)
817{
818 int i;
819
820 for (i = 0; i < lpi_constraints_table_size; ++i) {
821 struct acpi_device *adev;
822
823 if (acpi_bus_get_device(lpi_constraints_table[i].handle, &adev))
824 continue;
825
826 acpi_handle_debug(adev->handle,
827 "LPI: required min power state:%s current power state:%s\n",
828 acpi_power_state_string(lpi_constraints_table[i].min_dstate),
829 acpi_power_state_string(adev->power.state));
830
831 if (!adev->flags.power_manageable) {
832 acpi_handle_info(adev->handle, "LPI: Device not power manageble\n");
833 continue;
834 }
835
836 if (adev->power.state < lpi_constraints_table[i].min_dstate)
837 acpi_handle_info(adev->handle,
838 "LPI: Constraint not met; min power state:%s current power state:%s\n",
839 acpi_power_state_string(lpi_constraints_table[i].min_dstate),
840 acpi_power_state_string(adev->power.state));
841 }
842}
843
683static void acpi_sleep_run_lps0_dsm(unsigned int func) 844static void acpi_sleep_run_lps0_dsm(unsigned int func)
684{ 845{
685 union acpi_object *out_obj; 846 union acpi_object *out_obj;
@@ -714,6 +875,12 @@ static int lps0_device_attach(struct acpi_device *adev,
714 if ((bitmask & ACPI_S2IDLE_FUNC_MASK) == ACPI_S2IDLE_FUNC_MASK) { 875 if ((bitmask & ACPI_S2IDLE_FUNC_MASK) == ACPI_S2IDLE_FUNC_MASK) {
715 lps0_dsm_func_mask = bitmask; 876 lps0_dsm_func_mask = bitmask;
716 lps0_device_handle = adev->handle; 877 lps0_device_handle = adev->handle;
878 /*
879 * Use suspend-to-idle by default if the default
880 * suspend mode was not set from the command line.
881 */
882 if (mem_sleep_default > PM_SUSPEND_MEM)
883 mem_sleep_current = PM_SUSPEND_TO_IDLE;
717 } 884 }
718 885
719 acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", 886 acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
@@ -723,6 +890,9 @@ static int lps0_device_attach(struct acpi_device *adev,
723 "_DSM function 0 evaluation failed\n"); 890 "_DSM function 0 evaluation failed\n");
724 } 891 }
725 ACPI_FREE(out_obj); 892 ACPI_FREE(out_obj);
893
894 lpi_device_get_constraints();
895
726 return 0; 896 return 0;
727} 897}
728 898
@@ -731,14 +901,14 @@ static struct acpi_scan_handler lps0_handler = {
731 .attach = lps0_device_attach, 901 .attach = lps0_device_attach,
732}; 902};
733 903
734static int acpi_freeze_begin(void) 904static int acpi_s2idle_begin(void)
735{ 905{
736 acpi_scan_lock_acquire(); 906 acpi_scan_lock_acquire();
737 s2idle_in_progress = true; 907 s2idle_in_progress = true;
738 return 0; 908 return 0;
739} 909}
740 910
741static int acpi_freeze_prepare(void) 911static int acpi_s2idle_prepare(void)
742{ 912{
743 if (lps0_device_handle) { 913 if (lps0_device_handle) {
744 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); 914 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
@@ -758,8 +928,12 @@ static int acpi_freeze_prepare(void)
758 return 0; 928 return 0;
759} 929}
760 930
761static void acpi_freeze_wake(void) 931static void acpi_s2idle_wake(void)
762{ 932{
933
934 if (pm_debug_messages_on)
935 lpi_check_constraints();
936
763 /* 937 /*
764 * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means 938 * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
765 * that the SCI has triggered while suspended, so cancel the wakeup in 939 * that the SCI has triggered while suspended, so cancel the wakeup in
@@ -772,7 +946,7 @@ static void acpi_freeze_wake(void)
772 } 946 }
773} 947}
774 948
775static void acpi_freeze_sync(void) 949static void acpi_s2idle_sync(void)
776{ 950{
777 /* 951 /*
778 * Process all pending events in case there are any wakeup ones. 952 * Process all pending events in case there are any wakeup ones.
@@ -785,7 +959,7 @@ static void acpi_freeze_sync(void)
785 s2idle_wakeup = false; 959 s2idle_wakeup = false;
786} 960}
787 961
788static void acpi_freeze_restore(void) 962static void acpi_s2idle_restore(void)
789{ 963{
790 if (acpi_sci_irq_valid()) 964 if (acpi_sci_irq_valid())
791 disable_irq_wake(acpi_sci_irq); 965 disable_irq_wake(acpi_sci_irq);
@@ -798,19 +972,19 @@ static void acpi_freeze_restore(void)
798 } 972 }
799} 973}
800 974
801static void acpi_freeze_end(void) 975static void acpi_s2idle_end(void)
802{ 976{
803 s2idle_in_progress = false; 977 s2idle_in_progress = false;
804 acpi_scan_lock_release(); 978 acpi_scan_lock_release();
805} 979}
806 980
807static const struct platform_freeze_ops acpi_freeze_ops = { 981static const struct platform_s2idle_ops acpi_s2idle_ops = {
808 .begin = acpi_freeze_begin, 982 .begin = acpi_s2idle_begin,
809 .prepare = acpi_freeze_prepare, 983 .prepare = acpi_s2idle_prepare,
810 .wake = acpi_freeze_wake, 984 .wake = acpi_s2idle_wake,
811 .sync = acpi_freeze_sync, 985 .sync = acpi_s2idle_sync,
812 .restore = acpi_freeze_restore, 986 .restore = acpi_s2idle_restore,
813 .end = acpi_freeze_end, 987 .end = acpi_s2idle_end,
814}; 988};
815 989
816static void acpi_sleep_suspend_setup(void) 990static void acpi_sleep_suspend_setup(void)
@@ -825,7 +999,7 @@ static void acpi_sleep_suspend_setup(void)
825 &acpi_suspend_ops_old : &acpi_suspend_ops); 999 &acpi_suspend_ops_old : &acpi_suspend_ops);
826 1000
827 acpi_scan_add_handler(&lps0_handler); 1001 acpi_scan_add_handler(&lps0_handler);
828 freeze_set_ops(&acpi_freeze_ops); 1002 s2idle_set_ops(&acpi_s2idle_ops);
829} 1003}
830 1004
831#else /* !CONFIG_SUSPEND */ 1005#else /* !CONFIG_SUSPEND */