^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright 2017 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "ocxl_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) static inline struct ocxl_afu *to_afu(struct device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct ocxl_file_info *info = container_of(device, struct ocxl_file_info, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) return info->afu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static ssize_t global_mmio_size_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return scnprintf(buf, PAGE_SIZE, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) afu->config.global_mmio_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static ssize_t pp_mmio_size_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return scnprintf(buf, PAGE_SIZE, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) afu->config.pp_mmio_stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static ssize_t afu_version_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return scnprintf(buf, PAGE_SIZE, "%hhu:%hhu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) afu->config.version_major,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) afu->config.version_minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static ssize_t contexts_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return scnprintf(buf, PAGE_SIZE, "%d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) afu->pasid_count, afu->pasid_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static ssize_t reload_on_reset_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct ocxl_fn *fn = afu->fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct pci_dev *pci_dev = to_pci_dev(fn->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (ocxl_config_get_reset_reload(pci_dev, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return scnprintf(buf, PAGE_SIZE, "unavailable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return scnprintf(buf, PAGE_SIZE, "%d\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static ssize_t reload_on_reset_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct ocxl_afu *afu = to_afu(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct ocxl_fn *fn = afu->fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct pci_dev *pci_dev = to_pci_dev(fn->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int rc, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) rc = kstrtoint(buf, 0, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (rc || (val != 0 && val != 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ocxl_config_set_reset_reload(pci_dev, val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct device_attribute afu_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) __ATTR_RO(global_mmio_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) __ATTR_RO(pp_mmio_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) __ATTR_RO(afu_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) __ATTR_RO(contexts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __ATTR_RW(reload_on_reset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static ssize_t global_mmio_read(struct file *filp, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct bin_attribute *bin_attr, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) loff_t off, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct ocxl_afu *afu = to_afu(kobj_to_dev(kobj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (count == 0 || off < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) off >= afu->config.global_mmio_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) memcpy_fromio(buf, afu->global_mmio_ptr + off, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static vm_fault_t global_mmio_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct vm_area_struct *vma = vmf->vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct ocxl_afu *afu = vma->vm_private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (vmf->pgoff >= (afu->config.global_mmio_size >> PAGE_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) offset = vmf->pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) offset += (afu->global_mmio_start >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return vmf_insert_pfn(vma, vmf->address, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const struct vm_operations_struct global_mmio_vmops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .fault = global_mmio_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int global_mmio_mmap(struct file *filp, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct bin_attribute *bin_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct ocxl_afu *afu = to_afu(kobj_to_dev(kobj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if ((vma_pages(vma) + vma->vm_pgoff) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) (afu->config.global_mmio_size >> PAGE_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) vma->vm_flags |= VM_IO | VM_PFNMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) vma->vm_ops = &global_mmio_vmops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) vma->vm_private_data = afu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int ocxl_sysfs_register_afu(struct ocxl_file_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) rc = device_create_file(&info->dev, &afu_attrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) sysfs_attr_init(&info->attr_global_mmio.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) info->attr_global_mmio.attr.name = "global_mmio_area";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) info->attr_global_mmio.attr.mode = 0600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) info->attr_global_mmio.size = info->afu->config.global_mmio_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) info->attr_global_mmio.read = global_mmio_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) info->attr_global_mmio.mmap = global_mmio_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rc = device_create_bin_file(&info->dev, &info->attr_global_mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dev_err(&info->dev, "Unable to create global mmio attr for afu: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i--; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) device_remove_file(&info->dev, &afu_attrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) void ocxl_sysfs_unregister_afu(struct ocxl_file_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * device_remove_bin_file is safe to call if the file is not added as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * the files are removed by name, and early exit if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) for (i = 0; i < ARRAY_SIZE(afu_attrs); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) device_remove_file(&info->dev, &afu_attrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) device_remove_bin_file(&info->dev, &info->attr_global_mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }