Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'ffa-fixes-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes

Arm FF-A fixes for v6.4

Quite a few fixes to address set of assorted issues:
1. NULL pointer dereference if the ffa driver doesn't provide remove()
callback as it is currently executed unconditionally
2. FF-A core probe failure on systems with v1.0 firmware as the new
partition info get count flag is used unconditionally
3. Failure to register more than one logical partition or service within
the same physical partition as the device name contains only VM ID
which will be same for all but each will have unique UUID.
4. Rejection of certain memory interface transmissions by the receivers
(secure partitions) as few MBZ fields are non-zero due to lack of
explicit re-initialization of those fields

* tag 'ffa-fixes-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
firmware: arm_ffa: Set reserved/MBZ fields to zero in the memory descriptors
firmware: arm_ffa: Fix FFA device names for logical partitions
firmware: arm_ffa: Fix usage of partition info get count flag
firmware: arm_ffa: Check if ffa_driver remove is present before executing

Link: https://lore.kernel.org/r/20230509143453.1188753-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+25 -6
+16 -5
drivers/firmware/arm_ffa/bus.c
··· 15 15 16 16 #include "common.h" 17 17 18 + static DEFINE_IDA(ffa_bus_id); 19 + 18 20 static int ffa_device_match(struct device *dev, struct device_driver *drv) 19 21 { 20 22 const struct ffa_device_id *id_table; ··· 55 53 { 56 54 struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); 57 55 58 - ffa_drv->remove(to_ffa_dev(dev)); 56 + if (ffa_drv->remove) 57 + ffa_drv->remove(to_ffa_dev(dev)); 59 58 } 60 59 61 60 static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env) ··· 133 130 { 134 131 struct ffa_device *ffa_dev = to_ffa_dev(dev); 135 132 133 + ida_free(&ffa_bus_id, ffa_dev->id); 136 134 kfree(ffa_dev); 137 135 } 138 136 ··· 174 170 struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, 175 171 const struct ffa_ops *ops) 176 172 { 177 - int ret; 173 + int id, ret; 178 174 struct device *dev; 179 175 struct ffa_device *ffa_dev; 180 176 181 - ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL); 182 - if (!ffa_dev) 177 + id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL); 178 + if (id < 0) 183 179 return NULL; 180 + 181 + ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL); 182 + if (!ffa_dev) { 183 + ida_free(&ffa_bus_id, id); 184 + return NULL; 185 + } 184 186 185 187 dev = &ffa_dev->dev; 186 188 dev->bus = &ffa_bus_type; 187 189 dev->release = ffa_release_device; 188 - dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id); 190 + dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); 189 191 190 192 ffa_dev->vm_id = vm_id; 191 193 ffa_dev->ops = ops; ··· 227 217 { 228 218 ffa_devices_unregister(); 229 219 bus_unregister(&ffa_bus_type); 220 + ida_destroy(&ffa_bus_id); 230 221 }
+8 -1
drivers/firmware/arm_ffa/driver.c
··· 193 193 int idx, count, flags = 0, sz, buf_sz; 194 194 ffa_value_t partition_info; 195 195 196 - if (!buffer || !num_partitions) /* Just get the count for now */ 196 + if (drv_info->version > FFA_VERSION_1_0 && 197 + (!buffer || !num_partitions)) /* Just get the count for now */ 197 198 flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY; 198 199 199 200 mutex_lock(&drv_info->rx_lock); ··· 421 420 ep_mem_access->receiver = args->attrs[idx].receiver; 422 421 ep_mem_access->attrs = args->attrs[idx].attrs; 423 422 ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs); 423 + ep_mem_access->flag = 0; 424 + ep_mem_access->reserved = 0; 424 425 } 426 + mem_region->reserved_0 = 0; 427 + mem_region->reserved_1 = 0; 425 428 mem_region->ep_count = args->nattrs; 426 429 427 430 composite = buffer + COMPOSITE_OFFSET(args->nattrs); 428 431 composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg); 429 432 composite->addr_range_cnt = num_entries; 433 + composite->reserved = 0; 430 434 431 435 length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries); 432 436 frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0); ··· 466 460 467 461 constituents->address = sg_phys(args->sg); 468 462 constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE; 463 + constituents->reserved = 0; 469 464 constituents++; 470 465 frag_len += sizeof(struct ffa_mem_region_addr_range); 471 466 } while ((args->sg = sg_next(args->sg)));
+1
include/linux/arm_ffa.h
··· 96 96 97 97 /* FFA Bus/Device/Driver related */ 98 98 struct ffa_device { 99 + u32 id; 99 100 int vm_id; 100 101 bool mode_32bit; 101 102 uuid_t uuid;