]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.39/patches.arch/ppc-pcibios_allocate_bus_resources.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc-pcibios_allocate_bus_resources.patch
diff --git a/src/patches/suse-2.6.27.39/patches.arch/ppc-pcibios_allocate_bus_resources.patch b/src/patches/suse-2.6.27.39/patches.arch/ppc-pcibios_allocate_bus_resources.patch
new file mode 100644 (file)
index 0000000..de7b50d
--- /dev/null
@@ -0,0 +1,178 @@
+Subject: Fix DLPAR
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+References: 439491
+
+Signed-off-by: Olaf Hering <olh@suse.de>
+---
+ arch/powerpc/include/asm/pci.h             |    2 
+ arch/powerpc/kernel/pci-common.c           |  110 ++++++++++++++---------------
+ arch/powerpc/platforms/pseries/pci_dlpar.c |    2 
+ 3 files changed, 59 insertions(+), 55 deletions(-)
+
+--- a/arch/powerpc/include/asm/pci.h
++++ b/arch/powerpc/include/asm/pci.h
+@@ -196,6 +196,8 @@ extern void pcibios_setup_new_device(str
+ extern void pcibios_claim_one_bus(struct pci_bus *b);
++extern void pcibios_allocate_bus_resources(struct pci_bus *bus);
++
+ extern void pcibios_resource_survey(void);
+ extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -986,69 +986,66 @@ static int __init reparent_resources(str
+  *        as well.
+  */
+-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
++void pcibios_allocate_bus_resources(struct pci_bus *bus)
+ {
+-      struct pci_bus *bus;
++      struct pci_bus *b;
+       int i;
+       struct resource *res, *pr;
+-      /* Depth-First Search on bus tree */
+-      list_for_each_entry(bus, bus_list, node) {
+-              for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+-                      if ((res = bus->resource[i]) == NULL || !res->flags
+-                          || res->start > res->end)
+-                              continue;
+-                      if (bus->parent == NULL)
+-                              pr = (res->flags & IORESOURCE_IO) ?
+-                                      &ioport_resource : &iomem_resource;
+-                      else {
+-                              /* Don't bother with non-root busses when
+-                               * re-assigning all resources. We clear the
+-                               * resource flags as if they were colliding
+-                               * and as such ensure proper re-allocation
+-                               * later.
++      for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
++              if ((res = bus->resource[i]) == NULL || !res->flags
++                  || res->start > res->end)
++                      continue;
++              if (bus->parent == NULL)
++                      pr = (res->flags & IORESOURCE_IO) ?
++                              &ioport_resource : &iomem_resource;
++              else {
++                      /* Don't bother with non-root busses when
++                       * re-assigning all resources. We clear the
++                       * resource flags as if they were colliding
++                       * and as such ensure proper re-allocation
++                       * later.
++                       */
++                      if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
++                              goto clear_resource;
++                      pr = pci_find_parent_resource(bus->self, res);
++                      if (pr == res) {
++                              /* this happens when the generic PCI
++                               * code (wrongly) decides that this
++                               * bridge is transparent  -- paulus
+                                */
+-                              if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+-                                      goto clear_resource;
+-                              pr = pci_find_parent_resource(bus->self, res);
+-                              if (pr == res) {
+-                                      /* this happens when the generic PCI
+-                                       * code (wrongly) decides that this
+-                                       * bridge is transparent  -- paulus
+-                                       */
+-                                      continue;
+-                              }
++                              continue;
+                       }
++              }
+-                      DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
+-                          "[0x%x], parent %p (%s)\n",
+-                          bus->self ? pci_name(bus->self) : "PHB",
+-                          bus->number, i,
+-                          (unsigned long long)res->start,
+-                          (unsigned long long)res->end,
+-                          (unsigned int)res->flags,
+-                          pr, (pr && pr->name) ? pr->name : "nil");
+-
+-                      if (pr && !(pr->flags & IORESOURCE_UNSET)) {
+-                              if (request_resource(pr, res) == 0)
+-                                      continue;
+-                              /*
+-                               * Must be a conflict with an existing entry.
+-                               * Move that entry (or entries) under the
+-                               * bridge resource and try again.
+-                               */
+-                              if (reparent_resources(pr, res) == 0)
+-                                      continue;
+-                      }
+-                      printk(KERN_WARNING
+-                             "PCI: Cannot allocate resource region "
+-                             "%d of PCI bridge %d, will remap\n",
+-                             i, bus->number);
+-clear_resource:
+-                      res->flags = 0;
++              DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
++                  "[0x%x], parent %p (%s)\n",
++                  bus->self ? pci_name(bus->self) : "PHB",
++                  bus->number, i,
++                  (unsigned long long)res->start,
++                  (unsigned long long)res->end,
++                  (unsigned int)res->flags,
++                  pr, (pr && pr->name) ? pr->name : "nil");
++
++              if (pr && !(pr->flags & IORESOURCE_UNSET)) {
++                      if (request_resource(pr, res) == 0)
++                              continue;
++                      /*
++                       * Must be a conflict with an existing entry.
++                       * Move that entry (or entries) under the
++                       * bridge resource and try again.
++                       */
++                      if (reparent_resources(pr, res) == 0)
++                              continue;
+               }
+-              pcibios_allocate_bus_resources(&bus->children);
++              printk(KERN_WARNING "PCI: Cannot allocate resource region "
++                     "%d of PCI bridge %d, will remap\n", i, bus->number);
++clear_resource:
++              res->flags = 0;
+       }
++
++      list_for_each_entry(b, &bus->children, node)
++              pcibios_allocate_bus_resources(b);
+ }
+ static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
+@@ -1119,10 +1116,13 @@ static void __init pcibios_allocate_reso
+ void __init pcibios_resource_survey(void)
+ {
++      struct pci_bus *b;
++
+       /* Allocate and assign resources. If we re-assign everything, then
+        * we skip the allocate phase
+        */
+-      pcibios_allocate_bus_resources(&pci_root_buses);
++      list_for_each_entry(b, &pci_root_buses, node)
++              pcibios_allocate_bus_resources(b);
+       if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+               pcibios_allocate_resources(0);
+--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
+@@ -189,6 +189,7 @@ struct pci_controller * __devinit init_p
+ {
+       struct pci_controller *phb;
+       int primary;
++      struct pci_bus *b;
+       primary = list_empty(&hose_list);
+       phb = pcibios_alloc_controller(dn);
+@@ -203,6 +204,7 @@ struct pci_controller * __devinit init_p
+               eeh_add_device_tree_early(dn);
+       scan_phb(phb);
++      pcibios_allocate_bus_resources(phb->bus);
+       pcibios_fixup_new_pci_devices(phb->bus);
+       pci_bus_add_devices(phb->bus);
+       eeh_add_device_tree_late(phb->bus);