| From 5ee1e5bca5c2b5e5b4ac26e734e71514f47cd0c2 Mon Sep 17 00:00:00 2001 |
| From: Andrey Pronin <apronin@chromium.org> |
| Date: Thu, 6 Apr 2017 13:34:20 -0700 |
| Subject: [PATCH] CHROMIUM: tpm: block messages while suspended |
| |
| Other drivers or userspace may initiate sending a message to the tpm |
| while the device itself and the controller of the bus it is on are |
| suspended. That may break the bus driver logic. |
| Block sending messages while the device is suspended. |
| |
| BUG=b:35648537 |
| TEST=Continuously send messages to the tpm, go through suspend |
| to S0ix and back. Check that messages are rejected while |
| the tpm is suspended, and the tpm is accessible after resume. |
| |
| Change-Id: If5e2ee33ecb9e8e4afec20b2cf1b232b42859547 |
| Signed-off-by: Andrey Pronin <apronin@chromium.org> |
| Reviewed-on: https://chromium-review.googlesource.com/470747 |
| Reviewed-by: Duncan Laurie <dlaurie@google.com> |
| Conflicts: |
| drivers/char/tpm/tpm-interface.c |
| drivers/char/tpm/tpm.h |
| [rebase412(groeck): Resolved conflicts (context changes)] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| |
| Conflicts: |
| drivers/char/tpm/tpm-interface.c |
| drivers/char/tpm/tpm.h |
| |
| [rebase419(groeck): Resolved conflicts (context changes)] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| |
| [rebase54(groeck): Context conflicts; |
| replaced is_suspended bit operations with boolean] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| [rebase510(groeck): Context conflicts] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| --- |
| drivers/char/tpm/tpm-interface.c | 9 ++++++++- |
| include/linux/tpm.h | 2 ++ |
| 2 files changed, 10 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c |
| index 586ca10b0d72e5a0ed6fb84171b8ba1754def0d8..2f568196e8c4ae31a74dbf061b38c0eb91fa6699 100644 |
| --- a/drivers/char/tpm/tpm-interface.c |
| +++ b/drivers/char/tpm/tpm-interface.c |
| @@ -82,6 +82,11 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz) |
| return -E2BIG; |
| } |
| |
| + if (chip->is_suspended) { |
| + dev_warn(&chip->dev, "blocking transmit while suspended\n"); |
| + return -EAGAIN; |
| + } |
| + |
| rc = chip->ops->send(chip, buf, count); |
| if (rc < 0) { |
| if (rc != -EPIPE) |
| @@ -411,6 +416,8 @@ int tpm_pm_suspend(struct device *dev) |
| tpm_put_ops(chip); |
| } |
| |
| + if (!rc) |
| + chip->is_suspended = true; |
| suspended: |
| chip->flags |= TPM_CHIP_FLAG_SUSPENDED; |
| |
| @@ -438,7 +445,7 @@ int tpm_pm_resume(struct device *dev) |
| * activate before the chip has been fully resumed. |
| */ |
| wmb(); |
| - |
| + chip->is_suspended = false; |
| return 0; |
| } |
| EXPORT_SYMBOL_GPL(tpm_pm_resume); |
| diff --git a/include/linux/tpm.h b/include/linux/tpm.h |
| index 6eca8f544dfadbcd111dfdd8fd511fb43d7188a4..77b521ca4975111e38243a26be575bf1d233ad64 100644 |
| --- a/include/linux/tpm.h |
| +++ b/include/linux/tpm.h |
| @@ -138,6 +138,8 @@ struct tpm_chip { |
| int dev_num; /* /dev/tpm# */ |
| unsigned long is_open; /* only one allowed */ |
| |
| + bool is_suspended; |
| + |
| char hwrng_name[64]; |
| struct hwrng hwrng; |
| |
| -- |
| 2.34.1 |
| |