diff options
Diffstat (limited to 'drivers/char/tpm/tpm_ibmvtpm.c')
-rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 22 |
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: |