1From 06c3e612cb0927d783f115077d83ed97841c5668 Mon Sep 17 00:00:00 2001
2From: Emekcan Aras <emekcan.aras@arm.com>
3Date: Tue, 14 Nov 2023 14:43:44 +0000
4Subject: [PATCH] plat: corstone1000: fix synchronization issue on openamp notification
5
6This fixes a race that is observed rarely in the FVP. It occurs in FVP
7when Secure Enclave sends the notication ack in openamp, and then reset the access
8request which resets the mhu registers before received by the SE-proxy-sp in the
9host processort. This solution introduces polling on the status register of
10mhu until the notificaiton is read by the host processor. (Inspired by
11signal_and_wait_for_signal function in mhu_wrapper_v2_x.c in trusted-firmware-m
12https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git/tree/platform/ext/target/arm/rss/common/native_drivers/mhu_wrapper_v2_x.c#n61)
13
14Signed-off-by: Emekcan Aras <emekcan.aras@arm.com>
15Upstream-Status: Pending [Not submitted to upstream yet]
16---
17 components/messaging/openamp/sp/openamp_mhu.c |  9 ++++++++-
18 platform/drivers/arm/mhu_driver/mhu_v2.h      | 18 ++++++++++++++++++
19 platform/drivers/arm/mhu_driver/mhu_v2_x.c    | 17 +++++++++++++++++
20 3 files changed, 43 insertions(+), 1 deletion(-)
21
22diff --git a/components/messaging/openamp/sp/openamp_mhu.c b/components/messaging/openamp/sp/openamp_mhu.c
23index bafba3e3..0700b8b9 100644
24--- a/components/messaging/openamp/sp/openamp_mhu.c
25+++ b/components/messaging/openamp/sp/openamp_mhu.c
26@@ -85,7 +85,7 @@ int openamp_mhu_notify_peer(struct openamp_messenger *openamp)
27	struct mhu_v2_x_dev_t *tx_dev;
28	enum mhu_v2_x_error_t ret;
29	struct openamp_mhu *mhu;
30-	uint32_t access_ready;
31+	uint32_t access_ready,val;
32
33	if (!openamp->transport) {
34		EMSG("openamp: mhu: notify transport not initialized");
35@@ -116,6 +116,13 @@ int openamp_mhu_notify_peer(struct openamp_messenger *openamp)
36		return -EPROTO;
37	}
38
39+	do {
40+		ret = mhu_v2_x_channel_poll(tx_dev, MHU_V_2_NOTIFY_CHANNEL, &val);
41+		if (ret != MHU_V_2_X_ERR_NONE) {
42+			break;
43+		}
44+	} while (val != 0);
45+
46	ret = mhu_v2_x_reset_access_request(tx_dev);
47	if (ret != MHU_V_2_X_ERR_NONE) {
48		EMSG("openamp: mhu: failed reset access request");
49diff --git a/platform/drivers/arm/mhu_driver/mhu_v2.h b/platform/drivers/arm/mhu_driver/mhu_v2.h
50index 26b3a5d6..2b4d6fcb 100644
51--- a/platform/drivers/arm/mhu_driver/mhu_v2.h
52+++ b/platform/drivers/arm/mhu_driver/mhu_v2.h
53@@ -384,6 +384,24 @@ enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
54 enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
55      const struct mhu_v2_x_dev_t *dev, uint32_t *channel);
56
57+
58+/**
59+ * \brief Polls sender channel status.
60+ *
61+ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
62+ * \param[in]  channel     Channel to poll the status of.
63+ * \param[out] value       Pointer to variable that will store the value.
64+ *
65+ * Polls sender channel status.
66+ *
67+ * \return Returns mhu_v2_x_error_t error code
68+ *
69+ * \note This function doesn't check if dev is NULL.
70+ * \note This function doesn't check if channel is implemented.
71+ */
72+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
73+     uint32_t channel, uint32_t *value);
74+
75 #ifdef __cplusplus
76 }
77 #endif
78diff --git a/platform/drivers/arm/mhu_driver/mhu_v2_x.c b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
79index d7e70efa..022e287a 100644
80--- a/platform/drivers/arm/mhu_driver/mhu_v2_x.c
81+++ b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
82@@ -600,3 +600,20 @@ enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
83
84     return MHU_V_2_X_ERR_GENERAL;
85 }
86+
87+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
88+     uint32_t channel, uint32_t *value)
89+{
90+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
91+
92+    if ( !(dev->is_initialized) ) {
93+        return MHU_V_2_X_ERR_NOT_INIT;
94+    }
95+
96+    if (dev->frame == MHU_V2_X_SENDER_FRAME) {
97+        *value = (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_st;
98+        return MHU_V_2_X_ERR_NONE;
99+    } else {
100+        return MHU_V_2_X_ERR_INVALID_ARG;
101+    }
102+}
103--
1042.25.1
105
106