Merge branches 'pm-core', 'pm-pci', 'pm-sleep', 'pm-domains' and 'powercap'

* pm-core:
  PM: runtime: Add documentation for pm_runtime_resume_and_get()
  PM: runtime: Replace inline function pm_runtime_callbacks_present()
  PM: core: Remove duplicate declaration from header file

* pm-pci:
  PCI: PM: Do not read power state in pci_enable_device_flags()

* pm-sleep:
  PM: wakeup: remove redundant assignment to variable retval
  PM: hibernate: x86: Use crc32 instead of md5 for hibernation e820 integrity check
  PM: wakeup: use dev_set_name() directly
  PM: sleep: fix typos in comments
  freezer: Remove unused inline function try_to_freeze_nowarn()

* pm-domains:
  PM: domains: Don't runtime resume devices at genpd_prepare()

* powercap:
  powercap: RAPL: Fix struct declaration in header file
  MAINTAINERS: Add DTPM subsystem maintainer
  powercap: Add Hygon Fam18h RAPL support
This commit is contained in:
Rafael J. Wysocki 2021-04-26 16:57:17 +02:00
16 changed files with 41 additions and 135 deletions

View File

@ -339,6 +339,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
checked additionally, and -EACCES means that 'power.disable_depth' is checked additionally, and -EACCES means that 'power.disable_depth' is
different from 0 different from 0
`int pm_runtime_resume_and_get(struct device *dev);`
- run pm_runtime_resume(dev) and if successful, increment the device's
usage counter; return the result of pm_runtime_resume
`int pm_request_idle(struct device *dev);` `int pm_request_idle(struct device *dev);`
- submit a request to execute the subsystem-level idle callback for the - submit a request to execute the subsystem-level idle callback for the
device (the request is represented by a work item in pm_wq); returns 0 on device (the request is represented by a work item in pm_wq); returns 0 on

View File

@ -14312,6 +14312,15 @@ F: include/linux/pm_*
F: include/linux/powercap.h F: include/linux/powercap.h
F: kernel/configs/nopm.config F: kernel/configs/nopm.config
DYNAMIC THERMAL POWER MANAGEMENT (DTPM)
M: Daniel Lezcano <daniel.lezcano@kernel.org>
L: linux-pm@vger.kernel.org
S: Supported
B: https://bugzilla.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
F: drivers/powercap/dtpm*
F: include/linux/dtpm.h
POWER STATE COORDINATION INTERFACE (PSCI) POWER STATE COORDINATION INTERFACE (PSCI)
M: Mark Rutland <mark.rutland@arm.com> M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

View File

@ -31,8 +31,8 @@
* - inform the user about the firmware's notion of memory layout * - inform the user about the firmware's notion of memory layout
* via /sys/firmware/memmap * via /sys/firmware/memmap
* *
* - the hibernation code uses it to generate a kernel-independent MD5 * - the hibernation code uses it to generate a kernel-independent CRC32
* fingerprint of the physical memory layout of a system. * checksum of the physical memory layout of a system.
* *
* - 'e820_table_kexec': a slightly modified (by the kernel) firmware version * - 'e820_table_kexec': a slightly modified (by the kernel) firmware version
* passed to us by the bootloader - the major difference between * passed to us by the bootloader - the major difference between

View File

@ -13,8 +13,8 @@
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <linux/types.h>
#include <crypto/hash.h> #include <linux/crc32.h>
#include <asm/e820/api.h> #include <asm/e820/api.h>
#include <asm/init.h> #include <asm/init.h>
@ -54,95 +54,33 @@ int pfn_is_nosave(unsigned long pfn)
return pfn >= nosave_begin_pfn && pfn < nosave_end_pfn; return pfn >= nosave_begin_pfn && pfn < nosave_end_pfn;
} }
#define MD5_DIGEST_SIZE 16
struct restore_data_record { struct restore_data_record {
unsigned long jump_address; unsigned long jump_address;
unsigned long jump_address_phys; unsigned long jump_address_phys;
unsigned long cr3; unsigned long cr3;
unsigned long magic; unsigned long magic;
u8 e820_digest[MD5_DIGEST_SIZE]; unsigned long e820_checksum;
}; };
#if IS_BUILTIN(CONFIG_CRYPTO_MD5)
/** /**
* get_e820_md5 - calculate md5 according to given e820 table * compute_e820_crc32 - calculate crc32 of a given e820 table
* *
* @table: the e820 table to be calculated * @table: the e820 table to be calculated
* @buf: the md5 result to be stored to *
* Return: the resulting checksum
*/ */
static int get_e820_md5(struct e820_table *table, void *buf) static inline u32 compute_e820_crc32(struct e820_table *table)
{ {
struct crypto_shash *tfm; int size = offsetof(struct e820_table, entries) +
struct shash_desc *desc;
int size;
int ret = 0;
tfm = crypto_alloc_shash("md5", 0, 0);
if (IS_ERR(tfm))
return -ENOMEM;
desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
goto free_tfm;
}
desc->tfm = tfm;
size = offsetof(struct e820_table, entries) +
sizeof(struct e820_entry) * table->nr_entries; sizeof(struct e820_entry) * table->nr_entries;
if (crypto_shash_digest(desc, (u8 *)table, size, buf)) return ~crc32_le(~0, (unsigned char const *)table, size);
ret = -EINVAL;
kfree_sensitive(desc);
free_tfm:
crypto_free_shash(tfm);
return ret;
} }
static int hibernation_e820_save(void *buf)
{
return get_e820_md5(e820_table_firmware, buf);
}
static bool hibernation_e820_mismatch(void *buf)
{
int ret;
u8 result[MD5_DIGEST_SIZE];
memset(result, 0, MD5_DIGEST_SIZE);
/* If there is no digest in suspend kernel, let it go. */
if (!memcmp(result, buf, MD5_DIGEST_SIZE))
return false;
ret = get_e820_md5(e820_table_firmware, result);
if (ret)
return true;
return memcmp(result, buf, MD5_DIGEST_SIZE) ? true : false;
}
#else
static int hibernation_e820_save(void *buf)
{
return 0;
}
static bool hibernation_e820_mismatch(void *buf)
{
/* If md5 is not builtin for restore kernel, let it go. */
return false;
}
#endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#define RESTORE_MAGIC 0x23456789ABCDEF01UL #define RESTORE_MAGIC 0x23456789ABCDEF02UL
#else #else
#define RESTORE_MAGIC 0x12345678UL #define RESTORE_MAGIC 0x12345679UL
#endif #endif
/** /**
@ -179,7 +117,8 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
*/ */
rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK; rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK;
return hibernation_e820_save(rdr->e820_digest); rdr->e820_checksum = compute_e820_crc32(e820_table_firmware);
return 0;
} }
/** /**
@ -200,7 +139,7 @@ int arch_hibernation_header_restore(void *addr)
jump_address_phys = rdr->jump_address_phys; jump_address_phys = rdr->jump_address_phys;
restore_cr3 = rdr->cr3; restore_cr3 = rdr->cr3;
if (hibernation_e820_mismatch(rdr->e820_digest)) { if (rdr->e820_checksum != compute_e820_crc32(e820_table_firmware)) {
pr_crit("Hibernate inconsistent memory map detected!\n"); pr_crit("Hibernate inconsistent memory map detected!\n");
return -ENODEV; return -ENODEV;
} }

View File

@ -1087,34 +1087,6 @@ static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock,
genpd->status = GENPD_STATE_ON; genpd->status = GENPD_STATE_ON;
} }
/**
* resume_needed - Check whether to resume a device before system suspend.
* @dev: Device to check.
* @genpd: PM domain the device belongs to.
*
* There are two cases in which a device that can wake up the system from sleep
* states should be resumed by genpd_prepare(): (1) if the device is enabled
* to wake up the system and it has to remain active for this purpose while the
* system is in the sleep state and (2) if the device is not enabled to wake up
* the system from sleep states and it generally doesn't generate wakeup signals
* by itself (those signals are generated on its behalf by other parts of the
* system). In the latter case it may be necessary to reconfigure the device's
* wakeup settings during system suspend, because it may have been set up to
* signal remote wakeup from the system's working state as needed by runtime PM.
* Return 'true' in either of the above cases.
*/
static bool resume_needed(struct device *dev,
const struct generic_pm_domain *genpd)
{
bool active_wakeup;
if (!device_can_wakeup(dev))
return false;
active_wakeup = genpd_is_active_wakeup(genpd);
return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
}
/** /**
* genpd_prepare - Start power transition of a device in a PM domain. * genpd_prepare - Start power transition of a device in a PM domain.
* @dev: Device to start the transition of. * @dev: Device to start the transition of.
@ -1135,14 +1107,6 @@ static int genpd_prepare(struct device *dev)
if (IS_ERR(genpd)) if (IS_ERR(genpd))
return -EINVAL; return -EINVAL;
/*
* If a wakeup request is pending for the device, it should be woken up
* at this point and a system wakeup event should be reported if it's
* set up to wake up the system from sleep states.
*/
if (resume_needed(dev, genpd))
pm_runtime_resume(dev);
genpd_lock(genpd); genpd_lock(genpd);
if (genpd->prepared_count++ == 0) if (genpd->prepared_count++ == 0)

View File

@ -137,7 +137,7 @@ static struct device *wakeup_source_device_create(struct device *parent,
struct wakeup_source *ws) struct wakeup_source *ws)
{ {
struct device *dev = NULL; struct device *dev = NULL;
int retval = -ENODEV; int retval;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) { if (!dev) {
@ -154,7 +154,7 @@ static struct device *wakeup_source_device_create(struct device *parent,
dev_set_drvdata(dev, ws); dev_set_drvdata(dev, ws);
device_set_pm_not_required(dev); device_set_pm_not_required(dev);
retval = kobject_set_name(&dev->kobj, "wakeup%d", ws->id); retval = dev_set_name(dev, "wakeup%d", ws->id);
if (retval) if (retval)
goto error; goto error;

View File

@ -1870,20 +1870,10 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
int err; int err;
int i, bars = 0; int i, bars = 0;
/* if (atomic_inc_return(&dev->enable_cnt) > 1) {
* Power state could be unknown at this point, either due to a fresh pci_update_current_state(dev, dev->current_state);
* boot or a device removal call. So get the current power state
* so that things like MSI message writing will behave as expected
* (e.g. if the device really is in D0 at enable time).
*/
if (dev->pm_cap) {
u16 pmcsr;
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
}
if (atomic_inc_return(&dev->enable_cnt) > 1)
return 0; /* already enabled */ return 0; /* already enabled */
}
bridge = pci_upstream_bridge(dev); bridge = pci_upstream_bridge(dev);
if (bridge) if (bridge)

View File

@ -1069,6 +1069,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
X86_MATCH_VENDOR_FAM(AMD, 0x17, &rapl_defaults_amd), X86_MATCH_VENDOR_FAM(AMD, 0x17, &rapl_defaults_amd),
X86_MATCH_VENDOR_FAM(AMD, 0x19, &rapl_defaults_amd), X86_MATCH_VENDOR_FAM(AMD, 0x19, &rapl_defaults_amd),
X86_MATCH_VENDOR_FAM(HYGON, 0x18, &rapl_defaults_amd),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, rapl_ids); MODULE_DEVICE_TABLE(x86cpu, rapl_ids);

View File

@ -150,6 +150,7 @@ static int rapl_msr_probe(struct platform_device *pdev)
case X86_VENDOR_INTEL: case X86_VENDOR_INTEL:
rapl_msr_priv = &rapl_msr_priv_intel; rapl_msr_priv = &rapl_msr_priv_intel;
break; break;
case X86_VENDOR_HYGON:
case X86_VENDOR_AMD: case X86_VENDOR_AMD:
rapl_msr_priv = &rapl_msr_priv_amd; rapl_msr_priv = &rapl_msr_priv_amd;
break; break;

View File

@ -279,7 +279,6 @@ static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {} static inline void thaw_processes(void) {}
static inline void thaw_kernel_threads(void) {} static inline void thaw_kernel_threads(void) {}
static inline bool try_to_freeze_nowarn(void) { return false; }
static inline bool try_to_freeze(void) { return false; } static inline bool try_to_freeze(void) { return false; }
static inline void freezer_do_not_count(void) {} static inline void freezer_do_not_count(void) {}

View File

@ -33,7 +33,7 @@ enum rapl_domain_reg_id {
RAPL_DOMAIN_REG_MAX, RAPL_DOMAIN_REG_MAX,
}; };
struct rapl_package; struct rapl_domain;
enum rapl_primitives { enum rapl_primitives {
ENERGY_COUNTER, ENERGY_COUNTER,

View File

@ -39,7 +39,6 @@ static inline void pm_vt_switch_unregister(struct device *dev)
* Device power management * Device power management
*/ */
struct device;
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern const char power_group_name[]; /* = "power" */ extern const char power_group_name[]; /* = "power" */

View File

@ -265,7 +265,7 @@ static inline void pm_runtime_no_callbacks(struct device *dev) {}
static inline void pm_runtime_irq_safe(struct device *dev) {} static inline void pm_runtime_irq_safe(struct device *dev) {}
static inline bool pm_runtime_is_irq_safe(struct device *dev) { return false; } static inline bool pm_runtime_is_irq_safe(struct device *dev) { return false; }
static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } static inline bool pm_runtime_has_no_callbacks(struct device *dev) { return false; }
static inline void pm_runtime_mark_last_busy(struct device *dev) {} static inline void pm_runtime_mark_last_busy(struct device *dev) {}
static inline void __pm_runtime_use_autosuspend(struct device *dev, static inline void __pm_runtime_use_autosuspend(struct device *dev,
bool use) {} bool use) {}

View File

@ -54,7 +54,7 @@ static void try_to_suspend(struct work_struct *work)
goto out; goto out;
/* /*
* If the wakeup occured for an unknown reason, wait to prevent the * If the wakeup occurred for an unknown reason, wait to prevent the
* system from trying to suspend and waking up in a tight loop. * system from trying to suspend and waking up in a tight loop.
*/ */
if (final_count == initial_count) if (final_count == initial_count)

View File

@ -329,7 +329,7 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
/** /**
* Data types related to memory bitmaps. * Data types related to memory bitmaps.
* *
* Memory bitmap is a structure consiting of many linked lists of * Memory bitmap is a structure consisting of many linked lists of
* objects. The main list's elements are of type struct zone_bitmap * objects. The main list's elements are of type struct zone_bitmap
* and each of them corresonds to one zone. For each zone bitmap * and each of them corresonds to one zone. For each zone bitmap
* object there is a list of objects of type struct bm_block that * object there is a list of objects of type struct bm_block that

View File

@ -884,7 +884,7 @@ out_clean:
* enough_swap - Make sure we have enough swap to save the image. * enough_swap - Make sure we have enough swap to save the image.
* *
* Returns TRUE or FALSE after checking the total amount of swap * Returns TRUE or FALSE after checking the total amount of swap
* space avaiable from the resume partition. * space available from the resume partition.
*/ */
static int enough_swap(unsigned int nr_pages) static int enough_swap(unsigned int nr_pages)