This patch adds boot options so user can reassign device resources
of all devices under a bus.

The boot options can be used as:
        pci=assign-mmio=0000:01,assign-pio=0000:02
'[dddd:]bb' is the domain and bus number.

Cc: Alex Chiang <[EMAIL PROTECTED]>
Cc: Grant Grundler <[EMAIL PROTECTED]>
Cc: Greg KH <[EMAIL PROTECTED]>
Cc: Ingo Molnar <[EMAIL PROTECTED]>
Cc: Jesse Barnes <[EMAIL PROTECTED]>
Cc: Matthew Wilcox <[EMAIL PROTECTED]>
Cc: Randy Dunlap <[EMAIL PROTECTED]>
Cc: Roland Dreier <[EMAIL PROTECTED]>
Signed-off-by: Yu Zhao <[EMAIL PROTECTED]>

---
 arch/x86/pci/common.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/pci/i386.c   |   10 ++++---
 arch/x86/pci/pci.h    |    3 ++
 3 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index b67732b..06e1ce0 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -137,6 +137,72 @@ static void __devinit 
pcibios_fixup_device_resources(struct pci_dev *dev)
        }
 }
 
+static char *pci_assign_pio;
+static char *pci_assign_mmio;
+
+static int pcibios_bus_resource_needs_fixup(struct pci_bus *bus)
+{
+       int i;
+       int type = 0;
+       int domain, busnr;
+
+       if (!bus->self)
+               return 0;
+
+       for (i = 0; i < 2; i++) {
+               char *str = i ? pci_assign_pio : pci_assign_mmio;
+
+               while (str && *str) {
+                       if (sscanf(str, "%04x:%02x", &domain, &busnr) != 2) {
+                               if (sscanf(str, "%02x", &busnr) != 1)
+                                       break;
+                               domain = 0;
+                       }
+
+                       if (pci_domain_nr(bus) == domain &&
+                           bus->number == busnr) {
+                               type |= i ? IORESOURCE_IO : IORESOURCE_MEM;
+                               break;
+                       }
+
+                       str = strchr(str, ';');
+                       if (str)
+                               str++;
+               }
+       }
+
+       return type;
+}
+
+static void __devinit pcibios_fixup_bus_resources(struct pci_bus *bus)
+{
+       int i;
+       int type = pcibios_bus_resource_needs_fixup(bus);
+
+       if (!type)
+               return;
+
+       for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+               struct resource *res = bus->resource[i];
+
+               if (!res)
+                       continue;
+               if (res->flags & type)
+                       res->flags = 0;
+       }
+}
+
+int pcibios_resource_needs_fixup(struct pci_dev *dev, int resno)
+{
+       struct pci_bus *bus;
+
+       for (bus = dev->bus; bus && bus != pci_root_bus; bus = bus->parent)
+               if (pcibios_bus_resource_needs_fixup(bus))
+                       return 1;
+
+       return 0;
+}
+
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
@@ -147,6 +213,7 @@ void __devinit  pcibios_fixup_bus(struct pci_bus *b)
        struct pci_dev *dev;
 
        pci_read_bridge_bases(b);
+       pcibios_fixup_bus_resources(b);
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
 }
@@ -519,6 +586,12 @@ char * __devinit  pcibios_setup(char *str)
        } else if (!strcmp(str, "skip_isa_align")) {
                pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
                return NULL;
+       } else if (!strncmp(str, "assign-pio=", 11)) {
+               pci_assign_pio = str + 11;
+               return NULL;
+       } else if (!strncmp(str, "assign-mmio=", 12)) {
+               pci_assign_mmio = str + 12;
+               return NULL;
        }
        return str;
 }
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 8729bde..ea82a5b 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -169,10 +169,12 @@ static void __init pcibios_allocate_resources(int pass)
                                        (unsigned long long) r->start,
                                        (unsigned long long) r->end,
                                        r->flags, enabled, pass);
-                       pr = pci_find_parent_resource(dev, r);
-                       if (pr && !request_resource(pr, r))
-                               continue;
-                       dev_err(&dev->dev, "BAR %d: can't allocate resource\n", 
idx);
+                       if (!pcibios_resource_needs_fixup(dev, idx)) {
+                               pr = pci_find_parent_resource(dev, r);
+                               if (pr && !request_resource(pr, r))
+                                       continue;
+                               dev_err(&dev->dev, "BAR %d: can't allocate 
resource\n", idx);
+                       }
                        /* We'll assign a new address later */
                        r->end -= r->start;
                        r->start = 0;
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 15b9cf6..f22737d 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -117,6 +117,9 @@ extern int __init pcibios_init(void);
 extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
 
+/* pci-common.c */
+extern int pcibios_resource_needs_fixup(struct pci_dev *dev, int resno);
+
 /*
  * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
  * on their northbrige except through the * %eax register. As such, you MUST
-- 
1.5.6.4

_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/virtualization

Reply via email to