forked from Minki/linux
Merge https://github.com/PeterHuewe/linux-tpmdd into for-linus
This commit is contained in:
commit
cd07db5f27
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user