* [PATCH v5 0/1] tpm_crb_ffa: handle tpm busy return code
@ 2025-06-16 18:08 Prachotan Bathi
2025-06-16 18:08 ` [PATCH v5 1/1] " Prachotan Bathi
0 siblings, 1 reply; 2+ messages in thread
From: Prachotan Bathi @ 2025-06-16 18:08 UTC (permalink / raw)
To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe, Stuart Yoder
Cc: linux-integrity, linux-kernel, Prachotan Bathi
Platforms that support FF-A direct message request v2 can implement
Secure Partitions (SPs) that host multiple services. When the TPM
service shares its SP with other services, message requests from the
driver may fail with a BUSY response if another service is currently
active.
To improve robustness in such scenarios, we need to introduce retry
logic in the driver. When a BUSY error is received, the driver will
re-attempt the TPM request until it succeeds or a run-time configurable
timeout(default: 2000 ms) is reached. This ensures reliable TPM access
under shared-SP conditions.
Add a module parameter, `busy_timeout_ms`, which specifies the
maximum amount of time (in milliseconds) to retry on BUSY before giving
up.
This change builds on top of commit a85b55ee64a5, which introduced
support for TPM service communication using the FF-A direct message v2
path, in accordance with section 3.3 of the TPM Service Command
Response Buffer Interface specification.
https://developer.arm.com/documentation/den0138/latest/
This was tested with an FF-A based fTPM currently not publicly available.
There are plans to open source the fTPM.
Changes in v5:
- Updated variable name to reflect units.
- Added a dev log message to indicate the retry timeout.
- Updated commit message with directions for users to set the timeout.
Prachotan Bathi (1):
tpm_crb_ffa: handle tpm busy return code
drivers/char/tpm/tpm_crb_ffa.c | 77 +++++++++++++++++++++++-----------
1 file changed, 53 insertions(+), 24 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v5 1/1] tpm_crb_ffa: handle tpm busy return code
2025-06-16 18:08 [PATCH v5 0/1] tpm_crb_ffa: handle tpm busy return code Prachotan Bathi
@ 2025-06-16 18:08 ` Prachotan Bathi
0 siblings, 0 replies; 2+ messages in thread
From: Prachotan Bathi @ 2025-06-16 18:08 UTC (permalink / raw)
To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe, Stuart Yoder
Cc: linux-integrity, linux-kernel, Prachotan Bathi
Platforms supporting direct message request v2 [1] can support secure
partitions that support multiple services. For CRB over FF-A interface,
if the firmware TPM or TPM service [1] shares its Secure Partition (SP)
with another service, message requests may fail with a -EBUSY error.
To handle this, replace the single check and call with a retry loop
that attempts the TPM message send operation until it succeeds or a
configurable timeout is reached. The retry mechanism introduces a
module parameter (`busy_timeout_ms`, default: 2000ms) to control how long
to keep retrying on -EBUSY responses. Between retries, the code waits
briefly (50-100 microseconds) to avoid busy-waiting and handling
TPM BUSY conditions more gracefully.
The parameter can be modified at run-time as such:
echo 3000 | tee /sys/module/tpm_crb_ffa/parameters/busy_timeout_ms
This changes the timeout from the default 2000ms to 3000ms.
[1] TPM Service Command Response Buffer Interface Over FF-A
https://developer.arm.com/documentation/den0138/latest/
Signed-off-by: Prachotan Bathi <prachotan.bathi@arm.com>
---
drivers/char/tpm/tpm_crb_ffa.c | 77 +++++++++++++++++++++++-----------
1 file changed, 53 insertions(+), 24 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 4ead61f01299..19de2dda75de 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -10,6 +10,8 @@
#define pr_fmt(fmt) "CRB_FFA: " fmt
#include <linux/arm_ffa.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
#include "tpm_crb_ffa.h"
/* TPM service function status codes */
@@ -178,6 +180,17 @@ int tpm_crb_ffa_init(void)
}
EXPORT_SYMBOL_GPL(tpm_crb_ffa_init);
+static unsigned int busy_timeout_ms = 2000;
+/**
+ * busy_timeout_ms - Maximum time to retry before giving up on busy
+ *
+ * This parameter defines the maximum time in milliseconds to retry
+ * sending a message to the TPM service before giving up.
+ */
+module_param(busy_timeout_ms, uint, 0644);
+MODULE_PARM_DESC(busy_timeout_ms,
+ "Maximum time(in ms) to retry before giving up on busy");
+
static int __tpm_crb_ffa_send_recieve(unsigned long func_id,
unsigned long a0,
unsigned long a1,
@@ -191,34 +204,50 @@ static int __tpm_crb_ffa_send_recieve(unsigned long func_id,
msg_ops = tpm_crb_ffa->ffa_dev->ops->msg_ops;
- if (ffa_partition_supports_direct_req2_recv(tpm_crb_ffa->ffa_dev)) {
- memset(&tpm_crb_ffa->direct_msg_data2, 0x00,
- sizeof(struct ffa_send_direct_data2));
+ ktime_t start;
+ ktime_t stop;
+
+ start = ktime_get();
+ stop = ktime_add(start, ms_to_ktime(busy_timeout_ms));
+
+ do {
+ if (ffa_partition_supports_direct_req2_recv(tpm_crb_ffa->ffa_dev)) {
+ memset(&tpm_crb_ffa->direct_msg_data2, 0x00,
+ sizeof(struct ffa_send_direct_data2));
- tpm_crb_ffa->direct_msg_data2.data[0] = func_id;
- tpm_crb_ffa->direct_msg_data2.data[1] = a0;
- tpm_crb_ffa->direct_msg_data2.data[2] = a1;
- tpm_crb_ffa->direct_msg_data2.data[3] = a2;
+ tpm_crb_ffa->direct_msg_data2.data[0] = func_id;
+ tpm_crb_ffa->direct_msg_data2.data[1] = a0;
+ tpm_crb_ffa->direct_msg_data2.data[2] = a1;
+ tpm_crb_ffa->direct_msg_data2.data[3] = a2;
- ret = msg_ops->sync_send_receive2(tpm_crb_ffa->ffa_dev,
+ ret = msg_ops->sync_send_receive2(tpm_crb_ffa->ffa_dev,
&tpm_crb_ffa->direct_msg_data2);
- if (!ret)
- ret = tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data2.data[0]);
- } else {
- memset(&tpm_crb_ffa->direct_msg_data, 0x00,
- sizeof(struct ffa_send_direct_data));
-
- tpm_crb_ffa->direct_msg_data.data1 = func_id;
- tpm_crb_ffa->direct_msg_data.data2 = a0;
- tpm_crb_ffa->direct_msg_data.data3 = a1;
- tpm_crb_ffa->direct_msg_data.data4 = a2;
-
- ret = msg_ops->sync_send_receive(tpm_crb_ffa->ffa_dev,
- &tpm_crb_ffa->direct_msg_data);
- if (!ret)
- ret = tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data.data1);
- }
+ if (!ret)
+ ret = tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data2.data[0]);
+ } else {
+ memset(&tpm_crb_ffa->direct_msg_data, 0x00,
+ sizeof(struct ffa_send_direct_data));
+ tpm_crb_ffa->direct_msg_data.data1 = func_id;
+ tpm_crb_ffa->direct_msg_data.data2 = a0;
+ tpm_crb_ffa->direct_msg_data.data3 = a1;
+ tpm_crb_ffa->direct_msg_data.data4 = a2;
+
+ ret = msg_ops->sync_send_receive(tpm_crb_ffa->ffa_dev,
+ &tpm_crb_ffa->direct_msg_data);
+ if (!ret)
+ ret = tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data.data1);
+ }
+ if (ret == -EBUSY)
+ pr_err("TPM says busy, trying again, value, ret: %d\n",
+ ret);
+ else
+ break;
+ usleep_range(50, 100);
+ if (ktime_after(ktime_get(), stop))
+ dev_warn(&tpm_crb_ffa->ffa_dev->dev, "Busy retry timed out\n");
+
+ } while (ktime_before(ktime_get(), stop));
return ret;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-06-16 18:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-16 18:08 [PATCH v5 0/1] tpm_crb_ffa: handle tpm busy return code Prachotan Bathi
2025-06-16 18:08 ` [PATCH v5 1/1] " Prachotan Bathi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).