Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }