Skip to content

Commit 11fb1a8

Browse files
committed
firmware: arm_ffa: Add support for IMPDEF value in the memory access descriptor
FF-A v1.2 introduced 16 byte IMPLEMENTATION DEFINED value in the endpoint memory access descriptor to allow any sender could to specify an its any custom value for each receiver. Also this value must be specified by the receiver when retrieving the memory region. The sender must ensure it informs the receiver of this value via an IMPLEMENTATION DEFINED mechanism such as a partition message. So the FF-A driver can use the message interfaces to communicate the value and set the same in the ffa_mem_region_attributes structures when using the memory interfaces. The driver ensure that the size of the endpoint memory access descriptors is set correctly based on the FF-A version. Fixes: 9fac08d ("firmware: arm_ffa: Upgrade FF-A version to v1.2 in the driver") Reported-by: Lixiang Mao <[email protected]> Tested-by: Lixiang Mao <[email protected]> Message-Id: <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 3a86608 commit 11fb1a8

2 files changed

Lines changed: 46 additions & 12 deletions

File tree

drivers/firmware/arm_ffa/driver.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,26 @@ static u16 ffa_memory_attributes_get(u32 func_id)
649649
return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE;
650650
}
651651

652+
static void ffa_emad_impdef_value_init(u32 version, void *dst, void *src)
653+
{
654+
struct ffa_mem_region_attributes *ep_mem_access;
655+
656+
if (FFA_EMAD_HAS_IMPDEF_FIELD(version))
657+
memcpy(dst, src, sizeof(ep_mem_access->impdef_val));
658+
}
659+
660+
static void
661+
ffa_mem_region_additional_setup(u32 version, struct ffa_mem_region *mem_region)
662+
{
663+
if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version)) {
664+
mem_region->ep_mem_size = 0;
665+
} else {
666+
mem_region->ep_mem_size = ffa_emad_size_get(version);
667+
mem_region->ep_mem_offset = sizeof(*mem_region);
668+
memset(mem_region->reserved, 0, 12);
669+
}
670+
}
671+
652672
static int
653673
ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
654674
struct ffa_mem_ops_args *args)
@@ -667,27 +687,24 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
667687
mem_region->flags = args->flags;
668688
mem_region->sender_id = drv_info->vm_id;
669689
mem_region->attributes = ffa_memory_attributes_get(func_id);
670-
ep_mem_access = buffer +
671-
ffa_mem_desc_offset(buffer, 0, drv_info->version);
672690
composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
673691
drv_info->version);
674692

675-
for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
693+
for (idx = 0; idx < args->nattrs; idx++) {
694+
ep_mem_access = buffer +
695+
ffa_mem_desc_offset(buffer, idx, drv_info->version);
676696
ep_mem_access->receiver = args->attrs[idx].receiver;
677697
ep_mem_access->attrs = args->attrs[idx].attrs;
678698
ep_mem_access->composite_off = composite_offset;
679699
ep_mem_access->flag = 0;
680700
ep_mem_access->reserved = 0;
701+
ffa_emad_impdef_value_init(drv_info->version,
702+
ep_mem_access->impdef_val,
703+
args->attrs[idx].impdef_val);
681704
}
682705
mem_region->handle = 0;
683706
mem_region->ep_count = args->nattrs;
684-
if (drv_info->version <= FFA_VERSION_1_0) {
685-
mem_region->ep_mem_size = 0;
686-
} else {
687-
mem_region->ep_mem_size = sizeof(*ep_mem_access);
688-
mem_region->ep_mem_offset = sizeof(*mem_region);
689-
memset(mem_region->reserved, 0, 12);
690-
}
707+
ffa_mem_region_additional_setup(drv_info->version, mem_region);
691708

692709
composite = buffer + composite_offset;
693710
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);

include/linux/arm_ffa.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ struct ffa_mem_region_attributes {
338338
* an `struct ffa_mem_region_addr_range`.
339339
*/
340340
u32 composite_off;
341+
u8 impdef_val[16];
341342
u64 reserved;
342343
};
343344

@@ -417,15 +418,31 @@ struct ffa_mem_region {
417418
#define CONSTITUENTS_OFFSET(x) \
418419
(offsetof(struct ffa_composite_mem_region, constituents[x]))
419420

421+
#define FFA_EMAD_HAS_IMPDEF_FIELD(version) ((version) >= FFA_VERSION_1_2)
422+
#define FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version) ((version) > FFA_VERSION_1_0)
423+
424+
static inline u32 ffa_emad_size_get(u32 ffa_version)
425+
{
426+
u32 sz;
427+
struct ffa_mem_region_attributes *ep_mem_access;
428+
429+
if (FFA_EMAD_HAS_IMPDEF_FIELD(ffa_version))
430+
sz = sizeof(*ep_mem_access);
431+
else
432+
sz = sizeof(*ep_mem_access) - sizeof(ep_mem_access->impdef_val);
433+
434+
return sz;
435+
}
436+
420437
static inline u32
421438
ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version)
422439
{
423-
u32 offset = count * sizeof(struct ffa_mem_region_attributes);
440+
u32 offset = count * ffa_emad_size_get(ffa_version);
424441
/*
425442
* Earlier to v1.1, the endpoint memory descriptor array started at
426443
* offset 32(i.e. offset of ep_mem_offset in the current structure)
427444
*/
428-
if (ffa_version <= FFA_VERSION_1_0)
445+
if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version))
429446
offset += offsetof(struct ffa_mem_region, ep_mem_offset);
430447
else
431448
offset += sizeof(struct ffa_mem_region);

0 commit comments

Comments
 (0)