Merge cpuidle updates, PM core updates and one hiberation-related update for 5.17-rc1: - Make cpuidle use default_groups in kobj_type (Greg Kroah-Hartman). - Fix two comments in cpuidle code (Jason Wang, Yang Li). - Simplify locking in pm_runtime_put_suppliers() (Rafael Wysocki). - Add safety net to supplier device release in the runtime PM core code (Rafael Wysocki). - Capture device status before disabling runtime PM for it (Rafael Wysocki). - Add new macros for declaring PM operations to allow drivers to avoid guarding them with CONFIG_PM #ifdefs or __maybe_unused and update some drivers to use these macros (Paul Cercueil). - Allow ACPI hardware signature to be honoured during restore from hibernation (David Woodhouse). * pm-cpuidle: cpuidle: use default_groups in kobj_type cpuidle: Fix cpuidle_remove_state_sysfs() kerneldoc comment cpuidle: menu: Fix typo in a comment * pm-core: PM: runtime: Simplify locking in pm_runtime_put_suppliers() mmc: mxc: Use the new PM macros mmc: jz4740: Use the new PM macros PM: runtime: Add safety net to supplier device release PM: runtime: Capture device status before disabling runtime PM PM: core: Add new *_PM_OPS macros, deprecate old ones PM: core: Redefine pm_ptr() macro r8169: Avoid misuse of pm_ptr() macro * pm-sleep: PM: hibernate: Allow ACPI hardware signature to be honoured
Unified · Split
| @@ -225,14 +225,23 @@ · 224 unmodified lines | ||
| 225 | 225 | For broken nForce2 BIOS resulting in XT-PIC timer. |
| 226 | 226 | |
| 227 | 227 | acpi_sleep= [HW,ACPI] Sleep options |
| 228 | − Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, | |
| 229 | − old_ordering, nonvs, sci_force_enable, nobl } | |
| 228 | + Format: { s3_bios, s3_mode, s3_beep, s4_hwsig, | |
| 229 | + s4_nohwsig, old_ordering, nonvs, | |
| 230 | + sci_force_enable, nobl } | |
| 230 | 231 | See Documentation/power/video.rst for information on |
| 231 | 232 | s3_bios and s3_mode. |
| 232 | 233 | s3_beep is for debugging; it makes the PC's speaker beep |
| 233 | 234 | as soon as the kernel's real-mode entry point is called. |
| 235 | + s4_hwsig causes the kernel to check the ACPI hardware | |
| 236 | + signature during resume from hibernation, and gracefully | |
| 237 | + refuse to resume if it has changed. This complies with | |
| 238 | + the ACPI specification but not with reality, since | |
| 239 | + Windows does not do this and many laptops do change it | |
| 240 | + on docking. So the default behaviour is to allow resume | |
| 241 | + and simply warn when the signature changes, unless the | |
| 242 | + s4_hwsig option is enabled. | |
| 234 | 243 | s4_nohwsig prevents ACPI hardware signature from being |
| 235 | − used during resume from hibernation. | |
| 244 | + used (or even warned about) during resume. | |
| 236 | 245 | old_ordering causes the ACPI 1.0 ordering of the _PTS |
| 237 | 246 | control method, with respect to putting devices into |
| 238 | 247 | low power states, to be enforced (the ACPI 2.0 ordering |
| @@ -265,6 +265,10 @@ defined in include/linux/pm.h: · 264 unmodified lines | ||
| 265 | 265 | RPM_SUSPENDED, which means that each device is initially regarded by the |
| 266 | 266 | PM core as 'suspended', regardless of its real hardware status |
| 267 | 267 | |
| 268 | + `enum rpm_status last_status;` | |
| 269 | + - the last runtime PM status of the device captured before disabling runtime | |
| 270 | + PM for it (invalid initially and when disable_depth is 0) | |
| 271 | + | |
| 268 | 272 | `unsigned int runtime_auto;` |
| 269 | 273 | - if set, indicates that the user space has allowed the device driver to |
| 270 | 274 | power manage the device at run time via the /sys/devices/.../power/control |
| @@ -333,10 +337,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: · 62 unmodified lines | ||
| 333 | 337 | |
| 334 | 338 | `int pm_runtime_resume(struct device *dev);` |
| 335 | 339 | - execute the subsystem-level resume callback for the device; returns 0 on |
| 336 | − success, 1 if the device's runtime PM status was already 'active' or | |
| 337 | − error code on failure, where -EAGAIN means it may be safe to attempt to | |
| 338 | − resume the device again in future, but 'power.runtime_error' should be | |
| 339 | − checked additionally, and -EACCES means that 'power.disable_depth' is | |
| 340 | + success, 1 if the device's runtime PM status is already 'active' (also if | |
| 341 | + 'power.disable_depth' is nonzero, but the status was 'active' when it was | |
| 342 | + changing from 0 to 1) or error code on failure, where -EAGAIN means it may | |
| 343 | + be safe to attempt to resume the device again in future, but | |
| 344 | + 'power.runtime_error' should be checked additionally, and -EACCES means | |
| 345 | + that the callback could not be run, because 'power.disable_depth' was | |
| 340 | 346 | different from 0 |
| 341 | 347 | |
| 342 | 348 | `int pm_runtime_resume_and_get(struct device *dev);` |
| @@ -139,8 +139,10 @@ static int __init acpi_sleep_setup(char *str) · 138 unmodified lines | ||
| 139 | 139 | if (strncmp(str, "s3_beep", 7) == 0) |
| 140 | 140 | acpi_realmode_flags |= 4; |
| 141 | 141 | #ifdef CONFIG_HIBERNATION |
| 142 | + if (strncmp(str, "s4_hwsig", 8) == 0) | |
| 143 | + acpi_check_s4_hw_signature(1); | |
| 142 | 144 | if (strncmp(str, "s4_nohwsig", 10) == 0) |
| 143 | − acpi_no_s4_hw_signature(); | |
| 145 | + acpi_check_s4_hw_signature(0); | |
| 144 | 146 | #endif |
| 145 | 147 | if (strncmp(str, "nonvs", 5) == 0) |
| 146 | 148 | acpi_nvs_nosave(); |
| @@ -877,11 +877,11 @@ static inline void acpi_sleep_syscore_init(void) {} · 876 unmodified lines | ||
| 877 | 877 | #ifdef CONFIG_HIBERNATION |
| 878 | 878 | static unsigned long s4_hardware_signature; |
| 879 | 879 | static struct acpi_table_facs *facs; |
| 880 | −static bool nosigcheck; | |
| 880 | +static int sigcheck = -1; /* Default behaviour is just to warn */ | |
| 881 | 881 | |
| 882 | −void __init acpi_no_s4_hw_signature(void) | |
| 882 | +void __init acpi_check_s4_hw_signature(int check) | |
| 883 | 883 | { |
| 884 | − nosigcheck = true; | |
| 884 | + sigcheck = check; | |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | 887 | static int acpi_hibernation_begin(pm_message_t stage) |
| @@ -1009,12 +1009,28 @@ static void acpi_sleep_hibernate_setup(void) · 121 unmodified lines | ||
| 1009 | 1009 | hibernation_set_ops(old_suspend_ordering ? |
| 1010 | 1010 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
| 1011 | 1011 | sleep_states[ACPI_STATE_S4] = 1; |
| 1012 | − if (nosigcheck) | |
| 1012 | + if (!sigcheck) | |
| 1013 | 1013 | return; |
| 1014 | 1014 | |
| 1015 | 1015 | acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); |
| 1016 | − if (facs) | |
| 1016 | + if (facs) { | |
| 1017 | + /* | |
| 1018 | + * s4_hardware_signature is the local variable which is just | |
| 1019 | + * used to warn about mismatch after we're attempting to | |
| 1020 | + * resume (in violation of the ACPI specification.) | |
| 1021 | + */ | |
| 1017 | 1022 | s4_hardware_signature = facs->hardware_signature; |
| 1023 | + | |
| 1024 | + if (sigcheck > 0) { | |
| 1025 | + /* | |
| 1026 | + * If we're actually obeying the ACPI specification | |
| 1027 | + * then the signature is written out as part of the | |
| 1028 | + * swsusp header, in order to allow the boot kernel | |
| 1029 | + * to gracefully decline to resume. | |
| 1030 | + */ | |
| 1031 | + swsusp_hardware_signature = facs->hardware_signature; | |
| 1032 | + } | |
| 1033 | + } | |
| 1018 | 1034 | } |
| 1019 | 1035 | #else /* !CONFIG_HIBERNATION */ |
| 1020 | 1036 | static inline void acpi_sleep_hibernate_setup(void) {} |
| @@ -485,8 +485,7 @@ static void device_link_release_fn(struct work_struct *work) · 484 unmodified lines | ||
| 485 | 485 | /* Ensure that all references to the link object have been dropped. */ |
| 486 | 486 | device_link_synchronize_removal(); |
| 487 | 487 | |
| 488 | − while (refcount_dec_not_one(&link->rpm_active)) | |
| 489 | − pm_runtime_put(link->supplier); | |
| 488 | + pm_runtime_release_supplier(link, true); | |
| 490 | 489 | |
| 491 | 490 | put_device(link->consumer); |
| 492 | 491 | put_device(link->supplier); |
| @@ -305,19 +305,40 @@ static int rpm_get_suppliers(struct device *dev) · 304 unmodified lines | ||
| 305 | 305 | return 0; |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | +/** | |
| 309 | + * pm_runtime_release_supplier - Drop references to device link's supplier. | |
| 310 | + * @link: Target device link. | |
| 311 | + * @check_idle: Whether or not to check if the supplier device is idle. | |
| 312 | + * | |
| 313 | + * Drop all runtime PM references associated with @link to its supplier device | |
| 314 | + * and if @check_idle is set, check if that device is idle (and so it can be | |
| 315 | + * suspended). | |
| 316 | + */ | |
| 317 | +void pm_runtime_release_supplier(struct device_link *link, bool check_idle) | |
| 318 | +{ | |
| 319 | + struct device *supplier = link->supplier; | |
| 320 | + | |
| 321 | + /* | |
| 322 | + * The additional power.usage_count check is a safety net in case | |
| 323 | + * the rpm_active refcount becomes saturated, in which case | |
| 324 | + * refcount_dec_not_one() would return true forever, but it is not | |
| 325 | + * strictly necessary. | |
| 326 | + */ | |
| 327 | + while (refcount_dec_not_one(&link->rpm_active) && | |
| 328 | + atomic_read(&supplier->power.usage_count) > 0) | |
| 329 | + pm_runtime_put_noidle(supplier); | |
| 330 | + | |
| 331 | + if (check_idle) | |
| 332 | + pm_request_idle(supplier); | |
| 333 | +} | |
| 334 | + | |
| 308 | 335 | static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend) |
| 309 | 336 | { |
| 310 | 337 | struct device_link *link; |
| 311 | 338 | |
| 312 | 339 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, |
| 313 | − device_links_read_lock_held()) { | |
| 314 | − | |
| 315 | − while (refcount_dec_not_one(&link->rpm_active)) | |
| 316 | − pm_runtime_put_noidle(link->supplier); | |
| 317 | − | |
| 318 | − if (try_to_suspend) | |
| 319 | − pm_request_idle(link->supplier); | |
| 320 | − } | |
| 340 | + device_links_read_lock_held()) | |
| 341 | + pm_runtime_release_supplier(link, try_to_suspend); | |
| 321 | 342 | } |
| 322 | 343 | |
| 323 | 344 | static void rpm_put_suppliers(struct device *dev) |
| @@ -742,13 +763,15 @@ static int rpm_resume(struct device *dev, int rpmflags) · 418 unmodified lines | ||
| 742 | 763 | trace_rpm_resume_rcuidle(dev, rpmflags); |
| 743 | 764 | |
| 744 | 765 | repeat: |
| 745 | − if (dev->power.runtime_error) | |
| 766 | + if (dev->power.runtime_error) { | |
| 746 | 767 | retval = -EINVAL; |
| 747 | − else if (dev->power.disable_depth == 1 && dev->power.is_suspended | |
| 748 | − && dev->power.runtime_status == RPM_ACTIVE) | |
| 749 | − retval = 1; | |
| 750 | − else if (dev->power.disable_depth > 0) | |
| 751 | − retval = -EACCES; | |
| 768 | + } else if (dev->power.disable_depth > 0) { | |
| 769 | + if (dev->power.runtime_status == RPM_ACTIVE && | |
| 770 | + dev->power.last_status == RPM_ACTIVE) | |
| 771 | + retval = 1; | |
| 772 | + else | |
| 773 | + retval = -EACCES; | |
| 774 | + } | |
| 752 | 775 | if (retval) |
| 753 | 776 | goto out; |
| 754 | 777 | |
| @@ -1410,8 +1433,10 @@ void __pm_runtime_disable(struct device *dev, bool check_resume) · 655 unmodified lines | ||
| 1410 | 1433 | /* Update time accounting before disabling PM-runtime. */ |
| 1411 | 1434 | update_pm_runtime_accounting(dev); |
| 1412 | 1435 | |
| 1413 | − if (!dev->power.disable_depth++) | |
| 1436 | + if (!dev->power.disable_depth++) { | |
| 1414 | 1437 | __pm_runtime_barrier(dev); |
| 1438 | + dev->power.last_status = dev->power.runtime_status; | |
| 1439 | + } | |
| 1415 | 1440 | |
| 1416 | 1441 | out: |
| 1417 | 1442 | spin_unlock_irq(&dev->power.lock); |
| @@ -1428,23 +1453,23 @@ void pm_runtime_enable(struct device *dev) · 10 unmodified lines | ||
| 1428 | 1453 | |
| 1429 | 1454 | spin_lock_irqsave(&dev->power.lock, flags); |
| 1430 | 1455 | |
| 1431 | − if (dev->power.disable_depth > 0) { | |
| 1432 | − dev->power.disable_depth--; | |
| 1433 | − | |
| 1434 | − /* About to enable runtime pm, set accounting_timestamp to now */ | |
| 1435 | − if (!dev->power.disable_depth) | |
| 1436 | − dev->power.accounting_timestamp = ktime_get_mono_fast_ns(); | |
| 1437 | − } else { | |
| 1456 | + if (!dev->power.disable_depth) { | |
| 1438 | 1457 | dev_warn(dev, "Unbalanced %s!\n", __func__); |
| 1458 | + goto out; | |
| 1439 | 1459 | } |
| 1440 | 1460 | |
| 1441 | − WARN(!dev->power.disable_depth && | |
| 1442 | − dev->power.runtime_status == RPM_SUSPENDED && | |
| 1443 | − !dev->power.ignore_children && | |
| 1444 | − atomic_read(&dev->power.child_count) > 0, | |
| 1445 | − "Enabling runtime PM for inactive device (%s) with active children\n", | |
| 1446 | − dev_name(dev)); | |
| 1461 | + if (--dev->power.disable_depth > 0) | |
| 1462 | + goto out; | |
| 1463 | + | |
| 1464 | + dev->power.last_status = RPM_INVALID; | |
| 1465 | + dev->power.accounting_timestamp = ktime_get_mono_fast_ns(); | |
| 1466 | + | |
| 1467 | + if (dev->power.runtime_status == RPM_SUSPENDED && | |
| 1468 | + !dev->power.ignore_children && | |
| 1469 | + atomic_read(&dev->power.child_count) > 0) | |
| 1470 | + dev_warn(dev, "Enabling runtime PM for inactive device with active children\n"); | |
| 1447 | 1471 | |
| 1472 | +out: | |
| 1448 | 1473 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 1449 | 1474 | } |
| 1450 | 1475 | EXPORT_SYMBOL_GPL(pm_runtime_enable); |
| @@ -1640,6 +1665,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend); · 189 unmodified lines | ||
| 1640 | 1665 | void pm_runtime_init(struct device *dev) |
| 1641 | 1666 | { |
| 1642 | 1667 | dev->power.runtime_status = RPM_SUSPENDED; |
| 1668 | + dev->power.last_status = RPM_INVALID; | |
| 1643 | 1669 | dev->power.idle_notification = false; |
| 1644 | 1670 | |
| 1645 | 1671 | dev->power.disable_depth = 1; |
| @@ -1722,8 +1748,6 @@ void pm_runtime_get_suppliers(struct device *dev) · 76 unmodified lines | ||
| 1722 | 1748 | void pm_runtime_put_suppliers(struct device *dev) |
| 1723 | 1749 | { |
| 1724 | 1750 | struct device_link *link; |
| 1725 | − unsigned long flags; | |
| 1726 | − bool put; | |
| 1727 | 1751 | int idx; |
| 1728 | 1752 | |
| 1729 | 1753 | idx = device_links_read_lock(); |
| @@ -1731,11 +1755,17 @@ void pm_runtime_put_suppliers(struct device *dev) · 1 unmodified line | ||
| 1731 | 1755 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, |
| 1732 | 1756 | device_links_read_lock_held()) |
| 1733 | 1757 | if (link->supplier_preactivated) { |
| 1758 | + bool put; | |
| 1759 | + | |
| 1734 | 1760 | link->supplier_preactivated = false; |
| 1735 | − spin_lock_irqsave(&dev->power.lock, flags); | |
| 1761 | + | |
| 1762 | + spin_lock_irq(&dev->power.lock); | |
| 1763 | + | |
| 1736 | 1764 | put = pm_runtime_status_suspended(dev) && |
| 1737 | 1765 | refcount_dec_not_one(&link->rpm_active); |
| 1738 | − spin_unlock_irqrestore(&dev->power.lock, flags); | |
| 1766 | + | |
| 1767 | + spin_unlock_irq(&dev->power.lock); | |
| 1768 | + | |
| 1739 | 1769 | if (put) |
| 1740 | 1770 | pm_runtime_put(link->supplier); |
| 1741 | 1771 | } |
| @@ -1772,9 +1802,7 @@ void pm_runtime_drop_link(struct device_link *link) · 30 unmodified lines | ||
| 1772 | 1802 | return; |
| 1773 | 1803 | |
| 1774 | 1804 | pm_runtime_drop_link_count(link->consumer); |
| 1775 | − | |
| 1776 | − while (refcount_dec_not_one(&link->rpm_active)) | |
| 1777 | − pm_runtime_put(link->supplier); | |
| 1805 | + pm_runtime_release_supplier(link, true); | |
| 1778 | 1806 | } |
| 1779 | 1807 | |
| 1780 | 1808 | static bool pm_runtime_need_not_resume(struct device *dev) |
| @@ -34,7 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | * 1) Energy break even point |
| 35 | 35 | * 2) Performance impact |
| 36 | 36 | * 3) Latency tolerance (from pmqos infrastructure) |
| 37 | − * These these three factors are treated independently. | |
| 37 | + * These three factors are treated independently. | |
| 38 | 38 | * |
| 39 | 39 | * Energy break even point |
| 40 | 40 | * ----------------------- |
| @@ -335,6 +335,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { · 334 unmodified lines | ||
| 335 | 335 | &attr_default_status.attr, |
| 336 | 336 | NULL |
| 337 | 337 | }; |
| 338 | +ATTRIBUTE_GROUPS(cpuidle_state_default); | |
| 338 | 339 | |
| 339 | 340 | struct cpuidle_state_kobj { |
| 340 | 341 | struct cpuidle_state *state; |
| @@ -448,7 +449,7 @@ static void cpuidle_state_sysfs_release(struct kobject *kobj) · 107 unmodified lines | ||
| 448 | 449 | |
| 449 | 450 | static struct kobj_type ktype_state_cpuidle = { |
| 450 | 451 | .sysfs_ops = &cpuidle_state_sysfs_ops, |
| 451 | − .default_attrs = cpuidle_state_default_attrs, | |
| 452 | + .default_groups = cpuidle_state_default_groups, | |
| 452 | 453 | .release = cpuidle_state_sysfs_release, |
| 453 | 454 | }; |
| 454 | 455 | |
| @@ -505,7 +506,7 @@ error_state: · 50 unmodified lines | ||
| 505 | 506 | } |
| 506 | 507 | |
| 507 | 508 | /** |
| 508 | − * cpuidle_remove_driver_sysfs - removes the cpuidle states sysfs attributes | |
| 509 | + * cpuidle_remove_state_sysfs - removes the cpuidle states sysfs attributes | |
| 509 | 510 | * @device: the target device |
| 510 | 511 | */ |
| 511 | 512 | static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) |
| @@ -591,10 +592,11 @@ static struct attribute *cpuidle_driver_default_attrs[] = { · 79 unmodified lines | ||
| 591 | 592 | &attr_driver_name.attr, |
| 592 | 593 | NULL |
| 593 | 594 | }; |
| 595 | +ATTRIBUTE_GROUPS(cpuidle_driver_default); | |
| 594 | 596 | |
| 595 | 597 | static struct kobj_type ktype_driver_cpuidle = { |
| 596 | 598 | .sysfs_ops = &cpuidle_driver_sysfs_ops, |
| 597 | − .default_attrs = cpuidle_driver_default_attrs, | |
| 599 | + .default_groups = cpuidle_driver_default_groups, | |
| 598 | 600 | .release = cpuidle_driver_sysfs_release, |
| 599 | 601 | }; |
| 600 | 602 | |
| @@ -1103,17 +1103,17 @@ static int jz4740_mmc_remove(struct platform_device *pdev) · 1102 unmodified lines | ||
| 1103 | 1103 | return 0; |
| 1104 | 1104 | } |
| 1105 | 1105 | |
| 1106 | −static int __maybe_unused jz4740_mmc_suspend(struct device *dev) | |
| 1106 | +static int jz4740_mmc_suspend(struct device *dev) | |
| 1107 | 1107 | { |
| 1108 | 1108 | return pinctrl_pm_select_sleep_state(dev); |
| 1109 | 1109 | } |
| 1110 | 1110 | |
| 1111 | −static int __maybe_unused jz4740_mmc_resume(struct device *dev) | |
| 1111 | +static int jz4740_mmc_resume(struct device *dev) | |
| 1112 | 1112 | { |
| 1113 | 1113 | return pinctrl_select_default_state(dev); |
| 1114 | 1114 | } |
| 1115 | 1115 | |
| 1116 | −static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, | |
| 1116 | +DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, | |
| 1117 | 1117 | jz4740_mmc_resume); |
| 1118 | 1118 | |
| 1119 | 1119 | static struct platform_driver jz4740_mmc_driver = { |
| @@ -1123,7 +1123,7 @@ static struct platform_driver jz4740_mmc_driver = { · 3 unmodified lines | ||
| 1123 | 1123 | .name = "jz4740-mmc", |
| 1124 | 1124 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| 1125 | 1125 | .of_match_table = of_match_ptr(jz4740_mmc_of_match), |
| 1126 | − .pm = pm_ptr(&jz4740_mmc_pm_ops), | |
| 1126 | + .pm = pm_sleep_ptr(&jz4740_mmc_pm_ops), | |
| 1127 | 1127 | }, |
| 1128 | 1128 | }; |
| 1129 | 1129 | |
| @@ -1183,7 +1183,6 @@ static int mxcmci_remove(struct platform_device *pdev) · 1182 unmodified lines | ||
| 1183 | 1183 | return 0; |
| 1184 | 1184 | } |
| 1185 | 1185 | |
| 1186 | −#ifdef CONFIG_PM_SLEEP | |
| 1187 | 1186 | static int mxcmci_suspend(struct device *dev) |
| 1188 | 1187 | { |
| 1189 | 1188 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| @@ -1210,9 +1209,8 @@ static int mxcmci_resume(struct device *dev) · 20 unmodified lines | ||
| 1210 | 1209 | |
| 1211 | 1210 | return ret; |
| 1212 | 1211 | } |
| 1213 | −#endif | |
| 1214 | 1212 | |
| 1215 | −static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); | |
| 1213 | +DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); | |
| 1216 | 1214 | |
| 1217 | 1215 | static struct platform_driver mxcmci_driver = { |
| 1218 | 1216 | .probe = mxcmci_probe, |
| @@ -1220,7 +1218,7 @@ static struct platform_driver mxcmci_driver = { · 1 unmodified line | ||
| 1220 | 1218 | .driver = { |
| 1221 | 1219 | .name = DRIVER_NAME, |
| 1222 | 1220 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| 1223 | − .pm = &mxcmci_pm_ops, | |
| 1221 | + .pm = pm_sleep_ptr(&mxcmci_pm_ops), | |
| 1224 | 1222 | .of_match_table = mxcmci_of_match, |
| 1225 | 1223 | } |
| 1226 | 1224 | }; |
| @@ -5441,7 +5441,9 @@ static struct pci_driver rtl8169_pci_driver = { · 5440 unmodified lines | ||
| 5441 | 5441 | .probe = rtl_init_one, |
| 5442 | 5442 | .remove = rtl_remove_one, |
| 5443 | 5443 | .shutdown = rtl_shutdown, |
| 5444 | − .driver.pm = pm_ptr(&rtl8169_pm_ops), | |
| 5444 | +#ifdef CONFIG_PM | |
| 5445 | + .driver.pm = &rtl8169_pm_ops, | |
| 5446 | +#endif | |
| 5445 | 5447 | }; |
| 5446 | 5448 | |
| 5447 | 5449 | module_pci_driver(rtl8169_pci_driver); |
| @@ -506,7 +506,7 @@ acpi_status acpi_release_memory(acpi_handle handle, struct resource *res, · 505 unmodified lines | ||
| 506 | 506 | int acpi_resources_are_enforced(void); |
| 507 | 507 | |
| 508 | 508 | #ifdef CONFIG_HIBERNATION |
| 509 | −void __init acpi_no_s4_hw_signature(void); | |
| 509 | +void __init acpi_check_s4_hw_signature(int check); | |
| 510 | 510 | #endif |
| 511 | 511 | |
| 512 | 512 | #ifdef CONFIG_PM_SLEEP |
| @@ -300,47 +300,59 @@ struct dev_pm_ops { · 299 unmodified lines | ||
| 300 | 300 | int (*runtime_idle)(struct device *dev); |
| 301 | 301 | }; |
| 302 | 302 | |
| 303 | +#define SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 304 | + .suspend = pm_sleep_ptr(suspend_fn), \ | |
| 305 | + .resume = pm_sleep_ptr(resume_fn), \ | |
| 306 | + .freeze = pm_sleep_ptr(suspend_fn), \ | |
| 307 | + .thaw = pm_sleep_ptr(resume_fn), \ | |
| 308 | + .poweroff = pm_sleep_ptr(suspend_fn), \ | |
| 309 | + .restore = pm_sleep_ptr(resume_fn), | |
| 310 | + | |
| 311 | +#define LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 312 | + .suspend_late = pm_sleep_ptr(suspend_fn), \ | |
| 313 | + .resume_early = pm_sleep_ptr(resume_fn), \ | |
| 314 | + .freeze_late = pm_sleep_ptr(suspend_fn), \ | |
| 315 | + .thaw_early = pm_sleep_ptr(resume_fn), \ | |
| 316 | + .poweroff_late = pm_sleep_ptr(suspend_fn), \ | |
| 317 | + .restore_early = pm_sleep_ptr(resume_fn), | |
| 318 | + | |
| 319 | +#define NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 320 | + .suspend_noirq = pm_sleep_ptr(suspend_fn), \ | |
| 321 | + .resume_noirq = pm_sleep_ptr(resume_fn), \ | |
| 322 | + .freeze_noirq = pm_sleep_ptr(suspend_fn), \ | |
| 323 | + .thaw_noirq = pm_sleep_ptr(resume_fn), \ | |
| 324 | + .poweroff_noirq = pm_sleep_ptr(suspend_fn), \ | |
| 325 | + .restore_noirq = pm_sleep_ptr(resume_fn), | |
| 326 | + | |
| 327 | +#define RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ | |
| 328 | + .runtime_suspend = suspend_fn, \ | |
| 329 | + .runtime_resume = resume_fn, \ | |
| 330 | + .runtime_idle = idle_fn, | |
| 331 | + | |
| 303 | 332 | #ifdef CONFIG_PM_SLEEP |
| 304 | 333 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 305 | − .suspend = suspend_fn, \ | |
| 306 | − .resume = resume_fn, \ | |
| 307 | − .freeze = suspend_fn, \ | |
| 308 | − .thaw = resume_fn, \ | |
| 309 | − .poweroff = suspend_fn, \ | |
| 310 | − .restore = resume_fn, | |
| 334 | + SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | |
| 311 | 335 | #else |
| 312 | 336 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 313 | 337 | #endif |
| 314 | 338 | |
| 315 | 339 | #ifdef CONFIG_PM_SLEEP |
| 316 | 340 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 317 | − .suspend_late = suspend_fn, \ | |
| 318 | − .resume_early = resume_fn, \ | |
| 319 | − .freeze_late = suspend_fn, \ | |
| 320 | − .thaw_early = resume_fn, \ | |
| 321 | − .poweroff_late = suspend_fn, \ | |
| 322 | − .restore_early = resume_fn, | |
| 341 | + LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | |
| 323 | 342 | #else |
| 324 | 343 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 325 | 344 | #endif |
| 326 | 345 | |
| 327 | 346 | #ifdef CONFIG_PM_SLEEP |
| 328 | 347 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 329 | − .suspend_noirq = suspend_fn, \ | |
| 330 | − .resume_noirq = resume_fn, \ | |
| 331 | − .freeze_noirq = suspend_fn, \ | |
| 332 | − .thaw_noirq = resume_fn, \ | |
| 333 | − .poweroff_noirq = suspend_fn, \ | |
| 334 | − .restore_noirq = resume_fn, | |
| 348 | + NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | |
| 335 | 349 | #else |
| 336 | 350 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 337 | 351 | #endif |
| 338 | 352 | |
| 339 | 353 | #ifdef CONFIG_PM |
| 340 | 354 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ |
| 341 | − .runtime_suspend = suspend_fn, \ | |
| 342 | − .runtime_resume = resume_fn, \ | |
| 343 | − .runtime_idle = idle_fn, | |
| 355 | + RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) | |
| 344 | 356 | #else |
| 345 | 357 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) |
| 346 | 358 | #endif |
| @@ -349,9 +361,9 @@ struct dev_pm_ops { · 2 unmodified lines | ||
| 349 | 361 | * Use this if you want to use the same suspend and resume callbacks for suspend |
| 350 | 362 | * to RAM and hibernation. |
| 351 | 363 | */ |
| 352 | −#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | |
| 353 | −const struct dev_pm_ops __maybe_unused name = { \ | |
| 354 | − SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 364 | +#define DEFINE_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | |
| 365 | +static const struct dev_pm_ops name = { \ | |
| 366 | + SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 355 | 367 | } |
| 356 | 368 | |
| 357 | 369 | /* |
| @@ -367,17 +379,27 @@ const struct dev_pm_ops __maybe_unused name = { \ · 9 unmodified lines | ||
| 367 | 379 | * .resume_early(), to the same routines as .runtime_suspend() and |
| 368 | 380 | * .runtime_resume(), respectively (and analogously for hibernation). |
| 369 | 381 | */ |
| 382 | +#define DEFINE_UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ | |
| 383 | +static const struct dev_pm_ops name = { \ | |
| 384 | + SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 385 | + RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ | |
| 386 | +} | |
| 387 | + | |
| 388 | +/* Deprecated. Use DEFINE_SIMPLE_DEV_PM_OPS() instead. */ | |
| 389 | +#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | |
| 390 | +const struct dev_pm_ops __maybe_unused name = { \ | |
| 391 | + SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | |
| 392 | +} | |
| 393 | + | |
| 394 | +/* Deprecated. Use DEFINE_UNIVERSAL_DEV_PM_OPS() instead. */ | |
| 370 | 395 | #define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ |
| 371 | 396 | const struct dev_pm_ops __maybe_unused name = { \ |
| 372 | 397 | SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 373 | 398 | SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ |
| 374 | 399 | } |
| 375 | 400 | |
| 376 | −#ifdef CONFIG_PM | |
| 377 | −#define pm_ptr(_ptr) (_ptr) | |
| 378 | −#else | |
| 379 | −#define pm_ptr(_ptr) NULL | |
| 380 | −#endif | |
| 401 | +#define pm_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM), (_ptr)) | |
| 402 | +#define pm_sleep_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM_SLEEP), (_ptr)) | |
| 381 | 403 | |
| 382 | 404 | /* |
| 383 | 405 | * PM_EVENT_ messages |
| @@ -499,6 +521,7 @@ const struct dev_pm_ops __maybe_unused name = { \ · 115 unmodified lines | ||
| 499 | 521 | */ |
| 500 | 522 | |
| 501 | 523 | enum rpm_status { |
| 524 | + RPM_INVALID = -1, | |
| 502 | 525 | RPM_ACTIVE = 0, |
| 503 | 526 | RPM_RESUMING, |
| 504 | 527 | RPM_SUSPENDED, |
| @@ -612,6 +635,7 @@ struct dev_pm_info { · 107 unmodified lines | ||
| 612 | 635 | unsigned int links_count; |
| 613 | 636 | enum rpm_request request; |
| 614 | 637 | enum rpm_status runtime_status; |
| 638 | + enum rpm_status last_status; | |
| 615 | 639 | int runtime_error; |
| 616 | 640 | int autosuspend_delay; |
| 617 | 641 | u64 last_busy; |
| @@ -58,6 +58,7 @@ extern void pm_runtime_get_suppliers(struct device *dev); · 57 unmodified lines | ||
| 58 | 58 | extern void pm_runtime_put_suppliers(struct device *dev); |
| 59 | 59 | extern void pm_runtime_new_link(struct device *dev); |
| 60 | 60 | extern void pm_runtime_drop_link(struct device_link *link); |
| 61 | +extern void pm_runtime_release_supplier(struct device_link *link, bool check_idle); | |
| 61 | 62 | |
| 62 | 63 | extern int devm_pm_runtime_enable(struct device *dev); |
| 63 | 64 | |
| @@ -283,6 +284,8 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {} · 219 unmodified lines | ||
| 283 | 284 | static inline void pm_runtime_put_suppliers(struct device *dev) {} |
| 284 | 285 | static inline void pm_runtime_new_link(struct device *dev) {} |
| 285 | 286 | static inline void pm_runtime_drop_link(struct device_link *link) {} |
| 287 | +static inline void pm_runtime_release_supplier(struct device_link *link, | |
| 288 | + bool check_idle) {} | |
| 286 | 289 | |
| 287 | 290 | #endif /* !CONFIG_PM */ |
| 288 | 291 | |
| @@ -446,6 +446,7 @@ extern unsigned long get_safe_page(gfp_t gfp_mask); · 445 unmodified lines | ||
| 446 | 446 | extern asmlinkage int swsusp_arch_suspend(void); |
| 447 | 447 | extern asmlinkage int swsusp_arch_resume(void); |
| 448 | 448 | |
| 449 | +extern u32 swsusp_hardware_signature; | |
| 449 | 450 | extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); |
| 450 | 451 | extern int hibernate(void); |
| 451 | 452 | extern bool system_entering_hibernation(void); |
| @@ -170,6 +170,7 @@ extern int swsusp_swap_in_use(void); · 169 unmodified lines | ||
| 170 | 170 | #define SF_PLATFORM_MODE 1 |
| 171 | 171 | #define SF_NOCOMPRESS_MODE 2 |
| 172 | 172 | #define SF_CRC32_MODE 4 |
| 173 | +#define SF_HW_SIG 8 | |
| 173 | 174 | |
| 174 | 175 | /* kernel/power/hibernate.c */ |
| 175 | 176 | extern int swsusp_check(void); |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #define HIBERNATE_SIG "S1SUSPEND" |
| 38 | 38 | |
| 39 | +u32 swsusp_hardware_signature; | |
| 40 | + | |
| 39 | 41 | /* |
| 40 | 42 | * When reading an {un,}compressed image, we may restore pages in place, |
| 41 | 43 | * in which case some architectures need these pages cleaning before they |
| @@ -104,7 +106,8 @@ struct swap_map_handle { · 62 unmodified lines | ||
| 104 | 106 | |
| 105 | 107 | struct swsusp_header { |
| 106 | 108 | char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) - |
| 107 | − sizeof(u32)]; | |
| 109 | + sizeof(u32) - sizeof(u32)]; | |
| 110 | + u32 hw_sig; | |
| 108 | 111 | u32 crc32; |
| 109 | 112 | sector_t image; |
| 110 | 113 | unsigned int flags; /* Flags to pass to the "boot" kernel */ |
| @@ -312,7 +315,6 @@ static int hib_wait_io(struct hib_bio_batch *hb) · 201 unmodified lines | ||
| 312 | 315 | /* |
| 313 | 316 | * Saving part |
| 314 | 317 | */ |
| 315 | − | |
| 316 | 318 | static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) |
| 317 | 319 | { |
| 318 | 320 | int error; |
| @@ -324,6 +326,10 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) · 5 unmodified lines | ||
| 324 | 326 | memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); |
| 325 | 327 | memcpy(swsusp_header->sig, HIBERNATE_SIG, 10); |
| 326 | 328 | swsusp_header->image = handle->first_sector; |
| 329 | + if (swsusp_hardware_signature) { | |
| 330 | + swsusp_header->hw_sig = swsusp_hardware_signature; | |
| 331 | + flags |= SF_HW_SIG; | |
| 332 | + } | |
| 327 | 333 | swsusp_header->flags = flags; |
| 328 | 334 | if (flags & SF_CRC32_MODE) |
| 329 | 335 | swsusp_header->crc32 = handle->crc32; |
| @@ -1537,6 +1543,12 @@ int swsusp_check(void) · 1207 unmodified lines | ||
| 1537 | 1543 | } else { |
| 1538 | 1544 | error = -EINVAL; |
| 1539 | 1545 | } |
| 1546 | + if (!error && swsusp_header->flags & SF_HW_SIG && | |
| 1547 | + swsusp_header->hw_sig != swsusp_hardware_signature) { | |
| 1548 | + pr_info("Suspend image hardware signature mismatch (%08x now %08x); aborting resume.\n", | |
| 1549 | + swsusp_header->hw_sig, swsusp_hardware_signature); | |
| 1550 | + error = -EINVAL; | |
| 1551 | + } | |
| 1540 | 1552 | |
| 1541 | 1553 | put: |
| 1542 | 1554 | if (error) |