diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-11-06 07:54:47 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-11-06 07:54:47 -0500 |
commit | 69a10ca747c2d2d7c0354a883335e097c067ed35 (patch) | |
tree | a8b1f56f95af55a4d9bd826b7e5e6d31b8cd6b98 | |
parent | 96428e98aebe5db8a164711f102808651c7f518d (diff) | |
parent | a192aa923b66a435aae56983c4912ee150bc9b32 (diff) |
Merge branch 'acpi-pm' into pm-core
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-power | 16 | ||||
-rw-r--r-- | Documentation/acpi/lpit.txt | 25 | ||||
-rw-r--r-- | Documentation/power/pm_qos_interface.txt | 13 | ||||
-rw-r--r-- | drivers/acpi/Kconfig | 5 | ||||
-rw-r--r-- | drivers/acpi/Makefile | 1 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpit.c | 162 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 78 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 65 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 6 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 42 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 1 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 4 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 28 | ||||
-rw-r--r-- | include/acpi/acpiosxf.h | 2 | ||||
-rw-r--r-- | include/linux/acpi.h | 12 | ||||
-rw-r--r-- | include/linux/pm_qos.h | 1 |
16 files changed, 295 insertions, 166 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power index 676fdf5f2a99..f4b24c327665 100644 --- a/Documentation/ABI/testing/sysfs-devices-power +++ b/Documentation/ABI/testing/sysfs-devices-power | |||
@@ -258,19 +258,3 @@ Description: | |||
258 | 258 | ||
259 | This attribute has no effect on system-wide suspend/resume and | 259 | This attribute has no effect on system-wide suspend/resume and |
260 | hibernation. | 260 | hibernation. |
261 | |||
262 | What: /sys/devices/.../power/pm_qos_remote_wakeup | ||
263 | Date: September 2012 | ||
264 | Contact: Rafael J. Wysocki <rjw@rjwysocki.net> | ||
265 | Description: | ||
266 | The /sys/devices/.../power/pm_qos_remote_wakeup attribute | ||
267 | is used for manipulating the PM QoS "remote wakeup required" | ||
268 | flag. If set, this flag indicates to the kernel that the | ||
269 | device is a source of user events that have to be signaled from | ||
270 | its low-power states. | ||
271 | |||
272 | Not all drivers support this attribute. If it isn't supported, | ||
273 | it is not present. | ||
274 | |||
275 | This attribute has no effect on system-wide suspend/resume and | ||
276 | hibernation. | ||
diff --git a/Documentation/acpi/lpit.txt b/Documentation/acpi/lpit.txt new file mode 100644 index 000000000000..b426398d2e97 --- /dev/null +++ b/Documentation/acpi/lpit.txt | |||
@@ -0,0 +1,25 @@ | |||
1 | To enumerate platform Low Power Idle states, Intel platforms are using | ||
2 | “Low Power Idle Table” (LPIT). More details about this table can be | ||
3 | downloaded from: | ||
4 | http://www.uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf | ||
5 | |||
6 | Residencies for each low power state can be read via FFH | ||
7 | (Function fixed hardware) or a memory mapped interface. | ||
8 | |||
9 | On platforms supporting S0ix sleep states, there can be two types of | ||
10 | residencies: | ||
11 | - CPU PKG C10 (Read via FFH interface) | ||
12 | - Platform Controller Hub (PCH) SLP_S0 (Read via memory mapped interface) | ||
13 | |||
14 | The following attributes are added dynamically to the cpuidle | ||
15 | sysfs attribute group: | ||
16 | /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us | ||
17 | /sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us | ||
18 | |||
19 | The "low_power_idle_cpu_residency_us" attribute shows time spent | ||
20 | by the CPU package in PKG C10 | ||
21 | |||
22 | The "low_power_idle_system_residency_us" attribute shows SLP_S0 | ||
23 | residency, or system time spent with the SLP_S0# signal asserted. | ||
24 | This is the lowest possible system power state, achieved only when CPU is in | ||
25 | PKG C10 and all functional blocks in PCH are in a low power state. | ||
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt index 21d2d48f87a2..19c5f7b1a7ba 100644 --- a/Documentation/power/pm_qos_interface.txt +++ b/Documentation/power/pm_qos_interface.txt | |||
@@ -98,8 +98,7 @@ Values are updated in response to changes of the request list. | |||
98 | The target values of resume latency and active state latency tolerance are | 98 | The target values of resume latency and active state latency tolerance are |
99 | simply the minimum of the request values held in the parameter list elements. | 99 | simply the minimum of the request values held in the parameter list elements. |
100 | The PM QoS flags aggregate value is a gather (bitwise OR) of all list elements' | 100 | The PM QoS flags aggregate value is a gather (bitwise OR) of all list elements' |
101 | values. Two device PM QoS flags are defined currently: PM_QOS_FLAG_NO_POWER_OFF | 101 | values. One device PM QoS flag is defined currently: PM_QOS_FLAG_NO_POWER_OFF. |
102 | and PM_QOS_FLAG_REMOTE_WAKEUP. | ||
103 | 102 | ||
104 | Note: The aggregated target values are implemented in such a way that reading | 103 | Note: The aggregated target values are implemented in such a way that reading |
105 | the aggregated value does not require any locking mechanism. | 104 | the aggregated value does not require any locking mechanism. |
@@ -153,14 +152,14 @@ PM QoS list of resume latency constraints and remove sysfs attribute | |||
153 | pm_qos_resume_latency_us from the device's power directory. | 152 | pm_qos_resume_latency_us from the device's power directory. |
154 | 153 | ||
155 | int dev_pm_qos_expose_flags(device, value) | 154 | int dev_pm_qos_expose_flags(device, value) |
156 | Add a request to the device's PM QoS list of flags and create sysfs attributes | 155 | Add a request to the device's PM QoS list of flags and create sysfs attribute |
157 | pm_qos_no_power_off and pm_qos_remote_wakeup under the device's power directory | 156 | pm_qos_no_power_off under the device's power directory allowing user space to |
158 | allowing user space to change these flags' value. | 157 | change the value of the PM_QOS_FLAG_NO_POWER_OFF flag. |
159 | 158 | ||
160 | void dev_pm_qos_hide_flags(device) | 159 | void dev_pm_qos_hide_flags(device) |
161 | Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS list | 160 | Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS list |
162 | of flags and remove sysfs attributes pm_qos_no_power_off and pm_qos_remote_wakeup | 161 | of flags and remove sysfs attribute pm_qos_no_power_off from the device's power |
163 | under the device's power directory. | 162 | directory. |
164 | 163 | ||
165 | Notification mechanisms: | 164 | Notification mechanisms: |
166 | The per-device PM QoS framework has a per-device notification tree. | 165 | The per-device PM QoS framework has a per-device notification tree. |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1ce52f84dc23..4bfef0f78cde 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -80,6 +80,11 @@ endif | |||
80 | config ACPI_SPCR_TABLE | 80 | config ACPI_SPCR_TABLE |
81 | bool | 81 | bool |
82 | 82 | ||
83 | config ACPI_LPIT | ||
84 | bool | ||
85 | depends on X86_64 | ||
86 | default y | ||
87 | |||
83 | config ACPI_SLEEP | 88 | config ACPI_SLEEP |
84 | bool | 89 | bool |
85 | depends on SUSPEND || HIBERNATION | 90 | depends on SUSPEND || HIBERNATION |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 90265ab4437a..6a19bd7aba21 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -56,6 +56,7 @@ acpi-$(CONFIG_DEBUG_FS) += debugfs.o | |||
56 | acpi-$(CONFIG_ACPI_NUMA) += numa.o | 56 | acpi-$(CONFIG_ACPI_NUMA) += numa.o |
57 | acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o | 57 | acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o |
58 | acpi-y += acpi_lpat.o | 58 | acpi-y += acpi_lpat.o |
59 | acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o | ||
59 | acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o | 60 | acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o |
60 | acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o | 61 | acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o |
61 | 62 | ||
diff --git a/drivers/acpi/acpi_lpit.c b/drivers/acpi/acpi_lpit.c new file mode 100644 index 000000000000..e94e478dd18b --- /dev/null +++ b/drivers/acpi/acpi_lpit.c | |||
@@ -0,0 +1,162 @@ | |||
1 | |||
2 | /* | ||
3 | * acpi_lpit.c - LPIT table processing functions | ||
4 | * | ||
5 | * Copyright (C) 2017 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/cpu.h> | ||
18 | #include <linux/acpi.h> | ||
19 | #include <asm/msr.h> | ||
20 | #include <asm/tsc.h> | ||
21 | |||
22 | struct lpit_residency_info { | ||
23 | struct acpi_generic_address gaddr; | ||
24 | u64 frequency; | ||
25 | void __iomem *iomem_addr; | ||
26 | }; | ||
27 | |||
28 | /* Storage for an memory mapped and FFH based entries */ | ||
29 | static struct lpit_residency_info residency_info_mem; | ||
30 | static struct lpit_residency_info residency_info_ffh; | ||
31 | |||
32 | static int lpit_read_residency_counter_us(u64 *counter, bool io_mem) | ||
33 | { | ||
34 | int err; | ||
35 | |||
36 | if (io_mem) { | ||
37 | u64 count = 0; | ||
38 | int error; | ||
39 | |||
40 | error = acpi_os_read_iomem(residency_info_mem.iomem_addr, &count, | ||
41 | residency_info_mem.gaddr.bit_width); | ||
42 | if (error) | ||
43 | return error; | ||
44 | |||
45 | *counter = div64_u64(count * 1000000ULL, residency_info_mem.frequency); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | err = rdmsrl_safe(residency_info_ffh.gaddr.address, counter); | ||
50 | if (!err) { | ||
51 | u64 mask = GENMASK_ULL(residency_info_ffh.gaddr.bit_offset + | ||
52 | residency_info_ffh.gaddr. bit_width - 1, | ||
53 | residency_info_ffh.gaddr.bit_offset); | ||
54 | |||
55 | *counter &= mask; | ||
56 | *counter >>= residency_info_ffh.gaddr.bit_offset; | ||
57 | *counter = div64_u64(*counter * 1000000ULL, residency_info_ffh.frequency); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | return -ENODATA; | ||
62 | } | ||
63 | |||
64 | static ssize_t low_power_idle_system_residency_us_show(struct device *dev, | ||
65 | struct device_attribute *attr, | ||
66 | char *buf) | ||
67 | { | ||
68 | u64 counter; | ||
69 | int ret; | ||
70 | |||
71 | ret = lpit_read_residency_counter_us(&counter, true); | ||
72 | if (ret) | ||
73 | return ret; | ||
74 | |||
75 | return sprintf(buf, "%llu\n", counter); | ||
76 | } | ||
77 | static DEVICE_ATTR_RO(low_power_idle_system_residency_us); | ||
78 | |||
79 | static ssize_t low_power_idle_cpu_residency_us_show(struct device *dev, | ||
80 | struct device_attribute *attr, | ||
81 | char *buf) | ||
82 | { | ||
83 | u64 counter; | ||
84 | int ret; | ||
85 | |||
86 | ret = lpit_read_residency_counter_us(&counter, false); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | |||
90 | return sprintf(buf, "%llu\n", counter); | ||
91 | } | ||
92 | static DEVICE_ATTR_RO(low_power_idle_cpu_residency_us); | ||
93 | |||
94 | int lpit_read_residency_count_address(u64 *address) | ||
95 | { | ||
96 | if (!residency_info_mem.gaddr.address) | ||
97 | return -EINVAL; | ||
98 | |||
99 | *address = residency_info_mem.gaddr.address; | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static void lpit_update_residency(struct lpit_residency_info *info, | ||
105 | struct acpi_lpit_native *lpit_native) | ||
106 | { | ||
107 | info->frequency = lpit_native->counter_frequency ? | ||
108 | lpit_native->counter_frequency : tsc_khz * 1000; | ||
109 | if (!info->frequency) | ||
110 | info->frequency = 1; | ||
111 | |||
112 | info->gaddr = lpit_native->residency_counter; | ||
113 | if (info->gaddr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
114 | info->iomem_addr = ioremap_nocache(info->gaddr.address, | ||
115 | info->gaddr.bit_width / 8); | ||
116 | if (!info->iomem_addr) | ||
117 | return; | ||
118 | |||
119 | /* Silently fail, if cpuidle attribute group is not present */ | ||
120 | sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj, | ||
121 | &dev_attr_low_power_idle_system_residency_us.attr, | ||
122 | "cpuidle"); | ||
123 | } else if (info->gaddr.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { | ||
124 | /* Silently fail, if cpuidle attribute group is not present */ | ||
125 | sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj, | ||
126 | &dev_attr_low_power_idle_cpu_residency_us.attr, | ||
127 | "cpuidle"); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | static void lpit_process(u64 begin, u64 end) | ||
132 | { | ||
133 | while (begin + sizeof(struct acpi_lpit_native) < end) { | ||
134 | struct acpi_lpit_native *lpit_native = (struct acpi_lpit_native *)begin; | ||
135 | |||
136 | if (!lpit_native->header.type && !lpit_native->header.flags) { | ||
137 | if (lpit_native->residency_counter.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY && | ||
138 | !residency_info_mem.gaddr.address) { | ||
139 | lpit_update_residency(&residency_info_mem, lpit_native); | ||
140 | } else if (lpit_native->residency_counter.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE && | ||
141 | !residency_info_ffh.gaddr.address) { | ||
142 | lpit_update_residency(&residency_info_ffh, lpit_native); | ||
143 | } | ||
144 | } | ||
145 | begin += lpit_native->header.length; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | void acpi_init_lpit(void) | ||
150 | { | ||
151 | acpi_status status; | ||
152 | u64 lpit_begin; | ||
153 | struct acpi_table_lpit *lpit; | ||
154 | |||
155 | status = acpi_get_table(ACPI_SIG_LPIT, 0, (struct acpi_table_header **)&lpit); | ||
156 | |||
157 | if (ACPI_FAILURE(status)) | ||
158 | return; | ||
159 | |||
160 | lpit_begin = (u64)lpit + sizeof(*lpit); | ||
161 | lpit_process(lpit_begin, lpit_begin + lpit->header.length); | ||
162 | } | ||
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 97b753dd2e6e..04d32bdb5a95 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -713,43 +713,9 @@ static int acpi_lpss_activate(struct device *dev) | |||
713 | 713 | ||
714 | static void acpi_lpss_dismiss(struct device *dev) | 714 | static void acpi_lpss_dismiss(struct device *dev) |
715 | { | 715 | { |
716 | acpi_dev_runtime_suspend(dev); | 716 | acpi_dev_suspend(dev, false); |
717 | } | 717 | } |
718 | 718 | ||
719 | #ifdef CONFIG_PM_SLEEP | ||
720 | static int acpi_lpss_suspend_late(struct device *dev) | ||
721 | { | ||
722 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
723 | int ret; | ||
724 | |||
725 | ret = pm_generic_suspend_late(dev); | ||
726 | if (ret) | ||
727 | return ret; | ||
728 | |||
729 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | ||
730 | acpi_lpss_save_ctx(dev, pdata); | ||
731 | |||
732 | return acpi_dev_suspend_late(dev); | ||
733 | } | ||
734 | |||
735 | static int acpi_lpss_resume_early(struct device *dev) | ||
736 | { | ||
737 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
738 | int ret; | ||
739 | |||
740 | ret = acpi_dev_resume(dev); | ||
741 | if (ret) | ||
742 | return ret; | ||
743 | |||
744 | acpi_lpss_d3_to_d0_delay(pdata); | ||
745 | |||
746 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | ||
747 | acpi_lpss_restore_ctx(dev, pdata); | ||
748 | |||
749 | return pm_generic_resume_early(dev); | ||
750 | } | ||
751 | #endif /* CONFIG_PM_SLEEP */ | ||
752 | |||
753 | /* IOSF SB for LPSS island */ | 719 | /* IOSF SB for LPSS island */ |
754 | #define LPSS_IOSF_UNIT_LPIOEP 0xA0 | 720 | #define LPSS_IOSF_UNIT_LPIOEP 0xA0 |
755 | #define LPSS_IOSF_UNIT_LPIO1 0xAB | 721 | #define LPSS_IOSF_UNIT_LPIO1 0xAB |
@@ -835,19 +801,15 @@ static void lpss_iosf_exit_d3_state(void) | |||
835 | mutex_unlock(&lpss_iosf_mutex); | 801 | mutex_unlock(&lpss_iosf_mutex); |
836 | } | 802 | } |
837 | 803 | ||
838 | static int acpi_lpss_runtime_suspend(struct device *dev) | 804 | static int acpi_lpss_suspend(struct device *dev, bool wakeup) |
839 | { | 805 | { |
840 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | 806 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
841 | int ret; | 807 | int ret; |
842 | 808 | ||
843 | ret = pm_generic_runtime_suspend(dev); | ||
844 | if (ret) | ||
845 | return ret; | ||
846 | |||
847 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | 809 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
848 | acpi_lpss_save_ctx(dev, pdata); | 810 | acpi_lpss_save_ctx(dev, pdata); |
849 | 811 | ||
850 | ret = acpi_dev_runtime_suspend(dev); | 812 | ret = acpi_dev_suspend(dev, wakeup); |
851 | 813 | ||
852 | /* | 814 | /* |
853 | * This call must be last in the sequence, otherwise PMC will return | 815 | * This call must be last in the sequence, otherwise PMC will return |
@@ -860,7 +822,7 @@ static int acpi_lpss_runtime_suspend(struct device *dev) | |||
860 | return ret; | 822 | return ret; |
861 | } | 823 | } |
862 | 824 | ||
863 | static int acpi_lpss_runtime_resume(struct device *dev) | 825 | static int acpi_lpss_resume(struct device *dev) |
864 | { | 826 | { |
865 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | 827 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
866 | int ret; | 828 | int ret; |
@@ -881,7 +843,37 @@ static int acpi_lpss_runtime_resume(struct device *dev) | |||
881 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | 843 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
882 | acpi_lpss_restore_ctx(dev, pdata); | 844 | acpi_lpss_restore_ctx(dev, pdata); |
883 | 845 | ||
884 | return pm_generic_runtime_resume(dev); | 846 | return 0; |
847 | } | ||
848 | |||
849 | #ifdef CONFIG_PM_SLEEP | ||
850 | static int acpi_lpss_suspend_late(struct device *dev) | ||
851 | { | ||
852 | int ret = pm_generic_suspend_late(dev); | ||
853 | |||
854 | return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); | ||
855 | } | ||
856 | |||
857 | static int acpi_lpss_resume_early(struct device *dev) | ||
858 | { | ||
859 | int ret = acpi_lpss_resume(dev); | ||
860 | |||
861 | return ret ? ret : pm_generic_resume_early(dev); | ||
862 | } | ||
863 | #endif /* CONFIG_PM_SLEEP */ | ||
864 | |||
865 | static int acpi_lpss_runtime_suspend(struct device *dev) | ||
866 | { | ||
867 | int ret = pm_generic_runtime_suspend(dev); | ||
868 | |||
869 | return ret ? ret : acpi_lpss_suspend(dev, true); | ||
870 | } | ||
871 | |||
872 | static int acpi_lpss_runtime_resume(struct device *dev) | ||
873 | { | ||
874 | int ret = acpi_lpss_resume(dev); | ||
875 | |||
876 | return ret ? ret : pm_generic_runtime_resume(dev); | ||
885 | } | 877 | } |
886 | #endif /* CONFIG_PM */ | 878 | #endif /* CONFIG_PM */ |
887 | 879 | ||
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 764b8dfa04aa..17e8eb93a76c 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -581,8 +581,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
581 | d_min = ret; | 581 | d_min = ret; |
582 | wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid | 582 | wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid |
583 | && adev->wakeup.sleep_state >= target_state; | 583 | && adev->wakeup.sleep_state >= target_state; |
584 | } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) != | 584 | } else { |
585 | PM_QOS_FLAGS_NONE) { | ||
586 | wakeup = adev->wakeup.flags.valid; | 585 | wakeup = adev->wakeup.flags.valid; |
587 | } | 586 | } |
588 | 587 | ||
@@ -848,38 +847,39 @@ static int acpi_dev_pm_full_power(struct acpi_device *adev) | |||
848 | } | 847 | } |
849 | 848 | ||
850 | /** | 849 | /** |
851 | * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI. | 850 | * acpi_dev_suspend - Put device into a low-power state using ACPI. |
852 | * @dev: Device to put into a low-power state. | 851 | * @dev: Device to put into a low-power state. |
852 | * @wakeup: Whether or not to enable wakeup for the device. | ||
853 | * | 853 | * |
854 | * Put the given device into a runtime low-power state using the standard ACPI | 854 | * Put the given device into a low-power state using the standard ACPI |
855 | * mechanism. Set up remote wakeup if desired, choose the state to put the | 855 | * mechanism. Set up remote wakeup if desired, choose the state to put the |
856 | * device into (this checks if remote wakeup is expected to work too), and set | 856 | * device into (this checks if remote wakeup is expected to work too), and set |
857 | * the power state of the device. | 857 | * the power state of the device. |
858 | */ | 858 | */ |
859 | int acpi_dev_runtime_suspend(struct device *dev) | 859 | int acpi_dev_suspend(struct device *dev, bool wakeup) |
860 | { | 860 | { |
861 | struct acpi_device *adev = ACPI_COMPANION(dev); | 861 | struct acpi_device *adev = ACPI_COMPANION(dev); |
862 | bool remote_wakeup; | 862 | u32 target_state = acpi_target_system_state(); |
863 | int error; | 863 | int error; |
864 | 864 | ||
865 | if (!adev) | 865 | if (!adev) |
866 | return 0; | 866 | return 0; |
867 | 867 | ||
868 | remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > | 868 | if (wakeup && acpi_device_can_wakeup(adev)) { |
869 | PM_QOS_FLAGS_NONE; | 869 | error = acpi_device_wakeup_enable(adev, target_state); |
870 | if (remote_wakeup) { | ||
871 | error = acpi_device_wakeup_enable(adev, ACPI_STATE_S0); | ||
872 | if (error) | 870 | if (error) |
873 | return -EAGAIN; | 871 | return -EAGAIN; |
872 | } else { | ||
873 | wakeup = false; | ||
874 | } | 874 | } |
875 | 875 | ||
876 | error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); | 876 | error = acpi_dev_pm_low_power(dev, adev, target_state); |
877 | if (error && remote_wakeup) | 877 | if (error && wakeup) |
878 | acpi_device_wakeup_disable(adev); | 878 | acpi_device_wakeup_disable(adev); |
879 | 879 | ||
880 | return error; | 880 | return error; |
881 | } | 881 | } |
882 | EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend); | 882 | EXPORT_SYMBOL_GPL(acpi_dev_suspend); |
883 | 883 | ||
884 | /** | 884 | /** |
885 | * acpi_dev_resume - Put device into the full-power state using ACPI. | 885 | * acpi_dev_resume - Put device into the full-power state using ACPI. |
@@ -912,7 +912,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume); | |||
912 | int acpi_subsys_runtime_suspend(struct device *dev) | 912 | int acpi_subsys_runtime_suspend(struct device *dev) |
913 | { | 913 | { |
914 | int ret = pm_generic_runtime_suspend(dev); | 914 | int ret = pm_generic_runtime_suspend(dev); |
915 | return ret ? ret : acpi_dev_runtime_suspend(dev); | 915 | return ret ? ret : acpi_dev_suspend(dev, true); |
916 | } | 916 | } |
917 | EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); | 917 | EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); |
918 | 918 | ||
@@ -931,41 +931,6 @@ int acpi_subsys_runtime_resume(struct device *dev) | |||
931 | EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume); | 931 | EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume); |
932 | 932 | ||
933 | #ifdef CONFIG_PM_SLEEP | 933 | #ifdef CONFIG_PM_SLEEP |
934 | /** | ||
935 | * acpi_dev_suspend_late - Put device into a low-power state using ACPI. | ||
936 | * @dev: Device to put into a low-power state. | ||
937 | * | ||
938 | * Put the given device into a low-power state during system transition to a | ||
939 | * sleep state using the standard ACPI mechanism. Set up system wakeup if | ||
940 | * desired, choose the state to put the device into (this checks if system | ||
941 | * wakeup is expected to work too), and set the power state of the device. | ||
942 | */ | ||
943 | int acpi_dev_suspend_late(struct device *dev) | ||
944 | { | ||
945 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
946 | u32 target_state; | ||
947 | bool wakeup; | ||
948 | int error; | ||
949 | |||
950 | if (!adev) | ||
951 | return 0; | ||
952 | |||
953 | target_state = acpi_target_system_state(); | ||
954 | wakeup = device_may_wakeup(dev) && acpi_device_can_wakeup(adev); | ||
955 | if (wakeup) { | ||
956 | error = acpi_device_wakeup_enable(adev, target_state); | ||
957 | if (error) | ||
958 | return error; | ||
959 | } | ||
960 | |||
961 | error = acpi_dev_pm_low_power(dev, adev, target_state); | ||
962 | if (error && wakeup) | ||
963 | acpi_device_wakeup_disable(adev); | ||
964 | |||
965 | return error; | ||
966 | } | ||
967 | EXPORT_SYMBOL_GPL(acpi_dev_suspend_late); | ||
968 | |||
969 | static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev) | 934 | static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev) |
970 | { | 935 | { |
971 | u32 sys_target = acpi_target_system_state(); | 936 | u32 sys_target = acpi_target_system_state(); |
@@ -1048,7 +1013,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend); | |||
1048 | int acpi_subsys_suspend_late(struct device *dev) | 1013 | int acpi_subsys_suspend_late(struct device *dev) |
1049 | { | 1014 | { |
1050 | int ret = pm_generic_suspend_late(dev); | 1015 | int ret = pm_generic_suspend_late(dev); |
1051 | return ret ? ret : acpi_dev_suspend_late(dev); | 1016 | return ret ? ret : acpi_dev_suspend(dev, device_may_wakeup(dev)); |
1052 | } | 1017 | } |
1053 | EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); | 1018 | EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); |
1054 | 1019 | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4361c4415b4f..fc8c43e76707 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -248,4 +248,10 @@ void acpi_watchdog_init(void); | |||
248 | static inline void acpi_watchdog_init(void) {} | 248 | static inline void acpi_watchdog_init(void) {} |
249 | #endif | 249 | #endif |
250 | 250 | ||
251 | #ifdef CONFIG_ACPI_LPIT | ||
252 | void acpi_init_lpit(void); | ||
253 | #else | ||
254 | static inline void acpi_init_lpit(void) { } | ||
255 | #endif | ||
256 | |||
251 | #endif /* _ACPI_INTERNAL_H_ */ | 257 | #endif /* _ACPI_INTERNAL_H_ */ |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index db78d353bab1..3bb46cb24a99 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -663,6 +663,29 @@ acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) | |||
663 | 663 | ||
664 | EXPORT_SYMBOL(acpi_os_write_port); | 664 | EXPORT_SYMBOL(acpi_os_write_port); |
665 | 665 | ||
666 | int acpi_os_read_iomem(void __iomem *virt_addr, u64 *value, u32 width) | ||
667 | { | ||
668 | |||
669 | switch (width) { | ||
670 | case 8: | ||
671 | *(u8 *) value = readb(virt_addr); | ||
672 | break; | ||
673 | case 16: | ||
674 | *(u16 *) value = readw(virt_addr); | ||
675 | break; | ||
676 | case 32: | ||
677 | *(u32 *) value = readl(virt_addr); | ||
678 | break; | ||
679 | case 64: | ||
680 | *(u64 *) value = readq(virt_addr); | ||
681 | break; | ||
682 | default: | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
666 | acpi_status | 689 | acpi_status |
667 | acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width) | 690 | acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width) |
668 | { | 691 | { |
@@ -670,6 +693,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width) | |||
670 | unsigned int size = width / 8; | 693 | unsigned int size = width / 8; |
671 | bool unmap = false; | 694 | bool unmap = false; |
672 | u64 dummy; | 695 | u64 dummy; |
696 | int error; | ||
673 | 697 | ||
674 | rcu_read_lock(); | 698 | rcu_read_lock(); |
675 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); | 699 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); |
@@ -684,22 +708,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width) | |||
684 | if (!value) | 708 | if (!value) |
685 | value = &dummy; | 709 | value = &dummy; |
686 | 710 | ||
687 | switch (width) { | 711 | error = acpi_os_read_iomem(virt_addr, value, width); |
688 | case 8: | 712 | BUG_ON(error); |
689 | *(u8 *) value = readb(virt_addr); | ||
690 | break; | ||
691 | case 16: | ||
692 | *(u16 *) value = readw(virt_addr); | ||
693 | break; | ||
694 | case 32: | ||
695 | *(u32 *) value = readl(virt_addr); | ||
696 | break; | ||
697 | case 64: | ||
698 | *(u64 *) value = readq(virt_addr); | ||
699 | break; | ||
700 | default: | ||
701 | BUG(); | ||
702 | } | ||
703 | 713 | ||
704 | if (unmap) | 714 | if (unmap) |
705 | iounmap(virt_addr); | 715 | iounmap(virt_addr); |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 602f8ff212f2..81367edc8a10 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -2122,6 +2122,7 @@ int __init acpi_scan_init(void) | |||
2122 | acpi_int340x_thermal_init(); | 2122 | acpi_int340x_thermal_init(); |
2123 | acpi_amba_init(); | 2123 | acpi_amba_init(); |
2124 | acpi_watchdog_init(); | 2124 | acpi_watchdog_init(); |
2125 | acpi_init_lpit(); | ||
2125 | 2126 | ||
2126 | acpi_scan_add_handler(&generic_device_handler); | 2127 | acpi_scan_add_handler(&generic_device_handler); |
2127 | 2128 | ||
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e8ca5e2cf1e5..e6414e9998bb 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -346,9 +346,7 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on, | |||
346 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { | 346 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { |
347 | enum pm_qos_flags_status stat; | 347 | enum pm_qos_flags_status stat; |
348 | 348 | ||
349 | stat = dev_pm_qos_flags(pdd->dev, | 349 | stat = dev_pm_qos_flags(pdd->dev, PM_QOS_FLAG_NO_POWER_OFF); |
350 | PM_QOS_FLAG_NO_POWER_OFF | ||
351 | | PM_QOS_FLAG_REMOTE_WAKEUP); | ||
352 | if (stat > PM_QOS_FLAGS_NONE) | 350 | if (stat > PM_QOS_FLAGS_NONE) |
353 | return -EBUSY; | 351 | return -EBUSY; |
354 | 352 | ||
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 156ab57bca77..29bf28fef136 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -309,33 +309,6 @@ static ssize_t pm_qos_no_power_off_store(struct device *dev, | |||
309 | static DEVICE_ATTR(pm_qos_no_power_off, 0644, | 309 | static DEVICE_ATTR(pm_qos_no_power_off, 0644, |
310 | pm_qos_no_power_off_show, pm_qos_no_power_off_store); | 310 | pm_qos_no_power_off_show, pm_qos_no_power_off_store); |
311 | 311 | ||
312 | static ssize_t pm_qos_remote_wakeup_show(struct device *dev, | ||
313 | struct device_attribute *attr, | ||
314 | char *buf) | ||
315 | { | ||
316 | return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev) | ||
317 | & PM_QOS_FLAG_REMOTE_WAKEUP)); | ||
318 | } | ||
319 | |||
320 | static ssize_t pm_qos_remote_wakeup_store(struct device *dev, | ||
321 | struct device_attribute *attr, | ||
322 | const char *buf, size_t n) | ||
323 | { | ||
324 | int ret; | ||
325 | |||
326 | if (kstrtoint(buf, 0, &ret)) | ||
327 | return -EINVAL; | ||
328 | |||
329 | if (ret != 0 && ret != 1) | ||
330 | return -EINVAL; | ||
331 | |||
332 | ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP, ret); | ||
333 | return ret < 0 ? ret : n; | ||
334 | } | ||
335 | |||
336 | static DEVICE_ATTR(pm_qos_remote_wakeup, 0644, | ||
337 | pm_qos_remote_wakeup_show, pm_qos_remote_wakeup_store); | ||
338 | |||
339 | #ifdef CONFIG_PM_SLEEP | 312 | #ifdef CONFIG_PM_SLEEP |
340 | static const char _enabled[] = "enabled"; | 313 | static const char _enabled[] = "enabled"; |
341 | static const char _disabled[] = "disabled"; | 314 | static const char _disabled[] = "disabled"; |
@@ -671,7 +644,6 @@ static const struct attribute_group pm_qos_latency_tolerance_attr_group = { | |||
671 | 644 | ||
672 | static struct attribute *pm_qos_flags_attrs[] = { | 645 | static struct attribute *pm_qos_flags_attrs[] = { |
673 | &dev_attr_pm_qos_no_power_off.attr, | 646 | &dev_attr_pm_qos_no_power_off.attr, |
674 | &dev_attr_pm_qos_remote_wakeup.attr, | ||
675 | NULL, | 647 | NULL, |
676 | }; | 648 | }; |
677 | static const struct attribute_group pm_qos_flags_attr_group = { | 649 | static const struct attribute_group pm_qos_flags_attr_group = { |
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index c66eb8ffa454..d5c0f5153c4e 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h | |||
@@ -287,6 +287,8 @@ acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width); | |||
287 | /* | 287 | /* |
288 | * Platform and hardware-independent physical memory interfaces | 288 | * Platform and hardware-independent physical memory interfaces |
289 | */ | 289 | */ |
290 | int acpi_os_read_iomem(void __iomem *virt_addr, u64 *value, u32 width); | ||
291 | |||
290 | #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_memory | 292 | #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_memory |
291 | acpi_status | 293 | acpi_status |
292 | acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width); | 294 | acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d18c92d4ba19..0ada2a948b44 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -864,7 +864,7 @@ static inline void arch_reserve_mem_area(acpi_physical_address addr, | |||
864 | #endif | 864 | #endif |
865 | 865 | ||
866 | #if defined(CONFIG_ACPI) && defined(CONFIG_PM) | 866 | #if defined(CONFIG_ACPI) && defined(CONFIG_PM) |
867 | int acpi_dev_runtime_suspend(struct device *dev); | 867 | int acpi_dev_suspend(struct device *dev, bool wakeup); |
868 | int acpi_dev_resume(struct device *dev); | 868 | int acpi_dev_resume(struct device *dev); |
869 | int acpi_subsys_runtime_suspend(struct device *dev); | 869 | int acpi_subsys_runtime_suspend(struct device *dev); |
870 | int acpi_subsys_runtime_resume(struct device *dev); | 870 | int acpi_subsys_runtime_resume(struct device *dev); |
@@ -889,7 +889,6 @@ int acpi_subsys_resume_early(struct device *dev); | |||
889 | int acpi_subsys_suspend(struct device *dev); | 889 | int acpi_subsys_suspend(struct device *dev); |
890 | int acpi_subsys_freeze(struct device *dev); | 890 | int acpi_subsys_freeze(struct device *dev); |
891 | #else | 891 | #else |
892 | static inline int acpi_dev_suspend_late(struct device *dev) { return 0; } | ||
893 | static inline int acpi_dev_resume_early(struct device *dev) { return 0; } | 892 | static inline int acpi_dev_resume_early(struct device *dev) { return 0; } |
894 | static inline int acpi_subsys_prepare(struct device *dev) { return 0; } | 893 | static inline int acpi_subsys_prepare(struct device *dev) { return 0; } |
895 | static inline void acpi_subsys_complete(struct device *dev) {} | 894 | static inline void acpi_subsys_complete(struct device *dev) {} |
@@ -1248,4 +1247,13 @@ int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res) | |||
1248 | } | 1247 | } |
1249 | #endif | 1248 | #endif |
1250 | 1249 | ||
1250 | #ifdef CONFIG_ACPI_LPIT | ||
1251 | int lpit_read_residency_count_address(u64 *address); | ||
1252 | #else | ||
1253 | static inline int lpit_read_residency_count_address(u64 *address) | ||
1254 | { | ||
1255 | return -EINVAL; | ||
1256 | } | ||
1257 | #endif | ||
1258 | |||
1251 | #endif /*_LINUX_ACPI_H*/ | 1259 | #endif /*_LINUX_ACPI_H*/ |
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 032b55909145..51f0d7e0b15f 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h | |||
@@ -39,7 +39,6 @@ enum pm_qos_flags_status { | |||
39 | #define PM_QOS_LATENCY_ANY ((s32)(~(__u32)0 >> 1)) | 39 | #define PM_QOS_LATENCY_ANY ((s32)(~(__u32)0 >> 1)) |
40 | 40 | ||
41 | #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) | 41 | #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) |
42 | #define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1) | ||
43 | 42 | ||
44 | struct pm_qos_request { | 43 | struct pm_qos_request { |
45 | struct plist_node node; | 44 | struct plist_node node; |