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 ssize_t
reload_on_reset_show(struct device
*device
,
55 struct device_attribute
*attr
,
58 struct ocxl_afu
*afu
= to_afu(device
);
59 struct ocxl_fn
*fn
= afu
->fn
;
60 struct pci_dev
*pci_dev
= to_pci_dev(fn
->dev
.parent
);
63 if (ocxl_config_get_reset_reload(pci_dev
, &val
))
64 return scnprintf(buf
, PAGE_SIZE
, "unavailable\n");
66 return scnprintf(buf
, PAGE_SIZE
, "%d\n", val
);
69 static ssize_t
reload_on_reset_store(struct device
*device
,
70 struct device_attribute
*attr
,
71 const char *buf
, size_t count
)
73 struct ocxl_afu
*afu
= to_afu(device
);
74 struct ocxl_fn
*fn
= afu
->fn
;
75 struct pci_dev
*pci_dev
= to_pci_dev(fn
->dev
.parent
);
78 rc
= kstrtoint(buf
, 0, &val
);
79 if (rc
|| (val
!= 0 && val
!= 1))
82 if (ocxl_config_set_reset_reload(pci_dev
, val
))
88 static struct device_attribute afu_attrs
[] = {
89 __ATTR_RO(global_mmio_size
),
90 __ATTR_RO(pp_mmio_size
),
91 __ATTR_RO(afu_version
),
93 __ATTR_RW(reload_on_reset
),
96 static ssize_t
global_mmio_read(struct file
*filp
, struct kobject
*kobj
,
97 struct bin_attribute
*bin_attr
, char *buf
,
98 loff_t off
, size_t count
)
100 struct ocxl_afu
*afu
= to_afu(kobj_to_dev(kobj
));
102 if (count
== 0 || off
< 0 ||
103 off
>= afu
->config
.global_mmio_size
)
105 memcpy_fromio(buf
, afu
->global_mmio_ptr
+ off
, count
);
109 static vm_fault_t
global_mmio_fault(struct vm_fault
*vmf
)
111 struct vm_area_struct
*vma
= vmf
->vma
;
112 struct ocxl_afu
*afu
= vma
->vm_private_data
;
113 unsigned long offset
;
115 if (vmf
->pgoff
>= (afu
->config
.global_mmio_size
>> PAGE_SHIFT
))
116 return VM_FAULT_SIGBUS
;
119 offset
+= (afu
->global_mmio_start
>> PAGE_SHIFT
);
120 return vmf_insert_pfn(vma
, vmf
->address
, offset
);
123 static const struct vm_operations_struct global_mmio_vmops
= {
124 .fault
= global_mmio_fault
,
127 static int global_mmio_mmap(struct file
*filp
, struct kobject
*kobj
,
128 const struct bin_attribute
*bin_attr
,
129 struct vm_area_struct
*vma
)
131 struct ocxl_afu
*afu
= to_afu(kobj_to_dev(kobj
));
133 if ((vma_pages(vma
) + vma
->vm_pgoff
) >
134 (afu
->config
.global_mmio_size
>> PAGE_SHIFT
))
137 vm_flags_set(vma
, VM_IO
| VM_PFNMAP
);
138 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
139 vma
->vm_ops
= &global_mmio_vmops
;
140 vma
->vm_private_data
= afu
;
144 int ocxl_sysfs_register_afu(struct ocxl_file_info
*info
)
148 for (i
= 0; i
< ARRAY_SIZE(afu_attrs
); i
++) {
149 rc
= device_create_file(&info
->dev
, &afu_attrs
[i
]);
154 sysfs_attr_init(&info
->attr_global_mmio
.attr
);
155 info
->attr_global_mmio
.attr
.name
= "global_mmio_area";
156 info
->attr_global_mmio
.attr
.mode
= 0600;
157 info
->attr_global_mmio
.size
= info
->afu
->config
.global_mmio_size
;
158 info
->attr_global_mmio
.read
= global_mmio_read
;
159 info
->attr_global_mmio
.mmap
= global_mmio_mmap
;
160 rc
= device_create_bin_file(&info
->dev
, &info
->attr_global_mmio
);
162 dev_err(&info
->dev
, "Unable to create global mmio attr for afu: %d\n", rc
);
169 for (i
--; i
>= 0; i
--)
170 device_remove_file(&info
->dev
, &afu_attrs
[i
]);
175 void ocxl_sysfs_unregister_afu(struct ocxl_file_info
*info
)
180 * device_remove_bin_file is safe to call if the file is not added as
181 * the files are removed by name, and early exit if not found
183 for (i
= 0; i
< ARRAY_SIZE(afu_attrs
); i
++)
184 device_remove_file(&info
->dev
, &afu_attrs
[i
]);
185 device_remove_bin_file(&info
->dev
, &info
->attr_global_mmio
);