* pm-core: PM: runtime: Add pm_runtime_get_if_active() * pm-sleep: PM: sleep: wakeup: Skip wakeup_source_sysfs_remove() if device is not there PM / hibernate: Remove unnecessary compat ioctl overrides PM: hibernate: fix docs for ioctls that return loff_t via pointer PM: sleep: wakeup: Use built-in RCU list checking PM: sleep: core: Use built-in RCU list checking * pm-acpi: ACPI: PM: s2idle: Refine active GPEs check ACPICA: Allow acpi_any_gpe_status_set() to skip one GPE ACPI: PM: s2idle: Fix comment in acpi_s2idle_prepare_late() * pm-domains: cpuidle: psci: Split psci_dt_cpu_init_idle() PM / Domains: Allow no domain-idle-states DT property in genpd when parsing
Unified · Split
| @@ -382,6 +382,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: · 381 unmodified lines | ||
| 382 | 382 | nonzero, increment the counter and return 1; otherwise return 0 without |
| 383 | 383 | changing the counter |
| 384 | 384 | |
| 385 | + `int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count);` | |
| 386 | + - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the | |
| 387 | + runtime PM status is RPM_ACTIVE, and either ign_usage_count is true | |
| 388 | + or the device's usage_count is non-zero, increment the counter and | |
| 389 | + return 1; otherwise return 0 without changing the counter | |
| 390 | + | |
| 385 | 391 | `void pm_runtime_put_noidle(struct device *dev);` |
| 386 | 392 | - decrement the device's usage counter |
| 387 | 393 | |
| @@ -69,11 +69,13 @@ SNAPSHOT_PREF_IMAGE_SIZE · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | SNAPSHOT_GET_IMAGE_SIZE |
| 71 | 71 | return the actual size of the hibernation image |
| 72 | + (the last argument should be a pointer to a loff_t variable that | |
| 73 | + will contain the result if the call is successful) | |
| 72 | 74 | |
| 73 | 75 | SNAPSHOT_AVAIL_SWAP_SIZE |
| 74 | − return the amount of available swap in bytes (the | |
| 75 | − last argument should be a pointer to an unsigned int variable that will | |
| 76 | − contain the result if the call is successful). | |
| 76 | + return the amount of available swap in bytes | |
| 77 | + (the last argument should be a pointer to a loff_t variable that | |
| 78 | + will contain the result if the call is successful) | |
| 77 | 79 | |
| 78 | 80 | SNAPSHOT_ALLOC_SWAP_PAGE |
| 79 | 81 | allocate a swap page from the resume partition |
| @@ -101,7 +101,7 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void); · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | acpi_status acpi_hw_enable_all_wakeup_gpes(void); |
| 103 | 103 | |
| 104 | −u8 acpi_hw_check_all_gpes(void); | |
| 104 | +u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number); | |
| 105 | 105 | |
| 106 | 106 | acpi_status |
| 107 | 107 | acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
| @@ -799,17 +799,19 @@ ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes) · 798 unmodified lines | ||
| 799 | 799 | * |
| 800 | 800 | * FUNCTION: acpi_any_gpe_status_set |
| 801 | 801 | * |
| 802 | − * PARAMETERS: None | |
| 802 | + * PARAMETERS: gpe_skip_number - Number of the GPE to skip | |
| 803 | 803 | * |
| 804 | 804 | * RETURN: Whether or not the status bit is set for any GPE |
| 805 | 805 | * |
| 806 | − * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any | |
| 807 | − * of them is set or FALSE otherwise. | |
| 806 | + * DESCRIPTION: Check the status bits of all enabled GPEs, except for the one | |
| 807 | + * represented by the "skip" argument, and return TRUE if any of | |
| 808 | + * them is set or FALSE otherwise. | |
| 808 | 809 | * |
| 809 | 810 | ******************************************************************************/ |
| 810 | −u32 acpi_any_gpe_status_set(void) | |
| 811 | +u32 acpi_any_gpe_status_set(u32 gpe_skip_number) | |
| 811 | 812 | { |
| 812 | 813 | acpi_status status; |
| 814 | + acpi_handle gpe_device; | |
| 813 | 815 | u8 ret; |
| 814 | 816 | |
| 815 | 817 | ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set); |
| @@ -819,7 +821,12 @@ u32 acpi_any_gpe_status_set(void) · 3 unmodified lines | ||
| 819 | 821 | return (FALSE); |
| 820 | 822 | } |
| 821 | 823 | |
| 822 | − ret = acpi_hw_check_all_gpes(); | |
| 824 | + status = acpi_get_gpe_device(gpe_skip_number, &gpe_device); | |
| 825 | + if (ACPI_FAILURE(status)) { | |
| 826 | + gpe_device = NULL; | |
| 827 | + } | |
| 828 | + | |
| 829 | + ret = acpi_hw_check_all_gpes(gpe_device, gpe_skip_number); | |
| 823 | 830 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
| 824 | 831 | |
| 825 | 832 | return (ret); |
| @@ -444,12 +444,19 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, · 443 unmodified lines | ||
| 444 | 444 | return (AE_OK); |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | +struct acpi_gpe_block_status_context { | |
| 448 | + struct acpi_gpe_register_info *gpe_skip_register_info; | |
| 449 | + u8 gpe_skip_mask; | |
| 450 | + u8 retval; | |
| 451 | +}; | |
| 452 | + | |
| 447 | 453 | /****************************************************************************** |
| 448 | 454 | * |
| 449 | 455 | * FUNCTION: acpi_hw_get_gpe_block_status |
| 450 | 456 | * |
| 451 | 457 | * PARAMETERS: gpe_xrupt_info - GPE Interrupt info |
| 452 | 458 | * gpe_block - Gpe Block info |
| 459 | + * context - GPE list walk context data | |
| 453 | 460 | * |
| 454 | 461 | * RETURN: Success |
| 455 | 462 | * |
| @@ -460,12 +467,13 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, · 4 unmodified lines | ||
| 460 | 467 | static acpi_status |
| 461 | 468 | acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
| 462 | 469 | struct acpi_gpe_block_info *gpe_block, |
| 463 | − void *ret_ptr) | |
| 470 | + void *context) | |
| 464 | 471 | { |
| 472 | + struct acpi_gpe_block_status_context *c = context; | |
| 465 | 473 | struct acpi_gpe_register_info *gpe_register_info; |
| 466 | 474 | u64 in_enable, in_status; |
| 467 | 475 | acpi_status status; |
| 468 | − u8 *ret = ret_ptr; | |
| 476 | + u8 ret_mask; | |
| 469 | 477 | u32 i; |
| 470 | 478 | |
| 471 | 479 | /* Examine each GPE Register within the block */ |
| @@ -485,7 +493,11 @@ acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, · 13 unmodified lines | ||
| 485 | 493 | continue; |
| 486 | 494 | } |
| 487 | 495 | |
| 488 | − *ret |= in_enable & in_status; | |
| 496 | + ret_mask = in_enable & in_status; | |
| 497 | + if (ret_mask && c->gpe_skip_register_info == gpe_register_info) { | |
| 498 | + ret_mask &= ~c->gpe_skip_mask; | |
| 499 | + } | |
| 500 | + c->retval |= ret_mask; | |
| 489 | 501 | } |
| 490 | 502 | |
| 491 | 503 | return (AE_OK); |
| @@ -561,24 +573,41 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void) · 69 unmodified lines | ||
| 561 | 573 | * |
| 562 | 574 | * FUNCTION: acpi_hw_check_all_gpes |
| 563 | 575 | * |
| 564 | − * PARAMETERS: None | |
| 576 | + * PARAMETERS: gpe_skip_device - GPE devoce of the GPE to skip | |
| 577 | + * gpe_skip_number - Number of the GPE to skip | |
| 565 | 578 | * |
| 566 | 579 | * RETURN: Combined status of all GPEs |
| 567 | 580 | * |
| 568 | − * DESCRIPTION: Check all enabled GPEs in all GPE blocks and return TRUE if the | |
| 581 | + * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one | |
| 582 | + * represented by the "skip" arguments, and return TRUE if the | |
| 569 | 583 | * status bit is set for at least one of them of FALSE otherwise. |
| 570 | 584 | * |
| 571 | 585 | ******************************************************************************/ |
| 572 | 586 | |
| 573 | −u8 acpi_hw_check_all_gpes(void) | |
| 587 | +u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number) | |
| 574 | 588 | { |
| 575 | − u8 ret = 0; | |
| 589 | + struct acpi_gpe_block_status_context context = { | |
| 590 | + .gpe_skip_register_info = NULL, | |
| 591 | + .retval = 0, | |
| 592 | + }; | |
| 593 | + struct acpi_gpe_event_info *gpe_event_info; | |
| 594 | + acpi_cpu_flags flags; | |
| 576 | 595 | |
| 577 | 596 | ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes); |
| 578 | 597 | |
| 579 | − (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &ret); | |
| 598 | + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | |
| 599 | + | |
| 600 | + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device, | |
| 601 | + gpe_skip_number); | |
| 602 | + if (gpe_event_info) { | |
| 603 | + context.gpe_skip_register_info = gpe_event_info->register_info; | |
| 604 | + context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info); | |
| 605 | + } | |
| 606 | + | |
| 607 | + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | |
| 580 | 608 | |
| 581 | − return (ret != 0); | |
| 609 | + (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context); | |
| 610 | + return (context.retval != 0); | |
| 582 | 611 | } |
| 583 | 612 | |
| 584 | 613 | #endif /* !ACPI_REDUCED_HARDWARE */ |
| @@ -2037,6 +2037,11 @@ void acpi_ec_set_gpe_wake_mask(u8 action) · 2036 unmodified lines | ||
| 2037 | 2037 | acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); |
| 2038 | 2038 | } |
| 2039 | 2039 | |
| 2040 | +bool acpi_ec_other_gpes_active(void) | |
| 2041 | +{ | |
| 2042 | + return acpi_any_gpe_status_set(first_ec ? first_ec->gpe : U32_MAX); | |
| 2043 | +} | |
| 2044 | + | |
| 2040 | 2045 | bool acpi_ec_dispatch_gpe(void) |
| 2041 | 2046 | { |
| 2042 | 2047 | u32 ret; |
| @@ -202,6 +202,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); · 201 unmodified lines | ||
| 202 | 202 | |
| 203 | 203 | #ifdef CONFIG_PM_SLEEP |
| 204 | 204 | void acpi_ec_flush_work(void); |
| 205 | +bool acpi_ec_other_gpes_active(void); | |
| 205 | 206 | bool acpi_ec_dispatch_gpe(void); |
| 206 | 207 | #endif |
| 207 | 208 | |
| @@ -982,10 +982,7 @@ static int acpi_s2idle_prepare_late(void) · 981 unmodified lines | ||
| 982 | 982 | |
| 983 | 983 | static void acpi_s2idle_sync(void) |
| 984 | 984 | { |
| 985 | − /* | |
| 986 | − * The EC driver uses the system workqueue and an additional special | |
| 987 | − * one, so those need to be flushed too. | |
| 988 | − */ | |
| 985 | + /* The EC driver uses special workqueues that need to be flushed. */ | |
| 989 | 986 | acpi_ec_flush_work(); |
| 990 | 987 | acpi_os_wait_events_complete(); /* synchronize Notify handling */ |
| 991 | 988 | } |
| @@ -1013,18 +1010,19 @@ static bool acpi_s2idle_wake(void) · 21 unmodified lines | ||
| 1013 | 1010 | return true; |
| 1014 | 1011 | |
| 1015 | 1012 | /* |
| 1016 | − * If there are no EC events to process and at least one of the | |
| 1017 | − * other enabled GPEs is active, the wakeup is regarded as a | |
| 1018 | − * genuine one. | |
| 1019 | − * | |
| 1020 | − * Note that the checks below must be carried out in this order | |
| 1021 | − * to avoid returning prematurely due to a change of the EC GPE | |
| 1022 | − * status bit from unset to set between the checks with the | |
| 1023 | − * status bits of all the other GPEs unset. | |
| 1013 | + * If the status bit is set for any enabled GPE other than the | |
| 1014 | + * EC one, the wakeup is regarded as a genuine one. | |
| 1024 | 1015 | */ |
| 1025 | − if (acpi_any_gpe_status_set() && !acpi_ec_dispatch_gpe()) | |
| 1016 | + if (acpi_ec_other_gpes_active()) | |
| 1026 | 1017 | return true; |
| 1027 | 1018 | |
| 1019 | + /* | |
| 1020 | + * If the EC GPE status bit has not been set, the wakeup is | |
| 1021 | + * regarded as a spurious one. | |
| 1022 | + */ | |
| 1023 | + if (!acpi_ec_dispatch_gpe()) | |
| 1024 | + return false; | |
| 1025 | + | |
| 1028 | 1026 | /* |
| 1029 | 1027 | * Cancel the wakeup and process all pending events in case |
| 1030 | 1028 | * there are any wakeup ones in there. |
| @@ -2653,7 +2653,7 @@ static int genpd_iterate_idle_states(struct device_node *dn, · 2652 unmodified lines | ||
| 2653 | 2653 | |
| 2654 | 2654 | ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); |
| 2655 | 2655 | if (ret <= 0) |
| 2656 | − return ret; | |
| 2656 | + return ret == -ENOENT ? 0 : ret; | |
| 2657 | 2657 | |
| 2658 | 2658 | /* Loop over the phandles until all the requested entry is found */ |
| 2659 | 2659 | of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { |
| @@ -40,6 +40,10 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | typedef int (*pm_callback_t)(struct device *); |
| 42 | 42 | |
| 43 | +#define list_for_each_entry_rcu_locked(pos, head, member) \ | |
| 44 | + list_for_each_entry_rcu(pos, head, member, \ | |
| 45 | + device_links_read_lock_held()) | |
| 46 | + | |
| 43 | 47 | /* |
| 44 | 48 | * The entries in the dpm_list list are in a depth first order, simply |
| 45 | 49 | * because children are guaranteed to be discovered after parents, and |
| @@ -266,7 +270,7 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async) · 220 unmodified lines | ||
| 266 | 270 | * callbacks freeing the link objects for the links in the list we're |
| 267 | 271 | * walking. |
| 268 | 272 | */ |
| 269 | − list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) | |
| 273 | + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) | |
| 270 | 274 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 271 | 275 | dpm_wait(link->supplier, async); |
| 272 | 276 | |
| @@ -323,7 +327,7 @@ static void dpm_wait_for_consumers(struct device *dev, bool async) · 50 unmodified lines | ||
| 323 | 327 | * continue instead of trying to continue in parallel with its |
| 324 | 328 | * unregistration). |
| 325 | 329 | */ |
| 326 | − list_for_each_entry_rcu(link, &dev->links.consumers, s_node) | |
| 330 | + list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) | |
| 327 | 331 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 328 | 332 | dpm_wait(link->consumer, async); |
| 329 | 333 | |
| @@ -1235,7 +1239,7 @@ static void dpm_superior_set_must_resume(struct device *dev) · 905 unmodified lines | ||
| 1235 | 1239 | |
| 1236 | 1240 | idx = device_links_read_lock(); |
| 1237 | 1241 | |
| 1238 | − list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) | |
| 1242 | + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) | |
| 1239 | 1243 | link->supplier->power.must_resume = true; |
| 1240 | 1244 | |
| 1241 | 1245 | device_links_read_unlock(idx); |
| @@ -1695,7 +1699,7 @@ static void dpm_clear_superiors_direct_complete(struct device *dev) · 453 unmodified lines | ||
| 1695 | 1699 | |
| 1696 | 1700 | idx = device_links_read_lock(); |
| 1697 | 1701 | |
| 1698 | − list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { | |
| 1702 | + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { | |
| 1699 | 1703 | spin_lock_irq(&link->supplier->power.lock); |
| 1700 | 1704 | link->supplier->power.direct_complete = false; |
| 1701 | 1705 | spin_unlock_irq(&link->supplier->power.lock); |
| @@ -1087,29 +1087,47 @@ int __pm_runtime_resume(struct device *dev, int rpmflags) · 1086 unmodified lines | ||
| 1087 | 1087 | EXPORT_SYMBOL_GPL(__pm_runtime_resume); |
| 1088 | 1088 | |
| 1089 | 1089 | /** |
| 1090 | − * pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter. | |
| 1090 | + * pm_runtime_get_if_active - Conditionally bump up the device's usage counter. | |
| 1091 | 1091 | * @dev: Device to handle. |
| 1092 | 1092 | * |
| 1093 | 1093 | * Return -EINVAL if runtime PM is disabled for the device. |
| 1094 | 1094 | * |
| 1095 | − * If that's not the case and if the device's runtime PM status is RPM_ACTIVE | |
| 1096 | − * and the runtime PM usage counter is nonzero, increment the counter and | |
| 1097 | − * return 1. Otherwise return 0 without changing the counter. | |
| 1095 | + * Otherwise, if the device's runtime PM status is RPM_ACTIVE and either | |
| 1096 | + * ign_usage_count is true or the device's usage_count is non-zero, increment | |
| 1097 | + * the counter and return 1. Otherwise return 0 without changing the counter. | |
| 1098 | + * | |
| 1099 | + * If ign_usage_count is true, the function can be used to prevent suspending | |
| 1100 | + * the device when its runtime PM status is RPM_ACTIVE. | |
| 1101 | + * | |
| 1102 | + * If ign_usage_count is false, the function can be used to prevent suspending | |
| 1103 | + * the device when both its runtime PM status is RPM_ACTIVE and its usage_count | |
| 1104 | + * is non-zero. | |
| 1105 | + * | |
| 1106 | + * The caller is resposible for putting the device's usage count when ther | |
| 1107 | + * return value is greater than zero. | |
| 1098 | 1108 | */ |
| 1099 | −int pm_runtime_get_if_in_use(struct device *dev) | |
| 1109 | +int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count) | |
| 1100 | 1110 | { |
| 1101 | 1111 | unsigned long flags; |
| 1102 | 1112 | int retval; |
| 1103 | 1113 | |
| 1104 | 1114 | spin_lock_irqsave(&dev->power.lock, flags); |
| 1105 | − retval = dev->power.disable_depth > 0 ? -EINVAL : | |
| 1106 | − dev->power.runtime_status == RPM_ACTIVE | |
| 1107 | − && atomic_inc_not_zero(&dev->power.usage_count); | |
| 1115 | + if (dev->power.disable_depth > 0) { | |
| 1116 | + retval = -EINVAL; | |
| 1117 | + } else if (dev->power.runtime_status != RPM_ACTIVE) { | |
| 1118 | + retval = 0; | |
| 1119 | + } else if (ign_usage_count) { | |
| 1120 | + retval = 1; | |
| 1121 | + atomic_inc(&dev->power.usage_count); | |
| 1122 | + } else { | |
| 1123 | + retval = atomic_inc_not_zero(&dev->power.usage_count); | |
| 1124 | + } | |
| 1108 | 1125 | trace_rpm_usage_rcuidle(dev, 0); |
| 1109 | 1126 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 1127 | + | |
| 1110 | 1128 | return retval; |
| 1111 | 1129 | } |
| 1112 | −EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use); | |
| 1130 | +EXPORT_SYMBOL_GPL(pm_runtime_get_if_active); | |
| 1113 | 1131 | |
| 1114 | 1132 | /** |
| 1115 | 1133 | * __pm_runtime_set_status - Set runtime PM status of a device. |
| @@ -24,6 +24,9 @@ suspend_state_t pm_suspend_target_state; · 23 unmodified lines | ||
| 24 | 24 | #define pm_suspend_target_state (PM_SUSPEND_ON) |
| 25 | 25 | #endif |
| 26 | 26 | |
| 27 | +#define list_for_each_entry_rcu_locked(pos, head, member) \ | |
| 28 | + list_for_each_entry_rcu(pos, head, member, \ | |
| 29 | + srcu_read_lock_held(&wakeup_srcu)) | |
| 27 | 30 | /* |
| 28 | 31 | * If set, the suspend/hibernate code will abort transitions to a sleep state |
| 29 | 32 | * if wakeup events are registered during or immediately before the transition. |
| @@ -241,7 +244,9 @@ void wakeup_source_unregister(struct wakeup_source *ws) · 211 unmodified lines | ||
| 241 | 244 | { |
| 242 | 245 | if (ws) { |
| 243 | 246 | wakeup_source_remove(ws); |
| 244 | − wakeup_source_sysfs_remove(ws); | |
| 247 | + if (ws->dev) | |
| 248 | + wakeup_source_sysfs_remove(ws); | |
| 249 | + | |
| 245 | 250 | wakeup_source_destroy(ws); |
| 246 | 251 | } |
| 247 | 252 | } |
| @@ -405,7 +410,7 @@ void device_wakeup_arm_wake_irqs(void) · 157 unmodified lines | ||
| 405 | 410 | int srcuidx; |
| 406 | 411 | |
| 407 | 412 | srcuidx = srcu_read_lock(&wakeup_srcu); |
| 408 | − list_for_each_entry_rcu(ws, &wakeup_sources, entry) | |
| 413 | + list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) | |
| 409 | 414 | dev_pm_arm_wake_irq(ws->wakeirq); |
| 410 | 415 | srcu_read_unlock(&wakeup_srcu, srcuidx); |
| 411 | 416 | } |
| @@ -421,7 +426,7 @@ void device_wakeup_disarm_wake_irqs(void) · 9 unmodified lines | ||
| 421 | 426 | int srcuidx; |
| 422 | 427 | |
| 423 | 428 | srcuidx = srcu_read_lock(&wakeup_srcu); |
| 424 | − list_for_each_entry_rcu(ws, &wakeup_sources, entry) | |
| 429 | + list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) | |
| 425 | 430 | dev_pm_disarm_wake_irq(ws->wakeirq); |
| 426 | 431 | srcu_read_unlock(&wakeup_srcu, srcuidx); |
| 427 | 432 | } |
| @@ -874,7 +879,7 @@ void pm_print_active_wakeup_sources(void) · 446 unmodified lines | ||
| 874 | 879 | struct wakeup_source *last_activity_ws = NULL; |
| 875 | 880 | |
| 876 | 881 | srcuidx = srcu_read_lock(&wakeup_srcu); |
| 877 | − list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | |
| 882 | + list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) { | |
| 878 | 883 | if (ws->active) { |
| 879 | 884 | pm_pr_dbg("active wakeup source: %s\n", ws->name); |
| 880 | 885 | active = 1; |
| @@ -1025,7 +1030,7 @@ void pm_wakep_autosleep_enabled(bool set) · 144 unmodified lines | ||
| 1025 | 1030 | int srcuidx; |
| 1026 | 1031 | |
| 1027 | 1032 | srcuidx = srcu_read_lock(&wakeup_srcu); |
| 1028 | − list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | |
| 1033 | + list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) { | |
| 1029 | 1034 | spin_lock_irq(&ws->lock); |
| 1030 | 1035 | if (ws->autosleep_enabled != set) { |
| 1031 | 1036 | ws->autosleep_enabled = set; |
| @@ -1104,7 +1109,7 @@ static void *wakeup_sources_stats_seq_start(struct seq_file *m, · 72 unmodified lines | ||
| 1104 | 1109 | } |
| 1105 | 1110 | |
| 1106 | 1111 | *srcuidx = srcu_read_lock(&wakeup_srcu); |
| 1107 | − list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | |
| 1112 | + list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) { | |
| 1108 | 1113 | if (n-- <= 0) |
| 1109 | 1114 | return ws; |
| 1110 | 1115 | } |
| @@ -160,6 +160,29 @@ int __init psci_dt_parse_state_node(struct device_node *np, u32 *state) · 159 unmodified lines | ||
| 160 | 160 | return 0; |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | +static int __init psci_dt_cpu_init_topology(struct cpuidle_driver *drv, | |
| 164 | + struct psci_cpuidle_data *data, | |
| 165 | + unsigned int state_count, int cpu) | |
| 166 | +{ | |
| 167 | + /* Currently limit the hierarchical topology to be used in OSI mode. */ | |
| 168 | + if (!psci_has_osi_support()) | |
| 169 | + return 0; | |
| 170 | + | |
| 171 | + data->dev = psci_dt_attach_cpu(cpu); | |
| 172 | + if (IS_ERR_OR_NULL(data->dev)) | |
| 173 | + return PTR_ERR_OR_ZERO(data->dev); | |
| 174 | + | |
| 175 | + /* | |
| 176 | + * Using the deepest state for the CPU to trigger a potential selection | |
| 177 | + * of a shared state for the domain, assumes the domain states are all | |
| 178 | + * deeper states. | |
| 179 | + */ | |
| 180 | + drv->states[state_count - 1].enter = psci_enter_domain_idle_state; | |
| 181 | + psci_cpuidle_use_cpuhp = true; | |
| 182 | + | |
| 183 | + return 0; | |
| 184 | +} | |
| 185 | + | |
| 163 | 186 | static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv, |
| 164 | 187 | struct device_node *cpu_node, |
| 165 | 188 | unsigned int state_count, int cpu) |
| @@ -193,25 +216,10 @@ static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv, · 27 unmodified lines | ||
| 193 | 216 | goto free_mem; |
| 194 | 217 | } |
| 195 | 218 | |
| 196 | − /* Currently limit the hierarchical topology to be used in OSI mode. */ | |
| 197 | − if (psci_has_osi_support()) { | |
| 198 | − data->dev = psci_dt_attach_cpu(cpu); | |
| 199 | − if (IS_ERR(data->dev)) { | |
| 200 | − ret = PTR_ERR(data->dev); | |
| 201 | − goto free_mem; | |
| 202 | − } | |
| 203 | − | |
| 204 | − /* | |
| 205 | − * Using the deepest state for the CPU to trigger a potential | |
| 206 | − * selection of a shared state for the domain, assumes the | |
| 207 | − * domain states are all deeper states. | |
| 208 | − */ | |
| 209 | − if (data->dev) { | |
| 210 | − drv->states[state_count - 1].enter = | |
| 211 | − psci_enter_domain_idle_state; | |
| 212 | − psci_cpuidle_use_cpuhp = true; | |
| 213 | − } | |
| 214 | − } | |
| 219 | + /* Initialize optional data, used for the hierarchical topology. */ | |
| 220 | + ret = psci_dt_cpu_init_topology(drv, data, state_count, cpu); | |
| 221 | + if (ret < 0) | |
| 222 | + goto free_mem; | |
| 215 | 223 | |
| 216 | 224 | /* Idle states parsed correctly, store them in the per-cpu struct. */ |
| 217 | 225 | data->psci_states = psci_states; |
| @@ -752,7 +752,7 @@ ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u3 · 751 unmodified lines | ||
| 752 | 752 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) |
| 753 | 753 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) |
| 754 | 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 | +ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(u32 gpe_skip_number)) | |
| 756 | 756 | ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void)) |
| 757 | 757 | |
| 758 | 758 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status |
| @@ -38,7 +38,7 @@ extern int pm_runtime_force_resume(struct device *dev); · 37 unmodified lines | ||
| 38 | 38 | extern int __pm_runtime_idle(struct device *dev, int rpmflags); |
| 39 | 39 | extern int __pm_runtime_suspend(struct device *dev, int rpmflags); |
| 40 | 40 | extern int __pm_runtime_resume(struct device *dev, int rpmflags); |
| 41 | −extern int pm_runtime_get_if_in_use(struct device *dev); | |
| 41 | +extern int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count); | |
| 42 | 42 | extern int pm_schedule_suspend(struct device *dev, unsigned int delay); |
| 43 | 43 | extern int __pm_runtime_set_status(struct device *dev, unsigned int status); |
| 44 | 44 | extern int pm_runtime_barrier(struct device *dev); |
| @@ -60,6 +60,11 @@ extern void pm_runtime_put_suppliers(struct device *dev); · 15 unmodified lines | ||
| 60 | 60 | extern void pm_runtime_new_link(struct device *dev); |
| 61 | 61 | extern void pm_runtime_drop_link(struct device *dev); |
| 62 | 62 | |
| 63 | +static inline int pm_runtime_get_if_in_use(struct device *dev) | |
| 64 | +{ | |
| 65 | + return pm_runtime_get_if_active(dev, false); | |
| 66 | +} | |
| 67 | + | |
| 63 | 68 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) |
| 64 | 69 | { |
| 65 | 70 | dev->power.ignore_children = enable; |
| @@ -143,6 +148,11 @@ static inline int pm_runtime_get_if_in_use(struct device *dev) · 77 unmodified lines | ||
| 143 | 148 | { |
| 144 | 149 | return -EINVAL; |
| 145 | 150 | } |
| 151 | +static inline int pm_runtime_get_if_active(struct device *dev, | |
| 152 | + bool ign_usage_count) | |
| 153 | +{ | |
| 154 | + return -EINVAL; | |
| 155 | +} | |
| 146 | 156 | static inline int __pm_runtime_set_status(struct device *dev, |
| 147 | 157 | unsigned int status) { return 0; } |
| 148 | 158 | static inline int pm_runtime_barrier(struct device *dev) { return 0; } |
| @@ -409,21 +409,7 @@ snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 408 unmodified lines | ||
| 409 | 409 | switch (cmd) { |
| 410 | 410 | case SNAPSHOT_GET_IMAGE_SIZE: |
| 411 | 411 | case SNAPSHOT_AVAIL_SWAP_SIZE: |
| 412 | − case SNAPSHOT_ALLOC_SWAP_PAGE: { | |
| 413 | − compat_loff_t __user *uoffset = compat_ptr(arg); | |
| 414 | − loff_t offset; | |
| 415 | − mm_segment_t old_fs; | |
| 416 | − int err; | |
| 417 | − | |
| 418 | − old_fs = get_fs(); | |
| 419 | − set_fs(KERNEL_DS); | |
| 420 | − err = snapshot_ioctl(file, cmd, (unsigned long) &offset); | |
| 421 | − set_fs(old_fs); | |
| 422 | − if (!err && put_user(offset, uoffset)) | |
| 423 | − err = -EFAULT; | |
| 424 | − return err; | |
| 425 | − } | |
| 426 | − | |
| 412 | + case SNAPSHOT_ALLOC_SWAP_PAGE: | |
| 427 | 413 | case SNAPSHOT_CREATE_IMAGE: |
| 428 | 414 | return snapshot_ioctl(file, cmd, |
| 429 | 415 | (unsigned long) compat_ptr(arg)); |