mirror of
https://github.com/torvalds/linux.git
synced 2025-10-30 16:18:41 +02:00
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: 9fac08d9d9 ("firmware: arm_ffa: Upgrade FF-A version to v1.2 in the driver")
Reported-by: Lixiang Mao <liximao@qti.qualcomm.com>
Tested-by: Lixiang Mao <liximao@qti.qualcomm.com>
Message-Id: <20250923150927.1218364-1-sudeep.holla@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
parent
3a86608788
commit
11fb1a82ae
2 changed files with 46 additions and 12 deletions
|
|
@ -649,6 +649,26 @@ static u16 ffa_memory_attributes_get(u32 func_id)
|
|||
return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE;
|
||||
}
|
||||
|
||||
static void ffa_emad_impdef_value_init(u32 version, void *dst, void *src)
|
||||
{
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
|
||||
if (FFA_EMAD_HAS_IMPDEF_FIELD(version))
|
||||
memcpy(dst, src, sizeof(ep_mem_access->impdef_val));
|
||||
}
|
||||
|
||||
static void
|
||||
ffa_mem_region_additional_setup(u32 version, struct ffa_mem_region *mem_region)
|
||||
{
|
||||
if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version)) {
|
||||
mem_region->ep_mem_size = 0;
|
||||
} else {
|
||||
mem_region->ep_mem_size = ffa_emad_size_get(version);
|
||||
mem_region->ep_mem_offset = sizeof(*mem_region);
|
||||
memset(mem_region->reserved, 0, 12);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
||||
struct ffa_mem_ops_args *args)
|
||||
|
|
@ -667,27 +687,24 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
|||
mem_region->flags = args->flags;
|
||||
mem_region->sender_id = drv_info->vm_id;
|
||||
mem_region->attributes = ffa_memory_attributes_get(func_id);
|
||||
ep_mem_access = buffer +
|
||||
ffa_mem_desc_offset(buffer, 0, drv_info->version);
|
||||
composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
|
||||
drv_info->version);
|
||||
|
||||
for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
|
||||
for (idx = 0; idx < args->nattrs; idx++) {
|
||||
ep_mem_access = buffer +
|
||||
ffa_mem_desc_offset(buffer, idx, drv_info->version);
|
||||
ep_mem_access->receiver = args->attrs[idx].receiver;
|
||||
ep_mem_access->attrs = args->attrs[idx].attrs;
|
||||
ep_mem_access->composite_off = composite_offset;
|
||||
ep_mem_access->flag = 0;
|
||||
ep_mem_access->reserved = 0;
|
||||
ffa_emad_impdef_value_init(drv_info->version,
|
||||
ep_mem_access->impdef_val,
|
||||
args->attrs[idx].impdef_val);
|
||||
}
|
||||
mem_region->handle = 0;
|
||||
mem_region->ep_count = args->nattrs;
|
||||
if (drv_info->version <= FFA_VERSION_1_0) {
|
||||
mem_region->ep_mem_size = 0;
|
||||
} else {
|
||||
mem_region->ep_mem_size = sizeof(*ep_mem_access);
|
||||
mem_region->ep_mem_offset = sizeof(*mem_region);
|
||||
memset(mem_region->reserved, 0, 12);
|
||||
}
|
||||
ffa_mem_region_additional_setup(drv_info->version, mem_region);
|
||||
|
||||
composite = buffer + composite_offset;
|
||||
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ struct ffa_mem_region_attributes {
|
|||
* an `struct ffa_mem_region_addr_range`.
|
||||
*/
|
||||
u32 composite_off;
|
||||
u8 impdef_val[16];
|
||||
u64 reserved;
|
||||
};
|
||||
|
||||
|
|
@ -417,15 +418,31 @@ struct ffa_mem_region {
|
|||
#define CONSTITUENTS_OFFSET(x) \
|
||||
(offsetof(struct ffa_composite_mem_region, constituents[x]))
|
||||
|
||||
#define FFA_EMAD_HAS_IMPDEF_FIELD(version) ((version) >= FFA_VERSION_1_2)
|
||||
#define FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version) ((version) > FFA_VERSION_1_0)
|
||||
|
||||
static inline u32 ffa_emad_size_get(u32 ffa_version)
|
||||
{
|
||||
u32 sz;
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
|
||||
if (FFA_EMAD_HAS_IMPDEF_FIELD(ffa_version))
|
||||
sz = sizeof(*ep_mem_access);
|
||||
else
|
||||
sz = sizeof(*ep_mem_access) - sizeof(ep_mem_access->impdef_val);
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version)
|
||||
{
|
||||
u32 offset = count * sizeof(struct ffa_mem_region_attributes);
|
||||
u32 offset = count * ffa_emad_size_get(ffa_version);
|
||||
/*
|
||||
* Earlier to v1.1, the endpoint memory descriptor array started at
|
||||
* offset 32(i.e. offset of ep_mem_offset in the current structure)
|
||||
*/
|
||||
if (ffa_version <= FFA_VERSION_1_0)
|
||||
if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version))
|
||||
offset += offsetof(struct ffa_mem_region, ep_mem_offset);
|
||||
else
|
||||
offset += sizeof(struct ffa_mem_region);
|
||||
|
|
|
|||
Loading…
Reference in a new issue