From: Scot Doyle <lkml14@scotdoyle.com>
To: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Peter Huewe <peterhuewe@gmx.de>,
Ashley Lai <ashley@ashleylai.com>,
Marcel Selhorst <tpmdd@selhorst.net>,
Stefan Berger <stefanb@linux.vnet.ibm.com>,
Luigi Semenzato <semenzato@google.com>,
tpmdd-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org
Subject: [RFC PATCH v3] tpm_tis: verify interrupt during init
Date: Wed, 27 Aug 2014 21:32:10 +0000 (UTC) [thread overview]
Message-ID: <alpine.LNX.2.11.1408271755470.4371@localhost.localdomain> (raw)
In-Reply-To: <20140827173142.GA11183@obsidianresearch.com>
On Wed, 27 Aug 2014, Jason Gunthorpe wrote:
> On Wed, Aug 27, 2014 at 04:31:56AM +0000, Scot Doyle wrote:
>> It doesn't enable stock SeaBIOS machines to suspend/resume before the 30
>> second interrupt timeout, unless using interrupts=0 or force=1.
>
> ? Can you explain that a bit more? interrupts should be detected off
> by suspend/resume time, surely?
Yes, here's dmesg:
[ 1.491629] tpm_tis 00:08: 1.2 TPM (device-id 0xB, rev-id 16)
[ 33.247720] tpm_tis 00:08: tpm_transmit: tpm_send: error -62
[ 33.247731] tpm_tis 00:08: [Hardware Error]: TPM command timed out during continue self test
[ 33.349888] tpm_tis 00:08: tpm_transmit: tpm_send: error -5
[ 33.459911] tpm_tis 00:08: [Firmware Bug]: TPM interrupt not working, polling instead
At module load, the misconfigured DSDT is causing the interrupt to be used
during selftest. The interrupt wait times out after 30 seconds, and the
irq is freed, with the module falling back to polling mode.
If suspend/resume occur before falling back to polling mode (within 30
seconds after module load), then the machine freezes on resume because
the module is waiting on the interrupts.
So, this should only affect machines with incorrect ACPI, that are not
using a module parameter, and that are suspended within 30 seconds after
module load. Considering that we are enabling such machines to
automatically work otherwise, I think this is fair.
>> - if (tpm_do_selftest(chip)) {
>> - dev_err(dev, "TPM self test failed\n");
>> - rc = -ENODEV;
>> - goto out_err;
>> - }
>
> Move gettimeout too
Can it be moved? It sends startup(clear) if the TPM isn't yet operational.
>> - if (chip->vendor.irq) {
>> + if (interrupts && chip->vendor.irq) {
>
> Unrelated? Looks unnecessary:
>
> if (!interrupts) {
> irq = 0;
>
> chip->vendor.irq = irq;
>
> if (chip->vendor.irq) {
Setting chip->vendor.irq would erase any we just found in probing?
>> + /* Test interrupt and/or prepare for later save state */
>> + interrupted = false;
>> + if (tpm_do_selftest(chip)) {
>
> As you pointed out before, the commands don't actually fail if
> interrupts are not enabled, they just take a longer time to complete.
Right, the TPM commands don't fail, but tpm_get_timeouts does. I've
simplified the section in this version.
And I've incorporated the other suggestions, thanks!
---
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e4d0888..6747a47 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -69,6 +69,7 @@ struct tpm_vendor_specific {
int irq;
int probed_irq;
+ bool int_received;
int region_size;
int have_region;
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 2c46734..ad63027 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -505,6 +505,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
if (interrupt == 0)
return IRQ_NONE;
+ chip->vendor.int_received = true;
if (interrupt & TPM_INTF_DATA_AVAIL_INT)
wake_up_interruptible(&chip->vendor.read_queue);
if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
@@ -612,12 +613,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
goto out_err;
}
- if (tpm_do_selftest(chip)) {
- dev_err(dev, "TPM self test failed\n");
- rc = -ENODEV;
- goto out_err;
- }
-
/* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue);
init_waitqueue_head(&chip->vendor.int_queue);
@@ -693,7 +688,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
free_irq(i, chip);
}
}
- if (chip->vendor.irq) {
+ if (interrupts && chip->vendor.irq) {
iowrite8(chip->vendor.irq,
chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality));
@@ -719,6 +714,29 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
}
}
+ /* Test interrupt and/or prepare for later save state */
+ chip->vendor.int_received = false;
+ if (tpm_do_selftest(chip)) {
+ if (interrupts && !chip->vendor.int_received) {
+ /* Turn off interrupt */
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ free_irq(chip->vendor.irq, chip);
+
+ /* Retry in polling mode */
+ chip->vendor.irq = 0;
+ if (!tpm_do_selftest(chip)) {
+ dev_err(dev, FW_BUG "TPM interrupt not working, polling instead\n");
+ goto cont;
+ }
+ }
+ dev_err(dev, "TPM self test failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+cont:
INIT_LIST_HEAD(&chip->vendor.list);
mutex_lock(&tis_lock);
list_add(&chip->vendor.list, &tis_chips);
next prev parent reply other threads:[~2014-08-27 21:35 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-22 0:58 [PATCH] tpm_tis: Verify ACPI-specified interrupt Scot Doyle
2014-08-22 16:06 ` Jason Gunthorpe
2014-08-22 20:17 ` Scot Doyle
2014-08-22 20:32 ` Jason Gunthorpe
2014-08-22 22:48 ` Peter Hüwe
2014-08-25 6:38 ` Scot Doyle
2014-08-25 18:24 ` Jason Gunthorpe
2014-08-27 4:31 ` [RFC PATCH v2] tpm_tis: verify interrupt during init Scot Doyle
2014-08-27 17:31 ` Jason Gunthorpe
2014-08-27 21:32 ` Scot Doyle [this message]
2014-08-27 21:47 ` [RFC PATCH v3] " Jason Gunthorpe
2014-08-28 0:35 ` Scot Doyle
2014-08-28 16:53 ` Jason Gunthorpe
2014-08-29 23:59 ` [RFC PATCH v4] " Scot Doyle
2014-08-30 17:49 ` Jason Gunthorpe
2014-08-30 23:23 ` [RFC PATCH v5] " Scot Doyle
2014-09-02 17:20 ` Jason Gunthorpe
2014-09-02 20:22 ` [RFC PATCH v6] " Scot Doyle
2014-09-08 22:02 ` Jason Gunthorpe
2014-09-09 2:13 ` [PATCH v7] " Scot Doyle
2014-09-09 3:12 ` Scot Doyle
2014-09-11 0:50 ` [RFC PATCH v8] " Scot Doyle
2014-09-16 23:36 ` Scot Doyle
2014-09-22 17:13 ` Jason Gunthorpe
2014-09-22 19:01 ` Peter Hüwe
2014-10-19 20:08 ` Scot Doyle
2014-09-23 2:44 ` Scot Doyle
2014-09-23 2:51 ` [PATCH v9] " Scot Doyle
2014-09-23 11:55 ` Scot Doyle
2014-09-23 17:12 ` [tpmdd-devel] " Stefan Berger
2014-09-24 19:38 ` Scot Doyle
2014-09-24 19:41 ` Stefan Berger
2014-09-24 22:41 ` [PATCH v10] " Scot Doyle
2014-09-29 17:24 ` Jason Gunthorpe
2014-11-30 14:24 ` Peter Hüwe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LNX.2.11.1408271755470.4371@localhost.localdomain \
--to=lkml14@scotdoyle.com \
--cc=ashley@ashleylai.com \
--cc=jgunthorpe@obsidianresearch.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterhuewe@gmx.de \
--cc=semenzato@google.com \
--cc=stefanb@linux.vnet.ibm.com \
--cc=tpmdd-devel@lists.sourceforge.net \
--cc=tpmdd@selhorst.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox