| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012-2020 IBM Corporation |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Device driver for TCG/TCPA TPM (trusted platform module). |
|---|
| 9 | 10 | * Specifications at www.trustedcomputinggroup.org |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is free software; you can redistribute it and/or |
|---|
| 12 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 13 | | - * published by the Free Software Foundation, version 2 of the |
|---|
| 14 | | - * License. |
|---|
| 15 | | - * |
|---|
| 16 | 11 | */ |
|---|
| 17 | 12 | |
|---|
| 18 | 13 | #include <linux/dma-mapping.h> |
|---|
| .. | .. |
|---|
| 34 | 29 | |
|---|
| 35 | 30 | static const struct vio_device_id tpm_ibmvtpm_device_table[] = { |
|---|
| 36 | 31 | { "IBM,vtpm", "IBM,vtpm"}, |
|---|
| 32 | + { "IBM,vtpm", "IBM,vtpm20"}, |
|---|
| 37 | 33 | { "", "" } |
|---|
| 38 | 34 | }; |
|---|
| 39 | 35 | MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); |
|---|
| 40 | 36 | |
|---|
| 41 | 37 | /** |
|---|
| 42 | | - * |
|---|
| 43 | | - * ibmvtpm_send_crq_word - Send a CRQ request |
|---|
| 38 | + * ibmvtpm_send_crq_word() - Send a CRQ request |
|---|
| 44 | 39 | * @vdev: vio device struct |
|---|
| 45 | 40 | * @w1: pre-constructed first word of tpm crq (second word is reserved) |
|---|
| 46 | 41 | * |
|---|
| .. | .. |
|---|
| 54 | 49 | } |
|---|
| 55 | 50 | |
|---|
| 56 | 51 | /** |
|---|
| 57 | | - * |
|---|
| 58 | | - * ibmvtpm_send_crq - Send a CRQ request |
|---|
| 52 | + * ibmvtpm_send_crq() - Send a CRQ request |
|---|
| 59 | 53 | * |
|---|
| 60 | 54 | * @vdev: vio device struct |
|---|
| 61 | 55 | * @valid: Valid field |
|---|
| .. | .. |
|---|
| 112 | 106 | { |
|---|
| 113 | 107 | struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev); |
|---|
| 114 | 108 | u16 len; |
|---|
| 115 | | - int sig; |
|---|
| 116 | 109 | |
|---|
| 117 | 110 | if (!ibmvtpm->rtce_buf) { |
|---|
| 118 | 111 | dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); |
|---|
| 119 | 112 | return 0; |
|---|
| 120 | 113 | } |
|---|
| 121 | | - |
|---|
| 122 | | - sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd); |
|---|
| 123 | | - if (sig) |
|---|
| 124 | | - return -EINTR; |
|---|
| 125 | 114 | |
|---|
| 126 | 115 | len = ibmvtpm->res_len; |
|---|
| 127 | 116 | |
|---|
| .. | .. |
|---|
| 243 | 232 | * set the processing flag before the Hcall, since we may get the |
|---|
| 244 | 233 | * result (interrupt) before even being able to check rc. |
|---|
| 245 | 234 | */ |
|---|
| 246 | | - ibmvtpm->tpm_processing_cmd = true; |
|---|
| 235 | + ibmvtpm->tpm_processing_cmd = 1; |
|---|
| 247 | 236 | |
|---|
| 248 | 237 | again: |
|---|
| 249 | 238 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, |
|---|
| .. | .. |
|---|
| 261 | 250 | goto again; |
|---|
| 262 | 251 | } |
|---|
| 263 | 252 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); |
|---|
| 264 | | - ibmvtpm->tpm_processing_cmd = false; |
|---|
| 253 | + ibmvtpm->tpm_processing_cmd = 0; |
|---|
| 265 | 254 | } |
|---|
| 266 | 255 | |
|---|
| 267 | 256 | spin_unlock(&ibmvtpm->rtce_lock); |
|---|
| .. | .. |
|---|
| 275 | 264 | |
|---|
| 276 | 265 | static u8 tpm_ibmvtpm_status(struct tpm_chip *chip) |
|---|
| 277 | 266 | { |
|---|
| 278 | | - return 0; |
|---|
| 267 | + struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev); |
|---|
| 268 | + |
|---|
| 269 | + return ibmvtpm->tpm_processing_cmd; |
|---|
| 279 | 270 | } |
|---|
| 280 | 271 | |
|---|
| 281 | 272 | /** |
|---|
| .. | .. |
|---|
| 465 | 456 | .send = tpm_ibmvtpm_send, |
|---|
| 466 | 457 | .cancel = tpm_ibmvtpm_cancel, |
|---|
| 467 | 458 | .status = tpm_ibmvtpm_status, |
|---|
| 468 | | - .req_complete_mask = 0, |
|---|
| 459 | + .req_complete_mask = 1, |
|---|
| 469 | 460 | .req_complete_val = 0, |
|---|
| 470 | 461 | .req_canceled = tpm_ibmvtpm_req_canceled, |
|---|
| 471 | 462 | }; |
|---|
| .. | .. |
|---|
| 558 | 549 | case VTPM_TPM_COMMAND_RES: |
|---|
| 559 | 550 | /* len of the data in rtce buffer */ |
|---|
| 560 | 551 | ibmvtpm->res_len = be16_to_cpu(crq->len); |
|---|
| 561 | | - ibmvtpm->tpm_processing_cmd = false; |
|---|
| 552 | + ibmvtpm->tpm_processing_cmd = 0; |
|---|
| 562 | 553 | wake_up_interruptible(&ibmvtpm->wq); |
|---|
| 563 | 554 | return; |
|---|
| 564 | 555 | default: |
|---|
| .. | .. |
|---|
| 692 | 683 | if (!wait_event_timeout(ibmvtpm->crq_queue.wq, |
|---|
| 693 | 684 | ibmvtpm->rtce_buf != NULL, |
|---|
| 694 | 685 | HZ)) { |
|---|
| 686 | + rc = -ENODEV; |
|---|
| 695 | 687 | dev_err(dev, "CRQ response timed out\n"); |
|---|
| 696 | 688 | goto init_irq_cleanup; |
|---|
| 697 | 689 | } |
|---|
| 698 | 690 | |
|---|
| 691 | + |
|---|
| 692 | + if (!strcmp(id->compat, "IBM,vtpm20")) |
|---|
| 693 | + chip->flags |= TPM_CHIP_FLAG_TPM2; |
|---|
| 694 | + |
|---|
| 695 | + rc = tpm_get_timeouts(chip); |
|---|
| 696 | + if (rc) |
|---|
| 697 | + goto init_irq_cleanup; |
|---|
| 698 | + |
|---|
| 699 | + if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
|---|
| 700 | + rc = tpm2_get_cc_attrs_tbl(chip); |
|---|
| 701 | + if (rc) |
|---|
| 702 | + goto init_irq_cleanup; |
|---|
| 703 | + } |
|---|
| 704 | + |
|---|
| 699 | 705 | return tpm_chip_register(chip); |
|---|
| 700 | 706 | init_irq_cleanup: |
|---|
| 701 | 707 | do { |
|---|