This pull request has only some minor tweaks.
 
 BR, Jarkko
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQRE6pSOnaBC00OEHEIaerohdGur0gUCZz+7VQAKCRAaerohdGur
 0up2AQCVWdhQq3JdGyU6CHEz28ZrcFCR5Mlwr6XHhtXeDb/jlAEA1CjVtSFho2ir
 bfaTfirN7RWEFdZyDpzqwROYu03rfwg=
 =cm2z
 -----END PGP SIGNATURE-----

Merge tag 'tpmdd-next-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd

Pull TPM updates from Jarkko Sakkinen:
 "Only some minor tweaks"

* tag 'tpmdd-next-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm: atmel: Drop PPC64 specific MMIO setup
  char: tpm: cr50: Add new device/vendor ID 0x50666666
  char: tpm: cr50: Move i2c locking to request/relinquish locality ops
  char: tpm: cr50: Use generic request/relinquish locality ops
  tpm: ibmvtpm: Set TPM_OPS_AUTO_STARTUP flag on driver
This commit is contained in:
Linus Torvalds 2024-11-22 17:25:32 -08:00
commit 619d996c86
6 changed files with 167 additions and 222 deletions

View File

@ -162,7 +162,7 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
depends on PPC64 || HAS_IOPORT_MAP
depends on HAS_IOPORT_MAP
depends on HAS_IOPORT
help
If you have a TPM security chip from Atmel say Yes and it

View File

@ -1390,5 +1390,4 @@ int tpm2_sessions_init(struct tpm_chip *chip)
return rc;
}
EXPORT_SYMBOL(tpm2_sessions_init);
#endif /* CONFIG_TCG_TPM2_HMAC */

View File

@ -15,7 +15,66 @@
*/
#include "tpm.h"
#include "tpm_atmel.h"
struct tpm_atmel_priv {
int region_size;
int have_region;
unsigned long base;
void __iomem *iobase;
};
#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + (offset))
#define atmel_putb(val, chip, offset) \
outb(val, atmel_get_priv(chip)->base + (offset))
#define atmel_request_region request_region
#define atmel_release_region release_region
/* Atmel definitions */
enum tpm_atmel_addr {
TPM_ATMEL_BASE_ADDR_LO = 0x08,
TPM_ATMEL_BASE_ADDR_HI = 0x09
};
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
return inb(base + 1) & 0xFF;
}
/* Verify this is a 1.1 Atmel TPM */
static int atmel_verify_tpm11(void)
{
/* verify that it is an Atmel part */
if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
tpm_read_index(TPM_ADDR, 5) != 'T' ||
tpm_read_index(TPM_ADDR, 6) != 'M' ||
tpm_read_index(TPM_ADDR, 7) != 'L')
return 1;
/* query chip for its version number */
if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
tpm_read_index(TPM_ADDR, 0x01) != 1)
return 1;
/* This is an atmel supported part */
return 0;
}
/* Determine where to talk to device */
static void __iomem *atmel_get_base_addr(unsigned long *base, int *region_size)
{
int lo, hi;
if (atmel_verify_tpm11() != 0)
return NULL;
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
*base = (hi << 8) | lo;
*region_size = 2;
return ioport_map(*base, *region_size);
}
/* write status bits */
enum tpm_atmel_write_status {
@ -142,7 +201,6 @@ static void atml_plat_remove(void)
tpm_chip_unregister(chip);
if (priv->have_region)
atmel_release_region(priv->base, priv->region_size);
atmel_put_base_addr(priv->iobase);
platform_device_unregister(pdev);
}
@ -211,7 +269,6 @@ static int __init init_atmel(void)
err_unreg_dev:
platform_device_unregister(pdev);
err_rel_reg:
atmel_put_base_addr(iobase);
if (have_region)
atmel_release_region(base,
region_size);

View File

@ -1,140 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2005 IBM Corporation
*
* Authors:
* Kylene Hall <kjhall@us.ibm.com>
*
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
*
* Device driver for TCG/TCPA TPM (trusted platform module).
* Specifications at www.trustedcomputinggroup.org
*
* These difference are required on power because the device must be
* discovered through the device tree and iomap must be used to get
* around the need for holes in the io_page_mask. This does not happen
* automatically because the tpm is not a normal pci device and lives
* under the root node.
*/
struct tpm_atmel_priv {
int region_size;
int have_region;
unsigned long base;
void __iomem *iobase;
};
#ifdef CONFIG_PPC64
#include <linux/of.h>
#define atmel_getb(priv, offset) readb(priv->iobase + offset)
#define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
#define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region
static inline void atmel_put_base_addr(void __iomem *iobase)
{
iounmap(iobase);
}
static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
struct device_node *dn;
unsigned long address, size;
const unsigned int *reg;
int reglen;
int naddrc;
int nsizec;
dn = of_find_node_by_name(NULL, "tpm");
if (!dn)
return NULL;
if (!of_device_is_compatible(dn, "AT97SC3201")) {
of_node_put(dn);
return NULL;
}
reg = of_get_property(dn, "reg", &reglen);
naddrc = of_n_addr_cells(dn);
nsizec = of_n_size_cells(dn);
of_node_put(dn);
if (naddrc == 2)
address = ((unsigned long) reg[0] << 32) | reg[1];
else
address = reg[0];
if (nsizec == 2)
size =
((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1];
else
size = reg[naddrc];
*base = address;
*region_size = size;
return ioremap(*base, *region_size);
}
#else
#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
#define atmel_putb(val, chip, offset) \
outb(val, atmel_get_priv(chip)->base + offset)
#define atmel_request_region request_region
#define atmel_release_region release_region
/* Atmel definitions */
enum tpm_atmel_addr {
TPM_ATMEL_BASE_ADDR_LO = 0x08,
TPM_ATMEL_BASE_ADDR_HI = 0x09
};
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
return inb(base+1) & 0xFF;
}
/* Verify this is a 1.1 Atmel TPM */
static int atmel_verify_tpm11(void)
{
/* verify that it is an Atmel part */
if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
tpm_read_index(TPM_ADDR, 5) != 'T' ||
tpm_read_index(TPM_ADDR, 6) != 'M' ||
tpm_read_index(TPM_ADDR, 7) != 'L')
return 1;
/* query chip for its version number */
if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
tpm_read_index(TPM_ADDR, 0x01) != 1)
return 1;
/* This is an atmel supported part */
return 0;
}
static inline void atmel_put_base_addr(void __iomem *iobase)
{
}
/* Determine where to talk to device */
static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
int lo, hi;
if (atmel_verify_tpm11() != 0)
return NULL;
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
*base = (hi << 8) | lo;
*region_size = 2;
return ioport_map(*base, *region_size);
}
#endif

View File

@ -450,6 +450,7 @@ static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops tpm_ibmvtpm = {
.flags = TPM_OPS_AUTO_STARTUP,
.recv = tpm_ibmvtpm_recv,
.send = tpm_ibmvtpm_send,
.cancel = tpm_ibmvtpm_cancel,
@ -690,20 +691,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
if (!strcmp(id->compat, "IBM,vtpm20"))
chip->flags |= TPM_CHIP_FLAG_TPM2;
rc = tpm_get_timeouts(chip);
if (rc)
goto init_irq_cleanup;
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
rc = tpm2_get_cc_attrs_tbl(chip);
if (rc)
goto init_irq_cleanup;
rc = tpm2_sessions_init(chip);
if (rc)
goto init_irq_cleanup;
}
return tpm_chip_register(chip);
init_irq_cleanup:
do {

View File

@ -17,6 +17,7 @@
*/
#include <linux/acpi.h>
#include <linux/bug.h>
#include <linux/completion.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@ -30,11 +31,13 @@
#define TPM_CR50_MAX_BUFSIZE 64
#define TPM_CR50_TIMEOUT_SHORT_MS 2 /* Short timeout during transactions */
#define TPM_CR50_TIMEOUT_NOIRQ_MS 20 /* Timeout for TPM ready without IRQ */
#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID reg value */
#define TPM_TI50_I2C_DID_VID 0x504a6666L /* Device and vendor ID reg value */
#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID for Cr50 H1 */
#define TPM_TI50_DT_I2C_DID_VID 0x504a6666L /* Device and vendor ID for Ti50 DT */
#define TPM_TI50_OT_I2C_DID_VID 0x50666666L /* Device and vendor ID for TI50 OT */
#define TPM_CR50_I2C_MAX_RETRIES 3 /* Max retries due to I2C errors */
#define TPM_CR50_I2C_RETRY_DELAY_LO 55 /* Min usecs between retries on I2C */
#define TPM_CR50_I2C_RETRY_DELAY_HI 65 /* Max usecs between retries on I2C */
#define TPM_CR50_I2C_DEFAULT_LOC 0
#define TPM_I2C_ACCESS(l) (0x0000 | ((l) << 4))
#define TPM_I2C_STS(l) (0x0001 | ((l) << 4))
@ -199,8 +202,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
};
int rc;
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
/* Prepare for completion interrupt */
tpm_cr50_i2c_enable_tpm_irq(chip);
@ -219,7 +220,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
out:
tpm_cr50_i2c_disable_tpm_irq(chip);
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (rc < 0)
return rc;
@ -261,8 +261,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
priv->buf[0] = addr;
memcpy(priv->buf + 1, buffer, len);
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
/* Prepare for completion interrupt */
tpm_cr50_i2c_enable_tpm_irq(chip);
@ -276,7 +274,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
out:
tpm_cr50_i2c_disable_tpm_irq(chip);
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (rc < 0)
return rc;
@ -285,25 +282,26 @@ out:
}
/**
* tpm_cr50_check_locality() - Verify TPM locality 0 is active.
* tpm_cr50_check_locality() - Verify if required TPM locality is active.
* @chip: A TPM chip.
* @loc: Locality to be verified
*
* Return:
* - 0: Success.
* - loc: Success.
* - -errno: A POSIX error code.
*/
static int tpm_cr50_check_locality(struct tpm_chip *chip)
static int tpm_cr50_check_locality(struct tpm_chip *chip, int loc)
{
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;
u8 buf;
int rc;
rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
if (rc < 0)
return rc;
if ((buf & mask) == mask)
return 0;
return loc;
return -EIO;
}
@ -311,53 +309,72 @@ static int tpm_cr50_check_locality(struct tpm_chip *chip)
/**
* tpm_cr50_release_locality() - Release TPM locality.
* @chip: A TPM chip.
* @force: Flag to force release if set.
*/
static void tpm_cr50_release_locality(struct tpm_chip *chip, bool force)
{
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
u8 addr = TPM_I2C_ACCESS(0);
u8 buf;
if (tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf)) < 0)
return;
if (force || (buf & mask) == mask) {
buf = TPM_ACCESS_ACTIVE_LOCALITY;
tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
}
}
/**
* tpm_cr50_request_locality() - Request TPM locality 0.
* @chip: A TPM chip.
* @loc: Locality to be released
*
* Return:
* - 0: Success.
* - -errno: A POSIX error code.
*/
static int tpm_cr50_request_locality(struct tpm_chip *chip)
static int tpm_cr50_release_locality(struct tpm_chip *chip, int loc)
{
struct i2c_client *client = to_i2c_client(chip->dev.parent);
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
u8 addr = TPM_I2C_ACCESS(loc);
u8 buf;
int rc;
rc = tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf));
if (rc < 0)
goto unlock_out;
if ((buf & mask) == mask) {
buf = TPM_ACCESS_ACTIVE_LOCALITY;
rc = tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
}
unlock_out:
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return rc;
}
/**
* tpm_cr50_request_locality() - Request TPM locality.
* @chip: A TPM chip.
* @loc: Locality to be requested.
*
* Return:
* - loc: Success.
* - -errno: A POSIX error code.
*/
static int tpm_cr50_request_locality(struct tpm_chip *chip, int loc)
{
struct i2c_client *client = to_i2c_client(chip->dev.parent);
u8 buf = TPM_ACCESS_REQUEST_USE;
unsigned long stop;
int rc;
if (!tpm_cr50_check_locality(chip))
return 0;
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
if (tpm_cr50_check_locality(chip, loc) == loc)
return loc;
rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
if (rc < 0)
return rc;
goto unlock_out;
stop = jiffies + chip->timeout_a;
do {
if (!tpm_cr50_check_locality(chip))
return 0;
if (tpm_cr50_check_locality(chip, loc) == loc)
return loc;
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
} while (time_before(jiffies, stop));
return -ETIMEDOUT;
rc = -ETIMEDOUT;
unlock_out:
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return rc;
}
/**
@ -373,7 +390,7 @@ static u8 tpm_cr50_i2c_tis_status(struct tpm_chip *chip)
{
u8 buf[4];
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0)
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0)
return 0;
return buf[0];
@ -389,7 +406,7 @@ static void tpm_cr50_i2c_tis_set_ready(struct tpm_chip *chip)
{
u8 buf[4] = { TPM_STS_COMMAND_READY };
tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), buf, sizeof(buf));
tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf));
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
}
@ -419,7 +436,7 @@ static int tpm_cr50_i2c_get_burst_and_status(struct tpm_chip *chip, u8 mask,
stop = jiffies + chip->timeout_b;
do {
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0) {
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0) {
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
continue;
}
@ -453,7 +470,7 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
u8 mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
size_t burstcnt, cur, len, expected;
u8 addr = TPM_I2C_DATA_FIFO(0);
u8 addr = TPM_I2C_DATA_FIFO(chip->locality);
u32 status;
int rc;
@ -515,7 +532,6 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
goto out_err;
}
tpm_cr50_release_locality(chip, false);
return cur;
out_err:
@ -523,7 +539,6 @@ out_err:
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
tpm_cr50_i2c_tis_set_ready(chip);
tpm_cr50_release_locality(chip, false);
return rc;
}
@ -545,10 +560,6 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
u32 status;
int rc;
rc = tpm_cr50_request_locality(chip);
if (rc < 0)
return rc;
/* Wait until TPM is ready for a command */
stop = jiffies + chip->timeout_b;
while (!(tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) {
@ -577,7 +588,8 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
* that is inserted by tpm_cr50_i2c_write()
*/
limit = min_t(size_t, burstcnt - 1, len);
rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(0), &buf[sent], limit);
rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(chip->locality),
&buf[sent], limit);
if (rc < 0) {
dev_err(&chip->dev, "Write failed\n");
goto out_err;
@ -598,7 +610,7 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
}
/* Start the TPM command */
rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), tpm_go,
rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), tpm_go,
sizeof(tpm_go));
if (rc < 0) {
dev_err(&chip->dev, "Start command failed\n");
@ -611,7 +623,6 @@ out_err:
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
tpm_cr50_i2c_tis_set_ready(chip);
tpm_cr50_release_locality(chip, false);
return rc;
}
@ -650,6 +661,8 @@ static const struct tpm_class_ops cr50_i2c = {
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_canceled = &tpm_cr50_i2c_req_canceled,
.request_locality = &tpm_cr50_request_locality,
.relinquish_locality = &tpm_cr50_release_locality,
};
#ifdef CONFIG_ACPI
@ -668,6 +681,27 @@ static const struct of_device_id of_cr50_i2c_match[] = {
MODULE_DEVICE_TABLE(of, of_cr50_i2c_match);
#endif
/**
* tpm_cr50_vid_to_name() - Maps VID to name.
* @vendor: Vendor identifier to map to name
*
* Return:
* A valid string for the vendor or empty string
*/
static const char *tpm_cr50_vid_to_name(u32 vendor)
{
switch (vendor) {
case TPM_CR50_I2C_DID_VID:
return "cr50";
case TPM_TI50_DT_I2C_DID_VID:
return "ti50 DT";
case TPM_TI50_OT_I2C_DID_VID:
return "ti50 OT";
default:
return "unknown";
}
}
/**
* tpm_cr50_i2c_probe() - Driver probe function.
* @client: I2C client information.
@ -684,6 +718,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
u32 vendor;
u8 buf[4];
int rc;
int loc;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@ -726,29 +761,37 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
TPM_CR50_TIMEOUT_NOIRQ_MS);
}
rc = tpm_cr50_request_locality(chip);
if (rc < 0) {
loc = tpm_cr50_request_locality(chip, TPM_CR50_I2C_DEFAULT_LOC);
if (loc < 0) {
dev_err(dev, "Could not request locality\n");
return rc;
return loc;
}
/* Read four bytes from DID_VID register */
rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(0), buf, sizeof(buf));
rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(loc), buf, sizeof(buf));
if (rc < 0) {
dev_err(dev, "Could not read vendor id\n");
tpm_cr50_release_locality(chip, true);
if (tpm_cr50_release_locality(chip, loc))
dev_err(dev, "Could not release locality\n");
return rc;
}
rc = tpm_cr50_release_locality(chip, loc);
if (rc) {
dev_err(dev, "Could not release locality\n");
return rc;
}
vendor = le32_to_cpup((__le32 *)buf);
if (vendor != TPM_CR50_I2C_DID_VID && vendor != TPM_TI50_I2C_DID_VID) {
if (vendor != TPM_CR50_I2C_DID_VID &&
vendor != TPM_TI50_DT_I2C_DID_VID &&
vendor != TPM_TI50_OT_I2C_DID_VID) {
dev_err(dev, "Vendor ID did not match! ID was %08x\n", vendor);
tpm_cr50_release_locality(chip, true);
return -ENODEV;
}
dev_info(dev, "%s TPM 2.0 (i2c 0x%02x irq %d id 0x%x)\n",
vendor == TPM_TI50_I2C_DID_VID ? "ti50" : "cr50",
tpm_cr50_vid_to_name(vendor),
client->addr, client->irq, vendor >> 16);
return tpm_chip_register(chip);
}
@ -772,7 +815,6 @@ static void tpm_cr50_i2c_remove(struct i2c_client *client)
}
tpm_chip_unregister(chip);
tpm_cr50_release_locality(chip, true);
}
static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);