Skip to content

Commit aeda33a

Browse files
abhijitG-xlnxgregkh
authored andcommitted
cdx: create sysfs bin files for cdx resources
Resource binary file contains the content of the memory regions. These resources<x> devices can be used to mmap the MMIO regions in the user-space. Co-developed-by: Puneet Gupta <puneet.gupta@amd.com> Signed-off-by: Puneet Gupta <puneet.gupta@amd.com> Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com> Link: https://lore.kernel.org/r/20231222064627.2828960-1-abhijit.gangurde@amd.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6bafe07 commit aeda33a

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

Documentation/ABI/testing/sysfs-bus-cdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ Description:
9898

9999
# echo 1 > /sys/bus/cdx/devices/.../remove
100100

101+
What: /sys/bus/cdx/devices/.../resource<N>
102+
Date: July 2023
103+
Contact: puneet.gupta@amd.com
104+
Description:
105+
The resource binary file contains the content of the memory
106+
regions. These files can be m'maped from userspace.
107+
101108
What: /sys/bus/cdx/devices/.../modalias
102109
Date: July 2023
103110
Contact: nipun.gupta@amd.com

drivers/cdx/cdx.c

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ static DEFINE_MUTEX(cdx_controller_lock);
8080

8181
static 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+
646743
int 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);
694810
fail:
695811
/*
696812
* Do not free cdx_dev here as it would be freed in

include/linux/cdx/cdx_bus.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct cdx_device {
135135
u8 bus_num;
136136
u8 dev_num;
137137
struct resource res[MAX_CDX_DEV_RESOURCES];
138+
struct bin_attribute *res_attr[MAX_CDX_DEV_RESOURCES];
138139
u8 res_count;
139140
u64 dma_mask;
140141
u16 flags;
@@ -147,6 +148,15 @@ struct cdx_device {
147148
#define to_cdx_device(_dev) \
148149
container_of(_dev, struct cdx_device, dev)
149150

151+
#define cdx_resource_start(dev, num) ((dev)->res[(num)].start)
152+
#define cdx_resource_end(dev, num) ((dev)->res[(num)].end)
153+
#define cdx_resource_flags(dev, num) ((dev)->res[(num)].flags)
154+
#define cdx_resource_len(dev, num) \
155+
((cdx_resource_start((dev), (num)) == 0 && \
156+
cdx_resource_end((dev), (num)) == \
157+
cdx_resource_start((dev), (num))) ? 0 : \
158+
(cdx_resource_end((dev), (num)) - \
159+
cdx_resource_start((dev), (num)) + 1))
150160
/**
151161
* struct cdx_driver - CDX device driver
152162
* @driver: Generic device driver

0 commit comments

Comments
 (0)