* 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 | nonzero, increment the counter and return 1; otherwise return 0 without | 382 | nonzero, increment the counter and return 1; otherwise return 0 without |
| 383 | changing the counter | 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 | `void pm_runtime_put_noidle(struct device *dev);` | 391 | `void pm_runtime_put_noidle(struct device *dev);` |
| 386 | - decrement the device's usage counter | 392 | - decrement the device's usage counter |
| 387 | 393 | ||
| @@ -69,11 +69,13 @@ SNAPSHOT_PREF_IMAGE_SIZE · 68 unmodified lines | |||
| 69 | 69 | ||
| 70 | SNAPSHOT_GET_IMAGE_SIZE | 70 | SNAPSHOT_GET_IMAGE_SIZE |
| 71 | return the actual size of the hibernation image | 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 | SNAPSHOT_AVAIL_SWAP_SIZE | 75 | SNAPSHOT_AVAIL_SWAP_SIZE |
| 74 | return the amount of available swap in bytes (the | 76 | return the amount of available swap in bytes |
| 75 | last argument should be a pointer to an unsigned int variable that will | 77 | (the last argument should be a pointer to a loff_t variable that |
| 76 | contain the result if the call is successful). | 78 | will contain the result if the call is successful) |
| 77 | 79 | ||
| 78 | SNAPSHOT_ALLOC_SWAP_PAGE | 80 | SNAPSHOT_ALLOC_SWAP_PAGE |
| 79 | allocate a swap page from the resume partition | 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 | 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); | 104 | u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number); |
| 105 | 105 | ||
| 106 | acpi_status | 106 | acpi_status |
| 107 | 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, |
| @@ -799,17 +799,19 @@ ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes) · 798 unmodified lines | |||
| 799 | * | 799 | * |
| 800 | * FUNCTION: acpi_any_gpe_status_set | 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 | * RETURN: Whether or not the status bit is set for any GPE | 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 | 806 | * DESCRIPTION: Check the status bits of all enabled GPEs, except for the one |
| 807 | * of them is set or FALSE otherwise. | 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 | acpi_status status; | 813 | acpi_status status; |
| 814 | acpi_handle gpe_device; | ||
| 813 | u8 ret; | 815 | u8 ret; |
| 814 | 816 | ||
| 815 | ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set); | 817 | ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set); |
| @@ -819,7 +821,12 @@ u32 acpi_any_gpe_status_set(void) · 3 unmodified lines | |||
| 819 | return (FALSE); | 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 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 830 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
| 824 | 831 | ||
| 825 | return (ret); | 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 | return (AE_OK); | 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 | * FUNCTION: acpi_hw_get_gpe_block_status | 455 | * FUNCTION: acpi_hw_get_gpe_block_status |
| 450 | * | 456 | * |
| 451 | * PARAMETERS: gpe_xrupt_info - GPE Interrupt info | 457 | * PARAMETERS: gpe_xrupt_info - GPE Interrupt info |
| 452 | * gpe_block - Gpe Block info | 458 | * gpe_block - Gpe Block info |
| 459 | * context - GPE list walk context data | ||
| 453 | * | 460 | * |
| 454 | * RETURN: Success | 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 | static acpi_status | 467 | static acpi_status |
| 461 | acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | 468 | acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
| 462 | struct acpi_gpe_block_info *gpe_block, | 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 | struct acpi_gpe_register_info *gpe_register_info; | 473 | struct acpi_gpe_register_info *gpe_register_info; |
| 466 | u64 in_enable, in_status; | 474 | u64 in_enable, in_status; |
| 467 | acpi_status status; | 475 | acpi_status status; |
| 468 | u8 *ret = ret_ptr; | 476 | u8 ret_mask; |
| 469 | u32 i; | 477 | u32 i; |
| 470 | 478 | ||
| 471 | /* Examine each GPE Register within the block */ | 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 | continue; | 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 | return (AE_OK); | 503 | return (AE_OK); |
| @@ -561,24 +573,41 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void) · 69 unmodified lines | |||
| 561 | * | 573 | * |
| 562 | * FUNCTION: acpi_hw_check_all_gpes | 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 | * RETURN: Combined status of all GPEs | 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 | * status bit is set for at least one of them of FALSE otherwise. | 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 | ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes); | 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 | #endif /* !ACPI_REDUCED_HARDWARE */ | 613 | #endif /* !ACPI_REDUCED_HARDWARE */ |
| @@ -2037,6 +2037,11 @@ void acpi_ec_set_gpe_wake_mask(u8 action) · 2036 unmodified lines | |||
| 2037 | acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); | 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 | bool acpi_ec_dispatch_gpe(void) | 2045 | bool acpi_ec_dispatch_gpe(void) |
| 2041 | { | 2046 | { |
| 2042 | u32 ret; | 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 | #ifdef CONFIG_PM_SLEEP | 203 | #ifdef CONFIG_PM_SLEEP |
| 204 | void acpi_ec_flush_work(void); | 204 | void acpi_ec_flush_work(void); |
| 205 | bool acpi_ec_other_gpes_active(void); | ||
| 205 | bool acpi_ec_dispatch_gpe(void); | 206 | bool acpi_ec_dispatch_gpe(void); |
| 206 | #endif | 207 | #endif |
| 207 | 208 | ||
| @@ -982,10 +982,7 @@ static int acpi_s2idle_prepare_late(void) · 981 unmodified lines | |||
| 982 | 982 | ||
| 983 | static void acpi_s2idle_sync(void) | 983 | static void acpi_s2idle_sync(void) |
| 984 | { | 984 | { |
| 985 | /* | 985 | /* The EC driver uses special workqueues that need to be flushed. */ |
| 986 | * The EC driver uses the system workqueue and an additional special | ||
| 987 | * one, so those need to be flushed too. | ||
| 988 | */ | ||
| 989 | acpi_ec_flush_work(); | 986 | acpi_ec_flush_work(); |
| 990 | acpi_os_wait_events_complete(); /* synchronize Notify handling */ | 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 | return true; | 1010 | return true; |
| 1014 | 1011 | ||
| 1015 | /* | 1012 | /* |
| 1016 | * If there are no EC events to process and at least one of the | 1013 | * If the status bit is set for any enabled GPE other than the |
| 1017 | * other enabled GPEs is active, the wakeup is regarded as a | 1014 | * EC one, the wakeup is regarded as a genuine one. |
| 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. | ||
| 1024 | */ | 1015 | */ |
| 1025 | if (acpi_any_gpe_status_set() && !acpi_ec_dispatch_gpe()) | 1016 | if (acpi_ec_other_gpes_active()) |
| 1026 | return true; | 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 | * Cancel the wakeup and process all pending events in case | 1027 | * Cancel the wakeup and process all pending events in case |
| 1030 | * there are any wakeup ones in there. | 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 | ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); | 2654 | ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); |
| 2655 | if (ret <= 0) | 2655 | if (ret <= 0) |
| 2656 | return ret; | 2656 | return ret == -ENOENT ? 0 : ret; |
| 2657 | 2657 | ||
| 2658 | /* Loop over the phandles until all the requested entry is found */ | 2658 | /* Loop over the phandles until all the requested entry is found */ |
| 2659 | of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { | 2659 | of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { |
| @@ -40,6 +40,10 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | typedef int (*pm_callback_t)(struct device *); | 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 | * The entries in the dpm_list list are in a depth first order, simply | 48 | * The entries in the dpm_list list are in a depth first order, simply |
| 45 | * because children are guaranteed to be discovered after parents, and | 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 | * callbacks freeing the link objects for the links in the list we're | 270 | * callbacks freeing the link objects for the links in the list we're |
| 267 | * walking. | 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 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) | 274 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 271 | dpm_wait(link->supplier, async); | 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 | * continue instead of trying to continue in parallel with its | 327 | * continue instead of trying to continue in parallel with its |
| 324 | * unregistration). | 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 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) | 331 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 328 | dpm_wait(link->consumer, async); | 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 | idx = device_links_read_lock(); | 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 | link->supplier->power.must_resume = true; | 1243 | link->supplier->power.must_resume = true; |
| 1240 | 1244 | ||
| 1241 | device_links_read_unlock(idx); | 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 | idx = device_links_read_lock(); | 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 | spin_lock_irq(&link->supplier->power.lock); | 1703 | spin_lock_irq(&link->supplier->power.lock); |
| 1700 | link->supplier->power.direct_complete = false; | 1704 | link->supplier->power.direct_complete = false; |
| 1701 | spin_unlock_irq(&link->supplier->power.lock); | 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 | EXPORT_SYMBOL_GPL(__pm_runtime_resume); | 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 | * @dev: Device to handle. | 1091 | * @dev: Device to handle. |
| 1092 | * | 1092 | * |
| 1093 | * Return -EINVAL if runtime PM is disabled for the device. | 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 | 1095 | * Otherwise, if the device's runtime PM status is RPM_ACTIVE and either |
| 1096 | * and the runtime PM usage counter is nonzero, increment the counter and | 1096 | * ign_usage_count is true or the device's usage_count is non-zero, increment |
| 1097 | * return 1. Otherwise return 0 without changing the counter. | 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 | unsigned long flags; | 1111 | unsigned long flags; |
| 1102 | int retval; | 1112 | int retval; |
| 1103 | 1113 | ||
| 1104 | spin_lock_irqsave(&dev->power.lock, flags); | 1114 | spin_lock_irqsave(&dev->power.lock, flags); |
| 1105 | retval = dev->power.disable_depth > 0 ? -EINVAL : | 1115 | if (dev->power.disable_depth > 0) { |
| 1106 | dev->power.runtime_status == RPM_ACTIVE | 1116 | retval = -EINVAL; |
| 1107 | && atomic_inc_not_zero(&dev->power.usage_count); | 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 | trace_rpm_usage_rcuidle(dev, 0); | 1125 | trace_rpm_usage_rcuidle(dev, 0); |
| 1109 | spin_unlock_irqrestore(&dev->power.lock, flags); | 1126 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 1127 | |||
| 1110 | return retval; | 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 | * __pm_runtime_set_status - Set runtime PM status of a device. | 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 | #define pm_suspend_target_state (PM_SUSPEND_ON) | 24 | #define pm_suspend_target_state (PM_SUSPEND_ON) |
| 25 | #endif | 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 | * If set, the suspend/hibernate code will abort transitions to a sleep state | 31 | * If set, the suspend/hibernate code will abort transitions to a sleep state |
| 29 | * if wakeup events are registered during or immediately before the transition. | 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 | if (ws) { | 245 | if (ws) { |
| 243 | wakeup_source_remove(ws); | 246 | wakeup_source_remove(ws); |
| 244 | wakeup_source_sysfs_remove(ws); | 247 | if (ws->dev) |
| 248 | wakeup_source_sysfs_remove(ws); | ||
| 249 | |||
| 245 | wakeup_source_destroy(ws); | 250 | wakeup_source_destroy(ws); |
| 246 | } | 251 | } |
| 247 | } | 252 | } |
| @@ -405,7 +410,7 @@ void device_wakeup_arm_wake_irqs(void) · 157 unmodified lines | |||
| 405 | int srcuidx; | 410 | int srcuidx; |
| 406 | 411 | ||
| 407 | srcuidx = srcu_read_lock(&wakeup_srcu); | 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 | dev_pm_arm_wake_irq(ws->wakeirq); | 414 | dev_pm_arm_wake_irq(ws->wakeirq); |
| 410 | srcu_read_unlock(&wakeup_srcu, srcuidx); | 415 | srcu_read_unlock(&wakeup_srcu, srcuidx); |
| 411 | } | 416 | } |
| @@ -421,7 +426,7 @@ void device_wakeup_disarm_wake_irqs(void) · 9 unmodified lines | |||
| 421 | int srcuidx; | 426 | int srcuidx; |
| 422 | 427 | ||
| 423 | srcuidx = srcu_read_lock(&wakeup_srcu); | 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 | dev_pm_disarm_wake_irq(ws->wakeirq); | 430 | dev_pm_disarm_wake_irq(ws->wakeirq); |
| 426 | srcu_read_unlock(&wakeup_srcu, srcuidx); | 431 | srcu_read_unlock(&wakeup_srcu, srcuidx); |
| 427 | } | 432 | } |
| @@ -874,7 +879,7 @@ void pm_print_active_wakeup_sources(void) · 446 unmodified lines | |||
| 874 | struct wakeup_source *last_activity_ws = NULL; | 879 | struct wakeup_source *last_activity_ws = NULL; |
| 875 | 880 | ||
| 876 | srcuidx = srcu_read_lock(&wakeup_srcu); | 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 | if (ws->active) { | 883 | if (ws->active) { |
| 879 | pm_pr_dbg("active wakeup source: %s\n", ws->name); | 884 | pm_pr_dbg("active wakeup source: %s\n", ws->name); |
| 880 | active = 1; | 885 | active = 1; |
| @@ -1025,7 +1030,7 @@ void pm_wakep_autosleep_enabled(bool set) · 144 unmodified lines | |||
| 1025 | int srcuidx; | 1030 | int srcuidx; |
| 1026 | 1031 | ||
| 1027 | srcuidx = srcu_read_lock(&wakeup_srcu); | 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 | spin_lock_irq(&ws->lock); | 1034 | spin_lock_irq(&ws->lock); |
| 1030 | if (ws->autosleep_enabled != set) { | 1035 | if (ws->autosleep_enabled != set) { |
| 1031 | ws->autosleep_enabled = set; | 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 | *srcuidx = srcu_read_lock(&wakeup_srcu); | 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 | if (n-- <= 0) | 1113 | if (n-- <= 0) |
| 1109 | return ws; | 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 | return 0; | 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 | static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv, | 186 | static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv, |
| 164 | struct device_node *cpu_node, | 187 | struct device_node *cpu_node, |
| 165 | unsigned int state_count, int cpu) | 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 | goto free_mem; | 216 | goto free_mem; |
| 194 | } | 217 | } |
| 195 | 218 | ||
| 196 | /* Currently limit the hierarchical topology to be used in OSI mode. */ | 219 | /* Initialize optional data, used for the hierarchical topology. */ |
| 197 | if (psci_has_osi_support()) { | 220 | ret = psci_dt_cpu_init_topology(drv, data, state_count, cpu); |
| 198 | data->dev = psci_dt_attach_cpu(cpu); | 221 | if (ret < 0) |
| 199 | if (IS_ERR(data->dev)) { | 222 | goto free_mem; |
| 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 | } | ||
| 215 | 223 | ||
| 216 | /* Idle states parsed correctly, store them in the per-cpu struct. */ | 224 | /* Idle states parsed correctly, store them in the per-cpu struct. */ |
| 217 | data->psci_states = psci_states; | 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 | 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 | ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(u32 gpe_skip_number)) |
| 756 | ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void)) | 756 | ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void)) |
| 757 | 757 | ||
| 758 | ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status | 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 | extern int __pm_runtime_idle(struct device *dev, int rpmflags); | 38 | extern int __pm_runtime_idle(struct device *dev, int rpmflags); |
| 39 | extern int __pm_runtime_suspend(struct device *dev, int rpmflags); | 39 | extern int __pm_runtime_suspend(struct device *dev, int rpmflags); |
| 40 | extern int __pm_runtime_resume(struct device *dev, int rpmflags); | 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 | extern int pm_schedule_suspend(struct device *dev, unsigned int delay); | 42 | extern int pm_schedule_suspend(struct device *dev, unsigned int delay); |
| 43 | extern int __pm_runtime_set_status(struct device *dev, unsigned int status); | 43 | extern int __pm_runtime_set_status(struct device *dev, unsigned int status); |
| 44 | extern int pm_runtime_barrier(struct device *dev); | 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 | extern void pm_runtime_new_link(struct device *dev); | 60 | extern void pm_runtime_new_link(struct device *dev); |
| 61 | extern void pm_runtime_drop_link(struct device *dev); | 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 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) | 68 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) |
| 64 | { | 69 | { |
| 65 | dev->power.ignore_children = enable; | 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 | return -EINVAL; | 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 | static inline int __pm_runtime_set_status(struct device *dev, | 156 | static inline int __pm_runtime_set_status(struct device *dev, |
| 147 | unsigned int status) { return 0; } | 157 | unsigned int status) { return 0; } |
| 148 | static inline int pm_runtime_barrier(struct device *dev) { return 0; } | 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 | switch (cmd) { | 409 | switch (cmd) { |
| 410 | case SNAPSHOT_GET_IMAGE_SIZE: | 410 | case SNAPSHOT_GET_IMAGE_SIZE: |
| 411 | case SNAPSHOT_AVAIL_SWAP_SIZE: | 411 | case SNAPSHOT_AVAIL_SWAP_SIZE: |
| 412 | case SNAPSHOT_ALLOC_SWAP_PAGE: { | 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 | |||
| 427 | case SNAPSHOT_CREATE_IMAGE: | 413 | case SNAPSHOT_CREATE_IMAGE: |
| 428 | return snapshot_ioctl(file, cmd, | 414 | return snapshot_ioctl(file, cmd, |
| 429 | (unsigned long) compat_ptr(arg)); | 415 | (unsigned long) compat_ptr(arg)); |