mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-23 09:56:00 +00:00
tpm: Fix cancellation of TPM commands (polling mode)
On one of my machines the cancellation of TPM commands does not work. The reason is that by writing into sysfs 'cancel' the tpm_tis_ready call causes the status flag TPM_STS_VALID to be set in the statusregister. However, the TIS driver seems to wait for TPM_STS_COMMAND_READY. Once a 2nd time sysfs 'cancel' is written to, the TPM_STS_COMMAND_READY flag also gets set, resulting in TPM_STS_VALID|TPM_STS_COMMAND_READY to be read from the status register. This patch now converts req_canceled into a function to enable more complex comparisons against possible cancellation status codes. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
This commit is contained in:
parent
3e3a5e9069
commit
1f86605729
@ -393,7 +393,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
|
|||||||
chip->vendor.req_complete_val)
|
chip->vendor.req_complete_val)
|
||||||
goto out_recv;
|
goto out_recv;
|
||||||
|
|
||||||
if ((status == chip->vendor.req_canceled)) {
|
if (chip->vendor.req_canceled(chip, status)) {
|
||||||
dev_err(chip->dev, "Operation Canceled\n");
|
dev_err(chip->dev, "Operation Canceled\n");
|
||||||
rc = -ECANCELED;
|
rc = -ECANCELED;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -78,7 +78,7 @@ struct tpm_chip;
|
|||||||
struct tpm_vendor_specific {
|
struct tpm_vendor_specific {
|
||||||
const u8 req_complete_mask;
|
const u8 req_complete_mask;
|
||||||
const u8 req_complete_val;
|
const u8 req_complete_val;
|
||||||
const u8 req_canceled;
|
bool (*req_canceled)(struct tpm_chip *chip, u8 status);
|
||||||
void __iomem *iobase; /* ioremapped address */
|
void __iomem *iobase; /* ioremapped address */
|
||||||
unsigned long base; /* TPM base address */
|
unsigned long base; /* TPM base address */
|
||||||
|
|
||||||
@ -112,6 +112,8 @@ struct tpm_vendor_specific {
|
|||||||
#define TPM_VPRIV(c) (c)->vendor.priv
|
#define TPM_VPRIV(c) (c)->vendor.priv
|
||||||
|
|
||||||
#define TPM_VID_INTEL 0x8086
|
#define TPM_VID_INTEL 0x8086
|
||||||
|
#define TPM_VID_WINBOND 0x1050
|
||||||
|
#define TPM_VID_STM 0x104A
|
||||||
|
|
||||||
struct tpm_chip {
|
struct tpm_chip {
|
||||||
struct device *dev; /* Device stuff */
|
struct device *dev; /* Device stuff */
|
||||||
|
@ -116,6 +116,11 @@ static u8 tpm_atml_status(struct tpm_chip *chip)
|
|||||||
return ioread8(chip->vendor.iobase + 1);
|
return ioread8(chip->vendor.iobase + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
return (status == ATML_STATUS_READY);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations atmel_ops = {
|
static const struct file_operations atmel_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -147,7 +152,7 @@ static const struct tpm_vendor_specific tpm_atmel = {
|
|||||||
.status = tpm_atml_status,
|
.status = tpm_atml_status,
|
||||||
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
|
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
|
||||||
.req_complete_val = ATML_STATUS_DATA_AVAIL,
|
.req_complete_val = ATML_STATUS_DATA_AVAIL,
|
||||||
.req_canceled = ATML_STATUS_READY,
|
.req_canceled = tpm_atml_req_canceled,
|
||||||
.attr_group = &atmel_attr_grp,
|
.attr_group = &atmel_attr_grp,
|
||||||
.miscdev = { .fops = &atmel_ops, },
|
.miscdev = { .fops = &atmel_ops, },
|
||||||
};
|
};
|
||||||
|
@ -505,6 +505,11 @@ out_err:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
return (status == TPM_STS_COMMAND_READY);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations tis_ops = {
|
static const struct file_operations tis_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -550,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
|
|||||||
.cancel = tpm_tis_i2c_ready,
|
.cancel = tpm_tis_i2c_ready,
|
||||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_canceled = TPM_STS_COMMAND_READY,
|
.req_canceled = tpm_tis_i2c_req_canceled,
|
||||||
.attr_group = &tis_attr_grp,
|
.attr_group = &tis_attr_grp,
|
||||||
.miscdev.fops = &tis_ops,
|
.miscdev.fops = &tis_ops,
|
||||||
};
|
};
|
||||||
|
@ -587,6 +587,11 @@ out:
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
return (status == TPM_STS_COMMAND_READY);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations tpm_st33_i2c_fops = {
|
static const struct file_operations tpm_st33_i2c_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -627,7 +632,7 @@ static struct tpm_vendor_specific st_i2c_tpm = {
|
|||||||
.status = tpm_stm_i2c_status,
|
.status = tpm_stm_i2c_status,
|
||||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_canceled = TPM_STS_COMMAND_READY,
|
.req_canceled = tpm_st33_i2c_req_canceled,
|
||||||
.attr_group = &stm_tpm_attr_grp,
|
.attr_group = &stm_tpm_attr_grp,
|
||||||
.miscdev = {.fops = &tpm_st33_i2c_fops,},
|
.miscdev = {.fops = &tpm_st33_i2c_fops,},
|
||||||
};
|
};
|
||||||
|
@ -398,6 +398,11 @@ static int tpm_ibmvtpm_resume(struct device *dev)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
return (status == 0);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations ibmvtpm_ops = {
|
static const struct file_operations ibmvtpm_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -441,7 +446,7 @@ static const struct tpm_vendor_specific tpm_ibmvtpm = {
|
|||||||
.status = tpm_ibmvtpm_status,
|
.status = tpm_ibmvtpm_status,
|
||||||
.req_complete_mask = 0,
|
.req_complete_mask = 0,
|
||||||
.req_complete_val = 0,
|
.req_complete_val = 0,
|
||||||
.req_canceled = 0,
|
.req_canceled = tpm_ibmvtpm_req_canceled,
|
||||||
.attr_group = &ibmvtpm_attr_grp,
|
.attr_group = &ibmvtpm_attr_grp,
|
||||||
.miscdev = { .fops = &ibmvtpm_ops, },
|
.miscdev = { .fops = &ibmvtpm_ops, },
|
||||||
};
|
};
|
||||||
|
@ -227,6 +227,11 @@ static u8 tpm_nsc_status(struct tpm_chip *chip)
|
|||||||
return inb(chip->vendor.base + NSC_STATUS);
|
return inb(chip->vendor.base + NSC_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
return (status == NSC_STATUS_RDY);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations nsc_ops = {
|
static const struct file_operations nsc_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -258,7 +263,7 @@ static const struct tpm_vendor_specific tpm_nsc = {
|
|||||||
.status = tpm_nsc_status,
|
.status = tpm_nsc_status,
|
||||||
.req_complete_mask = NSC_STATUS_OBF,
|
.req_complete_mask = NSC_STATUS_OBF,
|
||||||
.req_complete_val = NSC_STATUS_OBF,
|
.req_complete_val = NSC_STATUS_OBF,
|
||||||
.req_canceled = NSC_STATUS_RDY,
|
.req_canceled = tpm_nsc_req_canceled,
|
||||||
.attr_group = &nsc_attr_grp,
|
.attr_group = &nsc_attr_grp,
|
||||||
.miscdev = { .fops = &nsc_ops, },
|
.miscdev = { .fops = &nsc_ops, },
|
||||||
};
|
};
|
||||||
|
@ -400,6 +400,19 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
|
||||||
|
{
|
||||||
|
switch (chip->vendor.manufacturer_id) {
|
||||||
|
case TPM_VID_WINBOND:
|
||||||
|
return ((status == TPM_STS_VALID) ||
|
||||||
|
(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
|
||||||
|
case TPM_VID_STM:
|
||||||
|
return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
|
||||||
|
default:
|
||||||
|
return (status == TPM_STS_COMMAND_READY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations tis_ops = {
|
static const struct file_operations tis_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
@ -445,7 +458,7 @@ static struct tpm_vendor_specific tpm_tis = {
|
|||||||
.cancel = tpm_tis_ready,
|
.cancel = tpm_tis_ready,
|
||||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
.req_canceled = TPM_STS_COMMAND_READY,
|
.req_canceled = tpm_tis_req_canceled,
|
||||||
.attr_group = &tis_attr_grp,
|
.attr_group = &tis_attr_grp,
|
||||||
.miscdev = {
|
.miscdev = {
|
||||||
.fops = &tis_ops,},
|
.fops = &tis_ops,},
|
||||||
|
Loading…
Reference in New Issue
Block a user