37
37
#include <linux/slab.h>
38
38
#include <linux/smp.h>
39
39
#include <linux/uuid.h>
40
+ #include <linux/xarray.h>
40
41
41
42
#include "common.h"
42
43
@@ -99,6 +100,8 @@ struct ffa_drv_info {
99
100
struct ffa_pcpu_irq __percpu * irq_pcpu ;
100
101
struct workqueue_struct * notif_pcpu_wq ;
101
102
struct work_struct irq_work ;
103
+ struct xarray partition_info ;
104
+ unsigned int partition_count ;
102
105
};
103
106
104
107
static struct ffa_drv_info * drv_info ;
@@ -694,9 +697,26 @@ static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
694
697
return 0 ;
695
698
}
696
699
697
- static void __do_sched_recv_cb (u16 partition_id , u16 vcpu , bool is_per_vcpu )
700
+ struct ffa_dev_part_info {
701
+ ffa_sched_recv_cb callback ;
702
+ void * cb_data ;
703
+ rwlock_t rw_lock ;
704
+ };
705
+
706
+ static void __do_sched_recv_cb (u16 part_id , u16 vcpu , bool is_per_vcpu )
698
707
{
699
- pr_err ("Callback for partition 0x%x failed.\n" , partition_id );
708
+ struct ffa_dev_part_info * partition ;
709
+ ffa_sched_recv_cb callback ;
710
+ void * cb_data ;
711
+
712
+ partition = xa_load (& drv_info -> partition_info , part_id );
713
+ read_lock (& partition -> rw_lock );
714
+ callback = partition -> callback ;
715
+ cb_data = partition -> cb_data ;
716
+ read_unlock (& partition -> rw_lock );
717
+
718
+ if (callback )
719
+ callback (vcpu , is_per_vcpu , cb_data );
700
720
}
701
721
702
722
static void ffa_notification_info_get (void )
@@ -845,6 +865,39 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
845
865
return ffa_memory_ops (FFA_MEM_LEND , args );
846
866
}
847
867
868
+ static int ffa_sched_recv_cb_update (u16 part_id , ffa_sched_recv_cb callback ,
869
+ void * cb_data , bool is_registration )
870
+ {
871
+ struct ffa_dev_part_info * partition ;
872
+ bool cb_valid ;
873
+
874
+ partition = xa_load (& drv_info -> partition_info , part_id );
875
+ write_lock (& partition -> rw_lock );
876
+
877
+ cb_valid = !!partition -> callback ;
878
+ if (!(is_registration ^ cb_valid )) {
879
+ write_unlock (& partition -> rw_lock );
880
+ return - EINVAL ;
881
+ }
882
+
883
+ partition -> callback = callback ;
884
+ partition -> cb_data = cb_data ;
885
+
886
+ write_unlock (& partition -> rw_lock );
887
+ return 0 ;
888
+ }
889
+
890
+ static int ffa_sched_recv_cb_register (struct ffa_device * dev ,
891
+ ffa_sched_recv_cb cb , void * cb_data )
892
+ {
893
+ return ffa_sched_recv_cb_update (dev -> vm_id , cb , cb_data , true);
894
+ }
895
+
896
+ static int ffa_sched_recv_cb_unregister (struct ffa_device * dev )
897
+ {
898
+ return ffa_sched_recv_cb_update (dev -> vm_id , NULL , NULL , false);
899
+ }
900
+
848
901
static const struct ffa_info_ops ffa_drv_info_ops = {
849
902
.api_version_get = ffa_api_version_get ,
850
903
.partition_info_get = ffa_partition_info_get ,
@@ -865,11 +918,17 @@ static const struct ffa_cpu_ops ffa_drv_cpu_ops = {
865
918
.run = ffa_run ,
866
919
};
867
920
921
+ static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
922
+ .sched_recv_cb_register = ffa_sched_recv_cb_register ,
923
+ .sched_recv_cb_unregister = ffa_sched_recv_cb_unregister ,
924
+ };
925
+
868
926
static const struct ffa_ops ffa_drv_ops = {
869
927
.info_ops = & ffa_drv_info_ops ,
870
928
.msg_ops = & ffa_drv_msg_ops ,
871
929
.mem_ops = & ffa_drv_mem_ops ,
872
930
.cpu_ops = & ffa_drv_cpu_ops ,
931
+ .notifier_ops = & ffa_drv_notifier_ops ,
873
932
};
874
933
875
934
void ffa_device_match_uuid (struct ffa_device * ffa_dev , const uuid_t * uuid )
@@ -900,6 +959,7 @@ static void ffa_setup_partitions(void)
900
959
int count , idx ;
901
960
uuid_t uuid ;
902
961
struct ffa_device * ffa_dev ;
962
+ struct ffa_dev_part_info * info ;
903
963
struct ffa_partition_info * pbuf , * tpbuf ;
904
964
905
965
count = ffa_partition_probe (& uuid_null , & pbuf );
@@ -908,6 +968,7 @@ static void ffa_setup_partitions(void)
908
968
return ;
909
969
}
910
970
971
+ xa_init (& drv_info -> partition_info );
911
972
for (idx = 0 , tpbuf = pbuf ; idx < count ; idx ++ , tpbuf ++ ) {
912
973
import_uuid (& uuid , (u8 * )tpbuf -> uuid );
913
974
@@ -927,10 +988,42 @@ static void ffa_setup_partitions(void)
927
988
if (drv_info -> version > FFA_VERSION_1_0 &&
928
989
!(tpbuf -> properties & FFA_PARTITION_AARCH64_EXEC ))
929
990
ffa_mode_32bit_set (ffa_dev );
991
+
992
+ info = kzalloc (sizeof (* info ), GFP_KERNEL );
993
+ if (!info ) {
994
+ ffa_device_unregister (ffa_dev );
995
+ continue ;
996
+ }
997
+ xa_store (& drv_info -> partition_info , tpbuf -> id , info , GFP_KERNEL );
930
998
}
999
+ drv_info -> partition_count = count ;
1000
+
931
1001
kfree (pbuf );
932
1002
}
933
1003
1004
+ static void ffa_partitions_cleanup (void )
1005
+ {
1006
+ struct ffa_dev_part_info * * info ;
1007
+ int idx , count = drv_info -> partition_count ;
1008
+
1009
+ if (!count )
1010
+ return ;
1011
+
1012
+ info = kcalloc (count , sizeof (* * info ), GFP_KERNEL );
1013
+ if (!info )
1014
+ return ;
1015
+
1016
+ xa_extract (& drv_info -> partition_info , (void * * )info , 0 , VM_ID_MASK ,
1017
+ count , XA_PRESENT );
1018
+
1019
+ for (idx = 0 ; idx < count ; idx ++ )
1020
+ kfree (info [idx ]);
1021
+ kfree (info );
1022
+
1023
+ drv_info -> partition_count = 0 ;
1024
+ xa_destroy (& drv_info -> partition_info );
1025
+ }
1026
+
934
1027
/* FFA FEATURE IDs */
935
1028
#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
936
1029
#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
@@ -1164,9 +1257,11 @@ static int __init ffa_init(void)
1164
1257
1165
1258
ret = ffa_notifications_setup ();
1166
1259
if (ret )
1167
- goto free_pages ;
1260
+ goto partitions_cleanup ;
1168
1261
1169
1262
return 0 ;
1263
+ partitions_cleanup :
1264
+ ffa_partitions_cleanup ();
1170
1265
free_pages :
1171
1266
if (drv_info -> tx_buffer )
1172
1267
free_pages_exact (drv_info -> tx_buffer , RXTX_BUFFER_SIZE );
@@ -1182,9 +1277,11 @@ subsys_initcall(ffa_init);
1182
1277
static void __exit ffa_exit (void )
1183
1278
{
1184
1279
ffa_notifications_cleanup ();
1280
+ ffa_partitions_cleanup ();
1185
1281
ffa_rxtx_unmap (drv_info -> vm_id );
1186
1282
free_pages_exact (drv_info -> tx_buffer , RXTX_BUFFER_SIZE );
1187
1283
free_pages_exact (drv_info -> rx_buffer , RXTX_BUFFER_SIZE );
1284
+ xa_destroy (& drv_info -> partition_info );
1188
1285
kfree (drv_info );
1189
1286
arm_ffa_bus_exit ();
1190
1287
}
0 commit comments