]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
PCI: Restore pref MMIO allocation logic for host bridge without mmio64
authorYinghai Lu <yinghai@kernel.org>
Thu, 8 Oct 2015 21:38:34 +0000 (14:38 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Mon, 19 Oct 2015 20:41:15 +0000 (13:41 -0700)
From 5b2854155 (PCI: Restrict 64-bit prefetchable bridge windows to 64-bit
resources), we change the logic for pref mmio allocation:
When bridge pref support mmio64, we will only put children pref
that support mmio64 into it, and will put children pref mmio32
into bridge's non-pref mmio32.

That could leave bridge pref bar not used when that pref bar is mmio64,
and children res only has mmio32.
Also could have allocation failure when non-pref mmio32 is not big
enough space for those children pref mmio32.

That is not rational when the host bridge does not 64bit mmio above 4g
at all.

The patch restore to old logic:
when host bridge does not have has_mem64, put children pref mmio64 and
pref mmio32 all under bridges pref bars.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Orabug: 21826746

Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com>
(cherry picked from commit 3317fa110f1c0c0f0a1d0f3ccd00d20319d76623)

drivers/pci/bus.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c

index 6fbd3f2b5992a2cdd53c759147629292463789fd..b043bdf642116389d0f6b9b1698f7691b3844ef0 100644 (file)
@@ -202,8 +202,10 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 {
 #ifdef CONFIG_PCI_BUS_ADDR_T_64BIT
        int rc;
+       unsigned long mmio64 = pci_find_host_bridge(bus)->has_mem64 ?
+                               IORESOURCE_MEM_64 : 0;
 
-       if (res->flags & IORESOURCE_MEM_64) {
+       if (res->flags & mmio64) {
                rc = pci_bus_alloc_from_region(bus, res, size, align, min,
                                               type_mask, alignf, alignf_data,
                                               &pci_high);
index 95d18ef267e1063773bcb703d7e5680632396f0c..0d64677e8b2fab1e9ae81c55ab70720563bdf162 100644 (file)
@@ -1311,7 +1311,8 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES];
                mask = IORESOURCE_MEM;
                prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-               if (b_res[2].flags & IORESOURCE_MEM_64) {
+               if ((b_res[2].flags & IORESOURCE_MEM_64) &&
+                   pci_find_host_bridge(bus)->has_mem64) {
                        prefmask |= IORESOURCE_MEM_64;
                        ret = pbus_size_mem(bus, prefmask, prefmask,
                                  prefmask, prefmask,
@@ -1470,17 +1471,21 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
         *        io port.
         *     2. if there is non pref mmio assign fail, release bridge
         *        nonpref mmio.
-        *     3. if there is 64bit pref mmio assign fail, and bridge pref
+        *     3. if there is pref mmio assign fail, and host bridge does
+        *        have 64bit mmio, release bridge pref mmio.
+        *     4. if there is 64bit pref mmio assign fail, and bridge pref
         *        is 64bit, release bridge pref mmio.
-        *     4. if there is pref mmio assign fail, and bridge pref is
+        *     5. if there is pref mmio assign fail, and bridge pref is
         *        32bit mmio, release bridge pref mmio
-        *     5. if there is pref mmio assign fail, and bridge pref is not
+        *     6. if there is pref mmio assign fail, and bridge pref is not
         *        assigned, release bridge nonpref mmio.
         */
        if (type & IORESOURCE_IO)
                idx = 0;
        else if (!(type & IORESOURCE_PREFETCH))
                idx = 1;
+       else if (!pci_find_host_bridge(bus)->has_mem64)
+               idx = 2;
        else if ((type & IORESOURCE_MEM_64) &&
                 (b_res[2].flags & IORESOURCE_MEM_64))
                idx = 2;
index b19aa5bec47e5e8bae898ade703a1aeda2e5a70d..26aeddea0524085ff4e5fa235d1ca0e456afded1 100644 (file)
@@ -205,6 +205,8 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
        struct resource *res = dev->resource + resno;
        resource_size_t min;
        int ret;
+       unsigned long mmio64 = pci_find_host_bridge(bus)->has_mem64 ?
+                               IORESOURCE_MEM_64 : 0;
 
        min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
 
@@ -216,7 +218,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
         * things differently than they were sized, not everything will fit.
         */
        ret = pci_bus_alloc_resource(bus, res, size, align, min,
-                                    IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
+                                    IORESOURCE_PREFETCH | mmio64,
                                     pcibios_align_resource, dev);
        if (ret == 0)
                return 0;
@@ -225,7 +227,8 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
         * If the prefetchable window is only 32 bits wide, we can put
         * 64-bit prefetchable resources in it.
         */
-       if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
+       if (mmio64 &&
+           (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
             (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
                ret = pci_bus_alloc_resource(bus, res, size, align, min,
                                             IORESOURCE_PREFETCH,
@@ -240,7 +243,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
         * non-prefetchable, the first call already tried the only possibility
         * so we don't need to try again.
         */
-       if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
+       if (res->flags & (IORESOURCE_PREFETCH | mmio64))
                ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
                                             pcibios_align_resource, dev);