@@ -246,6 +246,11 @@ static int ffa_features(u32 func_feat_id, u32 input_props,
246246}
247247
248248#define PARTITION_INFO_GET_RETURN_COUNT_ONLY BIT(0)
249+ #define FFA_SUPPORTS_GET_COUNT_ONLY (version ) ((version) > FFA_VERSION_1_0)
250+ #define FFA_PART_INFO_HAS_SIZE_IN_RESP (version ) ((version) > FFA_VERSION_1_0)
251+ #define FFA_PART_INFO_HAS_UUID_IN_RESP (version ) ((version) > FFA_VERSION_1_0)
252+ #define FFA_PART_INFO_HAS_EXEC_STATE_IN_RESP (version ) \
253+ ((version) > FFA_VERSION_1_0)
249254
250255/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
251256static int
@@ -255,7 +260,7 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
255260 int idx , count , flags = 0 , sz , buf_sz ;
256261 ffa_value_t partition_info ;
257262
258- if (drv_info -> version > FFA_VERSION_1_0 &&
263+ if (FFA_SUPPORTS_GET_COUNT_ONLY ( drv_info -> version ) &&
259264 (!buffer || !num_partitions )) /* Just get the count for now */
260265 flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY ;
261266
@@ -273,12 +278,11 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
273278
274279 count = partition_info .a2 ;
275280
276- if (drv_info -> version > FFA_VERSION_1_0 ) {
281+ if (FFA_PART_INFO_HAS_SIZE_IN_RESP ( drv_info -> version ) ) {
277282 buf_sz = sz = partition_info .a3 ;
278283 if (sz > sizeof (* buffer ))
279284 buf_sz = sizeof (* buffer );
280285 } else {
281- /* FFA_VERSION_1_0 lacks size in the response */
282286 buf_sz = sz = 8 ;
283287 }
284288
@@ -981,10 +985,27 @@ static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu)
981985 }
982986}
983987
988+ /*
989+ * Map logical ID index to the u16 index within the packed ID list.
990+ *
991+ * For native responses (FF-A width == kernel word size), IDs are
992+ * tightly packed: idx -> idx.
993+ *
994+ * For 32-bit responses on a 64-bit kernel, each 64-bit register
995+ * contributes 4 x u16 values but only the lower 2 are defined; the
996+ * upper 2 are garbage. This mapping skips those upper halves:
997+ * 0,1,2,3,4,5,... -> 0,1,4,5,8,9,...
998+ */
999+ static int list_idx_to_u16_idx (int idx , bool is_native_resp )
1000+ {
1001+ return is_native_resp ? idx : idx + 2 * (idx >> 1 );
1002+ }
1003+
9841004static void ffa_notification_info_get (void )
9851005{
986- int idx , list , max_ids , lists_cnt , ids_processed , ids_count [MAX_IDS_64 ];
987- bool is_64b_resp ;
1006+ int ids_processed , ids_count [MAX_IDS_64 ];
1007+ int idx , list , max_ids , lists_cnt ;
1008+ bool is_64b_resp , is_native_resp ;
9881009 ffa_value_t ret ;
9891010 u64 id_list ;
9901011
@@ -1001,6 +1022,7 @@ static void ffa_notification_info_get(void)
10011022 }
10021023
10031024 is_64b_resp = (ret .a0 == FFA_FN64_SUCCESS );
1025+ is_native_resp = (ret .a0 == FFA_FN_NATIVE (SUCCESS ));
10041026
10051027 ids_processed = 0 ;
10061028 lists_cnt = FIELD_GET (NOTIFICATION_INFO_GET_ID_COUNT , ret .a2 );
@@ -1017,12 +1039,16 @@ static void ffa_notification_info_get(void)
10171039
10181040 /* Process IDs */
10191041 for (list = 0 ; list < lists_cnt ; list ++ ) {
1042+ int u16_idx ;
10201043 u16 vcpu_id , part_id , * packed_id_list = (u16 * )& ret .a3 ;
10211044
10221045 if (ids_processed >= max_ids - 1 )
10231046 break ;
10241047
1025- part_id = packed_id_list [ids_processed ++ ];
1048+ u16_idx = list_idx_to_u16_idx (ids_processed ,
1049+ is_native_resp );
1050+ part_id = packed_id_list [u16_idx ];
1051+ ids_processed ++ ;
10261052
10271053 if (ids_count [list ] == 1 ) { /* Global Notification */
10281054 __do_sched_recv_cb (part_id , 0 , false);
@@ -1034,7 +1060,10 @@ static void ffa_notification_info_get(void)
10341060 if (ids_processed >= max_ids - 1 )
10351061 break ;
10361062
1037- vcpu_id = packed_id_list [ids_processed ++ ];
1063+ u16_idx = list_idx_to_u16_idx (ids_processed ,
1064+ is_native_resp );
1065+ vcpu_id = packed_id_list [u16_idx ];
1066+ ids_processed ++ ;
10381067
10391068 __do_sched_recv_cb (part_id , vcpu_id , true);
10401069 }
@@ -1706,7 +1735,7 @@ static int ffa_setup_partitions(void)
17061735 struct ffa_device * ffa_dev ;
17071736 struct ffa_partition_info * pbuf , * tpbuf ;
17081737
1709- if (drv_info -> version == FFA_VERSION_1_0 ) {
1738+ if (! FFA_PART_INFO_HAS_UUID_IN_RESP ( drv_info -> version ) ) {
17101739 ret = bus_register_notifier (& ffa_bus_type , & ffa_bus_nb );
17111740 if (ret )
17121741 pr_err ("Failed to register FF-A bus notifiers\n" );
@@ -1733,7 +1762,7 @@ static int ffa_setup_partitions(void)
17331762 continue ;
17341763 }
17351764
1736- if (drv_info -> version > FFA_VERSION_1_0 &&
1765+ if (FFA_PART_INFO_HAS_EXEC_STATE_IN_RESP ( drv_info -> version ) &&
17371766 !(tpbuf -> properties & FFA_PARTITION_AARCH64_EXEC ))
17381767 ffa_mode_32bit_set (ffa_dev );
17391768
@@ -2068,6 +2097,7 @@ static int __init ffa_init(void)
20682097
20692098 pr_err ("failed to setup partitions\n" );
20702099 ffa_notifications_cleanup ();
2100+ ffa_rxtx_unmap (drv_info -> vm_id );
20712101free_pages :
20722102 if (drv_info -> tx_buffer )
20732103 free_pages_exact (drv_info -> tx_buffer , rxtx_bufsz );
0 commit comments