]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
UBUNTU: SAUCE: PCI: Apply the new generic I/O management on PCI IO hosts
authorzhichang.yuan <yuanzhichang@hisilicon.com>
Sat, 11 Mar 2017 13:36:08 +0000 (21:36 +0800)
committerSeth Forshee <seth.forshee@canonical.com>
Tue, 5 Sep 2017 12:33:48 +0000 (07:33 -0500)
BugLink: http://bugs.launchpad.net/bugs/1677319
After introducing the new generic I/O space management(LIBIO), the original PCI
MMIO relevant helpers need to be updated based on the new interfaces defined in
LIBIO.
This patch adapts the corresponding code to match the changes introduced by
LIBIO.

[Note that the removal of __weak on pci_register_io_range is intentional, as
 there are no other users. See: https://lkml.org/lkml/2017/1/30/848 -dannf]

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de> #earlier draft
Acked-by: Bjorn Helgaas <bhelgaas@google.com> #drivers/pci parts
(v7 submission)
Reference: http://www.spinics.net/lists/linux-pci/msg59176.html
[dannf: included a few changes from zhichang based on list feedback:
 tighter arch-restriction, build fix for non-LIBIO builds & a return code
 optimization]
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Acked-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
drivers/acpi/pci_root.c
drivers/of/address.c
drivers/pci/pci.c
include/linux/io.h
include/linux/libio.h
include/linux/pci.h
lib/Kconfig

index 9eec3095e6c33eee313f64c7cc91ba525073cb95..40164e30e630d00e7724c6181cb06f0be35870c7 100644 (file)
@@ -729,7 +729,8 @@ next:
        }
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+                       struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
        struct resource *res = entry->res;
@@ -738,7 +739,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
        resource_size_t length = resource_size(res);
        unsigned long port;
 
-       if (pci_register_io_range(cpu_addr, length))
+       if (pci_register_io_range(fwnode, cpu_addr, length))
                goto err;
 
        port = pci_address_to_pio(cpu_addr);
@@ -780,7 +781,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
        else {
                resource_list_for_each_entry_safe(entry, tmp, list) {
                        if (entry->res->flags & IORESOURCE_IO)
-                               acpi_pci_root_remap_iospace(entry);
+                               acpi_pci_root_remap_iospace(&device->fwnode,
+                                               entry);
 
                        if (entry->res->flags & IORESOURCE_DISABLED)
                                resource_list_destroy_entry(entry);
index 3f91282672978cb253da29e291c15b5640d01399..aa9f63b1615ad3bbe7e643ee37c4ad95b3ceedbd 100644 (file)
@@ -2,6 +2,7 @@
 #define pr_fmt(fmt)    "OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/libio.h>
@@ -324,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
        if (res->flags & IORESOURCE_IO) {
                unsigned long port;
-               err = pci_register_io_range(range->cpu_addr, range->size);
+               err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+                               range->size);
                if (err)
                        goto invalid_range;
                port = pci_address_to_pio(range->cpu_addr);
index fdf65a6c13f62558e887cd001f4c61ca2daef989..245d8ede12b7efc93c3971384100171e707ebbf4 100644 (file)
@@ -3255,65 +3255,37 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
-struct io_range {
-       struct list_head list;
-       phys_addr_t start;
-       resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+                       resource_size_t size)
 {
        int err = 0;
 
 #ifdef PCI_IOBASE
-       struct io_range *range;
-       resource_size_t allocated_size = 0;
-
-       /* check if the range hasn't been previously recorded */
-       spin_lock(&io_range_lock);
-       list_for_each_entry(range, &io_range_list, list) {
-               if (addr >= range->start && addr + size <= range->start + size) {
-                       /* range already registered, bail out */
-                       goto end_register;
-               }
-               allocated_size += range->size;
-       }
-
-       /* range not registed yet, check for available space */
-       if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-               /* if it's too big check if 64K space can be reserved */
-               if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-                       err = -E2BIG;
-                       goto end_register;
-               }
+       struct libio_range *range, *tmprange;
 
-               size = SZ_64K;
-               pr_warn("Requested IO range too big, new size set to 64K\n");
-       }
+       if (!size || addr + size < addr)
+               return -EINVAL;
 
-       /* add the range to the list */
-       range = kzalloc(sizeof(*range), GFP_ATOMIC);
-       if (!range) {
-               err = -ENOMEM;
-               goto end_register;
-       }
+       WARN_ON(!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(size));
 
-       range->start = addr;
+       range = kzalloc(sizeof(*range), GFP_KERNEL);
+       if (!range)
+               return -ENOMEM;
+       range->node = fwnode;
+       range->flags = IO_CPU_MMIO;
        range->size = size;
+       range->hw_start = addr;
 
-       list_add_tail(&range->list, &io_range_list);
-
-end_register:
-       spin_unlock(&io_range_lock);
+       tmprange = register_libio_range(range);
+       if (tmprange != range) {
+               kfree(range);
+               if (IS_ERR(tmprange))
+                       return -EFAULT;
+       }
 #endif
 
        return err;
@@ -3324,21 +3296,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
        phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
-       struct io_range *range;
-       resource_size_t allocated_size = 0;
-
        if (pio > IO_SPACE_LIMIT)
                return address;
 
-       spin_lock(&io_range_lock);
-       list_for_each_entry(range, &io_range_list, list) {
-               if (pio >= allocated_size && pio < allocated_size + range->size) {
-                       address = range->start + pio - allocated_size;
-                       break;
-               }
-               allocated_size += range->size;
-       }
-       spin_unlock(&io_range_lock);
+       address = libio_to_hwaddr(pio);
 #endif
 
        return address;
@@ -3347,25 +3308,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
-       struct io_range *res;
-       resource_size_t offset = 0;
-       unsigned long addr = -1;
-
-       spin_lock(&io_range_lock);
-       list_for_each_entry(res, &io_range_list, list) {
-               if (address >= res->start && address < res->start + res->size) {
-                       addr = address - res->start + offset;
-                       break;
-               }
-               offset += res->size;
-       }
-       spin_unlock(&io_range_lock);
-
-       return addr;
+       return libio_translate_cpuaddr(address);
 #else
-       if (address > IO_SPACE_LIMIT)
-               return (unsigned long)-1;
-
        return (unsigned long) address;
 #endif
 }
index 90c7e5e99fb6a0077f4ff29c45f5ed4d3ad3f495..2195d9ea4aaae0c054f04aab2da7cff851d2b997 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/err.h>
 #include <asm/io.h>
 #include <asm/page.h>
-#include <linux/libio.h>
 
 struct device;
 struct resource;
index da6f41b6da6a3da909eb51490f5dd016959a55d3..562556470c9340f5fdb76742f2655a3d8d25988c 100644 (file)
@@ -72,6 +72,10 @@ extern struct libio_range
 *find_io_range_from_fwnode(struct fwnode_handle *fwnode);
 extern unsigned long libio_translate_hwaddr(struct fwnode_handle *fwnode,
                        resource_size_t hw_addr);
+extern struct libio_range *register_libio_range(struct libio_range *newrange);
+extern resource_size_t libio_to_hwaddr(unsigned long pio);
+
+extern unsigned long libio_translate_cpuaddr(resource_size_t hw_addr);
 #else
 static inline struct libio_range
 *find_io_range_from_fwnode(struct fwnode_handle *fwnode)
@@ -84,12 +88,23 @@ static inline unsigned long libio_translate_hwaddr(struct fwnode_handle *fwnode,
 {
        return -1;
 }
-#endif
 
-extern struct libio_range *register_libio_range(struct libio_range *newrange);
-extern resource_size_t libio_to_hwaddr(unsigned long pio);
+static inline struct libio_range 
+*register_libio_range(struct libio_range *newrange)
+{
+       return NULL;
+}
 
-extern unsigned long libio_translate_cpuaddr(resource_size_t hw_addr);
+static inline resource_size_t libio_to_hwaddr(unsigned long pio)
+{
+       return -1;
+}
+
+static inline unsigned long libio_translate_cpuaddr(resource_size_t hw_addr)
+{
+       return -1;
+}
+#endif
 
 #ifdef CONFIG_ACPI
 extern int acpi_set_libio_resource(struct device *child,
index f958d0732af685761c8b996cc6c79ca87f99f43f..6bac554e408952c88b2c2cf31995b51c84ef3eb9 100644 (file)
@@ -1209,7 +1209,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
                        void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+                       resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
index d7a1e4068f335d3b5abc76986b13b9f0e1c8a58c..90be4c091128f9d5ad988250f0bf9ef1c99b646a 100644 (file)
@@ -61,7 +61,7 @@ config ARCH_HAS_FAST_MULTIPLIER
 
 config LIBIO
        bool "Generic logical IO management"
-       def_bool y if PCI && (ARM || ARC || UNICORE32 || SPARC || S390 || CRIS || BLACKFIN || XTENSA || ARM64)
+       def_bool y if PCI && (ARM || UNICORE32 || MICROBLAZE || ARM64)
        help
          For some architectures, there are no IO space. To support the
          accesses to legacy I/O devices on those architectures, kernel