FAILED: patch "[PATCH] tpm: separate cmd_ready/go_idle from runtime_pm" failed to apply to 4.14-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
627448e85c766587f6fdde1ea3886d6615081c77Mon Sep 17 00:00:00 2001
From: Tomas Winkler <[email protected]>
Date: Thu, 28 Jun 2018 18:13:33 +0300
Subject: [PATCH] tpm: separate cmd_ready/go_idle from runtime_pm
Fix tpm ptt initialization error:
tpm tpm0: A TPM error (378) occurred get tpm pcr allocation.
We cannot use go_idle cmd_ready commands via runtime_pm handles as with the introduction of localities this is no longer an optional feature, while runtime pm can be not enabled.
Though cmd_ready/go_idle provides a power saving, it's also a part of TPM2 protocol and should be called explicitly.
This patch exposes cmd_read/go_idle via tpm class ops and removes runtime pm support as it is not used by any driver.
When calling from nested context always use both flags:TPM_TRANSMIT_UNLOCKED and TPM_TRANSMIT_RAW. Both are needed to resolve tpm spaces and locality request recursive calls to tpm_transmit(). TPM_TRANSMIT_RAW should never be used standalone as it will fail on double locking. While TPM_TRANSMIT_UNLOCKED standalone should be called from non-recursive locked contexts.
New wrappers are added tpm_cmd_ready() and tpm_go_idle() to streamline tpm_try_transmit code.
tpm_crb no longer needs own power saving functions and can drop using tpm_pm_suspend/resume.
This patch cannot be really separated from the locality fix.
drivers/char/tpm/tpm-interface.c +41 -10
@@ -29,7 +29,6 @@#include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> -#include <linux/pm_runtime.h> #include <linux/tpm_eventlog.h> #include "tpm.h"
@@ -369,10 +368,13 @@ err_len:return -EINVAL ; } -static int tpm_request_locality (struct tpm_chip *chip) +static int tpm_request_locality (struct tpm_chip *chip,unsigned int flags) {int rc; +if (flags &TPM_TRANSMIT_RAW ) +return 0 ; +if (!chip->ops->request_locality)return 0 ;
@@ -385,10 +387,13 @@ static int tpm_request_locality(struct tpm_chip *chip)return 0 ; } -static void tpm_relinquish_locality (struct tpm_chip *chip) +static void tpm_relinquish_locality (struct tpm_chip *chip,unsigned int flags) {int rc; +if (flags &TPM_TRANSMIT_RAW ) +return ; +if (!chip->ops->relinquish_locality)return ;
@@ -399,6 +404,28 @@ static void tpm_relinquish_locality(struct tpm_chip *chip) chip->locality =-1 ; } +static int tpm_cmd_ready (struct tpm_chip *chip,unsigned int flags) +{ +if (flags &TPM_TRANSMIT_RAW ) +return 0 ; + +if (!chip->ops->cmd_ready) +return 0 ; + +return chip->ops->cmd_ready (chip); +} + +static int tpm_go_idle (struct tpm_chip *chip,unsigned int flags) +{ +if (flags &TPM_TRANSMIT_RAW ) +return 0 ; + +if (!chip->ops->go_idle) +return 0 ; + +return chip->ops->go_idle (chip); +} + static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz,
@@ -449,14 +476,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,/* Store the decision as chip->locality will be changed. */ need_locality = chip->locality ==-1 ; -if (!(flags &TPM_TRANSMIT_RAW ) && need_locality) { - rc =tpm_request_locality (chip); +if (need_locality) { + rc =tpm_request_locality (chip, flags);if (rc <0 ) goto out_no_locality; } -if (chip->dev.parent) -pm_runtime_get_sync (chip->dev.parent); + rc =tpm_cmd_ready (chip, flags); +if (rc) + goto out; rc =tpm2_prepare_space (chip, space, ordinal, buf);if (rc)
@@ -516,13 +544,16 @@ out_recv: } rc =tpm2_commit_space (chip, space, ordinal, buf, &len); +if (rc) +dev_err (&chip->dev,"tpm2_commit_space: error %d\n" , rc); out: -if (chip->dev.parent) -pm_runtime_put_sync (chip->dev.parent); + rc =tpm_go_idle (chip, flags); +if (rc) + goto out;if (need_locality) -tpm_relinquish_locality (chip); +tpm_relinquish_locality (chip, flags); out_no_locality:if (chip->ops->clk_enable !=NULL )
drivers/char/tpm/tpm.h +10 -2
@@ -512,9 +512,17 @@ extern const struct file_operations tpm_fops;extern const struct file_operations tpmrm_fops;extern struct idr dev_nums_idr; +/** +* enum tpm_transmit_flags +* +* @TPM_TRANSMIT_UNLOCKED: used to lock sequence of tpm_transmit calls. +* @TPM_TRANSMIT_RAW: prevent recursive calls into setup steps +* (go idle, locality,..). Always use with UNLOCKED +* as it will fail on double locking. +*/ enum tpm_transmit_flags { -TPM_TRANSMIT_UNLOCKED =BIT (0 ), -TPM_TRANSMIT_RAW =BIT (1 ), +TPM_TRANSMIT_UNLOCKED =BIT (0 ), +TPM_TRANSMIT_RAW =BIT (1 ), }; ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
drivers/char/tpm/tpm2-space.c +10 -6
@@ -39,7 +39,8 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space)for (i =0 ; i <ARRAY_SIZE (space->session_tbl); i++) {if (space->session_tbl[i])tpm2_flush_context_cmd (chip, space->session_tbl[i], -TPM_TRANSMIT_UNLOCKED ); +TPM_TRANSMIT_UNLOCKED | +TPM_TRANSMIT_RAW ); } }
@@ -84,7 +85,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,tpm_buf_append (&tbuf, &buf[*offset], body_size); rc =tpm_transmit_cmd (chip,NULL , tbuf.data,PAGE_SIZE ,4 , -TPM_TRANSMIT_UNLOCKED ,NULL ); +TPM_TRANSMIT_UNLOCKED |TPM_TRANSMIT_RAW ,NULL );if (rc <0 ) {dev_warn (&chip->dev,"%s: failed with a system error %d\n" , __func__, rc);
@@ -133,7 +134,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,tpm_buf_append_u32 (&tbuf, handle); rc =tpm_transmit_cmd (chip,NULL , tbuf.data,PAGE_SIZE ,0 , -TPM_TRANSMIT_UNLOCKED ,NULL ); +TPM_TRANSMIT_UNLOCKED |TPM_TRANSMIT_RAW ,NULL );if (rc <0 ) {dev_warn (&chip->dev,"%s: failed with a system error %d\n" , __func__, rc);
@@ -170,7 +171,8 @@ static void tpm2_flush_space(struct tpm_chip *chip)for (i =0 ; i <ARRAY_SIZE (space->context_tbl); i++)if (space->context_tbl[i] && ~space->context_tbl[i])tpm2_flush_context_cmd (chip, space->context_tbl[i], -TPM_TRANSMIT_UNLOCKED ); +TPM_TRANSMIT_UNLOCKED | +TPM_TRANSMIT_RAW );tpm2_flush_sessions (chip, space); }
@@ -377,7 +379,8 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,return 0 ; out_no_slots: -tpm2_flush_context_cmd (chip, phandle,TPM_TRANSMIT_UNLOCKED ); +tpm2_flush_context_cmd (chip, phandle, +TPM_TRANSMIT_UNLOCKED |TPM_TRANSMIT_RAW );dev_warn (&chip->dev,"%s: out of slots for 0x%08X\n" , __func__, phandle);return -ENOMEM ;
@@ -465,7 +468,8 @@ static int tpm2_save_space(struct tpm_chip *chip)return rc;tpm2_flush_context_cmd (chip, space->context_tbl[i], -TPM_TRANSMIT_UNLOCKED ); +TPM_TRANSMIT_UNLOCKED | +TPM_TRANSMIT_RAW ); space->context_tbl[i] = ~0 ; }
drivers/char/tpm/tpm_crb.c +27 -74
169 lines not on this page · raw message
include/linux/tpm.h +2 -0
@@ -43,6 +43,8 @@ struct tpm_class_ops {u8 (*status) (struct tpm_chip *chip);bool (*update_timeouts)(struct tpm_chip *chip,unsigned long *timeout_cap); +int (*go_idle)(struct tpm_chip *chip); +int (*cmd_ready)(struct tpm_chip *chip);int (*request_locality)(struct tpm_chip *chip,int loc);int (*relinquish_locality)(struct tpm_chip *chip,int loc);void (*clk_enable)(struct tpm_chip *chip,bool value);