Commit bf0cc836 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+9 −0
Original line number Diff line number Diff line
@@ -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>
+2 −2
Original line number Diff line number Diff line
@@ -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
+14 −75
Original line number Diff line number Diff line
@@ -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;
}

static int hibernation_e820_save(void *buf)
{
	return get_e820_md5(e820_table_firmware, buf);
	return ~crc32_le(~0, (unsigned char const *)table, size);
}

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;
	}
+0 −36
Original line number Diff line number Diff line
@@ -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)
Loading