summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/arm_ffa/driver.c
diff options
context:
space:
mode:
authorMarc Bonnici <marc.bonnici@arm.com>2022-04-26 13:12:19 +0100
committerSudeep Holla <sudeep.holla@arm.com>2022-04-27 08:55:29 +0100
commit987756f67dee237ec35f3b249ab1ae25260c5340 (patch)
tree585fd07d0361c91ab4ee5363e40691d0d9081e89 /drivers/firmware/arm_ffa/driver.c
parent3123109284176b1532874591f7c81f3837bbdc17 (diff)
downloadlinux-stable-987756f67dee237ec35f3b249ab1ae25260c5340.tar.gz
linux-stable-987756f67dee237ec35f3b249ab1ae25260c5340.tar.bz2
linux-stable-987756f67dee237ec35f3b249ab1ae25260c5340.zip
firmware: arm_ffa: Fix handling of fragmented memory descriptors
Fix the handling of MEM_FRAG_TX/RX SMCs when the full memory descriptor does not fit in a single innovation of a memory sharing request. The current implementation expects a FFA_MEM_SHARE/FFA_MEM_LEND call to always receive a FFA_SUCCESS response, however in the case where a full descriptor does not fit inside the partitions TX buffer, the call can instead complete with a FFA_MEM_FRAG_RX SMC to request the next part of the descriptor to be transmitted. Similarly a FFA_MEM_FRAG_TX call currently only expects FFA_MEM_FRAG_RX as a response, however once the full descriptor has been transmitted the FFA_SUCCESS ABI will be used to indicate successful transmission. Update the existing code to match the expected behaviour. Link: https://lore.kernel.org/r/20220426121219.1801601-1-marc.bonnici@arm.com Signed-off-by: Marc Bonnici <marc.bonnici@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Diffstat (limited to 'drivers/firmware/arm_ffa/driver.c')
-rw-r--r--drivers/firmware/arm_ffa/driver.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 14f900047ac0..ccccecae615f 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -398,11 +398,15 @@ static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz,
if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2);
- if (ret.a0 != FFA_SUCCESS)
+ if (ret.a0 == FFA_SUCCESS) {
+ if (handle)
+ *handle = PACK_HANDLE(ret.a2, ret.a3);
+ } else if (ret.a0 == FFA_MEM_FRAG_RX) {
+ if (handle)
+ *handle = PACK_HANDLE(ret.a1, ret.a2);
+ } else {
return -EOPNOTSUPP;
-
- if (handle)
- *handle = PACK_HANDLE(ret.a2, ret.a3);
+ }
return frag_len;
}
@@ -426,10 +430,12 @@ static int ffa_mem_next_frag(u64 handle, u32 frag_len)
if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2);
- if (ret.a0 != FFA_MEM_FRAG_RX)
- return -EOPNOTSUPP;
+ if (ret.a0 == FFA_MEM_FRAG_RX)
+ return ret.a3;
+ else if (ret.a0 == FFA_SUCCESS)
+ return 0;
- return ret.a3;
+ return -EOPNOTSUPP;
}
static int