Skip to content

Commit 6674ff1

Browse files
stefanbergerJarkko Sakkinen
authored andcommitted
tpm_ibmvtpm: properly handle interrupted packet receptions
When the TPM response reception is interrupted in the wait_event_interruptable call, the TPM is still busy processing the command and will only deliver the response later. So we have to wait for an outstanding response before sending a new request to avoid trying to put a 2nd request into the CRQ. Also reset the res_len before sending a command so we will end up in that wait_event_interruptable() waiting for the response rather than reading the command packet as a response. The easiest way to trigger the problem is to run the following cd /sys/device/vio/71000004 while :; cat pcrs >/dev/null; done And press Ctrl-C. This will then display an error tpm_ibmvtpm 71000004: tpm_transmit: tpm_recv: error -4 followed by several other errors once interaction with the TPM resumes. tpm_ibmvtpm 71000004: A TPM error (101) occurred attempting to determine the number of PCRS. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Tested-by: Hon Ching(Vicky) Lo <honclo@linux.vnet.ibm.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Ashley Lai <ashley@ashleylai.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Acked-by: Peter Huewe <peterhuewe@gmx.de>
1 parent b8ba1e7 commit 6674ff1

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

drivers/char/tpm/tpm_ibmvtpm.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
9090
return 0;
9191
}
9292

93-
sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0);
93+
sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
9494
if (sig)
9595
return -EINTR;
9696

@@ -125,7 +125,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
125125
struct ibmvtpm_dev *ibmvtpm;
126126
struct ibmvtpm_crq crq;
127127
__be64 *word = (__be64 *)&crq;
128-
int rc;
128+
int rc, sig;
129129

130130
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
131131

@@ -141,18 +141,35 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
141141
return -EIO;
142142
}
143143

144+
if (ibmvtpm->tpm_processing_cmd) {
145+
dev_info(ibmvtpm->dev,
146+
"Need to wait for TPM to finish\n");
147+
/* wait for previous command to finish */
148+
sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
149+
if (sig)
150+
return -EINTR;
151+
}
152+
144153
spin_lock(&ibmvtpm->rtce_lock);
154+
ibmvtpm->res_len = 0;
145155
memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
146156
crq.valid = (u8)IBMVTPM_VALID_CMD;
147157
crq.msg = (u8)VTPM_TPM_COMMAND;
148158
crq.len = cpu_to_be16(count);
149159
crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
150160

161+
/*
162+
* set the processing flag before the Hcall, since we may get the
163+
* result (interrupt) before even being able to check rc.
164+
*/
165+
ibmvtpm->tpm_processing_cmd = true;
166+
151167
rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
152168
be64_to_cpu(word[1]));
153169
if (rc != H_SUCCESS) {
154170
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
155171
rc = 0;
172+
ibmvtpm->tpm_processing_cmd = false;
156173
} else
157174
rc = count;
158175

@@ -515,6 +532,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
515532
case VTPM_TPM_COMMAND_RES:
516533
/* len of the data in rtce buffer */
517534
ibmvtpm->res_len = be16_to_cpu(crq->len);
535+
ibmvtpm->tpm_processing_cmd = false;
518536
wake_up_interruptible(&ibmvtpm->wq);
519537
return;
520538
default:

drivers/char/tpm/tpm_ibmvtpm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct ibmvtpm_dev {
4545
wait_queue_head_t wq;
4646
u16 res_len;
4747
u32 vtpm_version;
48+
bool tpm_processing_cmd;
4849
};
4950

5051
#define CRQ_RES_BUF_SIZE PAGE_SIZE

0 commit comments

Comments
 (0)