diff options
| author | Sudeep Holla <[email protected]> | 2024-08-20 15:27:59 +0100 |
|---|---|---|
| committer | Sudeep Holla <[email protected]> | 2024-08-20 15:40:45 +0100 |
| commit | eaca7ef8f31a9040021683d381ddb83eb6fd7774 (patch) | |
| tree | 0f86a6762c7779389e6e8b595891e12bec378762 | |
| parent | aaef3bc98129c86078b336f16788dd733b0728a4 (diff) | |
firmware: arm_ffa: Add support for FFA_YIELD in direct messaging
Successful completion of both direct messaging function can be indicated
through an invocation of FFA_YIELD or GGA_INTERRUPT by the callee.
FFA_INTERRUPT indicates that the direct request was interrupted and must
be resumed through the FFA_RUN interface which is already done in the
driver.
FFA_YIELD indicates that the receiver endpoint has transitioned to the
blocked runtime state and must be resumed through the FFA_RUN interface.
However, the way receiver endpoint gets unblocked is implementation
defined. So, the driver just sleeps for 1 - 2ms and issues FFA_RUN. It
can return to the caller with FFA_YIELD is the receiver endpoint is still
blocked.
Message-Id: <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
| -rw-r--r-- | drivers/firmware/arm_ffa/driver.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index ec99fed5715d..d47272859190 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -26,6 +26,7 @@ #include <linux/arm_ffa.h> #include <linux/bitfield.h> #include <linux/cpuhotplug.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/hashtable.h> #include <linux/interrupt.h> @@ -397,6 +398,18 @@ static int ffa_id_get(u16 *vm_id) return 0; } +static inline void ffa_msg_send_wait_for_completion(ffa_value_t *ret) +{ + while (ret->a0 == FFA_INTERRUPT || ret->a0 == FFA_YIELD) { + if (ret->a0 == FFA_YIELD) + fsleep(1000); + + invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_RUN, .a1 = ret->a1, + }, ret); + } +} + static int ffa_msg_send_direct_req(u16 src_id, u16 dst_id, bool mode_32bit, struct ffa_send_direct_data *data) { @@ -417,10 +430,7 @@ static int ffa_msg_send_direct_req(u16 src_id, u16 dst_id, bool mode_32bit, .a6 = data->data3, .a7 = data->data4, }, &ret); - while (ret.a0 == FFA_INTERRUPT) - invoke_ffa_fn((ffa_value_t){ - .a0 = FFA_RUN, .a1 = ret.a1, - }, &ret); + ffa_msg_send_wait_for_completion(&ret); if (ret.a0 == FFA_ERROR) return ffa_to_linux_errno((int)ret.a2); @@ -482,10 +492,7 @@ static int ffa_msg_send_direct_req2(u16 src_id, u16 dst_id, const uuid_t *uuid, invoke_ffa_fn(args, &ret); - while (ret.a0 == FFA_INTERRUPT) - invoke_ffa_fn((ffa_value_t){ - .a0 = FFA_RUN, .a1 = ret.a1, - }, &ret); + ffa_msg_send_wait_for_completion(&ret); if (ret.a0 == FFA_ERROR) return ffa_to_linux_errno((int)ret.a2); |