1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright 2017 IBM Corp.
3 #include <linux/sysfs.h>
4 #include "ocxl_internal.h"
6 static inline struct ocxl_afu
*to_afu(struct device
*device
)
8 struct ocxl_file_info
*info
= container_of(device
, struct ocxl_file_info
, dev
);
13 static ssize_t
global_mmio_size_show(struct device
*device
,
14 struct device_attribute
*attr
,
17 struct ocxl_afu
*afu
= to_afu(device
);
19 return scnprintf(buf
, PAGE_SIZE
, "%d\n",
20 afu
->config
.global_mmio_size
);
23 static ssize_t
pp_mmio_size_show(struct device
*device
,
24 struct device_attribute
*attr
,
27 struct ocxl_afu
*afu
= to_afu(device
);
29 return scnprintf(buf
, PAGE_SIZE
, "%d\n",
30 afu
->config
.pp_mmio_stride
);
33 static ssize_t
afu_version_show(struct device
*device
,
34 struct device_attribute
*attr
,
37 struct ocxl_afu
*afu
= to_afu(device
);
39 return scnprintf(buf
, PAGE_SIZE
, "%hhu:%hhu\n",
40 afu
->config
.version_major
,
41 afu
->config
.version_minor
);
44 static ssize_t
contexts_show(struct device
*device
,
45 struct device_attribute
*attr
,
48 struct ocxl_afu
*afu
= to_afu(device
);
50 return scnprintf(buf
, PAGE_SIZE
, "%d/%d\n",
51 afu
->pasid_count
, afu
->pasid_max
);
54 static struct device_attribute afu_attrs
[] = {
55 __ATTR_RO(global_mmio_size
),
56 __ATTR_RO(pp_mmio_size
),
57 __ATTR_RO(afu_version
),
61 static ssize_t
global_mmio_read(struct file
*filp
, struct kobject
*kobj
,
62 struct bin_attribute
*bin_attr
, char *buf
,
63 loff_t off
, size_t count
)
65 struct ocxl_afu
*afu
= to_afu(kobj_to_dev(kobj
));
67 if (count
== 0 || off
< 0 ||
68 off
>= afu
->config
.global_mmio_size
)
70 memcpy_fromio(buf
, afu
->global_mmio_ptr
+ off
, count
);
74 static vm_fault_t
global_mmio_fault(struct vm_fault
*vmf
)
76 struct vm_area_struct
*vma
= vmf
->vma
;
77 struct ocxl_afu
*afu
= vma
->vm_private_data
;
80 if (vmf
->pgoff
>= (afu
->config
.global_mmio_size
>> PAGE_SHIFT
))
81 return VM_FAULT_SIGBUS
;
84 offset
+= (afu
->global_mmio_start
>> PAGE_SHIFT
);
85 return vmf_insert_pfn(vma
, vmf
->address
, offset
);
88 static const struct vm_operations_struct global_mmio_vmops
= {
89 .fault
= global_mmio_fault
,
92 static int global_mmio_mmap(struct file
*filp
, struct kobject
*kobj
,
93 struct bin_attribute
*bin_attr
,
94 struct vm_area_struct
*vma
)
96 struct ocxl_afu
*afu
= to_afu(kobj_to_dev(kobj
));
98 if ((vma_pages(vma
) + vma
->vm_pgoff
) >
99 (afu
->config
.global_mmio_size
>> PAGE_SHIFT
))
102 vma
->vm_flags
|= VM_IO
| VM_PFNMAP
;
103 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
104 vma
->vm_ops
= &global_mmio_vmops
;
105 vma
->vm_private_data
= afu
;
109 int ocxl_sysfs_register_afu(struct ocxl_file_info
*info
)
113 for (i
= 0; i
< ARRAY_SIZE(afu_attrs
); i
++) {
114 rc
= device_create_file(&info
->dev
, &afu_attrs
[i
]);
119 sysfs_attr_init(&info
->attr_global_mmio
.attr
);
120 info
->attr_global_mmio
.attr
.name
= "global_mmio_area";
121 info
->attr_global_mmio
.attr
.mode
= 0600;
122 info
->attr_global_mmio
.size
= info
->afu
->config
.global_mmio_size
;
123 info
->attr_global_mmio
.read
= global_mmio_read
;
124 info
->attr_global_mmio
.mmap
= global_mmio_mmap
;
125 rc
= device_create_bin_file(&info
->dev
, &info
->attr_global_mmio
);
127 dev_err(&info
->dev
, "Unable to create global mmio attr for afu: %d\n", rc
);
134 for (i
--; i
>= 0; i
--)
135 device_remove_file(&info
->dev
, &afu_attrs
[i
]);
140 void ocxl_sysfs_unregister_afu(struct ocxl_file_info
*info
)
145 * device_remove_bin_file is safe to call if the file is not added as
146 * the files are removed by name, and early exit if not found
148 for (i
= 0; i
< ARRAY_SIZE(afu_attrs
); i
++)
149 device_remove_file(&info
->dev
, &afu_attrs
[i
]);
150 device_remove_bin_file(&info
->dev
, &info
->attr_global_mmio
);