mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 23:20:05 +00:00
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:
commit
bf0cc8360e
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {}
|
||||
|
@ -33,7 +33,7 @@ enum rapl_domain_reg_id {
|
||||
RAPL_DOMAIN_REG_MAX,
|
||||
};
|
||||
|
||||
struct rapl_package;
|
||||
struct rapl_domain;
|
||||
|
||||
enum rapl_primitives {
|
||||
ENERGY_COUNTER,
|
||||
|
@ -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" */
|
||||
|
@ -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) {}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user