@@ -82,6 +82,7 @@ struct ffa_drv_info {
8282 struct mutex tx_lock ; /* lock to protect Tx buffer */
8383 void * rx_buffer ;
8484 void * tx_buffer ;
85+ bool mem_ops_native ;
8586};
8687
8788static struct ffa_drv_info * drv_info ;
@@ -182,18 +183,25 @@ static int ffa_rxtx_unmap(u16 vm_id)
182183 return 0 ;
183184}
184185
186+ #define PARTITION_INFO_GET_RETURN_COUNT_ONLY BIT(0)
187+
185188/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
186189static int
187190__ffa_partition_info_get (u32 uuid0 , u32 uuid1 , u32 uuid2 , u32 uuid3 ,
188191 struct ffa_partition_info * buffer , int num_partitions )
189192{
190- int count ;
193+ int idx , count , flags = 0 , sz , buf_sz ;
191194 ffa_value_t partition_info ;
192195
196+ if (drv_info -> version > FFA_VERSION_1_0 &&
197+ (!buffer || !num_partitions )) /* Just get the count for now */
198+ flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY ;
199+
193200 mutex_lock (& drv_info -> rx_lock );
194201 invoke_ffa_fn ((ffa_value_t ){
195202 .a0 = FFA_PARTITION_INFO_GET ,
196203 .a1 = uuid0 , .a2 = uuid1 , .a3 = uuid2 , .a4 = uuid3 ,
204+ .a5 = flags ,
197205 }, & partition_info );
198206
199207 if (partition_info .a0 == FFA_ERROR ) {
@@ -203,8 +211,19 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
203211
204212 count = partition_info .a2 ;
205213
214+ if (drv_info -> version > FFA_VERSION_1_0 ) {
215+ buf_sz = sz = partition_info .a3 ;
216+ if (sz > sizeof (* buffer ))
217+ buf_sz = sizeof (* buffer );
218+ } else {
219+ /* FFA_VERSION_1_0 lacks size in the response */
220+ buf_sz = sz = 8 ;
221+ }
222+
206223 if (buffer && count <= num_partitions )
207- memcpy (buffer , drv_info -> rx_buffer , sizeof (* buffer ) * count );
224+ for (idx = 0 ; idx < count ; idx ++ )
225+ memcpy (buffer + idx , drv_info -> rx_buffer + idx * sz ,
226+ buf_sz );
208227
209228 ffa_rx_release ();
210229
@@ -378,6 +397,19 @@ static u32 ffa_get_num_pages_sg(struct scatterlist *sg)
378397 return num_pages ;
379398}
380399
400+ static u8 ffa_memory_attributes_get (u32 func_id )
401+ {
402+ /*
403+ * For the memory lend or donate operation, if the receiver is a PE or
404+ * a proxy endpoint, the owner/sender must not specify the attributes
405+ */
406+ if (func_id == FFA_FN_NATIVE (MEM_LEND ) ||
407+ func_id == FFA_MEM_LEND )
408+ return 0 ;
409+
410+ return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE ;
411+ }
412+
381413static int
382414ffa_setup_and_transmit (u32 func_id , void * buffer , u32 max_fragsize ,
383415 struct ffa_mem_ops_args * args )
@@ -394,20 +426,25 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
394426 mem_region -> tag = args -> tag ;
395427 mem_region -> flags = args -> flags ;
396428 mem_region -> sender_id = drv_info -> vm_id ;
397- mem_region -> attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK |
398- FFA_MEM_INNER_SHAREABLE ;
429+ mem_region -> attributes = ffa_memory_attributes_get (func_id );
399430 ep_mem_access = & mem_region -> ep_mem_access [0 ];
400431
401432 for (idx = 0 ; idx < args -> nattrs ; idx ++ , ep_mem_access ++ ) {
402433 ep_mem_access -> receiver = args -> attrs [idx ].receiver ;
403434 ep_mem_access -> attrs = args -> attrs [idx ].attrs ;
404435 ep_mem_access -> composite_off = COMPOSITE_OFFSET (args -> nattrs );
436+ ep_mem_access -> flag = 0 ;
437+ ep_mem_access -> reserved = 0 ;
405438 }
439+ mem_region -> handle = 0 ;
440+ mem_region -> reserved_0 = 0 ;
441+ mem_region -> reserved_1 = 0 ;
406442 mem_region -> ep_count = args -> nattrs ;
407443
408444 composite = buffer + COMPOSITE_OFFSET (args -> nattrs );
409445 composite -> total_pg_cnt = ffa_get_num_pages_sg (args -> sg );
410446 composite -> addr_range_cnt = num_entries ;
447+ composite -> reserved = 0 ;
411448
412449 length = COMPOSITE_CONSTITUENTS_OFFSET (args -> nattrs , num_entries );
413450 frag_len = COMPOSITE_CONSTITUENTS_OFFSET (args -> nattrs , 0 );
@@ -442,6 +479,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
442479
443480 constituents -> address = sg_phys (args -> sg );
444481 constituents -> pg_cnt = args -> sg -> length / FFA_PAGE_SIZE ;
482+ constituents -> reserved = 0 ;
445483 constituents ++ ;
446484 frag_len += sizeof (struct ffa_mem_region_addr_range );
447485 } while ((args -> sg = sg_next (args -> sg )));
@@ -490,6 +528,39 @@ static int ffa_memory_reclaim(u64 g_handle, u32 flags)
490528 return 0 ;
491529}
492530
531+ static int ffa_features (u32 func_feat_id , u32 input_props ,
532+ u32 * if_props_1 , u32 * if_props_2 )
533+ {
534+ ffa_value_t id ;
535+
536+ if (!ARM_SMCCC_IS_FAST_CALL (func_feat_id ) && input_props ) {
537+ pr_err ("%s: Invalid Parameters: %x, %x" , __func__ ,
538+ func_feat_id , input_props );
539+ return ffa_to_linux_errno (FFA_RET_INVALID_PARAMETERS );
540+ }
541+
542+ invoke_ffa_fn ((ffa_value_t ){
543+ .a0 = FFA_FEATURES , .a1 = func_feat_id , .a2 = input_props ,
544+ }, & id );
545+
546+ if (id .a0 == FFA_ERROR )
547+ return ffa_to_linux_errno ((int )id .a2 );
548+
549+ if (if_props_1 )
550+ * if_props_1 = id .a2 ;
551+ if (if_props_2 )
552+ * if_props_2 = id .a3 ;
553+
554+ return 0 ;
555+ }
556+
557+ static void ffa_set_up_mem_ops_native_flag (void )
558+ {
559+ if (!ffa_features (FFA_FN_NATIVE (MEM_LEND ), 0 , NULL , NULL ) ||
560+ !ffa_features (FFA_FN_NATIVE (MEM_SHARE ), 0 , NULL , NULL ))
561+ drv_info -> mem_ops_native = true;
562+ }
563+
493564static u32 ffa_api_version_get (void )
494565{
495566 return drv_info -> version ;
@@ -528,17 +599,15 @@ static int ffa_sync_send_receive(struct ffa_device *dev,
528599 dev -> mode_32bit , data );
529600}
530601
531- static int
532- ffa_memory_share (struct ffa_device * dev , struct ffa_mem_ops_args * args )
602+ static int ffa_memory_share (struct ffa_mem_ops_args * args )
533603{
534- if (dev -> mode_32bit )
535- return ffa_memory_ops (FFA_MEM_SHARE , args );
604+ if (drv_info -> mem_ops_native )
605+ return ffa_memory_ops (FFA_FN_NATIVE ( MEM_SHARE ) , args );
536606
537- return ffa_memory_ops (FFA_FN_NATIVE ( MEM_SHARE ) , args );
607+ return ffa_memory_ops (FFA_MEM_SHARE , args );
538608}
539609
540- static int
541- ffa_memory_lend (struct ffa_device * dev , struct ffa_mem_ops_args * args )
610+ static int ffa_memory_lend (struct ffa_mem_ops_args * args )
542611{
543612 /* Note that upon a successful MEM_LEND request the caller
544613 * must ensure that the memory region specified is not accessed
@@ -547,36 +616,47 @@ ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
547616 * however on systems without a hypervisor the responsibility
548617 * falls to the calling kernel driver to prevent access.
549618 */
550- if (dev -> mode_32bit )
551- return ffa_memory_ops (FFA_MEM_LEND , args );
619+ if (drv_info -> mem_ops_native )
620+ return ffa_memory_ops (FFA_FN_NATIVE ( MEM_LEND ) , args );
552621
553- return ffa_memory_ops (FFA_FN_NATIVE ( MEM_LEND ) , args );
622+ return ffa_memory_ops (FFA_MEM_LEND , args );
554623}
555624
556- static const struct ffa_dev_ops ffa_ops = {
625+ static const struct ffa_info_ops ffa_drv_info_ops = {
557626 .api_version_get = ffa_api_version_get ,
558627 .partition_info_get = ffa_partition_info_get ,
628+ };
629+
630+ static const struct ffa_msg_ops ffa_drv_msg_ops = {
559631 .mode_32bit_set = ffa_mode_32bit_set ,
560632 .sync_send_receive = ffa_sync_send_receive ,
633+ };
634+
635+ static const struct ffa_mem_ops ffa_drv_mem_ops = {
561636 .memory_reclaim = ffa_memory_reclaim ,
562637 .memory_share = ffa_memory_share ,
563638 .memory_lend = ffa_memory_lend ,
564639};
565640
566- const struct ffa_dev_ops * ffa_dev_ops_get (struct ffa_device * dev )
567- {
568- if (ffa_device_is_valid (dev ))
569- return & ffa_ops ;
570-
571- return NULL ;
572- }
573- EXPORT_SYMBOL_GPL (ffa_dev_ops_get );
641+ static const struct ffa_ops ffa_drv_ops = {
642+ .info_ops = & ffa_drv_info_ops ,
643+ .msg_ops = & ffa_drv_msg_ops ,
644+ .mem_ops = & ffa_drv_mem_ops ,
645+ };
574646
575647void ffa_device_match_uuid (struct ffa_device * ffa_dev , const uuid_t * uuid )
576648{
577649 int count , idx ;
578650 struct ffa_partition_info * pbuf , * tpbuf ;
579651
652+ /*
653+ * FF-A v1.1 provides UUID for each partition as part of the discovery
654+ * API, the discovered UUID must be populated in the device's UUID and
655+ * there is no need to copy the same from the driver table.
656+ */
657+ if (drv_info -> version > FFA_VERSION_1_0 )
658+ return ;
659+
580660 count = ffa_partition_probe (uuid , & pbuf );
581661 if (count <= 0 )
582662 return ;
@@ -590,6 +670,7 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
590670static void ffa_setup_partitions (void )
591671{
592672 int count , idx ;
673+ uuid_t uuid ;
593674 struct ffa_device * ffa_dev ;
594675 struct ffa_partition_info * pbuf , * tpbuf ;
595676
@@ -600,19 +681,24 @@ static void ffa_setup_partitions(void)
600681 }
601682
602683 for (idx = 0 , tpbuf = pbuf ; idx < count ; idx ++ , tpbuf ++ ) {
603- /* Note that the &uuid_null parameter will require
684+ import_uuid (& uuid , (u8 * )tpbuf -> uuid );
685+
686+ /* Note that if the UUID will be uuid_null, that will require
604687 * ffa_device_match() to find the UUID of this partition id
605- * with help of ffa_device_match_uuid(). Once the FF-A spec
606- * is updated to provide correct UUID here for each partition
607- * as part of the discovery API, we need to pass the
608- * discovered UUID here instead.
688+ * with help of ffa_device_match_uuid(). FF-A v1.1 and above
689+ * provides UUID here for each partition as part of the
690+ * discovery API and the same is passed.
609691 */
610- ffa_dev = ffa_device_register (& uuid_null , tpbuf -> id );
692+ ffa_dev = ffa_device_register (& uuid , tpbuf -> id , & ffa_drv_ops );
611693 if (!ffa_dev ) {
612694 pr_err ("%s: failed to register partition ID 0x%x\n" ,
613695 __func__ , tpbuf -> id );
614696 continue ;
615697 }
698+
699+ if (drv_info -> version > FFA_VERSION_1_0 &&
700+ !(tpbuf -> properties & FFA_PARTITION_AARCH64_EXEC ))
701+ ffa_mode_32bit_set (ffa_dev );
616702 }
617703 kfree (pbuf );
618704}
@@ -670,6 +756,8 @@ static int __init ffa_init(void)
670756
671757 ffa_setup_partitions ();
672758
759+ ffa_set_up_mem_ops_native_flag ();
760+
673761 return 0 ;
674762free_pages :
675763 if (drv_info -> tx_buffer )
0 commit comments