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 | For broken nForce2 BIOS resulting in XT-PIC timer. | 225 | For broken nForce2 BIOS resulting in XT-PIC timer. |
| 226 | 226 | ||
| 227 | acpi_sleep= [HW,ACPI] Sleep options | 227 | acpi_sleep= [HW,ACPI] Sleep options |
| 228 | Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, | 228 | Format: { s3_bios, s3_mode, s3_beep, s4_hwsig, |
| 229 | old_ordering, nonvs, sci_force_enable, nobl } | 229 | s4_nohwsig, old_ordering, nonvs, |
| 230 | sci_force_enable, nobl } | ||
| 230 | See Documentation/power/video.rst for information on | 231 | See Documentation/power/video.rst for information on |
| 231 | s3_bios and s3_mode. | 232 | s3_bios and s3_mode. |
| 232 | s3_beep is for debugging; it makes the PC's speaker beep | 233 | s3_beep is for debugging; it makes the PC's speaker beep |
| 233 | as soon as the kernel's real-mode entry point is called. | 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 | s4_nohwsig prevents ACPI hardware signature from being | 243 | s4_nohwsig prevents ACPI hardware signature from being |
| 235 | used during resume from hibernation. | 244 | used (or even warned about) during resume. |
| 236 | old_ordering causes the ACPI 1.0 ordering of the _PTS | 245 | old_ordering causes the ACPI 1.0 ordering of the _PTS |
| 237 | control method, with respect to putting devices into | 246 | control method, with respect to putting devices into |
| 238 | low power states, to be enforced (the ACPI 2.0 ordering | 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 | RPM_SUSPENDED, which means that each device is initially regarded by the | 265 | RPM_SUSPENDED, which means that each device is initially regarded by the |
| 266 | PM core as 'suspended', regardless of its real hardware status | 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 | `unsigned int runtime_auto;` | 272 | `unsigned int runtime_auto;` |
| 269 | - if set, indicates that the user space has allowed the device driver to | 273 | - if set, indicates that the user space has allowed the device driver to |
| 270 | power manage the device at run time via the /sys/devices/.../power/control | 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 | `int pm_runtime_resume(struct device *dev);` | 338 | `int pm_runtime_resume(struct device *dev);` |
| 335 | - execute the subsystem-level resume callback for the device; returns 0 on | 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 | 340 | success, 1 if the device's runtime PM status is already 'active' (also if |
| 337 | error code on failure, where -EAGAIN means it may be safe to attempt to | 341 | 'power.disable_depth' is nonzero, but the status was 'active' when it was |
| 338 | resume the device again in future, but 'power.runtime_error' should be | 342 | changing from 0 to 1) or error code on failure, where -EAGAIN means it may |
| 339 | checked additionally, and -EACCES means that 'power.disable_depth' is | 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 | different from 0 | 346 | different from 0 |
| 341 | 347 | ||
| 342 | `int pm_runtime_resume_and_get(struct device *dev);` | 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 | if (strncmp(str, "s3_beep", 7) == 0) | 139 | if (strncmp(str, "s3_beep", 7) == 0) |
| 140 | acpi_realmode_flags |= 4; | 140 | acpi_realmode_flags |= 4; |
| 141 | #ifdef CONFIG_HIBERNATION | 141 | #ifdef CONFIG_HIBERNATION |
| 142 | if (strncmp(str, "s4_hwsig", 8) == 0) | ||
| 143 | acpi_check_s4_hw_signature(1); | ||
| 142 | if (strncmp(str, "s4_nohwsig", 10) == 0) | 144 | if (strncmp(str, "s4_nohwsig", 10) == 0) |
| 143 | acpi_no_s4_hw_signature(); | 145 | acpi_check_s4_hw_signature(0); |
| 144 | #endif | 146 | #endif |
| 145 | if (strncmp(str, "nonvs", 5) == 0) | 147 | if (strncmp(str, "nonvs", 5) == 0) |
| 146 | acpi_nvs_nosave(); | 148 | acpi_nvs_nosave(); |
| @@ -877,11 +877,11 @@ static inline void acpi_sleep_syscore_init(void) {} · 876 unmodified lines | |||
| 877 | #ifdef CONFIG_HIBERNATION | 877 | #ifdef CONFIG_HIBERNATION |
| 878 | static unsigned long s4_hardware_signature; | 878 | static unsigned long s4_hardware_signature; |
| 879 | static struct acpi_table_facs *facs; | 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 | static int acpi_hibernation_begin(pm_message_t stage) | 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 | hibernation_set_ops(old_suspend_ordering ? | 1009 | hibernation_set_ops(old_suspend_ordering ? |
| 1010 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 1010 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
| 1011 | sleep_states[ACPI_STATE_S4] = 1; | 1011 | sleep_states[ACPI_STATE_S4] = 1; |
| 1012 | if (nosigcheck) | 1012 | if (!sigcheck) |
| 1013 | return; | 1013 | return; |
| 1014 | 1014 | ||
| 1015 | acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); | 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 | s4_hardware_signature = facs->hardware_signature; | 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 | #else /* !CONFIG_HIBERNATION */ | 1035 | #else /* !CONFIG_HIBERNATION */ |
| 1020 | static inline void acpi_sleep_hibernate_setup(void) {} | 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 | /* Ensure that all references to the link object have been dropped. */ | 485 | /* Ensure that all references to the link object have been dropped. */ |
| 486 | device_link_synchronize_removal(); | 486 | device_link_synchronize_removal(); |
| 487 | 487 | ||
| 488 | while (refcount_dec_not_one(&link->rpm_active)) | 488 | pm_runtime_release_supplier(link, true); |
| 489 | pm_runtime_put(link->supplier); | ||
| 490 | 489 | ||
| 491 | put_device(link->consumer); | 490 | put_device(link->consumer); |
| 492 | put_device(link->supplier); | 491 | put_device(link->supplier); |
| @@ -305,19 +305,40 @@ static int rpm_get_suppliers(struct device *dev) · 304 unmodified lines | |||
| 305 | return 0; | 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 | static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend) | 335 | static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend) |
| 309 | { | 336 | { |
| 310 | struct device_link *link; | 337 | struct device_link *link; |
| 311 | 338 | ||
| 312 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, | 339 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, |
| 313 | device_links_read_lock_held()) { | 340 | device_links_read_lock_held()) |
| 314 | 341 | pm_runtime_release_supplier(link, try_to_suspend); | |
| 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 | } | ||
| 321 | } | 342 | } |
| 322 | 343 | ||
| 323 | static void rpm_put_suppliers(struct device *dev) | 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 | trace_rpm_resume_rcuidle(dev, rpmflags); | 763 | trace_rpm_resume_rcuidle(dev, rpmflags); |
| 743 | 764 | ||
| 744 | repeat: | 765 | repeat: |
| 745 | if (dev->power.runtime_error) | 766 | if (dev->power.runtime_error) { |
| 746 | retval = -EINVAL; | 767 | retval = -EINVAL; |
| 747 | else if (dev->power.disable_depth == 1 && dev->power.is_suspended | 768 | } else if (dev->power.disable_depth > 0) { |
| 748 | && dev->power.runtime_status == RPM_ACTIVE) | 769 | if (dev->power.runtime_status == RPM_ACTIVE && |
| 749 | retval = 1; | 770 | dev->power.last_status == RPM_ACTIVE) |
| 750 | else if (dev->power.disable_depth > 0) | 771 | retval = 1; |
| 751 | retval = -EACCES; | 772 | else |
| 773 | retval = -EACCES; | ||
| 774 | } | ||
| 752 | if (retval) | 775 | if (retval) |
| 753 | goto out; | 776 | goto out; |
| 754 | 777 | ||
| @@ -1410,8 +1433,10 @@ void __pm_runtime_disable(struct device *dev, bool check_resume) · 655 unmodified lines | |||
| 1410 | /* Update time accounting before disabling PM-runtime. */ | 1433 | /* Update time accounting before disabling PM-runtime. */ |
| 1411 | update_pm_runtime_accounting(dev); | 1434 | update_pm_runtime_accounting(dev); |
| 1412 | 1435 | ||
| 1413 | if (!dev->power.disable_depth++) | 1436 | if (!dev->power.disable_depth++) { |
| 1414 | __pm_runtime_barrier(dev); | 1437 | __pm_runtime_barrier(dev); |
| 1438 | dev->power.last_status = dev->power.runtime_status; | ||
| 1439 | } | ||
| 1415 | 1440 | ||
| 1416 | out: | 1441 | out: |
| 1417 | spin_unlock_irq(&dev->power.lock); | 1442 | spin_unlock_irq(&dev->power.lock); |
| @@ -1428,23 +1453,23 @@ void pm_runtime_enable(struct device *dev) · 10 unmodified lines | |||
| 1428 | 1453 | ||
| 1429 | spin_lock_irqsave(&dev->power.lock, flags); | 1454 | spin_lock_irqsave(&dev->power.lock, flags); |
| 1430 | 1455 | ||
| 1431 | if (dev->power.disable_depth > 0) { | 1456 | if (!dev->power.disable_depth) { |
| 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 { | ||
| 1438 | dev_warn(dev, "Unbalanced %s!\n", __func__); | 1457 | dev_warn(dev, "Unbalanced %s!\n", __func__); |
| 1458 | goto out; | ||
| 1439 | } | 1459 | } |
| 1440 | 1460 | ||
| 1441 | WARN(!dev->power.disable_depth && | 1461 | if (--dev->power.disable_depth > 0) |
| 1442 | dev->power.runtime_status == RPM_SUSPENDED && | 1462 | goto out; |
| 1443 | !dev->power.ignore_children && | 1463 | |
| 1444 | atomic_read(&dev->power.child_count) > 0, | 1464 | dev->power.last_status = RPM_INVALID; |
| 1445 | "Enabling runtime PM for inactive device (%s) with active children\n", | 1465 | dev->power.accounting_timestamp = ktime_get_mono_fast_ns(); |
| 1446 | dev_name(dev)); | 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 | spin_unlock_irqrestore(&dev->power.lock, flags); | 1473 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 1449 | } | 1474 | } |
| 1450 | EXPORT_SYMBOL_GPL(pm_runtime_enable); | 1475 | EXPORT_SYMBOL_GPL(pm_runtime_enable); |
| @@ -1640,6 +1665,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend); · 189 unmodified lines | |||
| 1640 | void pm_runtime_init(struct device *dev) | 1665 | void pm_runtime_init(struct device *dev) |
| 1641 | { | 1666 | { |
| 1642 | dev->power.runtime_status = RPM_SUSPENDED; | 1667 | dev->power.runtime_status = RPM_SUSPENDED; |
| 1668 | dev->power.last_status = RPM_INVALID; | ||
| 1643 | dev->power.idle_notification = false; | 1669 | dev->power.idle_notification = false; |
| 1644 | 1670 | ||
| 1645 | dev->power.disable_depth = 1; | 1671 | dev->power.disable_depth = 1; |
| @@ -1722,8 +1748,6 @@ void pm_runtime_get_suppliers(struct device *dev) · 76 unmodified lines | |||
| 1722 | void pm_runtime_put_suppliers(struct device *dev) | 1748 | void pm_runtime_put_suppliers(struct device *dev) |
| 1723 | { | 1749 | { |
| 1724 | struct device_link *link; | 1750 | struct device_link *link; |
| 1725 | unsigned long flags; | ||
| 1726 | bool put; | ||
| 1727 | int idx; | 1751 | int idx; |
| 1728 | 1752 | ||
| 1729 | idx = device_links_read_lock(); | 1753 | idx = device_links_read_lock(); |
| @@ -1731,11 +1755,17 @@ void pm_runtime_put_suppliers(struct device *dev) · 1 unmodified line | |||
| 1731 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, | 1755 | list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, |
| 1732 | device_links_read_lock_held()) | 1756 | device_links_read_lock_held()) |
| 1733 | if (link->supplier_preactivated) { | 1757 | if (link->supplier_preactivated) { |
| 1758 | bool put; | ||
| 1759 | |||
| 1734 | link->supplier_preactivated = false; | 1760 | link->supplier_preactivated = false; |
| 1735 | spin_lock_irqsave(&dev->power.lock, flags); | 1761 | |
| 1762 | spin_lock_irq(&dev->power.lock); | ||
| 1763 | |||
| 1736 | put = pm_runtime_status_suspended(dev) && | 1764 | put = pm_runtime_status_suspended(dev) && |
| 1737 | refcount_dec_not_one(&link->rpm_active); | 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 | if (put) | 1769 | if (put) |
| 1740 | pm_runtime_put(link->supplier); | 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 | return; | 1802 | return; |
| 1773 | 1803 | ||
| 1774 | pm_runtime_drop_link_count(link->consumer); | 1804 | pm_runtime_drop_link_count(link->consumer); |
| 1775 | 1805 | pm_runtime_release_supplier(link, true); | |
| 1776 | while (refcount_dec_not_one(&link->rpm_active)) | ||
| 1777 | pm_runtime_put(link->supplier); | ||
| 1778 | } | 1806 | } |
| 1779 | 1807 | ||
| 1780 | static bool pm_runtime_need_not_resume(struct device *dev) | 1808 | static bool pm_runtime_need_not_resume(struct device *dev) |
| @@ -34,7 +34,7 @@ · 33 unmodified lines | |||
| 34 | * 1) Energy break even point | 34 | * 1) Energy break even point |
| 35 | * 2) Performance impact | 35 | * 2) Performance impact |
| 36 | * 3) Latency tolerance (from pmqos infrastructure) | 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 | * Energy break even point | 39 | * Energy break even point |
| 40 | * ----------------------- | 40 | * ----------------------- |
| @@ -335,6 +335,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { · 334 unmodified lines | |||
| 335 | &attr_default_status.attr, | 335 | &attr_default_status.attr, |
| 336 | NULL | 336 | NULL |
| 337 | }; | 337 | }; |
| 338 | ATTRIBUTE_GROUPS(cpuidle_state_default); | ||
| 338 | 339 | ||
| 339 | struct cpuidle_state_kobj { | 340 | struct cpuidle_state_kobj { |
| 340 | struct cpuidle_state *state; | 341 | struct cpuidle_state *state; |
| @@ -448,7 +449,7 @@ static void cpuidle_state_sysfs_release(struct kobject *kobj) · 107 unmodified lines | |||
| 448 | 449 | ||
| 449 | static struct kobj_type ktype_state_cpuidle = { | 450 | static struct kobj_type ktype_state_cpuidle = { |
| 450 | .sysfs_ops = &cpuidle_state_sysfs_ops, | 451 | .sysfs_ops = &cpuidle_state_sysfs_ops, |
| 451 | .default_attrs = cpuidle_state_default_attrs, | 452 | .default_groups = cpuidle_state_default_groups, |
| 452 | .release = cpuidle_state_sysfs_release, | 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 | * @device: the target device | 510 | * @device: the target device |
| 510 | */ | 511 | */ |
| 511 | static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) | 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 | &attr_driver_name.attr, | 592 | &attr_driver_name.attr, |
| 592 | NULL | 593 | NULL |
| 593 | }; | 594 | }; |
| 595 | ATTRIBUTE_GROUPS(cpuidle_driver_default); | ||
| 594 | 596 | ||
| 595 | static struct kobj_type ktype_driver_cpuidle = { | 597 | static struct kobj_type ktype_driver_cpuidle = { |
| 596 | .sysfs_ops = &cpuidle_driver_sysfs_ops, | 598 | .sysfs_ops = &cpuidle_driver_sysfs_ops, |
| 597 | .default_attrs = cpuidle_driver_default_attrs, | 599 | .default_groups = cpuidle_driver_default_groups, |
| 598 | .release = cpuidle_driver_sysfs_release, | 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 | return 0; | 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 | return pinctrl_pm_select_sleep_state(dev); | 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 | return pinctrl_select_default_state(dev); | 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 | jz4740_mmc_resume); | 1117 | jz4740_mmc_resume); |
| 1118 | 1118 | ||
| 1119 | static struct platform_driver jz4740_mmc_driver = { | 1119 | static struct platform_driver jz4740_mmc_driver = { |
| @@ -1123,7 +1123,7 @@ static struct platform_driver jz4740_mmc_driver = { · 3 unmodified lines | |||
| 1123 | .name = "jz4740-mmc", | 1123 | .name = "jz4740-mmc", |
| 1124 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, | 1124 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| 1125 | .of_match_table = of_match_ptr(jz4740_mmc_of_match), | 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 | return 0; | 1183 | return 0; |
| 1184 | } | 1184 | } |
| 1185 | 1185 | ||
| 1186 | #ifdef CONFIG_PM_SLEEP | ||
| 1187 | static int mxcmci_suspend(struct device *dev) | 1186 | static int mxcmci_suspend(struct device *dev) |
| 1188 | { | 1187 | { |
| 1189 | struct mmc_host *mmc = dev_get_drvdata(dev); | 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 | return ret; | 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 | static struct platform_driver mxcmci_driver = { | 1215 | static struct platform_driver mxcmci_driver = { |
| 1218 | .probe = mxcmci_probe, | 1216 | .probe = mxcmci_probe, |
| @@ -1220,7 +1218,7 @@ static struct platform_driver mxcmci_driver = { · 1 unmodified line | |||
| 1220 | .driver = { | 1218 | .driver = { |
| 1221 | .name = DRIVER_NAME, | 1219 | .name = DRIVER_NAME, |
| 1222 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, | 1220 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| 1223 | .pm = &mxcmci_pm_ops, | 1221 | .pm = pm_sleep_ptr(&mxcmci_pm_ops), |
| 1224 | .of_match_table = mxcmci_of_match, | 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 | .probe = rtl_init_one, | 5441 | .probe = rtl_init_one, |
| 5442 | .remove = rtl_remove_one, | 5442 | .remove = rtl_remove_one, |
| 5443 | .shutdown = rtl_shutdown, | 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 | module_pci_driver(rtl8169_pci_driver); | 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 | int acpi_resources_are_enforced(void); | 506 | int acpi_resources_are_enforced(void); |
| 507 | 507 | ||
| 508 | #ifdef CONFIG_HIBERNATION | 508 | #ifdef CONFIG_HIBERNATION |
| 509 | void __init acpi_no_s4_hw_signature(void); | 509 | void __init acpi_check_s4_hw_signature(int check); |
| 510 | #endif | 510 | #endif |
| 511 | 511 | ||
| 512 | #ifdef CONFIG_PM_SLEEP | 512 | #ifdef CONFIG_PM_SLEEP |
| @@ -300,47 +300,59 @@ struct dev_pm_ops { · 299 unmodified lines | |||
| 300 | int (*runtime_idle)(struct device *dev); | 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 | #ifdef CONFIG_PM_SLEEP | 332 | #ifdef CONFIG_PM_SLEEP |
| 304 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | 333 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 305 | .suspend = suspend_fn, \ | 334 | SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 306 | .resume = resume_fn, \ | ||
| 307 | .freeze = suspend_fn, \ | ||
| 308 | .thaw = resume_fn, \ | ||
| 309 | .poweroff = suspend_fn, \ | ||
| 310 | .restore = resume_fn, | ||
| 311 | #else | 335 | #else |
| 312 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | 336 | #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 313 | #endif | 337 | #endif |
| 314 | 338 | ||
| 315 | #ifdef CONFIG_PM_SLEEP | 339 | #ifdef CONFIG_PM_SLEEP |
| 316 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | 340 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 317 | .suspend_late = suspend_fn, \ | 341 | LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_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, | ||
| 323 | #else | 342 | #else |
| 324 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | 343 | #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 325 | #endif | 344 | #endif |
| 326 | 345 | ||
| 327 | #ifdef CONFIG_PM_SLEEP | 346 | #ifdef CONFIG_PM_SLEEP |
| 328 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | 347 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 329 | .suspend_noirq = suspend_fn, \ | 348 | NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_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, | ||
| 335 | #else | 349 | #else |
| 336 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) | 350 | #define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) |
| 337 | #endif | 351 | #endif |
| 338 | 352 | ||
| 339 | #ifdef CONFIG_PM | 353 | #ifdef CONFIG_PM |
| 340 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ | 354 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ |
| 341 | .runtime_suspend = suspend_fn, \ | 355 | RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) |
| 342 | .runtime_resume = resume_fn, \ | ||
| 343 | .runtime_idle = idle_fn, | ||
| 344 | #else | 356 | #else |
| 345 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) | 357 | #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) |
| 346 | #endif | 358 | #endif |
| @@ -349,9 +361,9 @@ struct dev_pm_ops { · 2 unmodified lines | |||
| 349 | * Use this if you want to use the same suspend and resume callbacks for suspend | 361 | * Use this if you want to use the same suspend and resume callbacks for suspend |
| 350 | * to RAM and hibernation. | 362 | * to RAM and hibernation. |
| 351 | */ | 363 | */ |
| 352 | #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | 364 | #define DEFINE_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ |
| 353 | const struct dev_pm_ops __maybe_unused name = { \ | 365 | static const struct dev_pm_ops name = { \ |
| 354 | SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | 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 | * .resume_early(), to the same routines as .runtime_suspend() and | 379 | * .resume_early(), to the same routines as .runtime_suspend() and |
| 368 | * .runtime_resume(), respectively (and analogously for hibernation). | 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 | #define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ | 395 | #define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ |
| 371 | const struct dev_pm_ops __maybe_unused name = { \ | 396 | const struct dev_pm_ops __maybe_unused name = { \ |
| 372 | SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ | 397 | SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ |
| 373 | SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ | 398 | SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ |
| 374 | } | 399 | } |
| 375 | 400 | ||
| 376 | #ifdef CONFIG_PM | 401 | #define pm_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM), (_ptr)) |
| 377 | #define pm_ptr(_ptr) (_ptr) | 402 | #define pm_sleep_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM_SLEEP), (_ptr)) |
| 378 | #else | ||
| 379 | #define pm_ptr(_ptr) NULL | ||
| 380 | #endif | ||
| 381 | 403 | ||
| 382 | /* | 404 | /* |
| 383 | * PM_EVENT_ messages | 405 | * PM_EVENT_ messages |
| @@ -499,6 +521,7 @@ const struct dev_pm_ops __maybe_unused name = { \ · 115 unmodified lines | |||
| 499 | */ | 521 | */ |
| 500 | 522 | ||
| 501 | enum rpm_status { | 523 | enum rpm_status { |
| 524 | RPM_INVALID = -1, | ||
| 502 | RPM_ACTIVE = 0, | 525 | RPM_ACTIVE = 0, |
| 503 | RPM_RESUMING, | 526 | RPM_RESUMING, |
| 504 | RPM_SUSPENDED, | 527 | RPM_SUSPENDED, |
| @@ -612,6 +635,7 @@ struct dev_pm_info { · 107 unmodified lines | |||
| 612 | unsigned int links_count; | 635 | unsigned int links_count; |
| 613 | enum rpm_request request; | 636 | enum rpm_request request; |
| 614 | enum rpm_status runtime_status; | 637 | enum rpm_status runtime_status; |
| 638 | enum rpm_status last_status; | ||
| 615 | int runtime_error; | 639 | int runtime_error; |
| 616 | int autosuspend_delay; | 640 | int autosuspend_delay; |
| 617 | u64 last_busy; | 641 | u64 last_busy; |
| @@ -58,6 +58,7 @@ extern void pm_runtime_get_suppliers(struct device *dev); · 57 unmodified lines | |||
| 58 | extern void pm_runtime_put_suppliers(struct device *dev); | 58 | extern void pm_runtime_put_suppliers(struct device *dev); |
| 59 | extern void pm_runtime_new_link(struct device *dev); | 59 | extern void pm_runtime_new_link(struct device *dev); |
| 60 | extern void pm_runtime_drop_link(struct device_link *link); | 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 | extern int devm_pm_runtime_enable(struct device *dev); | 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 | static inline void pm_runtime_put_suppliers(struct device *dev) {} | 284 | static inline void pm_runtime_put_suppliers(struct device *dev) {} |
| 284 | static inline void pm_runtime_new_link(struct device *dev) {} | 285 | static inline void pm_runtime_new_link(struct device *dev) {} |
| 285 | static inline void pm_runtime_drop_link(struct device_link *link) {} | 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 | #endif /* !CONFIG_PM */ | 290 | #endif /* !CONFIG_PM */ |
| 288 | 291 | ||
| @@ -446,6 +446,7 @@ extern unsigned long get_safe_page(gfp_t gfp_mask); · 445 unmodified lines | |||
| 446 | extern asmlinkage int swsusp_arch_suspend(void); | 446 | extern asmlinkage int swsusp_arch_suspend(void); |
| 447 | extern asmlinkage int swsusp_arch_resume(void); | 447 | extern asmlinkage int swsusp_arch_resume(void); |
| 448 | 448 | ||
| 449 | extern u32 swsusp_hardware_signature; | ||
| 449 | extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); | 450 | extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); |
| 450 | extern int hibernate(void); | 451 | extern int hibernate(void); |
| 451 | extern bool system_entering_hibernation(void); | 452 | extern bool system_entering_hibernation(void); |
| @@ -170,6 +170,7 @@ extern int swsusp_swap_in_use(void); · 169 unmodified lines | |||
| 170 | #define SF_PLATFORM_MODE 1 | 170 | #define SF_PLATFORM_MODE 1 |
| 171 | #define SF_NOCOMPRESS_MODE 2 | 171 | #define SF_NOCOMPRESS_MODE 2 |
| 172 | #define SF_CRC32_MODE 4 | 172 | #define SF_CRC32_MODE 4 |
| 173 | #define SF_HW_SIG 8 | ||
| 173 | 174 | ||
| 174 | /* kernel/power/hibernate.c */ | 175 | /* kernel/power/hibernate.c */ |
| 175 | extern int swsusp_check(void); | 176 | extern int swsusp_check(void); |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | #define HIBERNATE_SIG "S1SUSPEND" | 37 | #define HIBERNATE_SIG "S1SUSPEND" |
| 38 | 38 | ||
| 39 | u32 swsusp_hardware_signature; | ||
| 40 | |||
| 39 | /* | 41 | /* |
| 40 | * When reading an {un,}compressed image, we may restore pages in place, | 42 | * When reading an {un,}compressed image, we may restore pages in place, |
| 41 | * in which case some architectures need these pages cleaning before they | 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 | struct swsusp_header { | 107 | struct swsusp_header { |
| 106 | char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) - | 108 | char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) - |
| 107 | sizeof(u32)]; | 109 | sizeof(u32) - sizeof(u32)]; |
| 110 | u32 hw_sig; | ||
| 108 | u32 crc32; | 111 | u32 crc32; |
| 109 | sector_t image; | 112 | sector_t image; |
| 110 | unsigned int flags; /* Flags to pass to the "boot" kernel */ | 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 | * Saving part | 316 | * Saving part |
| 314 | */ | 317 | */ |
| 315 | |||
| 316 | static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) | 318 | static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) |
| 317 | { | 319 | { |
| 318 | int error; | 320 | int error; |
| @@ -324,6 +326,10 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) · 5 unmodified lines | |||
| 324 | memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); | 326 | memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); |
| 325 | memcpy(swsusp_header->sig, HIBERNATE_SIG, 10); | 327 | memcpy(swsusp_header->sig, HIBERNATE_SIG, 10); |
| 326 | swsusp_header->image = handle->first_sector; | 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 | swsusp_header->flags = flags; | 333 | swsusp_header->flags = flags; |
| 328 | if (flags & SF_CRC32_MODE) | 334 | if (flags & SF_CRC32_MODE) |
| 329 | swsusp_header->crc32 = handle->crc32; | 335 | swsusp_header->crc32 = handle->crc32; |
| @@ -1537,6 +1543,12 @@ int swsusp_check(void) · 1207 unmodified lines | |||
| 1537 | } else { | 1543 | } else { |
| 1538 | error = -EINVAL; | 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 | put: | 1553 | put: |
| 1542 | if (error) | 1554 | if (error) |