Skip to content

Commit b0b2981

Browse files
committed
Merge tag 'ffa-fixes-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
Arm FF-A fixes for v6.7 A bunch of fixes addressing issues around the notification support that was added this cycle. They address issue in partition IDs handling in ffa_notification_info_get(), notifications cleanup path and the size of the allocation in ffa_partitions_cleanup(). It also adds check for the notification enabled state so that the drivers registering the callbacks can be rejected if not enabled/supported. It also moves the partitions setup operation after the notification initialisation so that the driver has the correct state for notification enabled/supported before the partitions are initialised/setup. It also now allows FF-A initialisation to complete successfully even when the notification initialisation fails as it is an optional support in the specification. Initial support just allowed it only if the firmware didn't support notifications. Finally, it also adds a fix for smatch warning by declaring ffa_bus_type structure in the header. * tag 'ffa-fixes-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_ffa: Fix ffa_notification_info_get() IDs handling firmware: arm_ffa: Fix the size of the allocation in ffa_partitions_cleanup() firmware: arm_ffa: Fix FFA notifications cleanup path firmware: arm_ffa: Add checks for the notification enabled state firmware: arm_ffa: Setup the partitions after the notification initialisation firmware: arm_ffa: Allow FF-A initialisation even when notification fails firmware: arm_ffa: Declare ffa_bus_type structure in the header Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 94ea0ed + f1ed48e commit b0b2981

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct ffa_drv_info {
9999
void *tx_buffer;
100100
bool mem_ops_native;
101101
bool bitmap_created;
102+
bool notif_enabled;
102103
unsigned int sched_recv_irq;
103104
unsigned int cpuhp_state;
104105
struct ffa_pcpu_irq __percpu *irq_pcpu;
@@ -782,7 +783,7 @@ static void ffa_notification_info_get(void)
782783
if (ids_processed >= max_ids - 1)
783784
break;
784785

785-
part_id = packed_id_list[++ids_processed];
786+
part_id = packed_id_list[ids_processed++];
786787

787788
if (!ids_count[list]) { /* Global Notification */
788789
__do_sched_recv_cb(part_id, 0, false);
@@ -794,7 +795,7 @@ static void ffa_notification_info_get(void)
794795
if (ids_processed >= max_ids - 1)
795796
break;
796797

797-
vcpu_id = packed_id_list[++ids_processed];
798+
vcpu_id = packed_id_list[ids_processed++];
798799

799800
__do_sched_recv_cb(part_id, vcpu_id, true);
800801
}
@@ -889,6 +890,8 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
889890

890891
#define FFA_SECURE_PARTITION_ID_FLAG BIT(15)
891892

893+
#define ffa_notifications_disabled() (!drv_info->notif_enabled)
894+
892895
enum notify_type {
893896
NON_SECURE_VM,
894897
SECURE_PARTITION,
@@ -908,6 +911,9 @@ static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
908911
struct ffa_dev_part_info *partition;
909912
bool cb_valid;
910913

914+
if (ffa_notifications_disabled())
915+
return -EOPNOTSUPP;
916+
911917
partition = xa_load(&drv_info->partition_info, part_id);
912918
write_lock(&partition->rw_lock);
913919

@@ -1001,6 +1007,9 @@ static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
10011007
int rc;
10021008
enum notify_type type = ffa_notify_type_get(dev->vm_id);
10031009

1010+
if (ffa_notifications_disabled())
1011+
return -EOPNOTSUPP;
1012+
10041013
if (notify_id >= FFA_MAX_NOTIFICATIONS)
10051014
return -EINVAL;
10061015

@@ -1027,6 +1036,9 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
10271036
u32 flags = 0;
10281037
enum notify_type type = ffa_notify_type_get(dev->vm_id);
10291038

1039+
if (ffa_notifications_disabled())
1040+
return -EOPNOTSUPP;
1041+
10301042
if (notify_id >= FFA_MAX_NOTIFICATIONS)
10311043
return -EINVAL;
10321044

@@ -1057,6 +1069,9 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
10571069
{
10581070
u32 flags = 0;
10591071

1072+
if (ffa_notifications_disabled())
1073+
return -EOPNOTSUPP;
1074+
10601075
if (is_per_vcpu)
10611076
flags |= (PER_VCPU_NOTIFICATION_FLAG | vcpu << 16);
10621077

@@ -1233,7 +1248,7 @@ static void ffa_partitions_cleanup(void)
12331248
if (!count)
12341249
return;
12351250

1236-
info = kcalloc(count, sizeof(**info), GFP_KERNEL);
1251+
info = kcalloc(count, sizeof(*info), GFP_KERNEL);
12371252
if (!info)
12381253
return;
12391254

@@ -1311,8 +1326,10 @@ static int ffa_sched_recv_irq_map(void)
13111326

13121327
static void ffa_sched_recv_irq_unmap(void)
13131328
{
1314-
if (drv_info->sched_recv_irq)
1329+
if (drv_info->sched_recv_irq) {
13151330
irq_dispose_mapping(drv_info->sched_recv_irq);
1331+
drv_info->sched_recv_irq = 0;
1332+
}
13161333
}
13171334

13181335
static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
@@ -1329,17 +1346,23 @@ static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
13291346

13301347
static void ffa_uninit_pcpu_irq(void)
13311348
{
1332-
if (drv_info->cpuhp_state)
1349+
if (drv_info->cpuhp_state) {
13331350
cpuhp_remove_state(drv_info->cpuhp_state);
1351+
drv_info->cpuhp_state = 0;
1352+
}
13341353

1335-
if (drv_info->notif_pcpu_wq)
1354+
if (drv_info->notif_pcpu_wq) {
13361355
destroy_workqueue(drv_info->notif_pcpu_wq);
1356+
drv_info->notif_pcpu_wq = NULL;
1357+
}
13371358

13381359
if (drv_info->sched_recv_irq)
13391360
free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
13401361

1341-
if (drv_info->irq_pcpu)
1362+
if (drv_info->irq_pcpu) {
13421363
free_percpu(drv_info->irq_pcpu);
1364+
drv_info->irq_pcpu = NULL;
1365+
}
13431366
}
13441367

13451368
static int ffa_init_pcpu_irq(unsigned int irq)
@@ -1388,22 +1411,23 @@ static void ffa_notifications_cleanup(void)
13881411
ffa_notification_bitmap_destroy();
13891412
drv_info->bitmap_created = false;
13901413
}
1414+
drv_info->notif_enabled = false;
13911415
}
13921416

1393-
static int ffa_notifications_setup(void)
1417+
static void ffa_notifications_setup(void)
13941418
{
13951419
int ret, irq;
13961420

13971421
ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
13981422
if (ret) {
1399-
pr_err("Notifications not supported, continuing with it ..\n");
1400-
return 0;
1423+
pr_info("Notifications not supported, continuing with it ..\n");
1424+
return;
14011425
}
14021426

14031427
ret = ffa_notification_bitmap_create();
14041428
if (ret) {
1405-
pr_err("notification_bitmap_create error %d\n", ret);
1406-
return ret;
1429+
pr_info("Notification bitmap create error %d\n", ret);
1430+
return;
14071431
}
14081432
drv_info->bitmap_created = true;
14091433

@@ -1422,14 +1446,11 @@ static int ffa_notifications_setup(void)
14221446
hash_init(drv_info->notifier_hash);
14231447
mutex_init(&drv_info->notify_lock);
14241448

1425-
/* Register internal scheduling callback */
1426-
ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
1427-
drv_info, true);
1428-
if (!ret)
1429-
return ret;
1449+
drv_info->notif_enabled = true;
1450+
return;
14301451
cleanup:
1452+
pr_info("Notification setup failed %d, not enabled\n", ret);
14311453
ffa_notifications_cleanup();
1432-
return ret;
14331454
}
14341455

14351456
static int __init ffa_init(void)
@@ -1483,17 +1504,18 @@ static int __init ffa_init(void)
14831504
mutex_init(&drv_info->rx_lock);
14841505
mutex_init(&drv_info->tx_lock);
14851506

1486-
ffa_setup_partitions();
1487-
14881507
ffa_set_up_mem_ops_native_flag();
14891508

1490-
ret = ffa_notifications_setup();
1509+
ffa_notifications_setup();
1510+
1511+
ffa_setup_partitions();
1512+
1513+
ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
1514+
drv_info, true);
14911515
if (ret)
1492-
goto partitions_cleanup;
1516+
pr_info("Failed to register driver sched callback %d\n", ret);
14931517

14941518
return 0;
1495-
partitions_cleanup:
1496-
ffa_partitions_cleanup();
14971519
free_pages:
14981520
if (drv_info->tx_buffer)
14991521
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);

include/linux/arm_ffa.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
209209
#define module_ffa_driver(__ffa_driver) \
210210
module_driver(__ffa_driver, ffa_register, ffa_unregister)
211211

212+
extern struct bus_type ffa_bus_type;
213+
212214
/* FFA transport related */
213215
struct ffa_partition_info {
214216
u16 id;

0 commit comments

Comments
 (0)