@@ -80,6 +80,8 @@ static DEFINE_MUTEX(cdx_controller_lock);
8080
8181static char * compat_node_name = "xlnx,versal-net-cdx" ;
8282
83+ static void cdx_destroy_res_attr (struct cdx_device * cdx_dev , int num );
84+
8385/**
8486 * cdx_dev_reset - Reset a CDX device
8587 * @dev: CDX device
@@ -148,6 +150,7 @@ static int cdx_unregister_device(struct device *dev,
148150 if (cdx_dev -> enabled && cdx -> ops -> bus_disable )
149151 cdx -> ops -> bus_disable (cdx , cdx_dev -> bus_num );
150152 } else {
153+ cdx_destroy_res_attr (cdx_dev , MAX_CDX_DEV_RESOURCES );
151154 kfree (cdx_dev -> driver_override );
152155 cdx_dev -> driver_override = NULL ;
153156 }
@@ -643,11 +646,105 @@ static void cdx_device_release(struct device *dev)
643646 kfree (cdx_dev );
644647}
645648
649+ static const struct vm_operations_struct cdx_phys_vm_ops = {
650+ #ifdef CONFIG_HAVE_IOREMAP_PROT
651+ .access = generic_access_phys ,
652+ #endif
653+ };
654+
655+ /**
656+ * cdx_mmap_resource - map a CDX resource into user memory space
657+ * @fp: File pointer. Not used in this function, but required where
658+ * this API is registered as a callback.
659+ * @kobj: kobject for mapping
660+ * @attr: struct bin_attribute for the file being mapped
661+ * @vma: struct vm_area_struct passed into the mmap
662+ *
663+ * Use the regular CDX mapping routines to map a CDX resource into userspace.
664+ *
665+ * Return: true on success, false otherwise.
666+ */
667+ static int cdx_mmap_resource (struct file * fp , struct kobject * kobj ,
668+ struct bin_attribute * attr ,
669+ struct vm_area_struct * vma )
670+ {
671+ struct cdx_device * cdx_dev = to_cdx_device (kobj_to_dev (kobj ));
672+ int num = (unsigned long )attr -> private ;
673+ struct resource * res ;
674+ unsigned long size ;
675+
676+ res = & cdx_dev -> res [num ];
677+ if (iomem_is_exclusive (res -> start ))
678+ return - EINVAL ;
679+
680+ /* Make sure the caller is mapping a valid resource for this device */
681+ size = ((cdx_resource_len (cdx_dev , num ) - 1 ) >> PAGE_SHIFT ) + 1 ;
682+ if (vma -> vm_pgoff + vma_pages (vma ) > size )
683+ return - EINVAL ;
684+
685+ /*
686+ * Map memory region and vm->vm_pgoff is expected to be an
687+ * offset within that region.
688+ */
689+ vma -> vm_page_prot = pgprot_device (vma -> vm_page_prot );
690+ vma -> vm_pgoff += (cdx_resource_start (cdx_dev , num ) >> PAGE_SHIFT );
691+ vma -> vm_ops = & cdx_phys_vm_ops ;
692+ return io_remap_pfn_range (vma , vma -> vm_start , vma -> vm_pgoff ,
693+ vma -> vm_end - vma -> vm_start ,
694+ vma -> vm_page_prot );
695+ }
696+
697+ static void cdx_destroy_res_attr (struct cdx_device * cdx_dev , int num )
698+ {
699+ int i ;
700+
701+ /* removing the bin attributes */
702+ for (i = 0 ; i < num ; i ++ ) {
703+ struct bin_attribute * res_attr ;
704+
705+ res_attr = cdx_dev -> res_attr [i ];
706+ if (res_attr ) {
707+ sysfs_remove_bin_file (& cdx_dev -> dev .kobj , res_attr );
708+ kfree (res_attr );
709+ }
710+ }
711+ }
712+
713+ #define CDX_RES_ATTR_NAME_LEN 10
714+ static int cdx_create_res_attr (struct cdx_device * cdx_dev , int num )
715+ {
716+ struct bin_attribute * res_attr ;
717+ char * res_attr_name ;
718+ int ret ;
719+
720+ res_attr = kzalloc (sizeof (* res_attr ) + CDX_RES_ATTR_NAME_LEN , GFP_ATOMIC );
721+ if (!res_attr )
722+ return - ENOMEM ;
723+
724+ res_attr_name = (char * )(res_attr + 1 );
725+
726+ sysfs_bin_attr_init (res_attr );
727+
728+ cdx_dev -> res_attr [num ] = res_attr ;
729+ sprintf (res_attr_name , "resource%d" , num );
730+
731+ res_attr -> mmap = cdx_mmap_resource ;
732+ res_attr -> attr .name = res_attr_name ;
733+ res_attr -> attr .mode = 0600 ;
734+ res_attr -> size = cdx_resource_len (cdx_dev , num );
735+ res_attr -> private = (void * )(unsigned long )num ;
736+ ret = sysfs_create_bin_file (& cdx_dev -> dev .kobj , res_attr );
737+ if (ret )
738+ kfree (res_attr );
739+
740+ return ret ;
741+ }
742+
646743int cdx_device_add (struct cdx_dev_params * dev_params )
647744{
648745 struct cdx_controller * cdx = dev_params -> cdx ;
649746 struct cdx_device * cdx_dev ;
650- int ret ;
747+ int ret , i ;
651748
652749 cdx_dev = kzalloc (sizeof (* cdx_dev ), GFP_KERNEL );
653750 if (!cdx_dev )
@@ -690,7 +787,26 @@ int cdx_device_add(struct cdx_dev_params *dev_params)
690787 goto fail ;
691788 }
692789
790+ /* Create resource<N> attributes */
791+ for (i = 0 ; i < MAX_CDX_DEV_RESOURCES ; i ++ ) {
792+ if (cdx_resource_flags (cdx_dev , i ) & IORESOURCE_MEM ) {
793+ /* skip empty resources */
794+ if (!cdx_resource_len (cdx_dev , i ))
795+ continue ;
796+
797+ ret = cdx_create_res_attr (cdx_dev , i );
798+ if (ret != 0 ) {
799+ dev_err (& cdx_dev -> dev ,
800+ "cdx device resource<%d> file creation failed: %d" , i , ret );
801+ goto resource_create_fail ;
802+ }
803+ }
804+ }
805+
693806 return 0 ;
807+ resource_create_fail :
808+ cdx_destroy_res_attr (cdx_dev , i );
809+ device_del (& cdx_dev -> dev );
694810fail :
695811 /*
696812 * Do not free cdx_dev here as it would be freed in
0 commit comments