@@ -87,6 +87,7 @@ static inline int ffa_to_linux_errno(int errno)
8787
8888struct ffa_pcpu_irq {
8989 struct ffa_drv_info * info ;
90+ struct work_struct notif_pcpu_work ;
9091};
9192
9293struct ffa_drv_info {
@@ -100,13 +101,13 @@ struct ffa_drv_info {
100101 bool mem_ops_native ;
101102 bool msg_direct_req2_supp ;
102103 bool bitmap_created ;
104+ bool bus_notifier_registered ;
103105 bool notif_enabled ;
104106 unsigned int sched_recv_irq ;
105107 unsigned int notif_pend_irq ;
106108 unsigned int cpuhp_state ;
107109 struct ffa_pcpu_irq __percpu * irq_pcpu ;
108110 struct workqueue_struct * notif_pcpu_wq ;
109- struct work_struct notif_pcpu_work ;
110111 struct work_struct sched_recv_irq_work ;
111112 struct xarray partition_info ;
112113 DECLARE_HASHTABLE (notifier_hash , ilog2 (FFA_MAX_NOTIFICATIONS ));
@@ -322,22 +323,26 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
322323#define PART_INFO_ID_MASK GENMASK(15, 0)
323324#define PART_INFO_EXEC_CXT_MASK GENMASK(31, 16)
324325#define PART_INFO_PROPS_MASK GENMASK(63, 32)
326+ #define FFA_PART_INFO_GET_REGS_FIRST_REG 3
327+ #define FFA_PART_INFO_GET_REGS_REGS_PER_DESC 3
328+ #define FFA_PART_INFO_GET_REGS_MAX_DESC \
329+ (((sizeof(ffa_value_t) / sizeof_field(ffa_value_t, a0)) - \
330+ FFA_PART_INFO_GET_REGS_FIRST_REG) / \
331+ FFA_PART_INFO_GET_REGS_REGS_PER_DESC)
325332#define PART_INFO_ID (x ) ((u16)(FIELD_GET(PART_INFO_ID_MASK, (x))))
326333#define PART_INFO_EXEC_CXT (x ) ((u16)(FIELD_GET(PART_INFO_EXEC_CXT_MASK, (x))))
327334#define PART_INFO_PROPERTIES (x ) ((u32)(FIELD_GET(PART_INFO_PROPS_MASK, (x))))
328335static int
329336__ffa_partition_info_get_regs (u32 uuid0 , u32 uuid1 , u32 uuid2 , u32 uuid3 ,
330337 struct ffa_partition_info * buffer , int num_parts )
331338{
332- u16 buf_sz , start_idx , cur_idx , count = 0 , prev_idx = 0 , tag = 0 ;
339+ u16 buf_sz , start_idx = 0 , cur_idx , count = 0 , tag = 0 ;
333340 struct ffa_partition_info * buf = buffer ;
334341 ffa_value_t partition_info ;
335342
336343 do {
337344 __le64 * regs ;
338- int idx ;
339-
340- start_idx = prev_idx ? prev_idx + 1 : 0 ;
345+ int idx , nr_desc , buf_idx ;
341346
342347 invoke_ffa_fn ((ffa_value_t ){
343348 .a0 = FFA_PARTITION_INFO_GET_REGS ,
@@ -353,15 +358,28 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
353358 count = PARTITION_COUNT (partition_info .a2 );
354359 if (!buffer || !num_parts ) /* count only */
355360 return count ;
361+ if (count > num_parts )
362+ return - EINVAL ;
356363
357364 cur_idx = CURRENT_INDEX (partition_info .a2 );
365+ if (cur_idx < start_idx || cur_idx >= count )
366+ return - EINVAL ;
367+
368+ nr_desc = cur_idx - start_idx + 1 ;
369+ if (nr_desc > FFA_PART_INFO_GET_REGS_MAX_DESC )
370+ return - EINVAL ;
371+
372+ buf_idx = buf - buffer ;
373+ if (buf_idx + nr_desc > num_parts )
374+ return - EINVAL ;
375+
358376 tag = UUID_INFO_TAG (partition_info .a2 );
359377 buf_sz = PARTITION_INFO_SZ (partition_info .a2 );
360378 if (buf_sz > sizeof (* buffer ))
361379 buf_sz = sizeof (* buffer );
362380
363381 regs = (void * )& partition_info .a3 ;
364- for (idx = 0 ; idx < cur_idx - start_idx + 1 ; idx ++ , buf ++ ) {
382+ for (idx = 0 ; idx < nr_desc ; idx ++ , buf ++ ) {
365383 union {
366384 uuid_t uuid ;
367385 u64 regs [2 ];
@@ -379,7 +397,7 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
379397 uuid_copy (& buf -> uuid , & uuid_regs .uuid );
380398 regs += 3 ;
381399 }
382- prev_idx = cur_idx ;
400+ start_idx = cur_idx + 1 ;
383401
384402 } while (cur_idx < (count - 1 ));
385403
@@ -1189,7 +1207,7 @@ static int
11891207ffa_sched_recv_cb_update (struct ffa_device * dev , ffa_sched_recv_cb callback ,
11901208 void * cb_data , bool is_registration )
11911209{
1192- struct ffa_dev_part_info * partition = NULL , * tmp ;
1210+ struct ffa_dev_part_info * partition = NULL ;
11931211 struct list_head * phead ;
11941212 bool cb_valid ;
11951213
@@ -1202,11 +1220,11 @@ ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
12021220 return - EINVAL ;
12031221 }
12041222
1205- list_for_each_entry_safe (partition , tmp , phead , node )
1223+ list_for_each_entry (partition , phead , node )
12061224 if (partition -> dev == dev )
12071225 break ;
12081226
1209- if (! partition ) {
1227+ if (& partition -> node == phead ) {
12101228 pr_err ("%s: No such partition ID 0x%x\n" , __func__ , dev -> vm_id );
12111229 return - EINVAL ;
12121230 }
@@ -1445,60 +1463,82 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
14451463
14461464static void handle_notif_callbacks (u64 bitmap , enum notify_type type )
14471465{
1466+ ffa_notifier_cb cb ;
1467+ void * cb_data ;
14481468 int notify_id ;
1449- struct notifier_cb_info * cb_info = NULL ;
14501469
14511470 for (notify_id = 0 ; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap ;
14521471 notify_id ++ , bitmap >>= 1 ) {
14531472 if (!(bitmap & 1 ))
14541473 continue ;
14551474
1456- read_lock (& drv_info -> notify_lock );
1457- cb_info = notifier_hnode_get_by_type (notify_id , type );
1458- read_unlock (& drv_info -> notify_lock );
1475+ scoped_guard (read_lock , & drv_info -> notify_lock ) {
1476+ struct notifier_cb_info * cb_info ;
14591477
1460- if (cb_info && cb_info -> cb )
1461- cb_info -> cb (notify_id , cb_info -> cb_data );
1478+ cb_info = notifier_hnode_get_by_type (notify_id , type );
1479+ cb = cb_info ? cb_info -> cb : NULL ;
1480+ cb_data = cb_info ? cb_info -> cb_data : NULL ;
1481+ }
1482+
1483+ if (cb )
1484+ cb (notify_id , cb_data );
14621485 }
14631486}
14641487
14651488static void handle_fwk_notif_callbacks (u32 bitmap )
14661489{
14671490 void * buf ;
14681491 uuid_t uuid ;
1492+ void * fwk_cb_data ;
14691493 int notify_id = 0 , target ;
1494+ ffa_fwk_notifier_cb fwk_cb ;
14701495 struct ffa_indirect_msg_hdr * msg ;
1471- struct notifier_cb_info * cb_info = NULL ;
1496+ size_t min_offset = offsetof( struct ffa_indirect_msg_hdr , uuid ) ;
14721497
14731498 /* Only one framework notification defined and supported for now */
14741499 if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL ))
14751500 return ;
14761501
1477- mutex_lock (& drv_info -> rx_lock );
1502+ scoped_guard (mutex , & drv_info -> rx_lock ) {
1503+ u32 offset , size ;
14781504
1479- msg = drv_info -> rx_buffer ;
1480- buf = kmemdup ((void * )msg + msg -> offset , msg -> size , GFP_KERNEL );
1481- if (!buf ) {
1482- mutex_unlock (& drv_info -> rx_lock );
1483- return ;
1484- }
1505+ msg = drv_info -> rx_buffer ;
1506+ offset = msg -> offset ;
1507+ size = msg -> size ;
14851508
1486- target = SENDER_ID (msg -> send_recv_id );
1487- if (msg -> offset >= sizeof (* msg ))
1488- uuid_copy (& uuid , & msg -> uuid );
1489- else
1490- uuid_copy (& uuid , & uuid_null );
1509+ if (!size || (offset != min_offset && offset < sizeof (* msg )) ||
1510+ offset > drv_info -> rxtx_bufsz ||
1511+ size > drv_info -> rxtx_bufsz - offset ) {
1512+ pr_err ("invalid framework notification message\n" );
1513+ ffa_rx_release ();
1514+ return ;
1515+ }
14911516
1492- mutex_unlock (& drv_info -> rx_lock );
1517+ buf = kmemdup ((void * )msg + offset , size , GFP_KERNEL );
1518+ if (!buf ) {
1519+ ffa_rx_release ();
1520+ return ;
1521+ }
1522+
1523+ target = SENDER_ID (msg -> send_recv_id );
1524+ if (offset >= sizeof (* msg ))
1525+ uuid_copy (& uuid , & msg -> uuid );
1526+ else
1527+ uuid_copy (& uuid , & uuid_null );
1528+ ffa_rx_release ();
1529+ }
14931530
1494- ffa_rx_release ();
1531+ scoped_guard (read_lock , & drv_info -> notify_lock ) {
1532+ struct notifier_cb_info * cb_info ;
14951533
1496- read_lock (& drv_info -> notify_lock );
1497- cb_info = notifier_hnode_get_by_vmid_uuid (notify_id , target , & uuid );
1498- read_unlock (& drv_info -> notify_lock );
1534+ cb_info = notifier_hnode_get_by_vmid_uuid (notify_id , target ,
1535+ & uuid );
1536+ fwk_cb = cb_info ? cb_info -> fwk_cb : NULL ;
1537+ fwk_cb_data = cb_info ? cb_info -> cb_data : NULL ;
1538+ }
14991539
1500- if (cb_info && cb_info -> fwk_cb )
1501- cb_info -> fwk_cb (notify_id , cb_info -> cb_data , buf );
1540+ if (fwk_cb )
1541+ fwk_cb (notify_id , fwk_cb_data , buf );
15021542 kfree (buf );
15031543}
15041544
@@ -1539,10 +1579,11 @@ ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
15391579
15401580static void notif_pcpu_irq_work_fn (struct work_struct * work )
15411581{
1542- struct ffa_drv_info * info = container_of (work , struct ffa_drv_info ,
1582+ struct ffa_pcpu_irq * pcpu = container_of (work , struct ffa_pcpu_irq ,
15431583 notif_pcpu_work );
1584+ struct ffa_drv_info * info = pcpu -> info ;
15441585
1545- ffa_self_notif_handle ( smp_processor_id (), true, info );
1586+ notif_get_and_handle ( info );
15461587}
15471588
15481589static const struct ffa_info_ops ffa_drv_info_ops = {
@@ -1629,6 +1670,15 @@ static struct notifier_block ffa_bus_nb = {
16291670 .notifier_call = ffa_bus_notifier ,
16301671};
16311672
1673+ static void ffa_bus_notifier_unregister (void )
1674+ {
1675+ if (!drv_info -> bus_notifier_registered )
1676+ return ;
1677+
1678+ bus_unregister_notifier (& ffa_bus_type , & ffa_bus_nb );
1679+ drv_info -> bus_notifier_registered = false;
1680+ }
1681+
16321682static int ffa_xa_add_partition_info (struct ffa_device * dev )
16331683{
16341684 struct ffa_dev_part_info * info ;
@@ -1712,6 +1762,8 @@ static void ffa_partitions_cleanup(void)
17121762 struct list_head * phead ;
17131763 unsigned long idx ;
17141764
1765+ ffa_bus_notifier_unregister ();
1766+
17151767 /* Clean up/free all registered devices */
17161768 ffa_devices_unregister ();
17171769
@@ -1739,11 +1791,14 @@ static int ffa_setup_partitions(void)
17391791 ret = bus_register_notifier (& ffa_bus_type , & ffa_bus_nb );
17401792 if (ret )
17411793 pr_err ("Failed to register FF-A bus notifiers\n" );
1794+ else
1795+ drv_info -> bus_notifier_registered = true;
17421796 }
17431797
17441798 count = ffa_partition_probe (& uuid_null , & pbuf );
17451799 if (count <= 0 ) {
17461800 pr_info ("%s: No partitions found, error %d\n" , __func__ , count );
1801+ ffa_bus_notifier_unregister ();
17471802 return - EINVAL ;
17481803 }
17491804
@@ -1811,7 +1866,7 @@ static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
18111866 struct ffa_drv_info * info = pcpu -> info ;
18121867
18131868 queue_work_on (smp_processor_id (), info -> notif_pcpu_wq ,
1814- & info -> notif_pcpu_work );
1869+ & pcpu -> notif_pcpu_work );
18151870
18161871 return IRQ_HANDLED ;
18171872}
@@ -1928,8 +1983,11 @@ static int ffa_init_pcpu_irq(void)
19281983 if (!irq_pcpu )
19291984 return - ENOMEM ;
19301985
1931- for_each_present_cpu (cpu )
1986+ for_each_present_cpu (cpu ) {
19321987 per_cpu_ptr (irq_pcpu , cpu )-> info = drv_info ;
1988+ INIT_WORK (& per_cpu_ptr (irq_pcpu , cpu )-> notif_pcpu_work ,
1989+ notif_pcpu_irq_work_fn );
1990+ }
19331991
19341992 drv_info -> irq_pcpu = irq_pcpu ;
19351993
@@ -1958,7 +2016,6 @@ static int ffa_init_pcpu_irq(void)
19582016 }
19592017
19602018 INIT_WORK (& drv_info -> sched_recv_irq_work , ffa_sched_recv_irq_work_fn );
1961- INIT_WORK (& drv_info -> notif_pcpu_work , notif_pcpu_irq_work_fn );
19622019 drv_info -> notif_pcpu_wq = create_workqueue ("ffa_pcpu_irq_notification" );
19632020 if (!drv_info -> notif_pcpu_wq )
19642021 return - EINVAL ;
@@ -2063,11 +2120,12 @@ static int __init ffa_init(void)
20632120 rxtx_bufsz = SZ_4K ;
20642121 }
20652122
2123+ rxtx_bufsz = PAGE_ALIGN (rxtx_bufsz );
20662124 drv_info -> rxtx_bufsz = rxtx_bufsz ;
20672125 drv_info -> rx_buffer = alloc_pages_exact (rxtx_bufsz , GFP_KERNEL );
20682126 if (!drv_info -> rx_buffer ) {
20692127 ret = - ENOMEM ;
2070- goto free_pages ;
2128+ goto free_drv_info ;
20712129 }
20722130
20732131 drv_info -> tx_buffer = alloc_pages_exact (rxtx_bufsz , GFP_KERNEL );
@@ -2078,7 +2136,7 @@ static int __init ffa_init(void)
20782136
20792137 ret = ffa_rxtx_map (virt_to_phys (drv_info -> tx_buffer ),
20802138 virt_to_phys (drv_info -> rx_buffer ),
2081- PAGE_ALIGN ( rxtx_bufsz ) / FFA_PAGE_SIZE );
2139+ rxtx_bufsz / FFA_PAGE_SIZE );
20822140 if (ret ) {
20832141 pr_err ("failed to register FFA RxTx buffers\n" );
20842142 goto free_pages ;
0 commit comments