Skip to content

Commit

Permalink
tpm: ibmvtpm: simplify crq initialization and document crq format
Browse files Browse the repository at this point in the history
The crq is passed in registers and is the same on BE and LE hosts.
However, current implementation allocates a structure on-stack to
represent the crq, initializes the members swapping them to BE, and
loads the structure swapping it from BE. This is pointless and causes
GCC warnings about ununitialized members. Get rid of the structure and
the warnings.

Signed-off-by: Michal Suchanek <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Signed-off-by: Jarkko Sakkinen <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
hramrach authored and James Morris committed Sep 24, 2017
1 parent 9f3fc7b commit fb154e0
Showing 1 changed file with 60 additions and 36 deletions.
96 changes: 60 additions & 36 deletions drivers/char/tpm/tpm_ibmvtpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,63 @@ static const struct vio_device_id tpm_ibmvtpm_device_table[] = {
MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);

/**
*
* ibmvtpm_send_crq_word - Send a CRQ request
* @vdev: vio device struct
* @w1: pre-constructed first word of tpm crq (second word is reserved)
*
* Return:
* 0 - Success
* Non-zero - Failure
*/
static int ibmvtpm_send_crq_word(struct vio_dev *vdev, u64 w1)
{
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, 0);
}

/**
*
* ibmvtpm_send_crq - Send a CRQ request
*
* @vdev: vio device struct
* @w1: first word
* @w2: second word
* @valid: Valid field
* @msg: Type field
* @len: Length field
* @data: Data field
*
* The ibmvtpm crq is defined as follows:
*
* Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
* -----------------------------------------------------------------------
* Word0 | Valid | Type | Length | Data
* -----------------------------------------------------------------------
* Word1 | Reserved
* -----------------------------------------------------------------------
*
* Which matches the following structure (on bigendian host):
*
* struct ibmvtpm_crq {
* u8 valid;
* u8 msg;
* __be16 len;
* __be32 data;
* __be64 reserved;
* } __attribute__((packed, aligned(8)));
*
* However, the value is passed in a register so just compute the numeric value
* to load into the register avoiding byteswap altogether. Endian only affects
* memory loads and stores - registers are internally represented the same.
*
* Return:
* 0 -Sucess
* 0 (H_SUCCESS) - Success
* Non-zero - Failure
*/
static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
static int ibmvtpm_send_crq(struct vio_dev *vdev,
u8 valid, u8 msg, u16 len, u32 data)
{
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
u64 w1 = ((u64)valid << 56) | ((u64)msg << 48) | ((u64)len << 32) |
(u64)data;
return ibmvtpm_send_crq_word(vdev, w1);
}

/**
Expand Down Expand Up @@ -109,8 +153,6 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq;
__be64 *word = (__be64 *)&crq;
int rc, sig;

if (!ibmvtpm->rtce_buf) {
Expand All @@ -137,19 +179,16 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
spin_lock(&ibmvtpm->rtce_lock);
ibmvtpm->res_len = 0;
memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_TPM_COMMAND;
crq.len = cpu_to_be16(count);
crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);

/*
* set the processing flag before the Hcall, since we may get the
* result (interrupt) before even being able to check rc.
*/
ibmvtpm->tpm_processing_cmd = true;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
be64_to_cpu(word[1]));
rc = ibmvtpm_send_crq(ibmvtpm->vdev,
IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
count, ibmvtpm->rtce_dma_handle);
if (rc != H_SUCCESS) {
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
rc = 0;
Expand Down Expand Up @@ -182,15 +221,10 @@ static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
*/
static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
{
struct ibmvtpm_crq crq;
u64 *buf = (u64 *) &crq;
int rc;

crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
rc = ibmvtpm_send_crq(ibmvtpm->vdev,
IBMVTPM_VALID_CMD, VTPM_GET_RTCE_BUFFER_SIZE, 0, 0);
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
Expand All @@ -210,15 +244,10 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
*/
static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
{
struct ibmvtpm_crq crq;
u64 *buf = (u64 *) &crq;
int rc;

crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_GET_VERSION;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
rc = ibmvtpm_send_crq(ibmvtpm->vdev,
IBMVTPM_VALID_CMD, VTPM_GET_VERSION, 0, 0);
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_get_version failed rc=%d\n", rc);
Expand All @@ -238,7 +267,7 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
{
int rc;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_COMP_CMD);
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
Expand All @@ -258,7 +287,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
{
int rc;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"ibmvtpm_crq_send_init failed rc=%d\n", rc);
Expand Down Expand Up @@ -340,15 +369,10 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq;
u64 *buf = (u64 *) &crq;
int rc = 0;

crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
cpu_to_be64(buf[1]));
rc = ibmvtpm_send_crq(ibmvtpm->vdev,
IBMVTPM_VALID_CMD, VTPM_PREPARE_TO_SUSPEND, 0, 0);
if (rc != H_SUCCESS)
dev_err(ibmvtpm->dev,
"tpm_ibmvtpm_suspend failed rc=%d\n", rc);
Expand Down

0 comments on commit fb154e0

Please sign in to comment.