1
1
// SPDX-License-Identifier: GPL-2.0-only
2
2
/*
3
- * Copyright (C) 2012 IBM Corporation
3
+ * Copyright (C) 2012-2020 IBM Corporation
4
4
*
5
5
* Author: Ashley Lai <[email protected] >
6
6
*
@@ -134,6 +134,64 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
134
134
return len ;
135
135
}
136
136
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
+
137
195
/**
138
196
* tpm_ibmvtpm_send() - Send a TPM command
139
197
* @chip: tpm chip struct
@@ -147,6 +205,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
147
205
static int tpm_ibmvtpm_send (struct tpm_chip * chip , u8 * buf , size_t count )
148
206
{
149
207
struct ibmvtpm_dev * ibmvtpm = dev_get_drvdata (& chip -> dev );
208
+ bool retry = true;
150
209
int rc , sig ;
151
210
152
211
if (!ibmvtpm -> rtce_buf ) {
@@ -180,18 +239,27 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
180
239
*/
181
240
ibmvtpm -> tpm_processing_cmd = true;
182
241
242
+ again :
183
243
rc = ibmvtpm_send_crq (ibmvtpm -> vdev ,
184
244
IBMVTPM_VALID_CMD , VTPM_TPM_COMMAND ,
185
245
count , ibmvtpm -> rtce_dma_handle );
186
246
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
+ }
187
257
dev_err (ibmvtpm -> dev , "tpm_ibmvtpm_send failed rc=%d\n" , rc );
188
- rc = 0 ;
189
258
ibmvtpm -> tpm_processing_cmd = false;
190
- } else
191
- rc = 0 ;
259
+ }
192
260
193
261
spin_unlock (& ibmvtpm -> rtce_lock );
194
- return rc ;
262
+ return 0 ;
195
263
}
196
264
197
265
static void tpm_ibmvtpm_cancel (struct tpm_chip * chip )
@@ -269,26 +337,6 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
269
337
return rc ;
270
338
}
271
339
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
-
292
340
/**
293
341
* tpm_ibmvtpm_remove - ibm vtpm remove entry point
294
342
* @vdev: vio device struct
@@ -401,44 +449,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
401
449
ibmvtpm -> crq_dma_handle , CRQ_RES_BUF_SIZE );
402
450
}
403
451
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
-
442
452
static bool tpm_ibmvtpm_req_canceled (struct tpm_chip * chip , u8 status )
443
453
{
444
454
return (status == 0 );
0 commit comments