diff options
author | Winkler, Tomas <tomas.winkler@intel.com> | 2016-10-08 07:59:39 -0400 |
---|---|---|
committer | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2016-11-27 18:31:30 -0500 |
commit | e74f2f76c13770bb8e004475a933923e9c92723d (patch) | |
tree | c011ae10c69e72a23f77e05342a0ff43f560c023 | |
parent | c58bd34cec4c05f8e3362a79ae94de9f405c39b5 (diff) |
tmp/tpm_crb: implement runtime pm for tpm_crb
Utilize runtime_pm for driving tpm crb idle states.
The framework calls cmd_ready from the pm_runtime_resume handler
and go idle from the pm_runtime_suspend handler.
The TPM framework should wake the device before transmit and receive.
In case the runtime_pm framework is not compiled in or enabled, the device
will be in the permanent ready state.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 42 |
2 files changed, 43 insertions, 4 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 3a9149cf0110..cb0e57ee053d 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/freezer.h> | 31 | #include <linux/freezer.h> |
32 | #include <linux/pm_runtime.h> | ||
32 | 33 | ||
33 | #include "tpm.h" | 34 | #include "tpm.h" |
34 | #include "tpm_eventlog.h" | 35 | #include "tpm_eventlog.h" |
@@ -356,6 +357,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | |||
356 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) | 357 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
357 | mutex_lock(&chip->tpm_mutex); | 358 | mutex_lock(&chip->tpm_mutex); |
358 | 359 | ||
360 | pm_runtime_get_sync(chip->dev.parent); | ||
361 | |||
359 | rc = chip->ops->send(chip, (u8 *) buf, count); | 362 | rc = chip->ops->send(chip, (u8 *) buf, count); |
360 | if (rc < 0) { | 363 | if (rc < 0) { |
361 | dev_err(&chip->dev, | 364 | dev_err(&chip->dev, |
@@ -397,6 +400,8 @@ out_recv: | |||
397 | dev_err(&chip->dev, | 400 | dev_err(&chip->dev, |
398 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 401 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
399 | out: | 402 | out: |
403 | pm_runtime_put_sync(chip->dev.parent); | ||
404 | |||
400 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) | 405 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
401 | mutex_unlock(&chip->tpm_mutex); | 406 | mutex_unlock(&chip->tpm_mutex); |
402 | return rc; | 407 | return rc; |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index f579f1ac4688..717b6b47c042 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
20 | #include <linux/rculist.h> | 20 | #include <linux/rculist.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/pm_runtime.h> | ||
22 | #include "tpm.h" | 23 | #include "tpm.h" |
23 | 24 | ||
24 | #define ACPI_SIG_TPM2 "TPM2" | 25 | #define ACPI_SIG_TPM2 "TPM2" |
@@ -149,8 +150,6 @@ static int __maybe_unused crb_cmd_ready(struct device *dev, | |||
149 | return 0; | 150 | return 0; |
150 | } | 151 | } |
151 | 152 | ||
152 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); | ||
153 | |||
154 | static u8 crb_status(struct tpm_chip *chip) | 153 | static u8 crb_status(struct tpm_chip *chip) |
155 | { | 154 | { |
156 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 155 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
@@ -433,11 +432,21 @@ static int crb_acpi_add(struct acpi_device *device) | |||
433 | if (rc) | 432 | if (rc) |
434 | return rc; | 433 | return rc; |
435 | 434 | ||
435 | pm_runtime_get_noresume(dev); | ||
436 | pm_runtime_set_active(dev); | ||
437 | pm_runtime_enable(dev); | ||
438 | |||
436 | rc = tpm_chip_register(chip); | 439 | rc = tpm_chip_register(chip); |
437 | if (rc) | 440 | if (rc) { |
438 | crb_go_idle(dev, priv); | 441 | crb_go_idle(dev, priv); |
442 | pm_runtime_put_noidle(dev); | ||
443 | pm_runtime_disable(dev); | ||
444 | return rc; | ||
445 | } | ||
439 | 446 | ||
440 | return rc; | 447 | pm_runtime_put(dev); |
448 | |||
449 | return 0; | ||
441 | } | 450 | } |
442 | 451 | ||
443 | static int crb_acpi_remove(struct acpi_device *device) | 452 | static int crb_acpi_remove(struct acpi_device *device) |
@@ -447,9 +456,34 @@ static int crb_acpi_remove(struct acpi_device *device) | |||
447 | 456 | ||
448 | tpm_chip_unregister(chip); | 457 | tpm_chip_unregister(chip); |
449 | 458 | ||
459 | pm_runtime_disable(dev); | ||
460 | |||
450 | return 0; | 461 | return 0; |
451 | } | 462 | } |
452 | 463 | ||
464 | #ifdef CONFIG_PM | ||
465 | static int crb_pm_runtime_suspend(struct device *dev) | ||
466 | { | ||
467 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
468 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
469 | |||
470 | return crb_go_idle(dev, priv); | ||
471 | } | ||
472 | |||
473 | static int crb_pm_runtime_resume(struct device *dev) | ||
474 | { | ||
475 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
476 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
477 | |||
478 | return crb_cmd_ready(dev, priv); | ||
479 | } | ||
480 | #endif /* CONFIG_PM */ | ||
481 | |||
482 | static const struct dev_pm_ops crb_pm = { | ||
483 | SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume) | ||
484 | SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL) | ||
485 | }; | ||
486 | |||
453 | static struct acpi_device_id crb_device_ids[] = { | 487 | static struct acpi_device_id crb_device_ids[] = { |
454 | {"MSFT0101", 0}, | 488 | {"MSFT0101", 0}, |
455 | {"", 0}, | 489 | {"", 0}, |