This commit is contained in:
James Morris 2015-02-16 13:41:46 +11:00
commit cd07db5f27
6 changed files with 85 additions and 62 deletions

View File

@ -901,8 +901,10 @@ int tpm_pm_suspend(struct device *dev)
if (chip == NULL)
return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return tpm2_shutdown(chip, TPM2_SU_CLEAR);
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
tpm2_shutdown(chip, TPM2_SU_STATE);
return 0;
}
/* for buggy tpm, flush pcrs with extend to selected dummy */
if (tpm_suspend_pcr) {

View File

@ -432,7 +432,8 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet);
extern int tpm2_gen_interrupt(struct tpm_chip *chip);
extern int tpm2_probe(struct tpm_chip *chip);

View File

@ -456,20 +456,23 @@ static const struct tpm_input_header tpm2_shutdown_header = {
* @chip: TPM chip to use.
* @shutdown_type shutdown type. The value is either
* TPM_SU_CLEAR or TPM_SU_STATE.
*
* 0 is returned when the operation is successful. If a negative number is
* returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error.
*/
int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
{
struct tpm2_cmd cmd;
int rc;
cmd.header.in = tpm2_shutdown_header;
cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
"stopping the TPM");
rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
/* In places where shutdown command is sent there's no much we can do
* except print the error code on a system failure.
*/
if (rc < 0)
dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
rc);
}
EXPORT_SYMBOL_GPL(tpm2_shutdown);
@ -598,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest);
/**
* tpm2_gen_interrupt() - generate an interrupt
* @chip: TPM chip to use
* @quiet: surpress the error message
*
* 0 is returned when the operation is successful. If a negative number is
* returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error.
*/
int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet)
int tpm2_gen_interrupt(struct tpm_chip *chip)
{
const char *desc = NULL;
u32 dummy;
if (!quiet)
desc = "attempting to generate an interrupt";
return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc);
return tpm2_get_tpm_pt(chip, 0x100, &dummy,
"attempting to generate an interrupt");
}
EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
/**
* tpm2_probe() - probe TPM 2.0
* @chip: TPM chip to use
*
* Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
* the reply tag.
*/
int tpm2_probe(struct tpm_chip *chip)
{
struct tpm2_cmd cmd;
int rc;
cmd.header.in = tpm2_get_tpm_pt_header;
cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
if (rc < 0)
return rc;
else if (rc < TPM_HEADER_SIZE)
return -EFAULT;
if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
chip->flags |= TPM_CHIP_FLAG_TPM2;
return 0;
}
EXPORT_SYMBOL_GPL(tpm2_probe);

View File

@ -95,21 +95,7 @@ struct crb_priv {
u8 __iomem *rsp;
};
#ifdef CONFIG_PM_SLEEP
static int crb_resume(struct device *dev)
{
int rc;
struct tpm_chip *chip = dev_get_drvdata(dev);
rc = tpm2_shutdown(chip, TPM2_SU_STATE);
if (!rc)
rc = tpm2_do_selftest(chip);
return rc;
}
#endif
static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume);
static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
static u8 crb_status(struct tpm_chip *chip)
{
@ -326,6 +312,10 @@ static int crb_acpi_remove(struct acpi_device *device)
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
return 0;
}

View File

@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
crq.len = (u16)count;
crq.data = ibmvtpm->rtce_dma_handle;
rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
cpu_to_be64(word[1]));
if (rc != H_SUCCESS) {
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
rc = 0;
@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_GET_VERSION;
rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_get_version failed rc=%d\n", rc);
@ -336,7 +339,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"tpm_ibmvtpm_suspend failed rc=%d\n", rc);
@ -481,11 +485,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
case IBMVTPM_VALID_CMD:
switch (crq->msg) {
case VTPM_GET_RTCE_BUFFER_SIZE_RES:
if (crq->len <= 0) {
if (be16_to_cpu(crq->len) <= 0) {
dev_err(ibmvtpm->dev, "Invalid rtce size\n");
return;
}
ibmvtpm->rtce_size = crq->len;
ibmvtpm->rtce_size = be16_to_cpu(crq->len);
ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
GFP_KERNEL);
if (!ibmvtpm->rtce_buf) {
@ -506,11 +510,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
return;
case VTPM_GET_VERSION_RES:
ibmvtpm->vtpm_version = crq->data;
ibmvtpm->vtpm_version = be32_to_cpu(crq->data);
return;
case VTPM_TPM_COMMAND_RES:
/* len of the data in rtce buffer */
ibmvtpm->res_len = crq->len;
ibmvtpm->res_len = be16_to_cpu(crq->len);
wake_up_interruptible(&ibmvtpm->wq);
return;
default:

View File

@ -588,6 +588,9 @@ MODULE_PARM_DESC(interrupts, "Enable interrupts");
static void tpm_tis_remove(struct tpm_chip *chip)
{
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
iowrite32(~TPM_GLOBAL_INT_ENABLE &
ioread32(chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.
@ -639,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
goto out_err;
}
/* Every TPM 2.x command has a higher ordinal than TPM 1.x commands.
* Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x.
*/
rc = tpm2_gen_interrupt(chip, true);
if (rc == 0 || rc == TPM2_RC_INITIALIZE)
chip->flags |= TPM_CHIP_FLAG_TPM2;
rc = tpm2_probe(chip);
if (rc)
goto out_err;
vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
chip->vendor.manufacturer_id = vendor;
@ -747,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
/* Generate Interrupts */
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_gen_interrupt(chip, false);
tpm2_gen_interrupt(chip);
else
tpm_gen_interrupt(chip);
@ -865,25 +865,22 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
static int tpm_tis_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
int ret = 0;
int ret;
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
/* NOP if firmware properly does this. */
tpm2_startup(chip, TPM2_SU_STATE);
ret = tpm_pm_resume(dev);
if (ret)
return ret;
ret = tpm2_shutdown(chip, TPM2_SU_STATE);
if (!ret)
ret = tpm2_do_selftest(chip);
} else {
ret = tpm_pm_resume(dev);
if (!ret)
tpm_do_selftest(chip);
}
/* TPM 1.2 requires self-test on resume. This function actually returns
* an error code but for unknown reason it isn't handled.
*/
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
tpm_do_selftest(chip);
return ret;
return 0;
}
#endif