]> 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)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Wed, 17 May 2017 16:36:54 +0000 (13:36 -0300)
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: Stefan Bader <stefan.bader@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 bf601d4df8cfcbb6e579b00cbff75efcb24d8071..aa5d820f12522dc10480219f1d8f5d121223e609 100644 (file)
@@ -730,7 +730,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;
@@ -739,7 +740,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);
@@ -781,7 +782,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 4d4fa221225225d36133d1bfdedbec2800097439..7ba422294c1f50e280227d21635c126d21fd9f0d 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 7904d02ffdb97e5f23d915e9c83edbf599ddf58b..5a64e14e156414cf78059682a875e62fdea10406 100644 (file)
@@ -3238,65 +3238,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;
@@ -3307,21 +3279,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;
@@ -3330,25 +3291,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 51ec1aa6fe75cc5260837ffb4529b9991aa23c8c..82ef36eac8a16a8fc2b7b021f345910ac04b04b4 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 e2d1a124216a9c36b580e68a6c79607cd6686215..580ae5aaa7527381a4f1e77578d028eb31eea8a8 100644 (file)
@@ -1198,7 +1198,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 17a97d4e43fceba9091bc05b6ce9702f6c56bf18..19de5006b5af56d03eaf416174bfb27bb2ae5567 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