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
Unified · Split
| @@ -101,6 +101,8 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void); · 100 unmodified lines | |||
| 101 | 101 | ||
| 102 | acpi_status acpi_hw_enable_all_wakeup_gpes(void); | 102 | acpi_status acpi_hw_enable_all_wakeup_gpes(void); |
| 103 | 103 | ||
| 104 | u8 acpi_hw_check_all_gpes(void); | ||
| 105 | |||
| 104 | acpi_status | 106 | acpi_status |
| 105 | acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | 107 | acpi_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, |
| @@ -795,6 +795,38 @@ acpi_status acpi_enable_all_wakeup_gpes(void) · 794 unmodified lines | |||
| 795 | 795 | ||
| 796 | ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes) | 796 | ACPI_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 | ******************************************************************************/ | ||
| 810 | u32 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 | |||
| 828 | ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set) | ||
| 829 | |||
| 798 | /******************************************************************************* | 830 | /******************************************************************************* |
| 799 | * | 831 | * |
| 800 | * FUNCTION: acpi_install_gpe_block | 832 | * FUNCTION: acpi_install_gpe_block |
| @@ -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 | |||
| 460 | static acpi_status | ||
| 461 | acpi_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_gpes | 496 | * 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 | |||
| 573 | u8 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 */ |
| @@ -179,6 +179,7 @@ EXPORT_SYMBOL(first_ec); · 178 unmodified lines | |||
| 179 | 179 | ||
| 180 | static struct acpi_ec *boot_ec; | 180 | static struct acpi_ec *boot_ec; |
| 181 | static bool boot_ec_is_ecdt = false; | 181 | static bool boot_ec_is_ecdt = false; |
| 182 | static struct workqueue_struct *ec_wq; | ||
| 182 | static struct workqueue_struct *ec_query_wq; | 183 | static struct workqueue_struct *ec_query_wq; |
| 183 | 184 | ||
| 184 | static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ | 185 | static 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_SLEEP | 536 | #ifdef CONFIG_PM_SLEEP |
| 536 | static void __acpi_ec_flush_work(void) | 537 | static 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 | ||
| 557 | void acpi_ec_flush_work(void) | 558 | void 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 | ||
| 2110 | static inline int acpi_ec_query_init(void) | 2111 | static 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 | |||
| 2121 | static 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 | ||
| 2123 | static 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 | |||
| 2129 | static const struct dmi_system_id acpi_ec_no_wakeup[] = { | 2138 | static 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 */ |
| @@ -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 | ||
| 993 | static void acpi_s2idle_wake(void) | 993 | static 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 has | 996 | 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 case | 1022 | * 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 | ||
| 1024 | static void acpi_s2idle_restore_early(void) | 1048 | static void acpi_s2idle_restore_early(void) |
| @@ -105,6 +105,8 @@ bool have_governor_per_policy(void) · 104 unmodified lines | |||
| 105 | } | 105 | } |
| 106 | EXPORT_SYMBOL_GPL(have_governor_per_policy); | 106 | EXPORT_SYMBOL_GPL(have_governor_per_policy); |
| 107 | 107 | ||
| 108 | static struct kobject *cpufreq_global_kobject; | ||
| 109 | |||
| 108 | struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) | 110 | struct 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 | } |
| 2746 | EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); | 2748 | EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); |
| 2747 | 2749 | ||
| 2748 | struct kobject *cpufreq_global_kobject; | ||
| 2749 | EXPORT_SYMBOL(cpufreq_global_kobject); | ||
| 2750 | |||
| 2751 | static int __init cpufreq_core_init(void) | 2750 | static int __init cpufreq_core_init(void) |
| 2752 | { | 2751 | { |
| 2753 | if (cpufreq_disabled()) | 2752 | if (cpufreq_disabled()) |
| @@ -752,6 +752,7 @@ ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u3 · 751 unmodified lines | |||
| 752 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) | 752 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) |
| 753 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) | 753 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) |
| 754 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) | 754 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) |
| 755 | ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(void)) | ||
| 755 | 756 | ||
| 756 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status | 757 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status |
| 757 | acpi_get_gpe_device(u32 gpe_index, | 758 | acpi_get_gpe_device(u32 gpe_index, |
| @@ -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 */ | ||
| 205 | extern struct kobject *cpufreq_global_kobject; | ||
| 206 | |||
| 207 | #ifdef CONFIG_CPU_FREQ | 204 | #ifdef CONFIG_CPU_FREQ |
| 208 | unsigned int cpufreq_get(unsigned int cpu); | 205 | unsigned int cpufreq_get(unsigned int cpu); |
| 209 | unsigned int cpufreq_quick_get(unsigned int cpu); | 206 | unsigned int cpufreq_quick_get(unsigned int cpu); |
| @@ -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); |
| @@ -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 | ||