Arm FF-A fixes for v6.8
Quite a few fixes addressing issues around missing RW lock initialisation in ffa_setup_partitions(), missing check for xa_load() return value, use of xa_insert instead of xa_store to flag case of duplicate insertion. It also simplifies ffa_partitions_cleanup() with xa_for_each() and xa_erase() instead of xa_extract() and kfree(). Finally it includes fixes around handling of partitions setup failures during initialisation. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmWuj+IACgkQAEG6vDF+ 4pgufA/9H73+TI0bKWhH9TqXONeJQEISJ3EKHJSsN1yuKsToYDetmadidXegLmGC nyJULeuTF9codmId5TQ8Zh29Bir38Nh4bFnfvVONPe78KYm6Xjt3HDei903fRIPK wch8ReenHdGzyhuAzcgL9CHUzgvJuM5KtaOgiAAOlNILzMk8nk1qbpoesTzvJOaD 0sLT/KiN2aTICk6YnSBAHnPFZ2GWGJ7PHqKvzgNMPLloOEQn0xGmKgegH+pWjkWm qnLI/Gw/m0Y1yqBF1ffDRhC4qH2lMH2cSBR4UJTFQ4e01Hlr+kNgDqBbYJtsOhPJ Fj36RA/mc0uSDrMxgwi2SOVnPOumIGVzH6TjoxBthrSLza6AtI+qocF9SUXxfNFv VT/CR3CCZhIpBkSWA6XpFLXivNs5wyPau8HPYyU8w7JAeAihYj294eJpLcYeTYi5 z6xyPbJFZQ1nTYmctMRaBgvOeJFUzpwlTeWkbjBAhsW5KrOKrdWqHv8/w7JSJEyS LGBEKWVKg0etx8tjKuR1nn2RsHegHWXqRiU0ahbhh5ukvOt6grfs/9tK8Nxh4N40 /xdoEgx1TeIbRfjkcnhcjLdHO92kjZnEvmdPVmZjk6o1MiYl1VqaMks4unJTMXh6 vYtDpK3LTZ7wq8y45IzXu1CZY+YfS+3J038eVp3KJjL2n5oX4Ig= =K7Rw -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmWymK8ACgkQYKtH/8kJ UieGsQ/+LqAXbaAL9RA8Mb54HeS1g6JGYj+vEPOjPXb0ie1ow/92Hia87sqvQhBx hu1Vf45wypkAvuPnRrUBNiL7SlC8ae6VGaKtswiDNt8vuvwBu4NoV4GDJgBa7Ney mNl1wOeaPVl3DQ/zCZaDGkAcq+dNquhFNYb9t7EtOLhTZVf+yNHPYEbcH2Mx/f3h guaJJODlKCQjqU22lCQiFTi5iWpie3S8Kgq4PEhfREHIq8Ttbll0ZNC1TUxdD854 Ye6JUE/xUb3rrUvgUMjA15xPzEd4kcJ/GMcMC7sISbUqJOlLCfv6HfEUM3lABbAA NNzbBXJAT9U8xu+qOiGLA8ddxqbkt9QrhftwZGBW93g+KgsTUBVv8AFzsrqba94Y o4sufePZd/siR66p2m/EvwT4RJFCZ+CKeu4Y+jSv4ki/5W6GgbB+jHgevLX+rSmW DeuRaFl6Up89VwmDpY5FdEJ/GQ0d4mzSJx7Yw0N/OITpYs6fZHhHyWKVMPCg7cSt NQn0r6YVh8x+ScwY6/m+ofFiuW+GWjNo+wSkAPW3fl3omChAI1KWwXuB7TfWP1io /lTl5Azjnd//2oMzdqqcca3m0p6ZHHOFWr9FfEXxpyUyh7aI3sPxM1yxvs3C77vq ID12SlHZRved2MuuO5vwVTH+b2w1ab57AA7lswviHqGY8eJO3QI= =IR2+ -----END PGP SIGNATURE----- Merge tag 'ffa-fixes-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes Arm FF-A fixes for v6.8 Quite a few fixes addressing issues around missing RW lock initialisation in ffa_setup_partitions(), missing check for xa_load() return value, use of xa_insert instead of xa_store to flag case of duplicate insertion. It also simplifies ffa_partitions_cleanup() with xa_for_each() and xa_erase() instead of xa_extract() and kfree(). Finally it includes fixes around handling of partitions setup failures during initialisation. * tag 'ffa-fixes-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_ffa: Handle partitions setup failures firmware: arm_ffa: Use xa_insert() and check for result firmware: arm_ffa: Simplify ffa_partitions_cleanup() firmware: arm_ffa: Check xa_load() return value firmware: arm_ffa: Add missing rwlock_init() for the driver partition firmware: arm_ffa: Add missing rwlock_init() in ffa_setup_partitions() Link: https://lore.kernel.org/r/20240122161652.3551159-1-sudeep.holla@arm.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
8ad2c84e2e
@ -107,12 +107,12 @@ struct ffa_drv_info {
|
||||
struct work_struct notif_pcpu_work;
|
||||
struct work_struct irq_work;
|
||||
struct xarray partition_info;
|
||||
unsigned int partition_count;
|
||||
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
|
||||
struct mutex notify_lock; /* lock to protect notifier hashtable */
|
||||
};
|
||||
|
||||
static struct ffa_drv_info *drv_info;
|
||||
static void ffa_partitions_cleanup(void);
|
||||
|
||||
/*
|
||||
* The driver must be able to support all the versions from the earliest
|
||||
@ -733,6 +733,11 @@ static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu)
|
||||
void *cb_data;
|
||||
|
||||
partition = xa_load(&drv_info->partition_info, part_id);
|
||||
if (!partition) {
|
||||
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
|
||||
return;
|
||||
}
|
||||
|
||||
read_lock(&partition->rw_lock);
|
||||
callback = partition->callback;
|
||||
cb_data = partition->cb_data;
|
||||
@ -915,6 +920,11 @@ static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
partition = xa_load(&drv_info->partition_info, part_id);
|
||||
if (!partition) {
|
||||
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
write_lock(&partition->rw_lock);
|
||||
|
||||
cb_valid = !!partition->callback;
|
||||
@ -1186,9 +1196,9 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
|
||||
kfree(pbuf);
|
||||
}
|
||||
|
||||
static void ffa_setup_partitions(void)
|
||||
static int ffa_setup_partitions(void)
|
||||
{
|
||||
int count, idx;
|
||||
int count, idx, ret;
|
||||
uuid_t uuid;
|
||||
struct ffa_device *ffa_dev;
|
||||
struct ffa_dev_part_info *info;
|
||||
@ -1197,7 +1207,7 @@ static void ffa_setup_partitions(void)
|
||||
count = ffa_partition_probe(&uuid_null, &pbuf);
|
||||
if (count <= 0) {
|
||||
pr_info("%s: No partitions found, error %d\n", __func__, count);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xa_init(&drv_info->partition_info);
|
||||
@ -1226,40 +1236,53 @@ static void ffa_setup_partitions(void)
|
||||
ffa_device_unregister(ffa_dev);
|
||||
continue;
|
||||
}
|
||||
xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
|
||||
rwlock_init(&info->rw_lock);
|
||||
ret = xa_insert(&drv_info->partition_info, tpbuf->id,
|
||||
info, GFP_KERNEL);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to save partition ID 0x%x - ret:%d\n",
|
||||
__func__, tpbuf->id, ret);
|
||||
ffa_device_unregister(ffa_dev);
|
||||
kfree(info);
|
||||
}
|
||||
}
|
||||
drv_info->partition_count = count;
|
||||
|
||||
kfree(pbuf);
|
||||
|
||||
/* Allocate for the host */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return;
|
||||
xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
|
||||
drv_info->partition_count++;
|
||||
if (!info) {
|
||||
pr_err("%s: failed to alloc Host partition ID 0x%x. Abort.\n",
|
||||
__func__, drv_info->vm_id);
|
||||
/* Already registered devices are freed on bus_exit */
|
||||
ffa_partitions_cleanup();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rwlock_init(&info->rw_lock);
|
||||
ret = xa_insert(&drv_info->partition_info, drv_info->vm_id,
|
||||
info, GFP_KERNEL);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to save Host partition ID 0x%x - ret:%d. Abort.\n",
|
||||
__func__, drv_info->vm_id, ret);
|
||||
kfree(info);
|
||||
/* Already registered devices are freed on bus_exit */
|
||||
ffa_partitions_cleanup();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ffa_partitions_cleanup(void)
|
||||
{
|
||||
struct ffa_dev_part_info **info;
|
||||
int idx, count = drv_info->partition_count;
|
||||
struct ffa_dev_part_info *info;
|
||||
unsigned long idx;
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
xa_for_each(&drv_info->partition_info, idx, info) {
|
||||
xa_erase(&drv_info->partition_info, idx);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
info = kcalloc(count, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK,
|
||||
count, XA_PRESENT);
|
||||
|
||||
for (idx = 0; idx < count; idx++)
|
||||
kfree(info[idx]);
|
||||
kfree(info);
|
||||
|
||||
drv_info->partition_count = 0;
|
||||
xa_destroy(&drv_info->partition_info);
|
||||
}
|
||||
|
||||
@ -1508,7 +1531,11 @@ static int __init ffa_init(void)
|
||||
|
||||
ffa_notifications_setup();
|
||||
|
||||
ffa_setup_partitions();
|
||||
ret = ffa_setup_partitions();
|
||||
if (ret) {
|
||||
pr_err("failed to setup partitions\n");
|
||||
goto cleanup_notifs;
|
||||
}
|
||||
|
||||
ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
|
||||
drv_info, true);
|
||||
@ -1516,6 +1543,9 @@ static int __init ffa_init(void)
|
||||
pr_info("Failed to register driver sched callback %d\n", ret);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_notifs:
|
||||
ffa_notifications_cleanup();
|
||||
free_pages:
|
||||
if (drv_info->tx_buffer)
|
||||
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
|
||||
@ -1535,7 +1565,6 @@ static void __exit ffa_exit(void)
|
||||
ffa_rxtx_unmap(drv_info->vm_id);
|
||||
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
|
||||
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
|
||||
xa_destroy(&drv_info->partition_info);
|
||||
kfree(drv_info);
|
||||
arm_ffa_bus_exit();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user