mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
Arm FF-A fix for v6.18
The FF-A driver was updated to support specification version 1.2 but omitted support for the 16-byte implementation-defined (IMPDEF) field introduced in FF-A v1.2 within the Endpoint Memory Access Descriptor (EMAD). This omission breaks all memory interfaces. This change updates the EMAD sizing and offset logic to correctly handle the FF-A v1.2 layout while preserving backward compatibility with older versions. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmjvqvQACgkQAEG6vDF+ 4pjTlBAAqdtLdU5yPTZF5twgMD0FFIZYXKAFrp6u9DuSAnI8bJkMuLdl67SFarSP csOOLg8OmHCmRIQ0I45UGUbz+IfgxzBIPi/A9zxxAVuOzMgWH5aE6zewlH01bz+X sfxsN/zluj2jF/WgDDH0vMsUwYDancfJBvm9Smf7mLuaHEo5KQJiqWPnMIgApyZL dx0Lh54cB3DYUHxZi7yE8ZOrzqKIwnGrzL020npcHLUCCZFdPi2kDMYhFVDqH32r X0PoYKHuclG3PnWZOLRzYr0n+FnsNMip1Cx52dPkzeOiNdB+rH39e3/Mba0FQ4yt 2cTHV6kjXvACCbYKVoZHATeBXrX8HBYnn12x90OUYDxGlbMnrQpDBvVSRdUnZ74g CQ3k2E8dH8IvSY+z4Yixh1BYmF0n1kkcJTjJ92DfF1GsN5QNO0wv7S24p4mdweu6 YOhI7WcvRrFMudrsgds9i0BtJpHgKv7sWcdJRD8h0riTiF2vsjWwTPBEWgf7j2+T 1/IWWvjgDr1CrBib2+3eHRlMdmUqOqxStFmFz8GrnTvHoZr2LVTEhr4hJ/vopuB2 N/4mf5naoDepnmDd+CtAdjnYFGbiwlOc/o4jDk2vPhcBcryvPMXfeYKrNye6lHCH 4l8S8KcMwUf+Hvn4seEFoqt8XP3HHC9Ru2mZRXCZA5C1z2VbqoQ= =RowC -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmj6kD8ACgkQmmx57+YA GNl6Rw/+Ipy2jWp+QD5uWb7isFoiUYicxYlIfqxRO9RvNLTflDJ5vt4V2O5uwxmH hSg3NCUYr103kQey51y2i2efWHILpCX394kNqPZv3g9pYdFBJbqMSfUXeawJjeMu 4Jn14kPzfb2zxXH88Y3NbkGT3wAlI00UAZTPT5pBGe5MWncptJTk1EJRZAdA5cV/ D8oL1DEuSQjHXhkn46uaIepIG42AMX27PwwjHIGD+UfNHleaRI/c2mff68Pcm1kv 9WDnC2RXnXRn5Z6XlskvcGp/fKQ/6mUSgOxPfB/sXCAMn/iwx+kDkgvemprEo2yR pi8YZ40+p4FYpyZ8oTIu0v4brwWeoJpf9qTQ7aRig5UD8cFLm/eKA5tjWIaDvhzx +d89PYGDRHApPZI4r8BIo1FjJFxooEnfb3gbGhrvqk1VNm5PIGtyySMzr0p9Y+TN iNwjzJxE6Pga6RBu3uxGPbinqVqqVndwYJPJ8UW8Ur3xFyXpWgF/ltAo4cU0M6VN GvmyEn4tWkNaV9/xU98gB0rNmcZI3IP9DptWlm5lqu7aw3vXadMlJ7y7VFpKYmcZ kKrKnHkoxs/B/vVpV3nvoFptelfxkSfrJP6VUGAX7FZiPlZ2jtmDLzGz7scxQtNy hT4Ccx0DHIPSfRrFCCeL9NAdE2nomJYRAZwnKQ4a9EHvA6FCrJ4= =ChU3 -----END PGP SIGNATURE----- Merge tag 'ffa-fix-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes Arm FF-A fix for v6.18 The FF-A driver was updated to support specification version 1.2 but omitted support for the 16-byte implementation-defined (IMPDEF) field introduced in FF-A v1.2 within the Endpoint Memory Access Descriptor (EMAD). This omission breaks all memory interfaces. This change updates the EMAD sizing and offset logic to correctly handle the FF-A v1.2 layout while preserving backward compatibility with older versions. * tag 'ffa-fix-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_ffa: Add support for IMPDEF value in the memory access descriptor Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
f4cb028320
|
|
@ -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 New Issue
Block a user