aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm_ibmvtpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tpm/tpm_ibmvtpm.c')
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 3e6a22658b63..b0a9a9e34241 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -90,7 +90,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
90 return 0; 90 return 0;
91 } 91 }
92 92
93 sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0); 93 sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
94 if (sig) 94 if (sig)
95 return -EINTR; 95 return -EINTR;
96 96
@@ -125,7 +125,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
125 struct ibmvtpm_dev *ibmvtpm; 125 struct ibmvtpm_dev *ibmvtpm;
126 struct ibmvtpm_crq crq; 126 struct ibmvtpm_crq crq;
127 __be64 *word = (__be64 *)&crq; 127 __be64 *word = (__be64 *)&crq;
128 int rc; 128 int rc, sig;
129 129
130 ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); 130 ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
131 131
@@ -141,18 +141,35 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
141 return -EIO; 141 return -EIO;
142 } 142 }
143 143
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
144 spin_lock(&ibmvtpm->rtce_lock); 153 spin_lock(&ibmvtpm->rtce_lock);
154 ibmvtpm->res_len = 0;
145 memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count); 155 memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
146 crq.valid = (u8)IBMVTPM_VALID_CMD; 156 crq.valid = (u8)IBMVTPM_VALID_CMD;
147 crq.msg = (u8)VTPM_TPM_COMMAND; 157 crq.msg = (u8)VTPM_TPM_COMMAND;
148 crq.len = cpu_to_be16(count); 158 crq.len = cpu_to_be16(count);
149 crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle); 159 crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
150 160
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
151 rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]), 167 rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
152 be64_to_cpu(word[1])); 168 be64_to_cpu(word[1]));
153 if (rc != H_SUCCESS) { 169 if (rc != H_SUCCESS) {
154 dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); 170 dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
155 rc = 0; 171 rc = 0;
172 ibmvtpm->tpm_processing_cmd = false;
156 } else 173 } else
157 rc = count; 174 rc = count;
158 175
@@ -515,6 +532,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
515 case VTPM_TPM_COMMAND_RES: 532 case VTPM_TPM_COMMAND_RES:
516 /* len of the data in rtce buffer */ 533 /* len of the data in rtce buffer */
517 ibmvtpm->res_len = be16_to_cpu(crq->len); 534 ibmvtpm->res_len = be16_to_cpu(crq->len);
535 ibmvtpm->tpm_processing_cmd = false;
518 wake_up_interruptible(&ibmvtpm->wq); 536 wake_up_interruptible(&ibmvtpm->wq);
519 return; 537 return;
520 default: 538 default: