| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2005, 2006 IBM Corporation |
|---|
| 3 | 4 | * Copyright (C) 2014, 2015 Intel Corporation |
|---|
| .. | .. |
|---|
| 13 | 14 | * |
|---|
| 14 | 15 | * This device driver implements the TPM interface as defined in |
|---|
| 15 | 16 | * the TCG TPM Interface Spec version 1.2, revision 1.0. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is free software; you can redistribute it and/or |
|---|
| 18 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 19 | | - * published by the Free Software Foundation, version 2 of the |
|---|
| 20 | | - * License. |
|---|
| 21 | 17 | */ |
|---|
| 22 | 18 | #include <linux/init.h> |
|---|
| 23 | 19 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 52 | 48 | unsigned long timeout, wait_queue_head_t *queue, |
|---|
| 53 | 49 | bool check_cancel) |
|---|
| 54 | 50 | { |
|---|
| 51 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 55 | 52 | unsigned long stop; |
|---|
| 56 | 53 | long rc; |
|---|
| 57 | 54 | u8 status; |
|---|
| .. | .. |
|---|
| 84 | 81 | } |
|---|
| 85 | 82 | } else { |
|---|
| 86 | 83 | do { |
|---|
| 87 | | - usleep_range(TPM_TIMEOUT_USECS_MIN, |
|---|
| 88 | | - TPM_TIMEOUT_USECS_MAX); |
|---|
| 84 | + usleep_range(priv->timeout_min, |
|---|
| 85 | + priv->timeout_max); |
|---|
| 89 | 86 | status = chip->ops->status(chip); |
|---|
| 90 | 87 | if ((status & mask) == mask) |
|---|
| 91 | 88 | return 0; |
|---|
| .. | .. |
|---|
| 139 | 136 | return false; |
|---|
| 140 | 137 | } |
|---|
| 141 | 138 | |
|---|
| 142 | | -static int release_locality(struct tpm_chip *chip, int l) |
|---|
| 139 | +static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l) |
|---|
| 143 | 140 | { |
|---|
| 144 | | - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 145 | | - |
|---|
| 146 | 141 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); |
|---|
| 147 | 142 | |
|---|
| 148 | 143 | return 0; |
|---|
| 149 | 144 | } |
|---|
| 150 | 145 | |
|---|
| 151 | | -static int request_locality(struct tpm_chip *chip, int l) |
|---|
| 146 | +static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l) |
|---|
| 147 | +{ |
|---|
| 148 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 149 | + |
|---|
| 150 | + mutex_lock(&priv->locality_count_mutex); |
|---|
| 151 | + priv->locality_count--; |
|---|
| 152 | + if (priv->locality_count == 0) |
|---|
| 153 | + __tpm_tis_relinquish_locality(priv, l); |
|---|
| 154 | + mutex_unlock(&priv->locality_count_mutex); |
|---|
| 155 | + |
|---|
| 156 | + return 0; |
|---|
| 157 | +} |
|---|
| 158 | + |
|---|
| 159 | +static int __tpm_tis_request_locality(struct tpm_chip *chip, int l) |
|---|
| 152 | 160 | { |
|---|
| 153 | 161 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 154 | 162 | unsigned long stop, timeout; |
|---|
| .. | .. |
|---|
| 189 | 197 | return -1; |
|---|
| 190 | 198 | } |
|---|
| 191 | 199 | |
|---|
| 200 | +static int tpm_tis_request_locality(struct tpm_chip *chip, int l) |
|---|
| 201 | +{ |
|---|
| 202 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 203 | + int ret = 0; |
|---|
| 204 | + |
|---|
| 205 | + mutex_lock(&priv->locality_count_mutex); |
|---|
| 206 | + if (priv->locality_count == 0) |
|---|
| 207 | + ret = __tpm_tis_request_locality(chip, l); |
|---|
| 208 | + if (!ret) |
|---|
| 209 | + priv->locality_count++; |
|---|
| 210 | + mutex_unlock(&priv->locality_count_mutex); |
|---|
| 211 | + return ret; |
|---|
| 212 | +} |
|---|
| 213 | + |
|---|
| 192 | 214 | static u8 tpm_tis_status(struct tpm_chip *chip) |
|---|
| 193 | 215 | { |
|---|
| 194 | 216 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| .. | .. |
|---|
| 198 | 220 | rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); |
|---|
| 199 | 221 | if (rc < 0) |
|---|
| 200 | 222 | return 0; |
|---|
| 223 | + |
|---|
| 224 | + if (unlikely((status & TPM_STS_READ_ZERO) != 0)) { |
|---|
| 225 | + if (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) { |
|---|
| 226 | + /* |
|---|
| 227 | + * If this trips, the chances are the read is |
|---|
| 228 | + * returning 0xff because the locality hasn't been |
|---|
| 229 | + * acquired. Usually because tpm_try_get_ops() hasn't |
|---|
| 230 | + * been called before doing a TPM operation. |
|---|
| 231 | + */ |
|---|
| 232 | + dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n", |
|---|
| 233 | + status); |
|---|
| 234 | + |
|---|
| 235 | + /* |
|---|
| 236 | + * Dump stack for forensics, as invalid TPM_STS.x could be |
|---|
| 237 | + * potentially triggered by impaired tpm_try_get_ops() or |
|---|
| 238 | + * tpm_find_get_ops(). |
|---|
| 239 | + */ |
|---|
| 240 | + dump_stack(); |
|---|
| 241 | + } |
|---|
| 242 | + |
|---|
| 243 | + return 0; |
|---|
| 244 | + } |
|---|
| 201 | 245 | |
|---|
| 202 | 246 | return status; |
|---|
| 203 | 247 | } |
|---|
| .. | .. |
|---|
| 270 | 314 | int size = 0; |
|---|
| 271 | 315 | int status; |
|---|
| 272 | 316 | u32 expected; |
|---|
| 317 | + int rc; |
|---|
| 273 | 318 | |
|---|
| 274 | 319 | if (count < TPM_HEADER_SIZE) { |
|---|
| 275 | 320 | size = -EIO; |
|---|
| .. | .. |
|---|
| 289 | 334 | goto out; |
|---|
| 290 | 335 | } |
|---|
| 291 | 336 | |
|---|
| 292 | | - size += recv_data(chip, &buf[TPM_HEADER_SIZE], |
|---|
| 293 | | - expected - TPM_HEADER_SIZE); |
|---|
| 337 | + rc = recv_data(chip, &buf[TPM_HEADER_SIZE], |
|---|
| 338 | + expected - TPM_HEADER_SIZE); |
|---|
| 339 | + if (rc < 0) { |
|---|
| 340 | + size = rc; |
|---|
| 341 | + goto out; |
|---|
| 342 | + } |
|---|
| 343 | + size += rc; |
|---|
| 294 | 344 | if (size < expected) { |
|---|
| 295 | 345 | dev_err(&chip->dev, "Unable to read remainder of result\n"); |
|---|
| 296 | 346 | size = -ETIME; |
|---|
| .. | .. |
|---|
| 419 | 469 | int rc; |
|---|
| 420 | 470 | u32 ordinal; |
|---|
| 421 | 471 | unsigned long dur; |
|---|
| 472 | + unsigned int try; |
|---|
| 422 | 473 | |
|---|
| 423 | | - rc = tpm_tis_send_data(chip, buf, len); |
|---|
| 424 | | - if (rc < 0) |
|---|
| 425 | | - return rc; |
|---|
| 474 | + for (try = 0; try < TPM_RETRY; try++) { |
|---|
| 475 | + rc = tpm_tis_send_data(chip, buf, len); |
|---|
| 476 | + if (rc >= 0) |
|---|
| 477 | + /* Data transfer done successfully */ |
|---|
| 478 | + break; |
|---|
| 479 | + else if (rc != -EIO) |
|---|
| 480 | + /* Data transfer failed, not recoverable */ |
|---|
| 481 | + return rc; |
|---|
| 482 | + } |
|---|
| 426 | 483 | |
|---|
| 427 | 484 | /* go and do it */ |
|---|
| 428 | 485 | rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); |
|---|
| .. | .. |
|---|
| 432 | 489 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { |
|---|
| 433 | 490 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
|---|
| 434 | 491 | |
|---|
| 435 | | - if (chip->flags & TPM_CHIP_FLAG_TPM2) |
|---|
| 436 | | - dur = tpm2_calc_ordinal_duration(chip, ordinal); |
|---|
| 437 | | - else |
|---|
| 438 | | - dur = tpm_calc_ordinal_duration(chip, ordinal); |
|---|
| 439 | | - |
|---|
| 492 | + dur = tpm_calc_ordinal_duration(chip, ordinal); |
|---|
| 440 | 493 | if (wait_for_tpm_stat |
|---|
| 441 | 494 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, |
|---|
| 442 | 495 | &priv->read_queue, false) < 0) { |
|---|
| .. | .. |
|---|
| 473 | 526 | return rc; |
|---|
| 474 | 527 | } |
|---|
| 475 | 528 | |
|---|
| 529 | +struct tis_vendor_durations_override { |
|---|
| 530 | + u32 did_vid; |
|---|
| 531 | + struct tpm1_version version; |
|---|
| 532 | + unsigned long durations[3]; |
|---|
| 533 | +}; |
|---|
| 534 | + |
|---|
| 535 | +static const struct tis_vendor_durations_override vendor_dur_overrides[] = { |
|---|
| 536 | + /* STMicroelectronics 0x104a */ |
|---|
| 537 | + { 0x0000104a, |
|---|
| 538 | + { 1, 2, 8, 28 }, |
|---|
| 539 | + { (2 * 60 * HZ), (2 * 60 * HZ), (2 * 60 * HZ) } }, |
|---|
| 540 | +}; |
|---|
| 541 | + |
|---|
| 542 | +static void tpm_tis_update_durations(struct tpm_chip *chip, |
|---|
| 543 | + unsigned long *duration_cap) |
|---|
| 544 | +{ |
|---|
| 545 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 546 | + struct tpm1_version *version; |
|---|
| 547 | + u32 did_vid; |
|---|
| 548 | + int i, rc; |
|---|
| 549 | + cap_t cap; |
|---|
| 550 | + |
|---|
| 551 | + chip->duration_adjusted = false; |
|---|
| 552 | + |
|---|
| 553 | + if (chip->ops->clk_enable != NULL) |
|---|
| 554 | + chip->ops->clk_enable(chip, true); |
|---|
| 555 | + |
|---|
| 556 | + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
|---|
| 557 | + if (rc < 0) { |
|---|
| 558 | + dev_warn(&chip->dev, "%s: failed to read did_vid. %d\n", |
|---|
| 559 | + __func__, rc); |
|---|
| 560 | + goto out; |
|---|
| 561 | + } |
|---|
| 562 | + |
|---|
| 563 | + /* Try to get a TPM version 1.2 or 1.1 TPM_CAP_VERSION_INFO */ |
|---|
| 564 | + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, |
|---|
| 565 | + "attempting to determine the 1.2 version", |
|---|
| 566 | + sizeof(cap.version2)); |
|---|
| 567 | + if (!rc) { |
|---|
| 568 | + version = &cap.version2.version; |
|---|
| 569 | + } else { |
|---|
| 570 | + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, |
|---|
| 571 | + "attempting to determine the 1.1 version", |
|---|
| 572 | + sizeof(cap.version1)); |
|---|
| 573 | + |
|---|
| 574 | + if (rc) |
|---|
| 575 | + goto out; |
|---|
| 576 | + |
|---|
| 577 | + version = &cap.version1; |
|---|
| 578 | + } |
|---|
| 579 | + |
|---|
| 580 | + for (i = 0; i != ARRAY_SIZE(vendor_dur_overrides); i++) { |
|---|
| 581 | + if (vendor_dur_overrides[i].did_vid != did_vid) |
|---|
| 582 | + continue; |
|---|
| 583 | + |
|---|
| 584 | + if ((version->major == |
|---|
| 585 | + vendor_dur_overrides[i].version.major) && |
|---|
| 586 | + (version->minor == |
|---|
| 587 | + vendor_dur_overrides[i].version.minor) && |
|---|
| 588 | + (version->rev_major == |
|---|
| 589 | + vendor_dur_overrides[i].version.rev_major) && |
|---|
| 590 | + (version->rev_minor == |
|---|
| 591 | + vendor_dur_overrides[i].version.rev_minor)) { |
|---|
| 592 | + |
|---|
| 593 | + memcpy(duration_cap, |
|---|
| 594 | + vendor_dur_overrides[i].durations, |
|---|
| 595 | + sizeof(vendor_dur_overrides[i].durations)); |
|---|
| 596 | + |
|---|
| 597 | + chip->duration_adjusted = true; |
|---|
| 598 | + goto out; |
|---|
| 599 | + } |
|---|
| 600 | + } |
|---|
| 601 | + |
|---|
| 602 | +out: |
|---|
| 603 | + if (chip->ops->clk_enable != NULL) |
|---|
| 604 | + chip->ops->clk_enable(chip, false); |
|---|
| 605 | +} |
|---|
| 606 | + |
|---|
| 476 | 607 | struct tis_vendor_timeout_override { |
|---|
| 477 | 608 | u32 did_vid; |
|---|
| 478 | 609 | unsigned long timeout_us[4]; |
|---|
| .. | .. |
|---|
| 484 | 615 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, |
|---|
| 485 | 616 | }; |
|---|
| 486 | 617 | |
|---|
| 487 | | -static bool tpm_tis_update_timeouts(struct tpm_chip *chip, |
|---|
| 618 | +static void tpm_tis_update_timeouts(struct tpm_chip *chip, |
|---|
| 488 | 619 | unsigned long *timeout_cap) |
|---|
| 489 | 620 | { |
|---|
| 490 | 621 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
|---|
| 491 | 622 | int i, rc; |
|---|
| 492 | 623 | u32 did_vid; |
|---|
| 493 | 624 | |
|---|
| 625 | + chip->timeout_adjusted = false; |
|---|
| 626 | + |
|---|
| 494 | 627 | if (chip->ops->clk_enable != NULL) |
|---|
| 495 | 628 | chip->ops->clk_enable(chip, true); |
|---|
| 496 | 629 | |
|---|
| 497 | 630 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
|---|
| 498 | | - if (rc < 0) |
|---|
| 631 | + if (rc < 0) { |
|---|
| 632 | + dev_warn(&chip->dev, "%s: failed to read did_vid: %d\n", |
|---|
| 633 | + __func__, rc); |
|---|
| 499 | 634 | goto out; |
|---|
| 635 | + } |
|---|
| 500 | 636 | |
|---|
| 501 | 637 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { |
|---|
| 502 | 638 | if (vendor_timeout_overrides[i].did_vid != did_vid) |
|---|
| 503 | 639 | continue; |
|---|
| 504 | 640 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, |
|---|
| 505 | 641 | sizeof(vendor_timeout_overrides[i].timeout_us)); |
|---|
| 506 | | - rc = true; |
|---|
| 642 | + chip->timeout_adjusted = true; |
|---|
| 507 | 643 | } |
|---|
| 508 | | - |
|---|
| 509 | | - rc = false; |
|---|
| 510 | 644 | |
|---|
| 511 | 645 | out: |
|---|
| 512 | 646 | if (chip->ops->clk_enable != NULL) |
|---|
| 513 | 647 | chip->ops->clk_enable(chip, false); |
|---|
| 514 | 648 | |
|---|
| 515 | | - return rc; |
|---|
| 649 | + return; |
|---|
| 516 | 650 | } |
|---|
| 517 | 651 | |
|---|
| 518 | 652 | /* |
|---|
| .. | .. |
|---|
| 542 | 676 | if (vendor != TPM_VID_INTEL) |
|---|
| 543 | 677 | return 0; |
|---|
| 544 | 678 | |
|---|
| 545 | | - if (request_locality(chip, 0) != 0) |
|---|
| 679 | + if (tpm_tis_request_locality(chip, 0) != 0) |
|---|
| 546 | 680 | return -EBUSY; |
|---|
| 547 | 681 | |
|---|
| 548 | 682 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
|---|
| .. | .. |
|---|
| 563 | 697 | |
|---|
| 564 | 698 | out: |
|---|
| 565 | 699 | tpm_tis_ready(chip); |
|---|
| 566 | | - release_locality(chip, priv->locality); |
|---|
| 700 | + tpm_tis_relinquish_locality(chip, priv->locality); |
|---|
| 567 | 701 | |
|---|
| 568 | 702 | return rc; |
|---|
| 569 | 703 | } |
|---|
| .. | .. |
|---|
| 610 | 744 | wake_up_interruptible(&priv->int_queue); |
|---|
| 611 | 745 | |
|---|
| 612 | 746 | /* Clear interrupts handled with TPM_EOI */ |
|---|
| 747 | + tpm_tis_request_locality(chip, 0); |
|---|
| 613 | 748 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); |
|---|
| 749 | + tpm_tis_relinquish_locality(chip, 0); |
|---|
| 614 | 750 | if (rc < 0) |
|---|
| 615 | 751 | return IRQ_NONE; |
|---|
| 616 | 752 | |
|---|
| .. | .. |
|---|
| 618 | 754 | return IRQ_HANDLED; |
|---|
| 619 | 755 | } |
|---|
| 620 | 756 | |
|---|
| 621 | | -static int tpm_tis_gen_interrupt(struct tpm_chip *chip) |
|---|
| 757 | +static void tpm_tis_gen_interrupt(struct tpm_chip *chip) |
|---|
| 622 | 758 | { |
|---|
| 623 | 759 | const char *desc = "attempting to generate an interrupt"; |
|---|
| 624 | 760 | u32 cap2; |
|---|
| 625 | 761 | cap_t cap; |
|---|
| 762 | + int ret; |
|---|
| 626 | 763 | |
|---|
| 627 | 764 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
|---|
| 628 | | - return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); |
|---|
| 765 | + ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); |
|---|
| 629 | 766 | else |
|---|
| 630 | | - return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, |
|---|
| 631 | | - 0); |
|---|
| 767 | + ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0); |
|---|
| 632 | 768 | } |
|---|
| 633 | 769 | |
|---|
| 634 | 770 | /* Register the IRQ and issue a command that will cause an interrupt. If an |
|---|
| .. | .. |
|---|
| 643 | 779 | int rc; |
|---|
| 644 | 780 | u32 int_status; |
|---|
| 645 | 781 | |
|---|
| 646 | | - if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags, |
|---|
| 647 | | - dev_name(&chip->dev), chip) != 0) { |
|---|
| 782 | + |
|---|
| 783 | + rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL, |
|---|
| 784 | + tis_int_handler, IRQF_ONESHOT | flags, |
|---|
| 785 | + dev_name(&chip->dev), chip); |
|---|
| 786 | + if (rc) { |
|---|
| 648 | 787 | dev_info(&chip->dev, "Unable to request irq: %d for probe\n", |
|---|
| 649 | 788 | irq); |
|---|
| 650 | 789 | return -1; |
|---|
| 651 | 790 | } |
|---|
| 652 | 791 | priv->irq = irq; |
|---|
| 653 | 792 | |
|---|
| 654 | | - rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), |
|---|
| 655 | | - &original_int_vec); |
|---|
| 793 | + rc = tpm_tis_request_locality(chip, 0); |
|---|
| 656 | 794 | if (rc < 0) |
|---|
| 657 | 795 | return rc; |
|---|
| 796 | + |
|---|
| 797 | + rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), |
|---|
| 798 | + &original_int_vec); |
|---|
| 799 | + if (rc < 0) { |
|---|
| 800 | + tpm_tis_relinquish_locality(chip, priv->locality); |
|---|
| 801 | + return rc; |
|---|
| 802 | + } |
|---|
| 658 | 803 | |
|---|
| 659 | 804 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq); |
|---|
| 660 | 805 | if (rc < 0) |
|---|
| 661 | | - return rc; |
|---|
| 806 | + goto restore_irqs; |
|---|
| 662 | 807 | |
|---|
| 663 | 808 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status); |
|---|
| 664 | 809 | if (rc < 0) |
|---|
| 665 | | - return rc; |
|---|
| 810 | + goto restore_irqs; |
|---|
| 666 | 811 | |
|---|
| 667 | 812 | /* Clear all existing */ |
|---|
| 668 | 813 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); |
|---|
| 669 | 814 | if (rc < 0) |
|---|
| 670 | | - return rc; |
|---|
| 671 | | - |
|---|
| 815 | + goto restore_irqs; |
|---|
| 672 | 816 | /* Turn on */ |
|---|
| 673 | 817 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), |
|---|
| 674 | 818 | intmask | TPM_GLOBAL_INT_ENABLE); |
|---|
| 675 | 819 | if (rc < 0) |
|---|
| 676 | | - return rc; |
|---|
| 820 | + goto restore_irqs; |
|---|
| 677 | 821 | |
|---|
| 678 | 822 | priv->irq_tested = false; |
|---|
| 679 | 823 | |
|---|
| 680 | 824 | /* Generate an interrupt by having the core call through to |
|---|
| 681 | 825 | * tpm_tis_send |
|---|
| 682 | 826 | */ |
|---|
| 683 | | - rc = tpm_tis_gen_interrupt(chip); |
|---|
| 684 | | - if (rc < 0) |
|---|
| 685 | | - return rc; |
|---|
| 827 | + tpm_tis_gen_interrupt(chip); |
|---|
| 686 | 828 | |
|---|
| 829 | +restore_irqs: |
|---|
| 687 | 830 | /* tpm_tis_send will either confirm the interrupt is working or it |
|---|
| 688 | 831 | * will call disable_irq which undoes all of the above. |
|---|
| 689 | 832 | */ |
|---|
| 690 | 833 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
|---|
| 691 | | - rc = tpm_tis_write8(priv, original_int_vec, |
|---|
| 692 | | - TPM_INT_VECTOR(priv->locality)); |
|---|
| 693 | | - if (rc < 0) |
|---|
| 694 | | - return rc; |
|---|
| 695 | | - |
|---|
| 696 | | - return 1; |
|---|
| 834 | + tpm_tis_write8(priv, original_int_vec, |
|---|
| 835 | + TPM_INT_VECTOR(priv->locality)); |
|---|
| 836 | + rc = -1; |
|---|
| 697 | 837 | } |
|---|
| 698 | 838 | |
|---|
| 699 | | - return 0; |
|---|
| 839 | + tpm_tis_relinquish_locality(chip, priv->locality); |
|---|
| 840 | + |
|---|
| 841 | + return rc; |
|---|
| 700 | 842 | } |
|---|
| 701 | 843 | |
|---|
| 702 | 844 | /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that |
|---|
| .. | .. |
|---|
| 806 | 948 | .send = tpm_tis_send, |
|---|
| 807 | 949 | .cancel = tpm_tis_ready, |
|---|
| 808 | 950 | .update_timeouts = tpm_tis_update_timeouts, |
|---|
| 951 | + .update_durations = tpm_tis_update_durations, |
|---|
| 809 | 952 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
|---|
| 810 | 953 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
|---|
| 811 | 954 | .req_canceled = tpm_tis_req_canceled, |
|---|
| 812 | | - .request_locality = request_locality, |
|---|
| 813 | | - .relinquish_locality = release_locality, |
|---|
| 955 | + .request_locality = tpm_tis_request_locality, |
|---|
| 956 | + .relinquish_locality = tpm_tis_relinquish_locality, |
|---|
| 814 | 957 | .clk_enable = tpm_tis_clkrun_enable, |
|---|
| 815 | 958 | }; |
|---|
| 816 | 959 | |
|---|
| .. | .. |
|---|
| 841 | 984 | chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); |
|---|
| 842 | 985 | chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); |
|---|
| 843 | 986 | chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); |
|---|
| 987 | + priv->timeout_min = TPM_TIMEOUT_USECS_MIN; |
|---|
| 988 | + priv->timeout_max = TPM_TIMEOUT_USECS_MAX; |
|---|
| 844 | 989 | priv->phy_ops = phy_ops; |
|---|
| 990 | + priv->locality_count = 0; |
|---|
| 991 | + mutex_init(&priv->locality_count_mutex); |
|---|
| 992 | + |
|---|
| 845 | 993 | dev_set_drvdata(&chip->dev, priv); |
|---|
| 994 | + |
|---|
| 995 | + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); |
|---|
| 996 | + if (rc < 0) |
|---|
| 997 | + return rc; |
|---|
| 998 | + |
|---|
| 999 | + priv->manufacturer_id = vendor; |
|---|
| 1000 | + |
|---|
| 1001 | + if (priv->manufacturer_id == TPM_VID_ATML && |
|---|
| 1002 | + !(chip->flags & TPM_CHIP_FLAG_TPM2)) { |
|---|
| 1003 | + priv->timeout_min = TIS_TIMEOUT_MIN_ATML; |
|---|
| 1004 | + priv->timeout_max = TIS_TIMEOUT_MAX_ATML; |
|---|
| 1005 | + } |
|---|
| 846 | 1006 | |
|---|
| 847 | 1007 | if (is_bsw()) { |
|---|
| 848 | 1008 | priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, |
|---|
| .. | .. |
|---|
| 875 | 1035 | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; |
|---|
| 876 | 1036 | intmask &= ~TPM_GLOBAL_INT_ENABLE; |
|---|
| 877 | 1037 | |
|---|
| 878 | | - rc = request_locality(chip, 0); |
|---|
| 1038 | + rc = tpm_tis_request_locality(chip, 0); |
|---|
| 879 | 1039 | if (rc < 0) { |
|---|
| 880 | 1040 | rc = -ENODEV; |
|---|
| 881 | 1041 | goto out_err; |
|---|
| 882 | 1042 | } |
|---|
| 883 | 1043 | |
|---|
| 884 | 1044 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); |
|---|
| 885 | | - release_locality(chip, 0); |
|---|
| 1045 | + tpm_tis_relinquish_locality(chip, 0); |
|---|
| 886 | 1046 | |
|---|
| 887 | | - rc = tpm2_probe(chip); |
|---|
| 1047 | + rc = tpm_chip_start(chip); |
|---|
| 888 | 1048 | if (rc) |
|---|
| 889 | 1049 | goto out_err; |
|---|
| 890 | | - |
|---|
| 891 | | - rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); |
|---|
| 892 | | - if (rc < 0) |
|---|
| 1050 | + rc = tpm2_probe(chip); |
|---|
| 1051 | + tpm_chip_stop(chip); |
|---|
| 1052 | + if (rc) |
|---|
| 893 | 1053 | goto out_err; |
|---|
| 894 | | - |
|---|
| 895 | | - priv->manufacturer_id = vendor; |
|---|
| 896 | 1054 | |
|---|
| 897 | 1055 | rc = tpm_tis_read8(priv, TPM_RID(0), &rid); |
|---|
| 898 | 1056 | if (rc < 0) |
|---|
| .. | .. |
|---|
| 938 | 1096 | init_waitqueue_head(&priv->read_queue); |
|---|
| 939 | 1097 | init_waitqueue_head(&priv->int_queue); |
|---|
| 940 | 1098 | if (irq != -1) { |
|---|
| 941 | | - /* Before doing irq testing issue a command to the TPM in polling mode |
|---|
| 1099 | + /* |
|---|
| 1100 | + * Before doing irq testing issue a command to the TPM in polling mode |
|---|
| 942 | 1101 | * to make sure it works. May as well use that command to set the |
|---|
| 943 | 1102 | * proper timeouts for the driver. |
|---|
| 944 | 1103 | */ |
|---|
| 945 | | - if (tpm_get_timeouts(chip)) { |
|---|
| 1104 | + |
|---|
| 1105 | + rc = tpm_tis_request_locality(chip, 0); |
|---|
| 1106 | + if (rc < 0) |
|---|
| 1107 | + goto out_err; |
|---|
| 1108 | + |
|---|
| 1109 | + rc = tpm_get_timeouts(chip); |
|---|
| 1110 | + |
|---|
| 1111 | + tpm_tis_relinquish_locality(chip, 0); |
|---|
| 1112 | + |
|---|
| 1113 | + if (rc) { |
|---|
| 946 | 1114 | dev_err(dev, "Could not get TPM timeouts and durations\n"); |
|---|
| 947 | 1115 | rc = -ENODEV; |
|---|
| 948 | 1116 | goto out_err; |
|---|
| 949 | 1117 | } |
|---|
| 950 | 1118 | |
|---|
| 951 | | - if (irq) { |
|---|
| 1119 | + if (irq) |
|---|
| 952 | 1120 | tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, |
|---|
| 953 | 1121 | irq); |
|---|
| 954 | | - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
|---|
| 955 | | - dev_err(&chip->dev, FW_BUG |
|---|
| 1122 | + else |
|---|
| 1123 | + tpm_tis_probe_irq(chip, intmask); |
|---|
| 1124 | + |
|---|
| 1125 | + if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
|---|
| 1126 | + dev_err(&chip->dev, FW_BUG |
|---|
| 956 | 1127 | "TPM interrupt not working, polling instead\n"); |
|---|
| 957 | 1128 | |
|---|
| 958 | | - disable_interrupts(chip); |
|---|
| 959 | | - } |
|---|
| 960 | | - } else { |
|---|
| 961 | | - tpm_tis_probe_irq(chip, intmask); |
|---|
| 1129 | + rc = tpm_tis_request_locality(chip, 0); |
|---|
| 1130 | + if (rc < 0) |
|---|
| 1131 | + goto out_err; |
|---|
| 1132 | + disable_interrupts(chip); |
|---|
| 1133 | + tpm_tis_relinquish_locality(chip, 0); |
|---|
| 962 | 1134 | } |
|---|
| 963 | 1135 | } |
|---|
| 964 | 1136 | |
|---|
| .. | .. |
|---|
| 1019 | 1191 | struct tpm_chip *chip = dev_get_drvdata(dev); |
|---|
| 1020 | 1192 | int ret; |
|---|
| 1021 | 1193 | |
|---|
| 1194 | + ret = tpm_tis_request_locality(chip, 0); |
|---|
| 1195 | + if (ret < 0) |
|---|
| 1196 | + return ret; |
|---|
| 1197 | + |
|---|
| 1022 | 1198 | if (chip->flags & TPM_CHIP_FLAG_IRQ) |
|---|
| 1023 | 1199 | tpm_tis_reenable_interrupts(chip); |
|---|
| 1024 | 1200 | |
|---|
| 1025 | 1201 | ret = tpm_pm_resume(dev); |
|---|
| 1026 | 1202 | if (ret) |
|---|
| 1027 | | - return ret; |
|---|
| 1203 | + goto out; |
|---|
| 1028 | 1204 | |
|---|
| 1029 | | - /* TPM 1.2 requires self-test on resume. This function actually returns |
|---|
| 1205 | + /* |
|---|
| 1206 | + * TPM 1.2 requires self-test on resume. This function actually returns |
|---|
| 1030 | 1207 | * an error code but for unknown reason it isn't handled. |
|---|
| 1031 | 1208 | */ |
|---|
| 1032 | 1209 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) |
|---|
| 1033 | | - tpm_do_selftest(chip); |
|---|
| 1210 | + tpm1_do_selftest(chip); |
|---|
| 1211 | +out: |
|---|
| 1212 | + tpm_tis_relinquish_locality(chip, 0); |
|---|
| 1034 | 1213 | |
|---|
| 1035 | | - return 0; |
|---|
| 1214 | + return ret; |
|---|
| 1036 | 1215 | } |
|---|
| 1037 | 1216 | EXPORT_SYMBOL_GPL(tpm_tis_resume); |
|---|
| 1038 | 1217 | #endif |
|---|