diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/rockchip-io-domain.txt | 15 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpe.c | 6 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 22 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 6 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 7 | ||||
-rw-r--r-- | drivers/base/power/wakeup.c | 18 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 5 | ||||
-rw-r--r-- | drivers/pci/pci.c | 6 | ||||
-rw-r--r-- | drivers/power/avs/rockchip-io-domain.c | 68 | ||||
-rw-r--r-- | include/acpi/acpixf.h | 1 | ||||
-rw-r--r-- | include/linux/kernel.h | 1 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 7 | ||||
-rw-r--r-- | kernel/power/suspend.c | 27 | ||||
-rw-r--r-- | kernel/power/user.c | 5 | ||||
-rw-r--r-- | kernel/time/tick-common.c | 2 |
16 files changed, 171 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt b/Documentation/devicetree/bindings/power/rockchip-io-domain.txt index 4a4766e9c254..e66fd4eab71c 100644 --- a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt +++ b/Documentation/devicetree/bindings/power/rockchip-io-domain.txt | |||
@@ -31,6 +31,8 @@ SoC is on the same page. | |||
31 | 31 | ||
32 | Required properties: | 32 | Required properties: |
33 | - compatible: should be one of: | 33 | - compatible: should be one of: |
34 | - "rockchip,px30-io-voltage-domain" for px30 | ||
35 | - "rockchip,px30-pmu-io-voltage-domain" for px30 pmu-domains | ||
34 | - "rockchip,rk3188-io-voltage-domain" for rk3188 | 36 | - "rockchip,rk3188-io-voltage-domain" for rk3188 |
35 | - "rockchip,rk3228-io-voltage-domain" for rk3228 | 37 | - "rockchip,rk3228-io-voltage-domain" for rk3228 |
36 | - "rockchip,rk3288-io-voltage-domain" for rk3288 | 38 | - "rockchip,rk3288-io-voltage-domain" for rk3288 |
@@ -51,6 +53,19 @@ a phandle the relevant regulator. All specified supplies must be able | |||
51 | to report their voltage. The IO Voltage Domain for any non-specified | 53 | to report their voltage. The IO Voltage Domain for any non-specified |
52 | supplies will be not be touched. | 54 | supplies will be not be touched. |
53 | 55 | ||
56 | Possible supplies for PX30: | ||
57 | - vccio6-supply: The supply connected to VCCIO6. | ||
58 | - vccio1-supply: The supply connected to VCCIO1. | ||
59 | - vccio2-supply: The supply connected to VCCIO2. | ||
60 | - vccio3-supply: The supply connected to VCCIO3. | ||
61 | - vccio4-supply: The supply connected to VCCIO4. | ||
62 | - vccio5-supply: The supply connected to VCCIO5. | ||
63 | - vccio-oscgpi-supply: The supply connected to VCCIO_OSCGPI. | ||
64 | |||
65 | Possible supplies for PX30 pmu-domains: | ||
66 | - pmuio1-supply: The supply connected to PMUIO1. | ||
67 | - pmuio2-supply: The supply connected to PMUIO2. | ||
68 | |||
54 | Possible supplies for rk3188: | 69 | Possible supplies for rk3188: |
55 | - ap0-supply: The supply connected to AP0_VCC. | 70 | - ap0-supply: The supply connected to AP0_VCC. |
56 | - ap1-supply: The supply connected to AP1_VCC. | 71 | - ap1-supply: The supply connected to AP1_VCC. |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index abbd59063906..e10fec99a182 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -634,6 +634,12 @@ acpi_ev_detect_gpe(struct acpi_namespace_node *gpe_device, | |||
634 | 634 | ||
635 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 635 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
636 | 636 | ||
637 | if (!gpe_event_info) { | ||
638 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
639 | if (!gpe_event_info) | ||
640 | goto error_exit; | ||
641 | } | ||
642 | |||
637 | /* Get the info block for the entire GPE register */ | 643 | /* Get the info block for the entire GPE register */ |
638 | 644 | ||
639 | gpe_register_info = gpe_event_info->register_info; | 645 | gpe_register_info = gpe_event_info->register_info; |
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index c80e3bdf4805..b2d5f66cc1b0 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -639,6 +639,28 @@ ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) | |||
639 | 639 | ||
640 | /******************************************************************************* | 640 | /******************************************************************************* |
641 | * | 641 | * |
642 | * FUNCTION: acpi_gispatch_gpe | ||
643 | * | ||
644 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
645 | * gpe_number - GPE level within the GPE block | ||
646 | * | ||
647 | * RETURN: None | ||
648 | * | ||
649 | * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function | ||
650 | * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. | ||
651 | * | ||
652 | ******************************************************************************/ | ||
653 | void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
654 | { | ||
655 | ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); | ||
656 | |||
657 | acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); | ||
658 | } | ||
659 | |||
660 | ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe) | ||
661 | |||
662 | /******************************************************************************* | ||
663 | * | ||
642 | * FUNCTION: acpi_finish_gpe | 664 | * FUNCTION: acpi_finish_gpe |
643 | * | 665 | * |
644 | * PARAMETERS: gpe_device - Namespace node for the GPE Block | 666 | * PARAMETERS: gpe_device - Namespace node for the GPE Block |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 30a572956557..bb94cf0731fe 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1034,6 +1034,12 @@ void acpi_ec_unblock_transactions(void) | |||
1034 | acpi_ec_start(first_ec, true); | 1034 | acpi_ec_start(first_ec, true); |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | void acpi_ec_dispatch_gpe(void) | ||
1038 | { | ||
1039 | if (first_ec) | ||
1040 | acpi_dispatch_gpe(NULL, first_ec->gpe); | ||
1041 | } | ||
1042 | |||
1037 | /* -------------------------------------------------------------------------- | 1043 | /* -------------------------------------------------------------------------- |
1038 | Event Management | 1044 | Event Management |
1039 | -------------------------------------------------------------------------- */ | 1045 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 1d0a501bc7f0..530a3f675490 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -188,6 +188,7 @@ int acpi_ec_ecdt_probe(void); | |||
188 | int acpi_ec_dsdt_probe(void); | 188 | int acpi_ec_dsdt_probe(void); |
189 | void acpi_ec_block_transactions(void); | 189 | void acpi_ec_block_transactions(void); |
190 | void acpi_ec_unblock_transactions(void); | 190 | void acpi_ec_unblock_transactions(void); |
191 | void acpi_ec_dispatch_gpe(void); | ||
191 | int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, | 192 | int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, |
192 | acpi_handle handle, acpi_ec_query_func func, | 193 | acpi_handle handle, acpi_ec_query_func func, |
193 | void *data); | 194 | void *data); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 974e58457697..5d0486f1cfcd 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -989,6 +989,13 @@ static void acpi_s2idle_wake(void) | |||
989 | !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { | 989 | !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { |
990 | pm_system_cancel_wakeup(); | 990 | pm_system_cancel_wakeup(); |
991 | s2idle_wakeup = true; | 991 | s2idle_wakeup = true; |
992 | /* | ||
993 | * On some platforms with the LPS0 _DSM device noirq resume | ||
994 | * takes too much time for EC wakeup events to survive, so look | ||
995 | * for them now. | ||
996 | */ | ||
997 | if (lps0_device_handle) | ||
998 | acpi_ec_dispatch_gpe(); | ||
992 | } | 999 | } |
993 | } | 1000 | } |
994 | 1001 | ||
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index e1322788eaee..5fa1898755a3 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -57,7 +57,7 @@ static void split_counters(unsigned int *cnt, unsigned int *inpr) | |||
57 | /* A preserved old value of the events counter. */ | 57 | /* A preserved old value of the events counter. */ |
58 | static unsigned int saved_count; | 58 | static unsigned int saved_count; |
59 | 59 | ||
60 | static DEFINE_SPINLOCK(events_lock); | 60 | static DEFINE_RAW_SPINLOCK(events_lock); |
61 | 61 | ||
62 | static void pm_wakeup_timer_fn(struct timer_list *t); | 62 | static void pm_wakeup_timer_fn(struct timer_list *t); |
63 | 63 | ||
@@ -184,9 +184,9 @@ void wakeup_source_add(struct wakeup_source *ws) | |||
184 | timer_setup(&ws->timer, pm_wakeup_timer_fn, 0); | 184 | timer_setup(&ws->timer, pm_wakeup_timer_fn, 0); |
185 | ws->active = false; | 185 | ws->active = false; |
186 | 186 | ||
187 | spin_lock_irqsave(&events_lock, flags); | 187 | raw_spin_lock_irqsave(&events_lock, flags); |
188 | list_add_rcu(&ws->entry, &wakeup_sources); | 188 | list_add_rcu(&ws->entry, &wakeup_sources); |
189 | spin_unlock_irqrestore(&events_lock, flags); | 189 | raw_spin_unlock_irqrestore(&events_lock, flags); |
190 | } | 190 | } |
191 | EXPORT_SYMBOL_GPL(wakeup_source_add); | 191 | EXPORT_SYMBOL_GPL(wakeup_source_add); |
192 | 192 | ||
@@ -201,9 +201,9 @@ void wakeup_source_remove(struct wakeup_source *ws) | |||
201 | if (WARN_ON(!ws)) | 201 | if (WARN_ON(!ws)) |
202 | return; | 202 | return; |
203 | 203 | ||
204 | spin_lock_irqsave(&events_lock, flags); | 204 | raw_spin_lock_irqsave(&events_lock, flags); |
205 | list_del_rcu(&ws->entry); | 205 | list_del_rcu(&ws->entry); |
206 | spin_unlock_irqrestore(&events_lock, flags); | 206 | raw_spin_unlock_irqrestore(&events_lock, flags); |
207 | synchronize_srcu(&wakeup_srcu); | 207 | synchronize_srcu(&wakeup_srcu); |
208 | } | 208 | } |
209 | EXPORT_SYMBOL_GPL(wakeup_source_remove); | 209 | EXPORT_SYMBOL_GPL(wakeup_source_remove); |
@@ -842,7 +842,7 @@ bool pm_wakeup_pending(void) | |||
842 | unsigned long flags; | 842 | unsigned long flags; |
843 | bool ret = false; | 843 | bool ret = false; |
844 | 844 | ||
845 | spin_lock_irqsave(&events_lock, flags); | 845 | raw_spin_lock_irqsave(&events_lock, flags); |
846 | if (events_check_enabled) { | 846 | if (events_check_enabled) { |
847 | unsigned int cnt, inpr; | 847 | unsigned int cnt, inpr; |
848 | 848 | ||
@@ -850,7 +850,7 @@ bool pm_wakeup_pending(void) | |||
850 | ret = (cnt != saved_count || inpr > 0); | 850 | ret = (cnt != saved_count || inpr > 0); |
851 | events_check_enabled = !ret; | 851 | events_check_enabled = !ret; |
852 | } | 852 | } |
853 | spin_unlock_irqrestore(&events_lock, flags); | 853 | raw_spin_unlock_irqrestore(&events_lock, flags); |
854 | 854 | ||
855 | if (ret) { | 855 | if (ret) { |
856 | pr_debug("PM: Wakeup pending, aborting suspend\n"); | 856 | pr_debug("PM: Wakeup pending, aborting suspend\n"); |
@@ -939,13 +939,13 @@ bool pm_save_wakeup_count(unsigned int count) | |||
939 | unsigned long flags; | 939 | unsigned long flags; |
940 | 940 | ||
941 | events_check_enabled = false; | 941 | events_check_enabled = false; |
942 | spin_lock_irqsave(&events_lock, flags); | 942 | raw_spin_lock_irqsave(&events_lock, flags); |
943 | split_counters(&cnt, &inpr); | 943 | split_counters(&cnt, &inpr); |
944 | if (cnt == count && inpr == 0) { | 944 | if (cnt == count && inpr == 0) { |
945 | saved_count = count; | 945 | saved_count = count; |
946 | events_check_enabled = true; | 946 | events_check_enabled = true; |
947 | } | 947 | } |
948 | spin_unlock_irqrestore(&events_lock, flags); | 948 | raw_spin_unlock_irqrestore(&events_lock, flags); |
949 | return events_check_enabled; | 949 | return events_check_enabled; |
950 | } | 950 | } |
951 | 951 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b9a131137e64..c816b0683a82 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -753,10 +753,11 @@ static int pci_pm_suspend(struct device *dev) | |||
753 | * better to resume the device from runtime suspend here. | 753 | * better to resume the device from runtime suspend here. |
754 | */ | 754 | */ |
755 | if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || | 755 | if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || |
756 | !pci_dev_keep_suspended(pci_dev)) | 756 | !pci_dev_keep_suspended(pci_dev)) { |
757 | pm_runtime_resume(dev); | 757 | pm_runtime_resume(dev); |
758 | pci_dev->state_saved = false; | ||
759 | } | ||
758 | 760 | ||
759 | pci_dev->state_saved = false; | ||
760 | if (pm->suspend) { | 761 | if (pm->suspend) { |
761 | pci_power_t prev = pci_dev->current_state; | 762 | pci_power_t prev = pci_dev->current_state; |
762 | int error; | 763 | int error; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index dbfe7c4f3776..e90cf5c32e14 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2025,8 +2025,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup) | |||
2025 | 2025 | ||
2026 | if (platform_pci_power_manageable(dev)) { | 2026 | if (platform_pci_power_manageable(dev)) { |
2027 | /* | 2027 | /* |
2028 | * Call the platform to choose the target state of the device | 2028 | * Call the platform to find the target state for the device. |
2029 | * and enable wake-up from this state if supported. | ||
2030 | */ | 2029 | */ |
2031 | pci_power_t state = platform_pci_choose_state(dev); | 2030 | pci_power_t state = platform_pci_choose_state(dev); |
2032 | 2031 | ||
@@ -2059,8 +2058,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup) | |||
2059 | if (wakeup) { | 2058 | if (wakeup) { |
2060 | /* | 2059 | /* |
2061 | * Find the deepest state from which the device can generate | 2060 | * Find the deepest state from which the device can generate |
2062 | * wake-up events, make it the target state and enable device | 2061 | * PME#. |
2063 | * to generate PME#. | ||
2064 | */ | 2062 | */ |
2065 | if (dev->pme_support) { | 2063 | if (dev->pme_support) { |
2066 | while (target_state | 2064 | while (target_state |
diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c index ed2b109ae8fc..d6a5e6bf5f12 100644 --- a/drivers/power/avs/rockchip-io-domain.c +++ b/drivers/power/avs/rockchip-io-domain.c | |||
@@ -39,6 +39,10 @@ | |||
39 | #define MAX_VOLTAGE_1_8 1980000 | 39 | #define MAX_VOLTAGE_1_8 1980000 |
40 | #define MAX_VOLTAGE_3_3 3600000 | 40 | #define MAX_VOLTAGE_3_3 3600000 |
41 | 41 | ||
42 | #define PX30_IO_VSEL 0x180 | ||
43 | #define PX30_IO_VSEL_VCCIO6_SRC BIT(0) | ||
44 | #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1 | ||
45 | |||
42 | #define RK3288_SOC_CON2 0x24c | 46 | #define RK3288_SOC_CON2 0x24c |
43 | #define RK3288_SOC_CON2_FLASH0 BIT(7) | 47 | #define RK3288_SOC_CON2_FLASH0 BIT(7) |
44 | #define RK3288_SOC_FLASH_SUPPLY_NUM 2 | 48 | #define RK3288_SOC_FLASH_SUPPLY_NUM 2 |
@@ -151,6 +155,25 @@ static int rockchip_iodomain_notify(struct notifier_block *nb, | |||
151 | return NOTIFY_OK; | 155 | return NOTIFY_OK; |
152 | } | 156 | } |
153 | 157 | ||
158 | static void px30_iodomain_init(struct rockchip_iodomain *iod) | ||
159 | { | ||
160 | int ret; | ||
161 | u32 val; | ||
162 | |||
163 | /* if no VCCIO0 supply we should leave things alone */ | ||
164 | if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg) | ||
165 | return; | ||
166 | |||
167 | /* | ||
168 | * set vccio0 iodomain to also use this framework | ||
169 | * instead of a special gpio. | ||
170 | */ | ||
171 | val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16); | ||
172 | ret = regmap_write(iod->grf, PX30_IO_VSEL, val); | ||
173 | if (ret < 0) | ||
174 | dev_warn(iod->dev, "couldn't update vccio0 ctrl\n"); | ||
175 | } | ||
176 | |||
154 | static void rk3288_iodomain_init(struct rockchip_iodomain *iod) | 177 | static void rk3288_iodomain_init(struct rockchip_iodomain *iod) |
155 | { | 178 | { |
156 | int ret; | 179 | int ret; |
@@ -227,6 +250,43 @@ static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod) | |||
227 | dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n"); | 250 | dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n"); |
228 | } | 251 | } |
229 | 252 | ||
253 | static const struct rockchip_iodomain_soc_data soc_data_px30 = { | ||
254 | .grf_offset = 0x180, | ||
255 | .supply_names = { | ||
256 | NULL, | ||
257 | "vccio6", | ||
258 | "vccio1", | ||
259 | "vccio2", | ||
260 | "vccio3", | ||
261 | "vccio4", | ||
262 | "vccio5", | ||
263 | "vccio-oscgpi", | ||
264 | }, | ||
265 | .init = px30_iodomain_init, | ||
266 | }; | ||
267 | |||
268 | static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = { | ||
269 | .grf_offset = 0x100, | ||
270 | .supply_names = { | ||
271 | NULL, | ||
272 | NULL, | ||
273 | NULL, | ||
274 | NULL, | ||
275 | NULL, | ||
276 | NULL, | ||
277 | NULL, | ||
278 | NULL, | ||
279 | NULL, | ||
280 | NULL, | ||
281 | NULL, | ||
282 | NULL, | ||
283 | NULL, | ||
284 | NULL, | ||
285 | "pmuio1", | ||
286 | "pmuio2", | ||
287 | }, | ||
288 | }; | ||
289 | |||
230 | /* | 290 | /* |
231 | * On the rk3188 the io-domains are handled by a shared register with the | 291 | * On the rk3188 the io-domains are handled by a shared register with the |
232 | * lower 8 bits being still being continuing drive-strength settings. | 292 | * lower 8 bits being still being continuing drive-strength settings. |
@@ -381,6 +441,14 @@ static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = { | |||
381 | 441 | ||
382 | static const struct of_device_id rockchip_iodomain_match[] = { | 442 | static const struct of_device_id rockchip_iodomain_match[] = { |
383 | { | 443 | { |
444 | .compatible = "rockchip,px30-io-voltage-domain", | ||
445 | .data = (void *)&soc_data_px30 | ||
446 | }, | ||
447 | { | ||
448 | .compatible = "rockchip,px30-pmu-io-voltage-domain", | ||
449 | .data = (void *)&soc_data_px30_pmu | ||
450 | }, | ||
451 | { | ||
384 | .compatible = "rockchip,rk3188-io-voltage-domain", | 452 | .compatible = "rockchip,rk3188-io-voltage-domain", |
385 | .data = &soc_data_rk3188 | 453 | .data = &soc_data_rk3188 |
386 | }, | 454 | }, |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index da0215ea9f44..c01d790c17c2 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
@@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status | |||
753 | u32 gpe_number, | 753 | u32 gpe_number, |
754 | acpi_event_status | 754 | acpi_event_status |
755 | *event_status)) | 755 | *event_status)) |
756 | ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) | ||
756 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) | 757 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) |
757 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) | 758 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) |
758 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) | 759 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 6a1eb0b0aad9..7aed92624531 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -542,6 +542,7 @@ extern enum system_states { | |||
542 | SYSTEM_HALT, | 542 | SYSTEM_HALT, |
543 | SYSTEM_POWER_OFF, | 543 | SYSTEM_POWER_OFF, |
544 | SYSTEM_RESTART, | 544 | SYSTEM_RESTART, |
545 | SYSTEM_SUSPEND, | ||
545 | } system_state; | 546 | } system_state; |
546 | 547 | ||
547 | /* This cannot be an enum because some may be used in assembly source. */ | 548 | /* This cannot be an enum because some may be used in assembly source. */ |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 5454cc639a8d..9c85c7822383 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -287,6 +287,8 @@ static int create_image(int platform_mode) | |||
287 | 287 | ||
288 | local_irq_disable(); | 288 | local_irq_disable(); |
289 | 289 | ||
290 | system_state = SYSTEM_SUSPEND; | ||
291 | |||
290 | error = syscore_suspend(); | 292 | error = syscore_suspend(); |
291 | if (error) { | 293 | if (error) { |
292 | pr_err("Some system devices failed to power down, aborting hibernation\n"); | 294 | pr_err("Some system devices failed to power down, aborting hibernation\n"); |
@@ -317,6 +319,7 @@ static int create_image(int platform_mode) | |||
317 | syscore_resume(); | 319 | syscore_resume(); |
318 | 320 | ||
319 | Enable_irqs: | 321 | Enable_irqs: |
322 | system_state = SYSTEM_RUNNING; | ||
320 | local_irq_enable(); | 323 | local_irq_enable(); |
321 | 324 | ||
322 | Enable_cpus: | 325 | Enable_cpus: |
@@ -445,6 +448,7 @@ static int resume_target_kernel(bool platform_mode) | |||
445 | goto Enable_cpus; | 448 | goto Enable_cpus; |
446 | 449 | ||
447 | local_irq_disable(); | 450 | local_irq_disable(); |
451 | system_state = SYSTEM_SUSPEND; | ||
448 | 452 | ||
449 | error = syscore_suspend(); | 453 | error = syscore_suspend(); |
450 | if (error) | 454 | if (error) |
@@ -478,6 +482,7 @@ static int resume_target_kernel(bool platform_mode) | |||
478 | syscore_resume(); | 482 | syscore_resume(); |
479 | 483 | ||
480 | Enable_irqs: | 484 | Enable_irqs: |
485 | system_state = SYSTEM_RUNNING; | ||
481 | local_irq_enable(); | 486 | local_irq_enable(); |
482 | 487 | ||
483 | Enable_cpus: | 488 | Enable_cpus: |
@@ -563,6 +568,7 @@ int hibernation_platform_enter(void) | |||
563 | goto Enable_cpus; | 568 | goto Enable_cpus; |
564 | 569 | ||
565 | local_irq_disable(); | 570 | local_irq_disable(); |
571 | system_state = SYSTEM_SUSPEND; | ||
566 | syscore_suspend(); | 572 | syscore_suspend(); |
567 | if (pm_wakeup_pending()) { | 573 | if (pm_wakeup_pending()) { |
568 | error = -EAGAIN; | 574 | error = -EAGAIN; |
@@ -575,6 +581,7 @@ int hibernation_platform_enter(void) | |||
575 | 581 | ||
576 | Power_up: | 582 | Power_up: |
577 | syscore_resume(); | 583 | syscore_resume(); |
584 | system_state = SYSTEM_RUNNING; | ||
578 | local_irq_enable(); | 585 | local_irq_enable(); |
579 | 586 | ||
580 | Enable_cpus: | 587 | Enable_cpus: |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 4c10be0f4843..87331565e505 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/export.h> | 27 | #include <linux/export.h> |
28 | #include <linux/suspend.h> | 28 | #include <linux/suspend.h> |
29 | #include <linux/syscore_ops.h> | 29 | #include <linux/syscore_ops.h> |
30 | #include <linux/swait.h> | ||
30 | #include <linux/ftrace.h> | 31 | #include <linux/ftrace.h> |
31 | #include <trace/events/power.h> | 32 | #include <trace/events/power.h> |
32 | #include <linux/compiler.h> | 33 | #include <linux/compiler.h> |
@@ -57,10 +58,10 @@ EXPORT_SYMBOL_GPL(pm_suspend_global_flags); | |||
57 | 58 | ||
58 | static const struct platform_suspend_ops *suspend_ops; | 59 | static const struct platform_suspend_ops *suspend_ops; |
59 | static const struct platform_s2idle_ops *s2idle_ops; | 60 | static const struct platform_s2idle_ops *s2idle_ops; |
60 | static DECLARE_WAIT_QUEUE_HEAD(s2idle_wait_head); | 61 | static DECLARE_SWAIT_QUEUE_HEAD(s2idle_wait_head); |
61 | 62 | ||
62 | enum s2idle_states __read_mostly s2idle_state; | 63 | enum s2idle_states __read_mostly s2idle_state; |
63 | static DEFINE_SPINLOCK(s2idle_lock); | 64 | static DEFINE_RAW_SPINLOCK(s2idle_lock); |
64 | 65 | ||
65 | void s2idle_set_ops(const struct platform_s2idle_ops *ops) | 66 | void s2idle_set_ops(const struct platform_s2idle_ops *ops) |
66 | { | 67 | { |
@@ -78,12 +79,12 @@ static void s2idle_enter(void) | |||
78 | { | 79 | { |
79 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, true); | 80 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, true); |
80 | 81 | ||
81 | spin_lock_irq(&s2idle_lock); | 82 | raw_spin_lock_irq(&s2idle_lock); |
82 | if (pm_wakeup_pending()) | 83 | if (pm_wakeup_pending()) |
83 | goto out; | 84 | goto out; |
84 | 85 | ||
85 | s2idle_state = S2IDLE_STATE_ENTER; | 86 | s2idle_state = S2IDLE_STATE_ENTER; |
86 | spin_unlock_irq(&s2idle_lock); | 87 | raw_spin_unlock_irq(&s2idle_lock); |
87 | 88 | ||
88 | get_online_cpus(); | 89 | get_online_cpus(); |
89 | cpuidle_resume(); | 90 | cpuidle_resume(); |
@@ -91,17 +92,17 @@ static void s2idle_enter(void) | |||
91 | /* Push all the CPUs into the idle loop. */ | 92 | /* Push all the CPUs into the idle loop. */ |
92 | wake_up_all_idle_cpus(); | 93 | wake_up_all_idle_cpus(); |
93 | /* Make the current CPU wait so it can enter the idle loop too. */ | 94 | /* Make the current CPU wait so it can enter the idle loop too. */ |
94 | wait_event(s2idle_wait_head, | 95 | swait_event(s2idle_wait_head, |
95 | s2idle_state == S2IDLE_STATE_WAKE); | 96 | s2idle_state == S2IDLE_STATE_WAKE); |
96 | 97 | ||
97 | cpuidle_pause(); | 98 | cpuidle_pause(); |
98 | put_online_cpus(); | 99 | put_online_cpus(); |
99 | 100 | ||
100 | spin_lock_irq(&s2idle_lock); | 101 | raw_spin_lock_irq(&s2idle_lock); |
101 | 102 | ||
102 | out: | 103 | out: |
103 | s2idle_state = S2IDLE_STATE_NONE; | 104 | s2idle_state = S2IDLE_STATE_NONE; |
104 | spin_unlock_irq(&s2idle_lock); | 105 | raw_spin_unlock_irq(&s2idle_lock); |
105 | 106 | ||
106 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, false); | 107 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_TO_IDLE, false); |
107 | } | 108 | } |
@@ -156,12 +157,12 @@ void s2idle_wake(void) | |||
156 | { | 157 | { |
157 | unsigned long flags; | 158 | unsigned long flags; |
158 | 159 | ||
159 | spin_lock_irqsave(&s2idle_lock, flags); | 160 | raw_spin_lock_irqsave(&s2idle_lock, flags); |
160 | if (s2idle_state > S2IDLE_STATE_NONE) { | 161 | if (s2idle_state > S2IDLE_STATE_NONE) { |
161 | s2idle_state = S2IDLE_STATE_WAKE; | 162 | s2idle_state = S2IDLE_STATE_WAKE; |
162 | wake_up(&s2idle_wait_head); | 163 | swake_up(&s2idle_wait_head); |
163 | } | 164 | } |
164 | spin_unlock_irqrestore(&s2idle_lock, flags); | 165 | raw_spin_unlock_irqrestore(&s2idle_lock, flags); |
165 | } | 166 | } |
166 | EXPORT_SYMBOL_GPL(s2idle_wake); | 167 | EXPORT_SYMBOL_GPL(s2idle_wake); |
167 | 168 | ||
@@ -428,6 +429,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
428 | arch_suspend_disable_irqs(); | 429 | arch_suspend_disable_irqs(); |
429 | BUG_ON(!irqs_disabled()); | 430 | BUG_ON(!irqs_disabled()); |
430 | 431 | ||
432 | system_state = SYSTEM_SUSPEND; | ||
433 | |||
431 | error = syscore_suspend(); | 434 | error = syscore_suspend(); |
432 | if (!error) { | 435 | if (!error) { |
433 | *wakeup = pm_wakeup_pending(); | 436 | *wakeup = pm_wakeup_pending(); |
@@ -443,6 +446,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
443 | syscore_resume(); | 446 | syscore_resume(); |
444 | } | 447 | } |
445 | 448 | ||
449 | system_state = SYSTEM_RUNNING; | ||
450 | |||
446 | arch_suspend_enable_irqs(); | 451 | arch_suspend_enable_irqs(); |
447 | BUG_ON(irqs_disabled()); | 452 | BUG_ON(irqs_disabled()); |
448 | 453 | ||
diff --git a/kernel/power/user.c b/kernel/power/user.c index 75c959de4b29..abd225550271 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -186,6 +186,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, | |||
186 | res = PAGE_SIZE - pg_offp; | 186 | res = PAGE_SIZE - pg_offp; |
187 | } | 187 | } |
188 | 188 | ||
189 | if (!data_of(data->handle)) { | ||
190 | res = -EINVAL; | ||
191 | goto unlock; | ||
192 | } | ||
193 | |||
189 | res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp, | 194 | res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp, |
190 | buf, count); | 195 | buf, count); |
191 | if (res > 0) | 196 | if (res > 0) |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 49edc1c4f3e6..14de3727b18e 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -490,6 +490,7 @@ void tick_freeze(void) | |||
490 | if (tick_freeze_depth == num_online_cpus()) { | 490 | if (tick_freeze_depth == num_online_cpus()) { |
491 | trace_suspend_resume(TPS("timekeeping_freeze"), | 491 | trace_suspend_resume(TPS("timekeeping_freeze"), |
492 | smp_processor_id(), true); | 492 | smp_processor_id(), true); |
493 | system_state = SYSTEM_SUSPEND; | ||
493 | timekeeping_suspend(); | 494 | timekeeping_suspend(); |
494 | } else { | 495 | } else { |
495 | tick_suspend_local(); | 496 | tick_suspend_local(); |
@@ -513,6 +514,7 @@ void tick_unfreeze(void) | |||
513 | 514 | ||
514 | if (tick_freeze_depth == num_online_cpus()) { | 515 | if (tick_freeze_depth == num_online_cpus()) { |
515 | timekeeping_resume(); | 516 | timekeeping_resume(); |
517 | system_state = SYSTEM_RUNNING; | ||
516 | trace_suspend_resume(TPS("timekeeping_freeze"), | 518 | trace_suspend_resume(TPS("timekeeping_freeze"), |
517 | smp_processor_id(), false); | 519 | smp_processor_id(), false); |
518 | } else { | 520 | } else { |