summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorSteven Price <steven.price@arm.com>2026-10-02 07:15:00 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2026-10-02 18:32:26 +0100
commitbc1360cabe273886c502d8b6b2da7f05474cb923 (patch)
treeb76ccdf98eaac16d22a55f1d8c8359eef13ee038 /include/linux
parenta0382431a0fe79d9e1c22420efc29f51234e3eff (diff)
firmware: arm_rmm: Add support for SRO
RMM v2.0 introduces the concept of "Stateful RMI Operations" (SRO). This means that an SMC can return with an operation still in progress. The host is expected to continue the operation until it reaches a conclusion (either success or failure). During this process the RMM can request additional memory ('donate') or hand memory back to the host ('reclaim'). The host can request an in progress operation is cancelled, but still continue the operation until it has completed (otherwise the incomplete operation may cause future RMM operations to fail). All memory donate operations are cancellable and if the RMM request cannot be satisfied, we cancel the request and fail the operation. (e.g., if the allocation size > MAX_PAGE_ORDER) The SRO is tracked using a struct rmi_sro_state object which keeps track of any memory which has been allocated but not yet consumed by the RMM or reclaimed from the RMM. This allows the memory to be reused in a future request within the same operation. It will also permit an operation to be done in a context where memory allocation may be difficult (e.g. atomic context) with the option to abort the operation and retry the memory allocation outside of the atomic context. The memory stored in the struct rmi_sro_state object can then be reused on the subsequent attempt. Wrappers for SRO RMI commands are also provided here because they depend on the rmi_sro_execute() implementation added by this patch. Delegate/undelegate handles are also added here because they now use the SRO/stateful command infrastructure and are also used for the memory DONATE/RECLAIM flows. Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Tested-by: Gavin Shan <gshan@redhat.com> Signed-off-by: Steven Price <steven.price@arm.com> Co-developed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/arm-rmi-cmds.h41
1 files changed, 41 insertions, 0 deletions
diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h
index 9718f2f5a88b..dd5380ace4e9 100644
--- a/include/linux/arm-rmi-cmds.h
+++ b/include/linux/arm-rmi-cmds.h
@@ -8,9 +8,19 @@
#include <linux/arm-smccc-rmi.h>
#include <linux/bug.h>
+#include <linux/gfp.h>
#include <linux/processor.h>
+#include <linux/string.h>
#include <linux/types.h>
+#define RMI_MAX_ADDR_LIST 256
+
+struct rmi_sro_state {
+ struct arm_smccc_1_2_regs regs;
+ int addr_count;
+ unsigned long addr_list[RMI_MAX_ADDR_LIST];
+};
+
#define RMM_BLOCKED_RETRY_COUNT 2
/*
* rmi_smccc_invoke: Invoke the RMI call and return the results, retrying the
@@ -45,4 +55,35 @@ static inline void rmi_smccc_invoke(struct arm_smccc_1_2_regs *regs)
unsigned long rmi_feat_reg(unsigned int index);
+int rmi_delegate_range(phys_addr_t phys, unsigned long size,
+ phys_addr_t *out_phys);
+int rmi_undelegate_range(phys_addr_t phys, unsigned long size);
+int rmi_free_delegated_page(phys_addr_t phys);
+
+static inline int rmi_delegate_page(phys_addr_t phys)
+{
+ return rmi_delegate_range(phys, PAGE_SIZE, NULL);
+}
+
+static inline int rmi_undelegate_page(phys_addr_t phys)
+{
+ return rmi_undelegate_range(phys, PAGE_SIZE);
+}
+
+long rmi_sro_memxfer_execute(struct rmi_sro_state *sro, gfp_t gfp);
+void rmi_sro_free(struct rmi_sro_state *sro);
+long rmi_sro_execute(struct arm_smccc_1_2_regs *regs);
+
+/*
+ * Resetting the addr_count is sufficient to ignore the addr_list contents.
+ */
+#define rmi_sro_memxfer_cmd(sro, gfp, ...) ({ \
+ struct rmi_sro_state *__sro = (sro); \
+ __sro->addr_count = 0; \
+ __sro->regs = (struct arm_smccc_1_2_regs){ __VA_ARGS__ }; \
+ long __ret = rmi_sro_memxfer_execute(__sro, gfp); \
+ rmi_sro_free(__sro); \
+ __ret; \
+})
+
#endif /* __LINUX_ARM_RMI_CMDS_H_ */