forked from Minki/linux
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".
This commit is contained in:
commit
a7d4026834
@ -2664,7 +2664,11 @@ void device_shutdown(void)
|
||||
pm_runtime_get_noresume(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)
|
||||
dev_info(dev, "shutdown\n");
|
||||
dev->bus->shutdown(dev);
|
||||
|
@ -142,6 +142,39 @@ static void tpm_devs_release(struct device *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
|
||||
* @pdev: device to which the chip is associated
|
||||
@ -181,6 +214,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
||||
device_initialize(&chip->devs);
|
||||
|
||||
chip->dev.class = tpm_class;
|
||||
chip->dev.class->shutdown = tpm_class_shutdown;
|
||||
chip->dev.release = tpm_dev_release;
|
||||
chip->dev.parent = pdev;
|
||||
chip->dev.groups = chip->groups;
|
||||
|
@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
|
||||
}
|
||||
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_RET_CODE_IDX 6
|
||||
#define TPM_INTERNAL_RESULT_SIZE 200
|
||||
@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
|
||||
}
|
||||
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)
|
||||
{
|
||||
cap_t cap;
|
||||
@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
|
||||
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
|
||||
sizeof(cap.timeout));
|
||||
if (rc == TPM_ERR_INVALID_POSTINIT) {
|
||||
/* The TPM is not started, we are the first to talk to it.
|
||||
Execute a startup command. */
|
||||
dev_info(&chip->dev, "Issuing TPM_STARTUP\n");
|
||||
if (tpm_startup(chip, TPM_ST_CLEAR))
|
||||
if (tpm_startup(chip))
|
||||
return rc;
|
||||
|
||||
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
|
||||
@ -1102,6 +1119,9 @@ int tpm_pm_suspend(struct device *dev)
|
||||
if (chip == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
|
||||
return 0;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
||||
tpm2_shutdown(chip, TPM2_SU_STATE);
|
||||
return 0;
|
||||
|
@ -36,9 +36,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
|
||||
ssize_t err;
|
||||
int i, rc;
|
||||
char *str = buf;
|
||||
|
||||
struct tpm_chip *chip = to_tpm_chip(dev);
|
||||
|
||||
memset(&tpm_cmd, 0, sizeof(tpm_cmd));
|
||||
|
||||
tpm_cmd.header.in = tpm_readpubek_header;
|
||||
err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
|
||||
READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
|
||||
@ -294,6 +295,9 @@ static const struct attribute_group tpm_dev_group = {
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
|
@ -36,6 +36,10 @@
|
||||
#include <linux/highmem.h>
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/intel-family.h>
|
||||
#endif
|
||||
|
||||
enum tpm_const {
|
||||
TPM_MINOR = 224, /* officially assigned */
|
||||
TPM_BUFSIZE = 4096,
|
||||
@ -170,6 +174,7 @@ enum tpm_chip_flags {
|
||||
TPM_CHIP_FLAG_IRQ = BIT(2),
|
||||
TPM_CHIP_FLAG_VIRTUAL = BIT(3),
|
||||
TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4),
|
||||
TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5),
|
||||
};
|
||||
|
||||
struct tpm_bios_log {
|
||||
@ -378,10 +383,6 @@ struct tpm_getrandom_in {
|
||||
__be32 num_bytes;
|
||||
} __packed;
|
||||
|
||||
struct tpm_startup_in {
|
||||
__be16 startup_type;
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct tpm_readpubek_params_out readpubek_out;
|
||||
u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
|
||||
@ -389,7 +390,6 @@ typedef union {
|
||||
struct tpm_pcrread_out pcrread_out;
|
||||
struct tpm_getrandom_in getrandom_in;
|
||||
struct tpm_getrandom_out getrandom_out;
|
||||
struct tpm_startup_in startup_in;
|
||||
} tpm_cmd_params;
|
||||
|
||||
struct tpm_cmd_t {
|
||||
@ -515,6 +515,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
|
||||
const void *buf, size_t bufsiz,
|
||||
size_t min_rsp_body_length, unsigned int flags,
|
||||
const char *desc);
|
||||
int tpm_startup(struct tpm_chip *chip);
|
||||
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
|
||||
const char *desc, size_t min_cap_length);
|
||||
int tpm_get_timeouts(struct tpm_chip *);
|
||||
|
@ -35,24 +35,6 @@ struct tpm2_self_test_in {
|
||||
u8 full_test;
|
||||
} __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 {
|
||||
__be32 cap_id;
|
||||
__be32 property_id;
|
||||
@ -79,8 +61,6 @@ struct tpm2_get_random_out {
|
||||
union tpm2_cmd_params {
|
||||
struct tpm2_startup_in startup_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_out get_tpm_pt_out;
|
||||
struct tpm2_get_random_in getrandom_in;
|
||||
@ -227,18 +207,16 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
|
||||
TPM_UNDEFINED /* 18f */
|
||||
};
|
||||
|
||||
#define TPM2_PCR_READ_IN_SIZE \
|
||||
(sizeof(struct tpm_input_header) + \
|
||||
sizeof(struct tpm2_pcr_read_in))
|
||||
|
||||
#define TPM2_PCR_READ_RESP_BODY_SIZE \
|
||||
sizeof(struct tpm2_pcr_read_out)
|
||||
|
||||
static const struct tpm_input_header tpm2_pcrread_header = {
|
||||
.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
|
||||
.length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE),
|
||||
.ordinal = cpu_to_be32(TPM2_CC_PCR_READ)
|
||||
};
|
||||
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[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* tpm2_pcr_read() - read a PCR value
|
||||
@ -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 rc;
|
||||
struct tpm2_cmd cmd;
|
||||
u8 *buf;
|
||||
struct tpm_buf buf;
|
||||
struct tpm2_pcr_read_out *out;
|
||||
u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
|
||||
|
||||
if (pcr_idx >= TPM2_PLATFORM_PCR)
|
||||
return -EINVAL;
|
||||
|
||||
cmd.header.in = tpm2_pcrread_header;
|
||||
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;
|
||||
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
memset(cmd.params.pcrread_in.pcr_select, 0,
|
||||
sizeof(cmd.params.pcrread_in.pcr_select));
|
||||
cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
|
||||
pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
|
||||
|
||||
rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
|
||||
TPM2_PCR_READ_RESP_BODY_SIZE,
|
||||
0, "attempting to read a pcr value");
|
||||
if (rc == 0) {
|
||||
buf = cmd.params.pcrread_out.digest;
|
||||
memcpy(res_buf, buf, TPM_DIGEST_SIZE);
|
||||
tpm_buf_append_u32(&buf, 1);
|
||||
tpm_buf_append_u16(&buf, TPM2_ALG_SHA1);
|
||||
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, buf.data, PAGE_SIZE, 0, 0,
|
||||
res_buf ? "attempting to read a pcr value" : NULL);
|
||||
if (rc == 0 && res_buf) {
|
||||
out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
|
||||
memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
tpm_buf_destroy(&buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
#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 \
|
||||
(sizeof(struct tpm_input_header) + \
|
||||
sizeof(struct tpm2_startup_in))
|
||||
@ -928,7 +880,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
|
||||
unsigned int loops;
|
||||
unsigned int delay_msec = 100;
|
||||
unsigned long duration;
|
||||
struct tpm2_cmd cmd;
|
||||
int i;
|
||||
|
||||
duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
|
||||
@ -941,20 +892,10 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
|
||||
|
||||
for (i = 0; i < loops; i++) {
|
||||
/* Attempt to read a PCR value */
|
||||
cmd.header.in = tpm2_pcrread_header;
|
||||
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);
|
||||
rc = tpm2_pcr_read(chip, 0, NULL);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
rc = be32_to_cpu(cmd.header.out.return_code);
|
||||
if (rc != TPM2_RC_TESTING)
|
||||
break;
|
||||
|
||||
@ -1150,7 +1091,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
|
||||
}
|
||||
|
||||
if (rc == TPM2_RC_INITIALIZE) {
|
||||
rc = tpm2_startup(chip, TPM2_SU_CLEAR);
|
||||
rc = tpm_startup(chip);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
@ -514,11 +514,12 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->cmd_size = cmd_size;
|
||||
|
||||
priv->rsp = priv->cmd;
|
||||
|
||||
out:
|
||||
if (!ret)
|
||||
priv->cmd_size = cmd_size;
|
||||
|
||||
crb_go_idle(dev, priv);
|
||||
|
||||
return ret;
|
||||
|
@ -36,6 +36,9 @@ int tpm_read_log_of(struct tpm_chip *chip)
|
||||
else
|
||||
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);
|
||||
basep = of_get_property(np, "linux,sml-base", NULL);
|
||||
if (sizep == NULL && basep == NULL)
|
||||
|
@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev)
|
||||
}
|
||||
#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,
|
||||
u8 *result)
|
||||
{
|
||||
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
|
||||
|
||||
tpm_platform_begin_xfer();
|
||||
|
||||
while (len--)
|
||||
*result++ = ioread8(phy->iobase + addr);
|
||||
|
||||
tpm_platform_end_xfer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
tpm_platform_begin_xfer();
|
||||
|
||||
while (len--)
|
||||
iowrite8(*value++, phy->iobase + addr);
|
||||
|
||||
tpm_platform_end_xfer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
tpm_platform_begin_xfer();
|
||||
|
||||
*result = ioread16(phy->iobase + addr);
|
||||
|
||||
tpm_platform_end_xfer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
tpm_platform_begin_xfer();
|
||||
|
||||
*result = ioread32(phy->iobase + addr);
|
||||
|
||||
tpm_platform_end_xfer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
tpm_platform_begin_xfer();
|
||||
|
||||
iowrite32(value, phy->iobase + addr);
|
||||
|
||||
tpm_platform_end_xfer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -360,6 +460,11 @@ static int __init init_tis(void)
|
||||
if (rc)
|
||||
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);
|
||||
if (rc)
|
||||
goto err_platform;
|
||||
@ -378,6 +483,10 @@ err_pnp:
|
||||
err_platform:
|
||||
if (force_pdev)
|
||||
platform_device_unregister(force_pdev);
|
||||
#ifdef CONFIG_X86
|
||||
if (is_bsw())
|
||||
iounmap(ilb_base_addr);
|
||||
#endif
|
||||
err_force:
|
||||
return rc;
|
||||
}
|
||||
@ -387,6 +496,10 @@ static void __exit cleanup_tis(void)
|
||||
pnp_unregister_driver(&tis_pnp_driver);
|
||||
platform_driver_unregister(&tis_drv);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if (is_bsw())
|
||||
iounmap(ilb_base_addr);
|
||||
#endif
|
||||
if (force_pdev)
|
||||
platform_device_unregister(force_pdev);
|
||||
}
|
||||
|
@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work)
|
||||
WARN_ONCE(ret,
|
||||
"ib_get_cached_subnet_prefix err: %d, this should never happen here\n",
|
||||
ret);
|
||||
ib_security_cache_change(dev, i, sp);
|
||||
if (!ret)
|
||||
ib_security_cache_change(dev, i, sp);
|
||||
}
|
||||
}
|
||||
up_read(&lists_rwsem);
|
||||
|
@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps,
|
||||
return 0;
|
||||
|
||||
if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {
|
||||
get_pkey_and_subnet_prefix(&pps->main,
|
||||
&pkey,
|
||||
&subnet_prefix);
|
||||
ret = get_pkey_and_subnet_prefix(&pps->main,
|
||||
&pkey,
|
||||
&subnet_prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = enforce_qp_pkey_security(pkey,
|
||||
subnet_prefix,
|
||||
sec);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {
|
||||
get_pkey_and_subnet_prefix(&pps->alt,
|
||||
&pkey,
|
||||
&subnet_prefix);
|
||||
ret = get_pkey_and_subnet_prefix(&pps->alt,
|
||||
&pkey,
|
||||
&subnet_prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = enforce_qp_pkey_security(pkey,
|
||||
subnet_prefix,
|
||||
|
@ -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
|
||||
* state.
|
||||
* @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.
|
||||
* @namespace: Namespace of the device belongs to this class.
|
||||
* @pm: The default device power management operations of this class.
|
||||
@ -403,6 +404,7 @@ struct class {
|
||||
|
||||
int (*suspend)(struct device *dev, pm_message_t state);
|
||||
int (*resume)(struct device *dev);
|
||||
int (*shutdown)(struct device *dev);
|
||||
|
||||
const struct kobj_ns_type_operations *ns_type;
|
||||
const void *(*namespace)(struct device *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user