[PATCH 8/16 v6] PCI: add boot options to reassign resources

From: Yu Zhao
Date: Wed Oct 22 2008 - 05:40:05 EST


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 <achiang@xxxxxx>
Cc: Grant Grundler <grundler@xxxxxxxxxxxxxxxx>
Cc: Greg KH <greg@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxx>
Cc: Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx>
Cc: Matthew Wilcox <matthew@xxxxxx>
Cc: Randy Dunlap <randy.dunlap@xxxxxxxxxx>
Cc: Roland Dreier <rdreier@xxxxxxxxx>
Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>

---
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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/