Skip to content

Commit

Permalink
tpm_tis: Delay ACPI S3 suspend while the TPM is busy
Browse files Browse the repository at this point in the history
This patch delays the (ACPI S3) suspend while the TPM is busy processing a
command and the TPM TIS driver is run in interrupt mode. This is the same
behavior as we already have it for the TPM TIS driver in polling mode.

Reasoning: Some of the TPM's commands advance the internal state of the TPM.
An example would be the extending of one of its PCR registers. Upper layers,
such as IMA or TSS (TrouSerS), would certainly want to be sure that the
command succeeded rather than getting an error code (-62 = -ETIME) that may
not give a conclusive answer as for what reason the command failed. Reissuing
such a command would put the TPM into the wrong state, so waiting for it to
finish is really the only option.

The downside is that some commands (key creation) can take a long time and
actually prevent the machine from entering S3 at all before the 20 second
timeout of the power management subsystem arrives.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
  • Loading branch information
Stefan Berger authored and Rajiv Andrade committed Jul 12, 2011
1 parent 45baa1d commit 20b87bb
Showing 1 changed file with 23 additions and 5 deletions.
28 changes: 23 additions & 5 deletions drivers/char/tpm/tpm_tis.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/acpi.h>
#include <linux/freezer.h>
#include "tpm.h"

#define TPM_HEADER_SIZE 10
Expand Down Expand Up @@ -120,7 +121,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)

static int request_locality(struct tpm_chip *chip, int l)
{
unsigned long stop;
unsigned long stop, timeout;
long rc;

if (check_locality(chip, l) >= 0)
Expand All @@ -129,17 +130,25 @@ static int request_locality(struct tpm_chip *chip, int l)
iowrite8(TPM_ACCESS_REQUEST_USE,
chip->vendor.iobase + TPM_ACCESS(l));

stop = jiffies + chip->vendor.timeout_a;

if (chip->vendor.irq) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -1;
rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
(check_locality
(chip, l) >= 0),
chip->vendor.timeout_a);
timeout);
if (rc > 0)
return l;

if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else {
/* wait for burstcount */
stop = jiffies + chip->vendor.timeout_a;
do {
if (check_locality(chip, l) >= 0)
return l;
Expand Down Expand Up @@ -196,15 +205,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
if ((status & mask) == mask)
return 0;

stop = jiffies + timeout;

if (chip->vendor.irq) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -ETIME;
rc = wait_event_interruptible_timeout(*queue,
((tpm_tis_status
(chip) & mask) ==
mask), timeout);
if (rc > 0)
return 0;
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else {
stop = jiffies + timeout;
do {
msleep(TPM_TIMEOUT);
status = tpm_tis_status(chip);
Expand Down

0 comments on commit 20b87bb

Please sign in to comment.