blob: 5d8f73185452354ebbad3bebc6c2e7314252eb95 [file] [log] [blame]
From 06c3e612cb0927d783f115077d83ed97841c5668 Mon Sep 17 00:00:00 2001
From: Emekcan Aras <emekcan.aras@arm.com>
Date: Tue, 14 Nov 2023 14:43:44 +0000
Subject: [PATCH] plat: corstone1000: fix synchronization issue on openamp notification
This fixes a race that is observed rarely in the FVP. It occurs in FVP
when Secure Enclave sends the notication ack in openamp, and then reset the access
request which resets the mhu registers before received by the SE-proxy-sp in the
host processort. This solution introduces polling on the status register of
mhu until the notificaiton is read by the host processor. (Inspired by
signal_and_wait_for_signal function in mhu_wrapper_v2_x.c in trusted-firmware-m
https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git/tree/platform/ext/target/arm/rss/common/native_drivers/mhu_wrapper_v2_x.c#n61)
Signed-off-by: Emekcan Aras <emekcan.aras@arm.com>
Upstream-Status: Pending [Not submitted to upstream yet]
---
components/messaging/openamp/sp/openamp_mhu.c | 9 ++++++++-
platform/drivers/arm/mhu_driver/mhu_v2.h | 18 ++++++++++++++++++
platform/drivers/arm/mhu_driver/mhu_v2_x.c | 17 +++++++++++++++++
3 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/components/messaging/openamp/sp/openamp_mhu.c b/components/messaging/openamp/sp/openamp_mhu.c
index bafba3e3..0700b8b9 100644
--- a/components/messaging/openamp/sp/openamp_mhu.c
+++ b/components/messaging/openamp/sp/openamp_mhu.c
@@ -85,7 +85,7 @@ int openamp_mhu_notify_peer(struct openamp_messenger *openamp)
struct mhu_v2_x_dev_t *tx_dev;
enum mhu_v2_x_error_t ret;
struct openamp_mhu *mhu;
- uint32_t access_ready;
+ uint32_t access_ready,val;
if (!openamp->transport) {
EMSG("openamp: mhu: notify transport not initialized");
@@ -116,6 +116,13 @@ int openamp_mhu_notify_peer(struct openamp_messenger *openamp)
return -EPROTO;
}
+ do {
+ ret = mhu_v2_x_channel_poll(tx_dev, MHU_V_2_NOTIFY_CHANNEL, &val);
+ if (ret != MHU_V_2_X_ERR_NONE) {
+ break;
+ }
+ } while (val != 0);
+
ret = mhu_v2_x_reset_access_request(tx_dev);
if (ret != MHU_V_2_X_ERR_NONE) {
EMSG("openamp: mhu: failed reset access request");
diff --git a/platform/drivers/arm/mhu_driver/mhu_v2.h b/platform/drivers/arm/mhu_driver/mhu_v2.h
index 26b3a5d6..2b4d6fcb 100644
--- a/platform/drivers/arm/mhu_driver/mhu_v2.h
+++ b/platform/drivers/arm/mhu_driver/mhu_v2.h
@@ -384,6 +384,24 @@ enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
const struct mhu_v2_x_dev_t *dev, uint32_t *channel);
+
+/**
+ * \brief Polls sender channel status.
+ *
+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel Channel to poll the status of.
+ * \param[out] value Pointer to variable that will store the value.
+ *
+ * Polls sender channel status.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t *value);
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/drivers/arm/mhu_driver/mhu_v2_x.c b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
index d7e70efa..022e287a 100644
--- a/platform/drivers/arm/mhu_driver/mhu_v2_x.c
+++ b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
@@ -600,3 +600,20 @@ enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
return MHU_V_2_X_ERR_GENERAL;
}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t *value)
+{
+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+ if ( !(dev->is_initialized) ) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_SENDER_FRAME) {
+ *value = (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_st;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
--
2.25.1