Skip to content

Commit 8ad2c84

Browse files
committed
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/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents d77b016 + 0c565d1 commit 8ad2c84

File tree

1 file changed

+57
-28
lines changed

1 file changed

+57
-28
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ struct ffa_drv_info {
107107
struct work_struct notif_pcpu_work;
108108
struct work_struct irq_work;
109109
struct xarray partition_info;
110-
unsigned int partition_count;
111110
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
112111
struct mutex notify_lock; /* lock to protect notifier hashtable */
113112
};
114113

115114
static struct ffa_drv_info *drv_info;
115+
static void ffa_partitions_cleanup(void);
116116

117117
/*
118118
* 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)
733733
void *cb_data;
734734

735735
partition = xa_load(&drv_info->partition_info, part_id);
736+
if (!partition) {
737+
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
738+
return;
739+
}
740+
736741
read_lock(&partition->rw_lock);
737742
callback = partition->callback;
738743
cb_data = partition->cb_data;
@@ -915,6 +920,11 @@ static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
915920
return -EOPNOTSUPP;
916921

917922
partition = xa_load(&drv_info->partition_info, part_id);
923+
if (!partition) {
924+
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
925+
return -EINVAL;
926+
}
927+
918928
write_lock(&partition->rw_lock);
919929

920930
cb_valid = !!partition->callback;
@@ -1186,9 +1196,9 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
11861196
kfree(pbuf);
11871197
}
11881198

1189-
static void ffa_setup_partitions(void)
1199+
static int ffa_setup_partitions(void)
11901200
{
1191-
int count, idx;
1201+
int count, idx, ret;
11921202
uuid_t uuid;
11931203
struct ffa_device *ffa_dev;
11941204
struct ffa_dev_part_info *info;
@@ -1197,7 +1207,7 @@ static void ffa_setup_partitions(void)
11971207
count = ffa_partition_probe(&uuid_null, &pbuf);
11981208
if (count <= 0) {
11991209
pr_info("%s: No partitions found, error %d\n", __func__, count);
1200-
return;
1210+
return -EINVAL;
12011211
}
12021212

12031213
xa_init(&drv_info->partition_info);
@@ -1226,40 +1236,53 @@ static void ffa_setup_partitions(void)
12261236
ffa_device_unregister(ffa_dev);
12271237
continue;
12281238
}
1229-
xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
1239+
rwlock_init(&info->rw_lock);
1240+
ret = xa_insert(&drv_info->partition_info, tpbuf->id,
1241+
info, GFP_KERNEL);
1242+
if (ret) {
1243+
pr_err("%s: failed to save partition ID 0x%x - ret:%d\n",
1244+
__func__, tpbuf->id, ret);
1245+
ffa_device_unregister(ffa_dev);
1246+
kfree(info);
1247+
}
12301248
}
1231-
drv_info->partition_count = count;
12321249

12331250
kfree(pbuf);
12341251

12351252
/* Allocate for the host */
12361253
info = kzalloc(sizeof(*info), GFP_KERNEL);
1237-
if (!info)
1238-
return;
1239-
xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
1240-
drv_info->partition_count++;
1254+
if (!info) {
1255+
pr_err("%s: failed to alloc Host partition ID 0x%x. Abort.\n",
1256+
__func__, drv_info->vm_id);
1257+
/* Already registered devices are freed on bus_exit */
1258+
ffa_partitions_cleanup();
1259+
return -ENOMEM;
1260+
}
1261+
1262+
rwlock_init(&info->rw_lock);
1263+
ret = xa_insert(&drv_info->partition_info, drv_info->vm_id,
1264+
info, GFP_KERNEL);
1265+
if (ret) {
1266+
pr_err("%s: failed to save Host partition ID 0x%x - ret:%d. Abort.\n",
1267+
__func__, drv_info->vm_id, ret);
1268+
kfree(info);
1269+
/* Already registered devices are freed on bus_exit */
1270+
ffa_partitions_cleanup();
1271+
}
1272+
1273+
return ret;
12411274
}
12421275

12431276
static void ffa_partitions_cleanup(void)
12441277
{
1245-
struct ffa_dev_part_info **info;
1246-
int idx, count = drv_info->partition_count;
1247-
1248-
if (!count)
1249-
return;
1250-
1251-
info = kcalloc(count, sizeof(*info), GFP_KERNEL);
1252-
if (!info)
1253-
return;
1254-
1255-
xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK,
1256-
count, XA_PRESENT);
1278+
struct ffa_dev_part_info *info;
1279+
unsigned long idx;
12571280

1258-
for (idx = 0; idx < count; idx++)
1259-
kfree(info[idx]);
1260-
kfree(info);
1281+
xa_for_each(&drv_info->partition_info, idx, info) {
1282+
xa_erase(&drv_info->partition_info, idx);
1283+
kfree(info);
1284+
}
12611285

1262-
drv_info->partition_count = 0;
12631286
xa_destroy(&drv_info->partition_info);
12641287
}
12651288

@@ -1508,14 +1531,21 @@ static int __init ffa_init(void)
15081531

15091532
ffa_notifications_setup();
15101533

1511-
ffa_setup_partitions();
1534+
ret = ffa_setup_partitions();
1535+
if (ret) {
1536+
pr_err("failed to setup partitions\n");
1537+
goto cleanup_notifs;
1538+
}
15121539

15131540
ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
15141541
drv_info, true);
15151542
if (ret)
15161543
pr_info("Failed to register driver sched callback %d\n", ret);
15171544

15181545
return 0;
1546+
1547+
cleanup_notifs:
1548+
ffa_notifications_cleanup();
15191549
free_pages:
15201550
if (drv_info->tx_buffer)
15211551
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
@@ -1535,7 +1565,6 @@ static void __exit ffa_exit(void)
15351565
ffa_rxtx_unmap(drv_info->vm_id);
15361566
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
15371567
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
1538-
xa_destroy(&drv_info->partition_info);
15391568
kfree(drv_info);
15401569
arm_ffa_bus_exit();
15411570
}

0 commit comments

Comments
 (0)