History

Merge tag 'pm-5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki: "Fix three issues related to the handling of wakeup events signaled through the ACPI SCI while suspended to idle (Rafael Wysocki) and unexport an internal cpufreq variable (Yangtao Li)" * tag 'pm-5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: PM: s2idle: Prevent spurious SCIs from waking up the system ACPICA: Introduce acpi_any_gpe_status_set() ACPI: PM: s2idle: Avoid possible race related to the EC GPE ACPI: EC: Fix flushing of pending work cpufreq: Make cpufreq_global_kobject static

Linus Torvalds committed 6 years ago

Commit 4e03e4e2 parents 81f3011 3629ac510 files · +177 −42Browse files

Unified · Split

10 files
  1. drivers/acpi/acpica/achware.h +2 −0
  2. drivers/acpi/acpica/evxfgpe.c +32 −0
  3. drivers/acpi/acpica/hwgpe.c +71 −0
  4. drivers/acpi/ec.c +26 −18
  5. drivers/acpi/sleep.c +37 −13
  6. drivers/cpufreq/cpufreq.c +2 −3
  7. include/acpi/acpixf.h +1 −0
  8. include/linux/cpufreq.h +0 −3
  9. include/linux/suspend.h +1 −1
  10. kernel/power/suspend.c +5 −4
drivers/acpi/acpica/achware.h+2−0
@@ -101,6 +101,8 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void); · 100 unmodified lines
101 101
102acpi_status acpi_hw_enable_all_wakeup_gpes(void);102acpi_status acpi_hw_enable_all_wakeup_gpes(void);
103 103
104u8 acpi_hw_check_all_gpes(void);
105
104acpi_status106acpi_status
105acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,107acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
106 struct acpi_gpe_block_info *gpe_block,108 struct acpi_gpe_block_info *gpe_block,
drivers/acpi/acpica/evxfgpe.c+32−0
@@ -795,6 +795,38 @@ acpi_status acpi_enable_all_wakeup_gpes(void) · 794 unmodified lines
795 795
796ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)796ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
797 797
798/******************************************************************************
799 *
800 * FUNCTION: acpi_any_gpe_status_set
801 *
802 * PARAMETERS: None
803 *
804 * RETURN: Whether or not the status bit is set for any GPE
805 *
806 * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any
807 * of them is set or FALSE otherwise.
808 *
809 ******************************************************************************/
810u32 acpi_any_gpe_status_set(void)
811{
812 acpi_status status;
813 u8 ret;
814
815 ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set);
816
817 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
818 if (ACPI_FAILURE(status)) {
819 return (FALSE);
820 }
821
822 ret = acpi_hw_check_all_gpes();
823 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
824
825 return (ret);
826}
827
828ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)
829
798/*******************************************************************************830/*******************************************************************************
799 *831 *
800 * FUNCTION: acpi_install_gpe_block832 * FUNCTION: acpi_install_gpe_block
drivers/acpi/acpica/hwgpe.c+71−0
@@ -444,6 +444,53 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, · 443 unmodified lines
444 return (AE_OK);444 return (AE_OK);
445}445}
446 446
447/******************************************************************************
448 *
449 * FUNCTION: acpi_hw_get_gpe_block_status
450 *
451 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
452 * gpe_block - Gpe Block info
453 *
454 * RETURN: Success
455 *
456 * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
457 *
458 ******************************************************************************/
459
460static acpi_status
461acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
462 struct acpi_gpe_block_info *gpe_block,
463 void *ret_ptr)
464{
465 struct acpi_gpe_register_info *gpe_register_info;
466 u64 in_enable, in_status;
467 acpi_status status;
468 u8 *ret = ret_ptr;
469 u32 i;
470
471 /* Examine each GPE Register within the block */
472
473 for (i = 0; i < gpe_block->register_count; i++) {
474 gpe_register_info = &gpe_block->register_info[i];
475
476 status = acpi_hw_read(&in_enable,
477 &gpe_register_info->enable_address);
478 if (ACPI_FAILURE(status)) {
479 continue;
480 }
481
482 status = acpi_hw_read(&in_status,
483 &gpe_register_info->status_address);
484 if (ACPI_FAILURE(status)) {
485 continue;
486 }
487
488 *ret |= in_enable & in_status;
489 }
490
491 return (AE_OK);
492}
493
447/******************************************************************************494/******************************************************************************
448 *495 *
449 * FUNCTION: acpi_hw_disable_all_gpes496 * FUNCTION: acpi_hw_disable_all_gpes
@@ -510,4 +557,28 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void) · 60 unmodified lines
510 return_ACPI_STATUS(status);557 return_ACPI_STATUS(status);
511}558}
512 559
560/******************************************************************************
561 *
562 * FUNCTION: acpi_hw_check_all_gpes
563 *
564 * PARAMETERS: None
565 *
566 * RETURN: Combined status of all GPEs
567 *
568 * DESCRIPTION: Check all enabled GPEs in all GPE blocks and return TRUE if the
569 * status bit is set for at least one of them of FALSE otherwise.
570 *
571 ******************************************************************************/
572
573u8 acpi_hw_check_all_gpes(void)
574{
575 u8 ret = 0;
576
577 ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
578
579 (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &ret);
580
581 return (ret != 0);
582}
583
513#endif /* !ACPI_REDUCED_HARDWARE */584#endif /* !ACPI_REDUCED_HARDWARE */
drivers/acpi/ec.c+26−18
@@ -179,6 +179,7 @@ EXPORT_SYMBOL(first_ec); · 178 unmodified lines
179 179
180static struct acpi_ec *boot_ec;180static struct acpi_ec *boot_ec;
181static bool boot_ec_is_ecdt = false;181static bool boot_ec_is_ecdt = false;
182static struct workqueue_struct *ec_wq;
182static struct workqueue_struct *ec_query_wq;183static struct workqueue_struct *ec_query_wq;
183 184
184static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */185static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
@@ -469,7 +470,7 @@ static void acpi_ec_submit_query(struct acpi_ec *ec) · 284 unmodified lines
469 ec_dbg_evt("Command(%s) submitted/blocked",470 ec_dbg_evt("Command(%s) submitted/blocked",
470 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));471 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
471 ec->nr_pending_queries++;472 ec->nr_pending_queries++;
472 schedule_work(&ec->work);473 queue_work(ec_wq, &ec->work);
473 }474 }
474}475}
475 476
@@ -535,7 +536,7 @@ static void acpi_ec_enable_event(struct acpi_ec *ec) · 59 unmodified lines
535#ifdef CONFIG_PM_SLEEP536#ifdef CONFIG_PM_SLEEP
536static void __acpi_ec_flush_work(void)537static void __acpi_ec_flush_work(void)
537{538{
538 flush_scheduled_work(); /* flush ec->work */539 drain_workqueue(ec_wq); /* flush ec->work */
539 flush_workqueue(ec_query_wq); /* flush queries */540 flush_workqueue(ec_query_wq); /* flush queries */
540}541}
541 542
@@ -556,8 +557,8 @@ static void acpi_ec_disable_event(struct acpi_ec *ec) · 14 unmodified lines
556 557
557void acpi_ec_flush_work(void)558void acpi_ec_flush_work(void)
558{559{
559 /* Without ec_query_wq there is nothing to flush. */560 /* Without ec_wq there is nothing to flush. */
560 if (!ec_query_wq)561 if (!ec_wq)
561 return;562 return;
562 563
563 __acpi_ec_flush_work();564 __acpi_ec_flush_work();
@@ -2107,25 +2108,33 @@ static struct acpi_driver acpi_ec_driver = { · 1543 unmodified lines
2107 .drv.pm = &acpi_ec_pm,2108 .drv.pm = &acpi_ec_pm,
2108};2109};
2109 2110
2110static inline int acpi_ec_query_init(void)2111static void acpi_ec_destroy_workqueues(void)
2111{2112{
2112 if (!ec_query_wq) {2113 if (ec_wq) {
2113 ec_query_wq = alloc_workqueue("kec_query", 0,2114 destroy_workqueue(ec_wq);
2114 ec_max_queries);2115 ec_wq = NULL;
2115 if (!ec_query_wq)
2116 return -ENODEV;
2117 }2116 }
2118 return 0;
2119}
2120
2121static inline void acpi_ec_query_exit(void)
2122{
2123 if (ec_query_wq) {2117 if (ec_query_wq) {
2124 destroy_workqueue(ec_query_wq);2118 destroy_workqueue(ec_query_wq);
2125 ec_query_wq = NULL;2119 ec_query_wq = NULL;
2126 }2120 }
2127}2121}
2128 2122
2123static int acpi_ec_init_workqueues(void)
2124{
2125 if (!ec_wq)
2126 ec_wq = alloc_ordered_workqueue("kec", 0);
2127
2128 if (!ec_query_wq)
2129 ec_query_wq = alloc_workqueue("kec_query", 0, ec_max_queries);
2130
2131 if (!ec_wq || !ec_query_wq) {
2132 acpi_ec_destroy_workqueues();
2133 return -ENODEV;
2134 }
2135 return 0;
2136}
2137
2129static const struct dmi_system_id acpi_ec_no_wakeup[] = {2138static const struct dmi_system_id acpi_ec_no_wakeup[] = {
2130 {2139 {
2131 .ident = "Thinkpad X1 Carbon 6th",2140 .ident = "Thinkpad X1 Carbon 6th",
@@ -2156,8 +2165,7 @@ int __init acpi_ec_init(void) · 24 unmodified lines
2156 int result;2165 int result;
2157 int ecdt_fail, dsdt_fail;2166 int ecdt_fail, dsdt_fail;
2158 2167
2159 /* register workqueue for _Qxx evaluations */2168 result = acpi_ec_init_workqueues();
2160 result = acpi_ec_query_init();
2161 if (result)2169 if (result)
2162 return result;2170 return result;
2163 2171
@@ -2188,6 +2196,6 @@ static void __exit acpi_ec_exit(void) · 24 unmodified lines
2188{2196{
2189 2197
2190 acpi_bus_unregister_driver(&acpi_ec_driver);2198 acpi_bus_unregister_driver(&acpi_ec_driver);
2191 acpi_ec_query_exit();2199 acpi_ec_destroy_workqueues();
2192}2200}
2193#endif /* 0 */2201#endif /* 0 */
drivers/acpi/sleep.c+37−13
@@ -990,21 +990,34 @@ static void acpi_s2idle_sync(void) · 989 unmodified lines
990 acpi_os_wait_events_complete(); /* synchronize Notify handling */990 acpi_os_wait_events_complete(); /* synchronize Notify handling */
991}991}
992 992
993static void acpi_s2idle_wake(void)993static bool acpi_s2idle_wake(void)
994{994{
995 /*995 if (!acpi_sci_irq_valid())
996 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has996 return pm_wakeup_pending();
997 * not triggered while suspended, so bail out.997
998 */998 while (pm_wakeup_pending()) {
999 if (!acpi_sci_irq_valid() ||999 /*
1000 irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))1000 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the
1001 return;1001 * SCI has not triggered while suspended, so bail out (the
1002 * wakeup is pending anyway and the SCI is not the source of
1003 * it).
1004 */
1005 if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
1006 return true;
1007
1008 /*
1009 * If there are no EC events to process and at least one of the
1010 * other enabled GPEs is active, the wakeup is regarded as a
1011 * genuine one.
1012 *
1013 * Note that the checks below must be carried out in this order
1014 * to avoid returning prematurely due to a change of the EC GPE
1015 * status bit from unset to set between the checks with the
1016 * status bits of all the other GPEs unset.
1017 */
1018 if (acpi_any_gpe_status_set() && !acpi_ec_dispatch_gpe())
1019 return true;
1002 1020
1003 /*
1004 * If there are EC events to process, the wakeup may be a spurious one
1005 * coming from the EC.
1006 */
1007 if (acpi_ec_dispatch_gpe()) {
1008 /*1021 /*
1009 * Cancel the wakeup and process all pending events in case1022 * Cancel the wakeup and process all pending events in case
1010 * there are any wakeup ones in there.1023 * there are any wakeup ones in there.
@@ -1017,8 +1030,19 @@ static void acpi_s2idle_wake(void) · 6 unmodified lines
1017 1030
1018 acpi_s2idle_sync();1031 acpi_s2idle_sync();
1019 1032
1033 /*
1034 * The SCI is in the "suspended" state now and it cannot produce
1035 * new wakeup events till the rearming below, so if any of them
1036 * are pending here, they must be resulting from the processing
1037 * of EC events above or coming from somewhere else.
1038 */
1039 if (pm_wakeup_pending())
1040 return true;
1041
1020 rearm_wake_irq(acpi_sci_irq);1042 rearm_wake_irq(acpi_sci_irq);
1021 }1043 }
1044
1045 return false;
1022}1046}
1023 1047
1024static void acpi_s2idle_restore_early(void)1048static void acpi_s2idle_restore_early(void)
drivers/cpufreq/cpufreq.c+2−3
@@ -105,6 +105,8 @@ bool have_governor_per_policy(void) · 104 unmodified lines
105}105}
106EXPORT_SYMBOL_GPL(have_governor_per_policy);106EXPORT_SYMBOL_GPL(have_governor_per_policy);
107 107
108static struct kobject *cpufreq_global_kobject;
109
108struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)110struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
109{111{
110 if (have_governor_per_policy())112 if (have_governor_per_policy())
@@ -2745,9 +2747,6 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) · 2634 unmodified lines
2745}2747}
2746EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);2748EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
2747 2749
2748struct kobject *cpufreq_global_kobject;
2749EXPORT_SYMBOL(cpufreq_global_kobject);
2750
2751static int __init cpufreq_core_init(void)2750static int __init cpufreq_core_init(void)
2752{2751{
2753 if (cpufreq_disabled())2752 if (cpufreq_disabled())
include/acpi/acpixf.h+1−0
@@ -752,6 +752,7 @@ ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u3 · 751 unmodified lines
752ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))752ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
753ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))753ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
754ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))754ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
755ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(void))
755 756
756ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status757ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
757 acpi_get_gpe_device(u32 gpe_index,758 acpi_get_gpe_device(u32 gpe_index,
include/linux/cpufreq.h+0−3
@@ -201,9 +201,6 @@ static inline bool policy_is_shared(struct cpufreq_policy *policy) · 200 unmodified lines
201 return cpumask_weight(policy->cpus) > 1;201 return cpumask_weight(policy->cpus) > 1;
202}202}
203 203
204/* /sys/devices/system/cpu/cpufreq: entry point for global variables */
205extern struct kobject *cpufreq_global_kobject;
206
207#ifdef CONFIG_CPU_FREQ204#ifdef CONFIG_CPU_FREQ
208unsigned int cpufreq_get(unsigned int cpu);205unsigned int cpufreq_get(unsigned int cpu);
209unsigned int cpufreq_quick_get(unsigned int cpu);206unsigned int cpufreq_quick_get(unsigned int cpu);
include/linux/suspend.h+1−1
@@ -191,7 +191,7 @@ struct platform_s2idle_ops { · 190 unmodified lines
191 int (*begin)(void);191 int (*begin)(void);
192 int (*prepare)(void);192 int (*prepare)(void);
193 int (*prepare_late)(void);193 int (*prepare_late)(void);
194 void (*wake)(void);194 bool (*wake)(void);
195 void (*restore_early)(void);195 void (*restore_early)(void);
196 void (*restore)(void);196 void (*restore)(void);
197 void (*end)(void);197 void (*end)(void);
kernel/power/suspend.c+5−4
@@ -131,11 +131,12 @@ static void s2idle_loop(void) · 130 unmodified lines
131 * to avoid them upfront.131 * to avoid them upfront.
132 */132 */
133 for (;;) {133 for (;;) {
134 if (s2idle_ops && s2idle_ops->wake)134 if (s2idle_ops && s2idle_ops->wake) {
135 s2idle_ops->wake();135 if (s2idle_ops->wake())
136 136 break;
137 if (pm_wakeup_pending())137 } else if (pm_wakeup_pending()) {
138 break;138 break;
139 }
139 140
140 pm_wakeup_clear(false);141 pm_wakeup_clear(false);
141 142