Skip to content

Commit eba5cf3

Browse files
George WilsonJarkko Sakkinen
authored andcommitted
tpm: ibmvtpm: retry on H_CLOSED in tpm_ibmvtpm_send()
tpm_ibmvtpm_send() can fail during PowerVM Live Partition Mobility resume with an H_CLOSED return from ibmvtpm_send_crq(). The PAPR says, 'The "partner partition suspended" transport event disables the associated CRQ such that any H_SEND_CRQ hcall() to the associated CRQ returns H_Closed until the CRQ has been explicitly enabled using the H_ENABLE_CRQ hcall.' This patch adds a check in tpm_ibmvtpm_send() for an H_CLOSED return from ibmvtpm_send_crq() and in that case calls tpm_ibmvtpm_resume() and retries the ibmvtpm_send_crq() once. Cc: [email protected] # 3.7.x Fixes: 132f762 ("drivers/char/tpm: Add new device driver to support IBM vTPM") Reported-by: Linh Pham <[email protected]> Reviewed-by: Stefan Berger <[email protected]> Signed-off-by: George Wilson <[email protected]> Tested-by: Linh Pham <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent 684c6bd commit eba5cf3

File tree

1 file changed

+73
-63
lines changed

1 file changed

+73
-63
lines changed

drivers/char/tpm/tpm_ibmvtpm.c

Lines changed: 73 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (C) 2012 IBM Corporation
3+
* Copyright (C) 2012-2020 IBM Corporation
44
*
55
* Author: Ashley Lai <[email protected]>
66
*
@@ -134,6 +134,64 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
134134
return len;
135135
}
136136

137+
/**
138+
* ibmvtpm_crq_send_init - Send a CRQ initialize message
139+
* @ibmvtpm: vtpm device struct
140+
*
141+
* Return:
142+
* 0 on success.
143+
* Non-zero on failure.
144+
*/
145+
static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
146+
{
147+
int rc;
148+
149+
rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
150+
if (rc != H_SUCCESS)
151+
dev_err(ibmvtpm->dev,
152+
"%s failed rc=%d\n", __func__, rc);
153+
154+
return rc;
155+
}
156+
157+
/**
158+
* tpm_ibmvtpm_resume - Resume from suspend
159+
*
160+
* @dev: device struct
161+
*
162+
* Return: Always 0.
163+
*/
164+
static int tpm_ibmvtpm_resume(struct device *dev)
165+
{
166+
struct tpm_chip *chip = dev_get_drvdata(dev);
167+
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
168+
int rc = 0;
169+
170+
do {
171+
if (rc)
172+
msleep(100);
173+
rc = plpar_hcall_norets(H_ENABLE_CRQ,
174+
ibmvtpm->vdev->unit_address);
175+
} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
176+
177+
if (rc) {
178+
dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
179+
return rc;
180+
}
181+
182+
rc = vio_enable_interrupts(ibmvtpm->vdev);
183+
if (rc) {
184+
dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
185+
return rc;
186+
}
187+
188+
rc = ibmvtpm_crq_send_init(ibmvtpm);
189+
if (rc)
190+
dev_err(dev, "Error send_init rc=%d\n", rc);
191+
192+
return rc;
193+
}
194+
137195
/**
138196
* tpm_ibmvtpm_send() - Send a TPM command
139197
* @chip: tpm chip struct
@@ -147,6 +205,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
147205
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
148206
{
149207
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
208+
bool retry = true;
150209
int rc, sig;
151210

152211
if (!ibmvtpm->rtce_buf) {
@@ -180,18 +239,27 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
180239
*/
181240
ibmvtpm->tpm_processing_cmd = true;
182241

242+
again:
183243
rc = ibmvtpm_send_crq(ibmvtpm->vdev,
184244
IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
185245
count, ibmvtpm->rtce_dma_handle);
186246
if (rc != H_SUCCESS) {
247+
/*
248+
* H_CLOSED can be returned after LPM resume. Call
249+
* tpm_ibmvtpm_resume() to re-enable the CRQ then retry
250+
* ibmvtpm_send_crq() once before failing.
251+
*/
252+
if (rc == H_CLOSED && retry) {
253+
tpm_ibmvtpm_resume(ibmvtpm->dev);
254+
retry = false;
255+
goto again;
256+
}
187257
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
188-
rc = 0;
189258
ibmvtpm->tpm_processing_cmd = false;
190-
} else
191-
rc = 0;
259+
}
192260

193261
spin_unlock(&ibmvtpm->rtce_lock);
194-
return rc;
262+
return 0;
195263
}
196264

197265
static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
@@ -269,26 +337,6 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
269337
return rc;
270338
}
271339

272-
/**
273-
* ibmvtpm_crq_send_init - Send a CRQ initialize message
274-
* @ibmvtpm: vtpm device struct
275-
*
276-
* Return:
277-
* 0 on success.
278-
* Non-zero on failure.
279-
*/
280-
static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
281-
{
282-
int rc;
283-
284-
rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
285-
if (rc != H_SUCCESS)
286-
dev_err(ibmvtpm->dev,
287-
"ibmvtpm_crq_send_init failed rc=%d\n", rc);
288-
289-
return rc;
290-
}
291-
292340
/**
293341
* tpm_ibmvtpm_remove - ibm vtpm remove entry point
294342
* @vdev: vio device struct
@@ -401,44 +449,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
401449
ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
402450
}
403451

404-
/**
405-
* tpm_ibmvtpm_resume - Resume from suspend
406-
*
407-
* @dev: device struct
408-
*
409-
* Return: Always 0.
410-
*/
411-
static int tpm_ibmvtpm_resume(struct device *dev)
412-
{
413-
struct tpm_chip *chip = dev_get_drvdata(dev);
414-
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
415-
int rc = 0;
416-
417-
do {
418-
if (rc)
419-
msleep(100);
420-
rc = plpar_hcall_norets(H_ENABLE_CRQ,
421-
ibmvtpm->vdev->unit_address);
422-
} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
423-
424-
if (rc) {
425-
dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
426-
return rc;
427-
}
428-
429-
rc = vio_enable_interrupts(ibmvtpm->vdev);
430-
if (rc) {
431-
dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
432-
return rc;
433-
}
434-
435-
rc = ibmvtpm_crq_send_init(ibmvtpm);
436-
if (rc)
437-
dev_err(dev, "Error send_init rc=%d\n", rc);
438-
439-
return rc;
440-
}
441-
442452
static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
443453
{
444454
return (status == 0);

0 commit comments

Comments
 (0)