aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power/rockchip-io-domain.txt15
-rw-r--r--drivers/acpi/acpica/evgpe.c6
-rw-r--r--drivers/acpi/acpica/evxfgpe.c22
-rw-r--r--drivers/acpi/ec.c6
-rw-r--r--drivers/acpi/internal.h1
-rw-r--r--drivers/acpi/sleep.c7
-rw-r--r--drivers/base/power/wakeup.c18
-rw-r--r--drivers/pci/pci-driver.c5
-rw-r--r--drivers/pci/pci.c6
-rw-r--r--drivers/power/avs/rockchip-io-domain.c68
-rw-r--r--include/acpi/acpixf.h1
-rw-r--r--include/linux/kernel.h1
-rw-r--r--kernel/power/hibernate.c7
-rw-r--r--kernel/power/suspend.c27
-rw-r--r--kernel/power/user.c5
-rw-r--r--kernel/time/tick-common.c2
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
32Required properties: 32Required 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
51to report their voltage. The IO Voltage Domain for any non-specified 53to report their voltage. The IO Voltage Domain for any non-specified
52supplies will be not be touched. 54supplies will be not be touched.
53 55
56Possible 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
65Possible supplies for PX30 pmu-domains:
66- pmuio1-supply: The supply connected to PMUIO1.
67- pmuio2-supply: The supply connected to PMUIO2.
68
54Possible supplies for rk3188: 69Possible 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 ******************************************************************************/
653void 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
660ACPI_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
1037void 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);
188int acpi_ec_dsdt_probe(void); 188int acpi_ec_dsdt_probe(void);
189void acpi_ec_block_transactions(void); 189void acpi_ec_block_transactions(void);
190void acpi_ec_unblock_transactions(void); 190void acpi_ec_unblock_transactions(void);
191void acpi_ec_dispatch_gpe(void);
191int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, 192int 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. */
58static unsigned int saved_count; 58static unsigned int saved_count;
59 59
60static DEFINE_SPINLOCK(events_lock); 60static DEFINE_RAW_SPINLOCK(events_lock);
61 61
62static void pm_wakeup_timer_fn(struct timer_list *t); 62static 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}
191EXPORT_SYMBOL_GPL(wakeup_source_add); 191EXPORT_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}
209EXPORT_SYMBOL_GPL(wakeup_source_remove); 209EXPORT_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
158static 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
154static void rk3288_iodomain_init(struct rockchip_iodomain *iod) 177static 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
253static 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
268static 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
382static const struct of_device_id rockchip_iodomain_match[] = { 442static 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))
756ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
756ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) 757ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
757ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) 758ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
758ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) 759ACPI_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
58static const struct platform_suspend_ops *suspend_ops; 59static const struct platform_suspend_ops *suspend_ops;
59static const struct platform_s2idle_ops *s2idle_ops; 60static const struct platform_s2idle_ops *s2idle_ops;
60static DECLARE_WAIT_QUEUE_HEAD(s2idle_wait_head); 61static DECLARE_SWAIT_QUEUE_HEAD(s2idle_wait_head);
61 62
62enum s2idle_states __read_mostly s2idle_state; 63enum s2idle_states __read_mostly s2idle_state;
63static DEFINE_SPINLOCK(s2idle_lock); 64static DEFINE_RAW_SPINLOCK(s2idle_lock);
64 65
65void s2idle_set_ops(const struct platform_s2idle_ops *ops) 66void 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}
166EXPORT_SYMBOL_GPL(s2idle_wake); 167EXPORT_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 {