Skip to content

Commit

Permalink
Merge branches 'pm-core', 'pm-pci', 'pm-sleep', 'pm-domains' and 'pow…
Browse files Browse the repository at this point in the history
…ercap'

* 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
  • Loading branch information
Rafael J. Wysocki committed Apr 26, 2021
6 parents dd9f2ae + 2c41233 + 4514d99 + e488023 + c1df456 + 35eb1f5 commit bf0cc83
Show file tree
Hide file tree
Showing 16 changed files with 41 additions and 135 deletions.
4 changes: 4 additions & 0 deletions Documentation/power/runtime_pm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/e820.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
89 changes: 14 additions & 75 deletions arch/x86/power/hibernate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
}

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;
return ~crc32_le(~0, (unsigned char const *)table, size);
}
#endif

#ifdef CONFIG_X86_64
#define RESTORE_MAGIC 0x23456789ABCDEF01UL
#define RESTORE_MAGIC 0x23456789ABCDEF02UL
#else
#define RESTORE_MAGIC 0x12345678UL
#define RESTORE_MAGIC 0x12345679UL
#endif

/**
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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;
}
Expand Down
36 changes: 0 additions & 36 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/base/power/wakeup_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;

Expand Down
16 changes: 3 additions & 13 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/powercap/intel_rapl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/powercap/intel_rapl_msr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion include/linux/freezer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/intel_rapl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ enum rapl_domain_reg_id {
RAPL_DOMAIN_REG_MAX,
};

struct rapl_package;
struct rapl_domain;

enum rapl_primitives {
ENERGY_COUNTER,
Expand Down
1 change: 0 additions & 1 deletion include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" */
Expand Down
2 changes: 1 addition & 1 deletion include/linux/pm_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down
2 changes: 1 addition & 1 deletion kernel/power/autosleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion kernel/power/snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion kernel/power/swap.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
* 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)
Expand Down

0 comments on commit bf0cc83

Please sign in to comment.