Commit a7d40268 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security layer fixes from James Morris:
 "Bugfixes for TPM and SELinux"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  IB/core: Fix static analysis warning in ib_policy_change_task
  IB/core: Fix uninitialized variable use in check_qp_port_pkey_settings
  tpm: do not suspend/resume if power stays on
  tpm: use tpm2_pcr_read() in tpm2_do_selftest()
  tpm: use tpm_buf functions in tpm2_pcr_read()
  tpm_tis: make ilb_base_addr static
  tpm: consolidate the TPM startup code
  tpm: Enable CLKRUN protocol for Braswell systems
  tpm/tpm_crb: fix priv->cmd_size initialisation
  tpm: fix a kernel memory leak in tpm-sysfs.c
  tpm: Issue a TPM2_Shutdown for TPM2 devices.
  Add "shutdown" to "struct class".
parents 98ced886 a750cfde
...@@ -2664,7 +2664,11 @@ void device_shutdown(void) ...@@ -2664,7 +2664,11 @@ void device_shutdown(void)
pm_runtime_get_noresume(dev); pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev); pm_runtime_barrier(dev);
if (dev->bus && dev->bus->shutdown) { if (dev->class && dev->class->shutdown) {
if (initcall_debug)
dev_info(dev, "shutdown\n");
dev->class->shutdown(dev);
} else if (dev->bus && dev->bus->shutdown) {
if (initcall_debug) if (initcall_debug)
dev_info(dev, "shutdown\n"); dev_info(dev, "shutdown\n");
dev->bus->shutdown(dev); dev->bus->shutdown(dev);
......
...@@ -142,6 +142,39 @@ static void tpm_devs_release(struct device *dev) ...@@ -142,6 +142,39 @@ static void tpm_devs_release(struct device *dev)
put_device(&chip->dev); put_device(&chip->dev);
} }
/**
* tpm_class_shutdown() - prepare the TPM device for loss of power.
* @dev: device to which the chip is associated.
*
* Issues a TPM2_Shutdown command prior to loss of power, as required by the
* TPM 2.0 spec.
* Then, calls bus- and device- specific shutdown code.
*
* XXX: This codepath relies on the fact that sysfs is not enabled for
* TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2
* has sysfs support enabled before TPM sysfs's implicit locking is fixed.
*/
static int tpm_class_shutdown(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
down_write(&chip->ops_sem);
tpm2_shutdown(chip, TPM2_SU_CLEAR);
chip->ops = NULL;
up_write(&chip->ops_sem);
}
/* Allow bus- and device-specific code to run. Note: since chip->ops
* is NULL, more-specific shutdown code will not be able to issue TPM
* commands.
*/
if (dev->bus && dev->bus->shutdown)
dev->bus->shutdown(dev);
else if (dev->driver && dev->driver->shutdown)
dev->driver->shutdown(dev);
return 0;
}
/** /**
* tpm_chip_alloc() - allocate a new struct tpm_chip instance * tpm_chip_alloc() - allocate a new struct tpm_chip instance
* @pdev: device to which the chip is associated * @pdev: device to which the chip is associated
...@@ -181,6 +214,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, ...@@ -181,6 +214,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
device_initialize(&chip->devs); device_initialize(&chip->devs);
chip->dev.class = tpm_class; chip->dev.class = tpm_class;
chip->dev.class->shutdown = tpm_class_shutdown;
chip->dev.release = tpm_dev_release; chip->dev.release = tpm_dev_release;
chip->dev.parent = pdev; chip->dev.parent = pdev;
chip->dev.groups = chip->groups; chip->dev.groups = chip->groups;
......
...@@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, ...@@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
} }
EXPORT_SYMBOL_GPL(tpm_transmit_cmd); EXPORT_SYMBOL_GPL(tpm_transmit_cmd);
#define TPM_ORD_STARTUP 153
#define TPM_ST_CLEAR 1
/**
* tpm_startup - turn on the TPM
* @chip: TPM chip to use
*
* Normally the firmware should start the TPM. This function is provided as a
* workaround if this does not happen. A legal case for this could be for
* example when a TPM emulator is used.
*
* Return: same as tpm_transmit_cmd()
*/
int tpm_startup(struct tpm_chip *chip)
{
struct tpm_buf buf;
int rc;
dev_info(&chip->dev, "starting up the TPM manually\n");
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
if (rc < 0)
return rc;
tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
} else {
rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
if (rc < 0)
return rc;
tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
}
rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
"attempting to start the TPM");
tpm_buf_destroy(&buf);
return rc;
}
#define TPM_DIGEST_SIZE 20 #define TPM_DIGEST_SIZE 20
#define TPM_RET_CODE_IDX 6 #define TPM_RET_CODE_IDX 6
#define TPM_INTERNAL_RESULT_SIZE 200 #define TPM_INTERNAL_RESULT_SIZE 200
...@@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, ...@@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
} }
EXPORT_SYMBOL_GPL(tpm_getcap); EXPORT_SYMBOL_GPL(tpm_getcap);
#define TPM_ORD_STARTUP 153
#define TPM_ST_CLEAR cpu_to_be16(1)
#define TPM_ST_STATE cpu_to_be16(2)
#define TPM_ST_DEACTIVATED cpu_to_be16(3)
static const struct tpm_input_header tpm_startup_header = {
.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
.length = cpu_to_be32(12),
.ordinal = cpu_to_be32(TPM_ORD_STARTUP)
};
static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
{
struct tpm_cmd_t start_cmd;
start_cmd.header.in = tpm_startup_header;
start_cmd.params.startup_in.startup_type = startup_type;
return tpm_transmit_cmd(chip, NULL, &start_cmd,
TPM_INTERNAL_RESULT_SIZE, 0,
0, "attempting to start the TPM");
}
int tpm_get_timeouts(struct tpm_chip *chip) int tpm_get_timeouts(struct tpm_chip *chip)
{ {
cap_t cap; cap_t cap;
...@@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
sizeof(cap.timeout)); sizeof(cap.timeout));
if (rc == TPM_ERR_INVALID_POSTINIT) { if (rc == TPM_ERR_INVALID_POSTINIT) {
/* The TPM is not started, we are the first to talk to it. if (tpm_startup(chip))
Execute a startup command. */
dev_info(&chip->dev, "Issuing TPM_STARTUP\n");
if (tpm_startup(chip, TPM_ST_CLEAR))
return rc; return rc;
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
...@@ -1102,6 +1119,9 @@ int tpm_pm_suspend(struct device *dev) ...@@ -1102,6 +1119,9 @@ int tpm_pm_suspend(struct device *dev)
if (chip == NULL) if (chip == NULL)
return -ENODEV; return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
return 0;
if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (chip->flags & TPM_CHIP_FLAG_TPM2) {
tpm2_shutdown(chip, TPM2_SU_STATE); tpm2_shutdown(chip, TPM2_SU_STATE);
return 0; return 0;
......
...@@ -36,9 +36,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, ...@@ -36,9 +36,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
ssize_t err; ssize_t err;
int i, rc; int i, rc;
char *str = buf; char *str = buf;
struct tpm_chip *chip = to_tpm_chip(dev); struct tpm_chip *chip = to_tpm_chip(dev);
memset(&tpm_cmd, 0, sizeof(tpm_cmd));
tpm_cmd.header.in = tpm_readpubek_header; tpm_cmd.header.in = tpm_readpubek_header;
err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
...@@ -294,6 +295,9 @@ static const struct attribute_group tpm_dev_group = { ...@@ -294,6 +295,9 @@ static const struct attribute_group tpm_dev_group = {
void tpm_sysfs_add_device(struct tpm_chip *chip) void tpm_sysfs_add_device(struct tpm_chip *chip)
{ {
/* XXX: If you wish to remove this restriction, you must first update
* tpm_sysfs to explicitly lock chip->ops.
*/
if (chip->flags & TPM_CHIP_FLAG_TPM2) if (chip->flags & TPM_CHIP_FLAG_TPM2)
return; return;
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <crypto/hash_info.h> #include <crypto/hash_info.h>
#ifdef CONFIG_X86
#include <asm/intel-family.h>
#endif
enum tpm_const { enum tpm_const {
TPM_MINOR = 224, /* officially assigned */ TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 4096, TPM_BUFSIZE = 4096,
...@@ -170,6 +174,7 @@ enum tpm_chip_flags { ...@@ -170,6 +174,7 @@ enum tpm_chip_flags {
TPM_CHIP_FLAG_IRQ = BIT(2), TPM_CHIP_FLAG_IRQ = BIT(2),
TPM_CHIP_FLAG_VIRTUAL = BIT(3), TPM_CHIP_FLAG_VIRTUAL = BIT(3),
TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4),
TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5),
}; };
struct tpm_bios_log { struct tpm_bios_log {
...@@ -378,10 +383,6 @@ struct tpm_getrandom_in { ...@@ -378,10 +383,6 @@ struct tpm_getrandom_in {
__be32 num_bytes; __be32 num_bytes;
} __packed; } __packed;
struct tpm_startup_in {
__be16 startup_type;
} __packed;
typedef union { typedef union {
struct tpm_readpubek_params_out readpubek_out; struct tpm_readpubek_params_out readpubek_out;
u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
...@@ -389,7 +390,6 @@ typedef union { ...@@ -389,7 +390,6 @@ typedef union {
struct tpm_pcrread_out pcrread_out; struct tpm_pcrread_out pcrread_out;
struct tpm_getrandom_in getrandom_in; struct tpm_getrandom_in getrandom_in;
struct tpm_getrandom_out getrandom_out; struct tpm_getrandom_out getrandom_out;
struct tpm_startup_in startup_in;
} tpm_cmd_params; } tpm_cmd_params;
struct tpm_cmd_t { struct tpm_cmd_t {
...@@ -515,6 +515,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, ...@@ -515,6 +515,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
const void *buf, size_t bufsiz, const void *buf, size_t bufsiz,
size_t min_rsp_body_length, unsigned int flags, size_t min_rsp_body_length, unsigned int flags,
const char *desc); const char *desc);
int tpm_startup(struct tpm_chip *chip);
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length); const char *desc, size_t min_cap_length);
int tpm_get_timeouts(struct tpm_chip *); int tpm_get_timeouts(struct tpm_chip *);
......
...@@ -35,24 +35,6 @@ struct tpm2_self_test_in { ...@@ -35,24 +35,6 @@ struct tpm2_self_test_in {
u8 full_test; u8 full_test;
} __packed; } __packed;
struct tpm2_pcr_read_in {
__be32 pcr_selects_cnt;
__be16 hash_alg;
u8 pcr_select_size;
u8 pcr_select[TPM2_PCR_SELECT_MIN];
} __packed;
struct tpm2_pcr_read_out {
__be32 update_cnt;
__be32 pcr_selects_cnt;
__be16 hash_alg;
u8 pcr_select_size;
u8 pcr_select[TPM2_PCR_SELECT_MIN];
__be32 digests_cnt;
__be16 digest_size;
u8 digest[TPM_DIGEST_SIZE];
} __packed;
struct tpm2_get_tpm_pt_in { struct tpm2_get_tpm_pt_in {
__be32 cap_id; __be32 cap_id;
__be32 property_id; __be32 property_id;
...@@ -79,8 +61,6 @@ struct tpm2_get_random_out { ...@@ -79,8 +61,6 @@ struct tpm2_get_random_out {
union tpm2_cmd_params { union tpm2_cmd_params {
struct tpm2_startup_in startup_in; struct tpm2_startup_in startup_in;
struct tpm2_self_test_in selftest_in; struct tpm2_self_test_in selftest_in;
struct tpm2_pcr_read_in pcrread_in;
struct tpm2_pcr_read_out pcrread_out;
struct tpm2_get_tpm_pt_in get_tpm_pt_in; struct tpm2_get_tpm_pt_in get_tpm_pt_in;
struct tpm2_get_tpm_pt_out get_tpm_pt_out; struct tpm2_get_tpm_pt_out get_tpm_pt_out;
struct tpm2_get_random_in getrandom_in; struct tpm2_get_random_in getrandom_in;
...@@ -227,18 +207,16 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { ...@@ -227,18 +207,16 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
TPM_UNDEFINED /* 18f */ TPM_UNDEFINED /* 18f */
}; };
#define TPM2_PCR_READ_IN_SIZE \ struct tpm2_pcr_read_out {
(sizeof(struct tpm_input_header) + \ __be32 update_cnt;
sizeof(struct tpm2_pcr_read_in)) __be32 pcr_selects_cnt;
__be16 hash_alg;
#define TPM2_PCR_READ_RESP_BODY_SIZE \ u8 pcr_select_size;
sizeof(struct tpm2_pcr_read_out) u8 pcr_select[TPM2_PCR_SELECT_MIN];
__be32 digests_cnt;
static const struct tpm_input_header tpm2_pcrread_header = { __be16 digest_size;
.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), u8 digest[];
.length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE), } __packed;
.ordinal = cpu_to_be32(TPM2_CC_PCR_READ)
};
/** /**
* tpm2_pcr_read() - read a PCR value * tpm2_pcr_read() - read a PCR value
...@@ -251,29 +229,33 @@ static const struct tpm_input_header tpm2_pcrread_header = { ...@@ -251,29 +229,33 @@ static const struct tpm_input_header tpm2_pcrread_header = {
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{ {
int rc; int rc;
struct tpm2_cmd cmd; struct tpm_buf buf;
u8 *buf; struct tpm2_pcr_read_out *out;
u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
if (pcr_idx >= TPM2_PLATFORM_PCR) if (pcr_idx >= TPM2_PLATFORM_PCR)
return -EINVAL; return -EINVAL;
cmd.header.in = tpm2_pcrread_header; rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); if (rc)
cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); return rc;
cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
memset(cmd.params.pcrread_in.pcr_select, 0, tpm_buf_append_u32(&buf, 1);
sizeof(cmd.params.pcrread_in.pcr_select)); tpm_buf_append_u16(&buf, TPM2_ALG_SHA1);
cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
tpm_buf_append(&buf, (const unsigned char *)pcr_select,
sizeof(pcr_select));
rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
TPM2_PCR_READ_RESP_BODY_SIZE, res_buf ? "attempting to read a pcr value" : NULL);
0, "attempting to read a pcr value"); if (rc == 0 && res_buf) {
if (rc == 0) { out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
buf = cmd.params.pcrread_out.digest; memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE);
memcpy(res_buf, buf, TPM_DIGEST_SIZE);
} }
tpm_buf_destroy(&buf);
return rc; return rc;
} }
...@@ -779,36 +761,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, ...@@ -779,36 +761,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
} }
EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
#define TPM2_STARTUP_IN_SIZE \
(sizeof(struct tpm_input_header) + \
sizeof(struct tpm2_startup_in))
static const struct tpm_input_header tpm2_startup_header = {
.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
.length = cpu_to_be32(TPM2_STARTUP_IN_SIZE),
.ordinal = cpu_to_be32(TPM2_CC_STARTUP)
};
/**
* tpm2_startup() - send startup command to the TPM chip
*
* @chip: TPM chip to use.
* @startup_type: startup type. The value is either
* TPM_SU_CLEAR or TPM_SU_STATE.
*
* Return: Same as with tpm_transmit_cmd.
*/
static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
{
struct tpm2_cmd cmd;
cmd.header.in = tpm2_startup_header;
cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
"attempting to start the TPM");
}
#define TPM2_SHUTDOWN_IN_SIZE \ #define TPM2_SHUTDOWN_IN_SIZE \
(sizeof(struct tpm_input_header) + \ (sizeof(struct tpm_input_header) + \
sizeof(struct tpm2_startup_in)) sizeof(struct tpm2_startup_in))
...@@ -928,7 +880,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip) ...@@ -928,7 +880,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
unsigned int loops; unsigned int loops;
unsigned int delay_msec = 100; unsigned int delay_msec = 100;
unsigned long duration; unsigned long duration;
struct tpm2_cmd cmd;
int i; int i;
duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
...@@ -941,20 +892,10 @@ static int tpm2_do_selftest(struct tpm_chip *chip) ...@@ -941,20 +892,10 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
for (i = 0; i < loops; i++) { for (i = 0; i < loops; i++) {
/* Attempt to read a PCR value */ /* Attempt to read a PCR value */
cmd.header.in = tpm2_pcrread_header; rc = tpm2_pcr_read(chip, 0, NULL);
cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
cmd.params.pcrread_in.pcr_select[0] = 0x01;
cmd.params.pcrread_in.pcr_select[1] = 0x00;
cmd.params.pcrread_in.pcr_select[2] = 0x00;
rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
NULL);
if (rc < 0) if (rc < 0)
break; break;
rc = be32_to_cpu(cmd.header.out.return_code);
if (rc != TPM2_RC_TESTING) if (rc != TPM2_RC_TESTING)
break; break;
...@@ -1150,7 +1091,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) ...@@ -1150,7 +1091,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
} }
if (rc == TPM2_RC_INITIALIZE) { if (rc == TPM2_RC_INITIALIZE) {
rc = tpm2_startup(chip, TPM2_SU_CLEAR); rc = tpm_startup(chip);
if (rc) if (rc)
goto out; goto out;
......
...@@ -514,11 +514,12 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, ...@@ -514,11 +514,12 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
goto out; goto out;
} }
priv->cmd_size = cmd_size;
priv->rsp = priv->cmd; priv->rsp = priv->cmd;
out: out:
if (!ret)
priv->cmd_size = cmd_size;
crb_go_idle(dev, priv); crb_go_idle(dev, priv);
return ret; return ret;
......
...@@ -36,6 +36,9 @@ int tpm_read_log_of(struct tpm_chip *chip) ...@@ -36,6 +36,9 @@ int tpm_read_log_of(struct tpm_chip *chip)
else else
return -ENODEV; return -ENODEV;
if (of_property_read_bool(np, "powered-while-suspended"))
chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
sizep = of_get_property(np, "linux,sml-size", NULL); sizep = of_get_property(np, "linux,sml-size", NULL);
basep = of_get_property(np, "linux,sml-base", NULL); basep = of_get_property(np, "linux,sml-base", NULL);
if (sizep == NULL && basep == NULL) if (sizep == NULL && basep == NULL)
......
...@@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev) ...@@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev)
} }
#endif #endif
#ifdef CONFIG_X86
#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000
#define ILB_REMAP_SIZE 0x100
#define LPC_CNTRL_REG_OFFSET 0x84
#define LPC_CLKRUN_EN (1 << 2)
static void __iomem *ilb_base_addr;
static inline bool is_bsw(void)
{
return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0);
}
/**
* tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
*/
static void tpm_platform_begin_xfer(void)
{
u32 clkrun_val;
if (!is_bsw())
return;
clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/* Disable LPC CLKRUN# */
clkrun_val &= ~LPC_CLKRUN_EN;
iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
}
/**
* tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
*/
static void tpm_platform_end_xfer(void)
{
u32 clkrun_val;
if (!is_bsw())
return;
clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/* Enable LPC CLKRUN# */
clkrun_val |= LPC_CLKRUN_EN;
iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
}
#else
static inline bool is_bsw(void)
{
return false;
}
static void tpm_platform_begin_xfer(void)
{
}
static void tpm_platform_end_xfer(void)
{
}
#endif
static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
u8 *result) u8 *result)
{ {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
while (len--) while (len--)
*result++ = ioread8(phy->iobase + addr); *result++ = ioread8(phy->iobase + addr);
tpm_platform_end_xfer();
return 0; return 0;
} }
...@@ -147,8 +227,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, ...@@ -147,8 +227,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
{ {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
while (len--) while (len--)
iowrite8(*value++, phy->iobase + addr); iowrite8(*value++, phy->iobase + addr);
tpm_platform_end_xfer();
return 0; return 0;
} }
...@@ -156,7 +241,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) ...@@ -156,7 +241,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
{ {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
*result = ioread16(phy->iobase + addr); *result = ioread16(phy->iobase + addr);
tpm_platform_end_xfer();
return 0; return 0;
} }
...@@ -164,7 +254,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) ...@@ -164,7 +254,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
{ {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
*result = ioread32(phy->iobase + addr); *result = ioread32(phy->iobase + addr);
tpm_platform_end_xfer();
return 0; return 0;
} }
...@@ -172,7 +267,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) ...@@ -172,7 +267,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
{ {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
iowrite32(value, phy->iobase + addr); iowrite32(value, phy->iobase + addr);
tpm_platform_end_xfer();
return 0; return 0;
} }
...@@ -360,6 +460,11 @@ static int __init init_tis(void) ...@@ -360,6 +460,11 @@ static int __init init_tis(void)
if (rc) if (rc)
goto err_force; goto err_force;
#ifdef CONFIG_X86
if (is_bsw())
ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
ILB_REMAP_SIZE);
#endif
rc = platform_driver_register(&tis_drv); rc = platform_driver_register(&tis_drv);
if (rc) if (rc)
goto err_platform; goto err_platform;
...@@ -378,6 +483,10 @@ static int __init init_tis(void) ...@@ -378,6 +483,10 @@ static int __init init_tis(void)
err_platform: err_platform:
if (force_pdev) if (force_pdev)
platform_device_unregister(force_pdev); platform_device_unregister(force_pdev);
#ifdef CONFIG_X86
if (is_bsw())
iounmap(ilb_base_addr);
#endif
err_force: err_force:
return rc; return rc;
} }
...@@ -387,6 +496,10 @@ static void __exit cleanup_tis(void) ...@@ -387,6 +496,10 @@ static void __exit cleanup_tis(void)
pnp_unregister_driver(&tis_pnp_driver); pnp_unregister_driver(&tis_pnp_driver);
platform_driver_unregister(&tis_drv); platform_driver_unregister(&tis_drv);
#ifdef CONFIG_X86
if (is_bsw())
iounmap(ilb_base_addr);
#endif
if (force_pdev) if (force_pdev)
platform_device_unregister(force_pdev); platform_device_unregister(force_pdev);
} }
......
...@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work) ...@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work)
WARN_ONCE(ret, WARN_ONCE(ret,
"ib_get_cached_subnet_prefix err: %d, this should never happen here\n", "ib_get_cached_subnet_prefix err: %d, this should never happen here\n",
ret); ret);
ib_security_cache_change(dev, i, sp); if (!ret)
ib_security_cache_change(dev, i, sp);
} }
} }
up_read(&lists_rwsem); up_read(&lists_rwsem);
......
...@@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps, ...@@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps,
return 0; return 0;
if (pps->main.state != IB_PORT_PKEY_NOT_VALID) { if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {
get_pkey_and_subnet_prefix(&pps->main, ret = get_pkey_and_subnet_prefix(&pps->main,
&pkey, &pkey,
&subnet_prefix); &subnet_prefix);
if (ret)
return ret;
ret = enforce_qp_pkey_security(pkey, ret = enforce_qp_pkey_security(pkey,
subnet_prefix, subnet_prefix,
sec); sec);
if (ret)
return ret;
} }
if (ret)
return ret;
if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) { if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {
get_pkey_and_subnet_prefix(&pps->alt, ret = get_pkey_and_subnet_prefix(&pps->alt,
&pkey, &pkey,
&subnet_prefix); &subnet_prefix);
if (ret)
return ret;
ret = enforce_qp_pkey_security(pkey, ret = enforce_qp_pkey_security(pkey,
subnet_prefix, subnet_prefix,
......
...@@ -375,6 +375,7 @@ int subsys_virtual_register(struct bus_type *subsys, ...@@ -375,6 +375,7 @@ int subsys_virtual_register(struct bus_type *subsys,
* @suspend: Used to put the device to sleep mode, usually to a low power * @suspend: Used to put the device to sleep mode, usually to a low power
* state. * state.
* @resume: Used to bring the device from the sleep mode. * @resume: Used to bring the device from the sleep mode.
* @shutdown: Called at shut-down time to quiesce the device.
* @ns_type: Callbacks so sysfs can detemine namespaces. * @ns_type: Callbacks so sysfs can detemine namespaces.
* @namespace: Namespace of the device belongs to this class. * @namespace: Namespace of the device belongs to this class.
* @pm: The default device power management operations of this class. * @pm: The default device power management operations of this class.
...@@ -403,6 +404,7 @@ struct class { ...@@ -403,6 +404,7 @@ struct class {
int (*suspend)(struct device *dev, pm_message_t state); int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev); int (*resume)(struct device *dev);
int (*shutdown)(struct device *dev);
const struct kobj_ns_type_operations *ns_type; const struct kobj_ns_type_operations *ns_type;
const void *(*namespace)(struct device *dev); const void *(*namespace)(struct device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment