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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * arch/alpha/kernel/pci-sysfs.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2009 Ivan Kokshaysky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Alpha PCI resource files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Loosely based on generic HAVE_PCI_MMAP implementation in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * drivers/pci/pci-sysfs.c
^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) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static int hose_mmap_page_range(struct pci_controller *hose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 				struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 				enum pci_mmap_state mmap_type, int sparse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	if (mmap_type == pci_mmap_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		base = sparse ? hose->sparse_mem_base : hose->dense_mem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 		base = sparse ? hose->sparse_io_base : hose->dense_io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	vma->vm_pgoff += base >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 				  vma->vm_end - vma->vm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 				  vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static int __pci_mmap_fits(struct pci_dev *pdev, int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 			   struct vm_area_struct *vma, int sparse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	unsigned long nr, start, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int shift = sparse ? 5 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	nr = vma_pages(vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	start = vma->vm_pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	size = ((pci_resource_len(pdev, num) - 1) >> (PAGE_SHIFT - shift)) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	if (start < size && size - start >= nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on %s BAR %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		"(size 0x%08lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		current->comm, sparse ? " sparse" : "", start, start + nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		pci_name(pdev), num, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * pci_mmap_resource - map a PCI resource into user memory space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * @kobj: kobject for mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * @attr: struct bin_attribute for the file being mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * @vma: struct vm_area_struct passed into the mmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * @sparse: address space type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * Use the bus mapping routines to map a PCI resource into userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int pci_mmap_resource(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 			     struct bin_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			     struct vm_area_struct *vma, int sparse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct resource *res = attr->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	enum pci_mmap_state mmap_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct pci_bus_region bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	for (i = 0; i < PCI_STD_NUM_BARS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		if (res == &pdev->resource[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (i >= PCI_STD_NUM_BARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (!__pci_mmap_fits(pdev, i, vma, sparse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	pcibios_resource_to_bus(pdev->bus, &bar, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				    struct bin_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 				    struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	return pci_mmap_resource(kobj, attr, vma, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 				   struct bin_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 				   struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	return pci_mmap_resource(kobj, attr, vma, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * pci_remove_resource_files - cleanup resource files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * @dev: dev to cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * If we created resource files for @dev, remove them from sysfs and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * free their resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void pci_remove_resource_files(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		struct bin_attribute *res_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		res_attr = pdev->res_attr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		if (res_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			kfree(res_attr);
^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) 		res_attr = pdev->res_attr_wc[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		if (res_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			kfree(res_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct pci_bus_region bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	struct pci_controller *hose = pdev->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	long dense_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	unsigned long sparse_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	pcibios_resource_to_bus(pdev->bus, &bar, &pdev->resource[num]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	/* All core logic chips have 4G sparse address space, except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	   CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	   definitions in asm/core_xxx.h files). This corresponds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	   to 128M or 512M of the bus space. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	dense_offset = (long)(hose->dense_mem_base - hose->sparse_mem_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	sparse_size = dense_offset >= 0x400000000UL ? 0x20000000 : 0x8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return bar.end < sparse_size;
^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) static int pci_create_one_attr(struct pci_dev *pdev, int num, char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			       char *suffix, struct bin_attribute *res_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			       unsigned long sparse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	size_t size = pci_resource_len(pdev, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	sprintf(name, "resource%d%s", num, suffix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	res_attr->mmap = sparse ? pci_mmap_resource_sparse :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				  pci_mmap_resource_dense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	res_attr->attr.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	res_attr->attr.mode = S_IRUSR | S_IWUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	res_attr->size = sparse ? size << 5 : size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	res_attr->private = &pdev->resource[num];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	return sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int pci_create_attr(struct pci_dev *pdev, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	/* allocate attribute structure, piggyback attribute name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	int retval, nlen1, nlen2 = 0, res_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	unsigned long sparse_base, dense_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	struct bin_attribute *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	struct pci_controller *hose = pdev->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	char *suffix, *attr_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	suffix = "";	/* Assume bwx machine, normal resourceN files. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	nlen1 = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (pdev->resource[num].flags & IORESOURCE_MEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		sparse_base = hose->sparse_mem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		dense_base = hose->dense_mem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		if (sparse_base && !sparse_mem_mmap_fits(pdev, num)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			sparse_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			suffix = "_dense";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			nlen1 = 16;	/* resourceN_dense */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		sparse_base = hose->sparse_io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		dense_base = hose->dense_io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	if (sparse_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		suffix = "_sparse";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		nlen1 = 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (dense_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			nlen2 = 16;	/* resourceN_dense */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			res_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	attr = kzalloc(sizeof(*attr) * res_count + nlen1 + nlen2, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	/* Create bwx, sparse or single dense file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	attr_name = (char *)(attr + res_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	pdev->res_attr[num] = attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	retval = pci_create_one_attr(pdev, num, attr_name, suffix, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 				     sparse_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (retval || res_count == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	/* Create dense file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	attr_name += nlen1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	attr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	pdev->res_attr_wc[num] = attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	return pci_create_one_attr(pdev, num, attr_name, "_dense", attr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  * pci_create_resource_files - create resource files in sysfs for @dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * @dev: dev in question
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  * Walk the resources in @dev creating files for each resource available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int pci_create_resource_files(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	/* Expose the PCI resources from this device as files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		/* skip empty resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		if (!pci_resource_len(pdev, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		retval = pci_create_attr(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			pci_remove_resource_files(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Legacy I/O bus mapping stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int __legacy_mmap_fits(struct pci_controller *hose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			      struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			      unsigned long res_size, int sparse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	unsigned long nr, start, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	nr = vma_pages(vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	start = vma->vm_pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	size = ((res_size - 1) >> PAGE_SHIFT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	if (start < size && size - start >= nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on hose %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		"(size 0x%08lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		current->comm, sparse ? " sparse" : "", start, start + nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		hose->index, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static inline int has_sparse(struct pci_controller *hose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			     enum pci_mmap_state mmap_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	base = (mmap_type == pci_mmap_mem) ? hose->sparse_mem_base :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 					     hose->sparse_io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	return base != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			       enum pci_mmap_state mmap_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	struct pci_controller *hose = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	int sparse = has_sparse(hose, mmap_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	unsigned long res_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	res_size = (mmap_type == pci_mmap_mem) ? bus->legacy_mem->size :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 						 bus->legacy_io->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (!__legacy_mmap_fits(hose, vma, res_size, sparse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	return hose_mmap_page_range(hose, vma, mmap_type, sparse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  * pci_adjust_legacy_attr - adjustment of legacy file attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  * @b: bus to create files under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  * @mmap_type: I/O port or memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  * Adjust file name and size for sparse mappings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) void pci_adjust_legacy_attr(struct pci_bus *bus, enum pci_mmap_state mmap_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	struct pci_controller *hose = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (!has_sparse(hose, mmap_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (mmap_type == pci_mmap_mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		bus->legacy_mem->attr.name = "legacy_mem_sparse";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		bus->legacy_mem->size <<= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		bus->legacy_io->attr.name = "legacy_io_sparse";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		bus->legacy_io->size <<= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* Legacy I/O bus read/write functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	struct pci_controller *hose = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	port += hose->io_space->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	switch(size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		*((u8 *)val) = inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		if (port & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		*((u16 *)val) = inw(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		if (port & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		*((u32 *)val) = inl(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	struct pci_controller *hose = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	port += hose->io_space->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	switch(size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		outb(port, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		if (port & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		outw(port, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		if (port & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		outl(port, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }