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
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);`
- 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

View File

@ -14312,6 +14312,15 @@ F: include/linux/pm_*
F: include/linux/powercap.h
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)
M: Mark Rutland <mark.rutland@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
* via /sys/firmware/memmap
*
* - the hibernation code uses it to generate a kernel-independent MD5
* fingerprint of the physical memory layout of a system.
* - the hibernation code uses it to generate a kernel-independent CRC32
* checksum of the physical memory layout of a system.
*
* - 'e820_table_kexec': a slightly modified (by the kernel) firmware version
* passed to us by the bootloader - the major difference between

View File

@ -13,8 +13,8 @@
#include <linux/kdebug.h>
#include <linux/cpu.h>
#include <linux/pgtable.h>
#include <crypto/hash.h>
#include <linux/types.h>
#include <linux/crc32.h>
#include <asm/e820/api.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;
}
#define MD5_DIGEST_SIZE 16
struct restore_data_record {
unsigned long jump_address;
unsigned long jump_address_phys;
unsigned long cr3;
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
* @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;
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) +
int size = offsetof(struct e820_table, entries) +
sizeof(struct e820_entry) * table->nr_entries;
if (crypto_shash_digest(desc, (u8 *)table, size, buf))
ret = -EINVAL;
kfree_sensitive(desc);
free_tfm:
crypto_free_shash(tfm);
return ret;
return ~crc32_le(~0, (unsigned char const *)table, size);
}
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
#define RESTORE_MAGIC 0x23456789ABCDEF01UL
#define RESTORE_MAGIC 0x23456789ABCDEF02UL
#else
#define RESTORE_MAGIC 0x12345678UL
#define RESTORE_MAGIC 0x12345679UL
#endif
/**
@ -179,7 +117,8 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
*/
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;
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");
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;
}
/**
* 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.
* @dev: Device to start the transition of.
@ -1135,14 +1107,6 @@ static int genpd_prepare(struct device *dev)
if (IS_ERR(genpd))
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);
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 device *dev = NULL;
int retval = -ENODEV;
int retval;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
@ -154,7 +154,7 @@ static struct device *wakeup_source_device_create(struct device *parent,
dev_set_drvdata(dev, ws);
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)
goto error;

View File

@ -1870,20 +1870,10 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
int err;
int i, bars = 0;
/*
* Power state could be unknown at this point, either due to a fresh
* 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)
if (atomic_inc_return(&dev->enable_cnt) > 1) {
pci_update_current_state(dev, dev->current_state);
return 0; /* already enabled */
}
bridge = pci_upstream_bridge(dev);
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, 0x19, &rapl_defaults_amd),
X86_MATCH_VENDOR_FAM(HYGON, 0x18, &rapl_defaults_amd),
{}
};
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:
rapl_msr_priv = &rapl_msr_priv_intel;
break;
case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
rapl_msr_priv = &rapl_msr_priv_amd;
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_kernel_threads(void) {}
static inline bool try_to_freeze_nowarn(void) { return false; }
static inline bool try_to_freeze(void) { return false; }
static inline void freezer_do_not_count(void) {}

View File

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

View File

@ -39,7 +39,6 @@ static inline void pm_vt_switch_unregister(struct device *dev)
* Device power management
*/
struct device;
#ifdef CONFIG_PM
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 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_use_autosuspend(struct device *dev,
bool use) {}

View File

@ -54,7 +54,7 @@ static void try_to_suspend(struct work_struct *work)
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.
*/
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.
*
* 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
* 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

View File

@ -884,7 +884,7 @@ out_clean:
* enough_swap - Make sure we have enough swap to save the image.
*
* 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)