2012-02-29 23:08:55

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 00/39] PCI: pci_host_bridge related cleanup and busn_alloc

The first 14 patches are hostbridge clean up.
will add struct device dev into host_bridge struct.
also will add release support to make sure allocated resource get
freed during root bus removal including hostbridge and pci_sysdata.

others 25 patches are busn_alloc related.
Set up iobusn_resource tree, and register bus number range to it.
Later when need to find bus range, will try to allocate from the tree
Need to test on arches other than x86. esp for ia64 and powerpc that support
more than on peer root buses.

The patches need to apply to pci/for-linus and pci/linux-next
because one patch that is needed only is only in pci/for-linus

could get from
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-next

please put them into pci/linux-next branch for more testing.

Thanks

Yinghai

Yinghai Lu (39):
PCI: Separate host_bridge code out from probe.c
x86, PCI: have own version for pcibios_bus_to_resource
x86, PCI: Fix memleak with get_current_resources
PCI: rename pci_host_bridge() to find_pci_root_bridge()
PCI: add generic device into pci_host_bridge struct
PCI: add host bridge release support
x86, PCI: break down get_current_resource()
x86, PCI: add host bridge resource release for using _CRS
x86, PCI: embed name acpi version pci_root_info struct
x86, PCI: embed pci_sysdata into pci_root_info on acpi path
x86, PCI: Allocating pci_root_info for not using _CRS path
x86, PCI: Merge root info printing for nocrs path
x86, PCI: add print all root info for nocrs path
x86, PCI: allocate temp range array in amd_bus pci_root_info probing
x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node
PCI: skip busn resource at first.
x86, PCI: put busn resource in pci_root_info for acpi path
PCI: default busn_resource
x86, PCI: put busn resource in pci_root_info for no_crs path
PCI: Add busn_res into struct pci_bus.
PCI: Add busn_res operation functions
PCI: release busn when removing bus
PCI: insert busn_res in pci_create_root_bus
PCI: checking busn_res in pci_scan_root_bus
PCI: add default res for pci_scan_bus
PCI, ia64: Register busn_res for root buses
PCI, sparc: Register busn_res for root buses
PCI, powerpc: Register busn_res for root buses
PCI, parisc: Register busn_res for root buses
PCI: Add pci_bus_extend/shrink_top()
PCI: Probe safe range that we can use for unassigned bridge.
PCI: Strict checking of valid range for bridge
PCI: Allocate bus range instead of use max blindly
PCI: kill pci_fixup_parent_subordinate_busnr()
PCI: Seperate child bus scanning to two passes overall
pcmcia: remove workaround for fixing pci parent bus subordinate
PCI: Double checking setting for bus register and bus struct.
PCI, pciehp: Remove not needed bus number range checking
x86, PCI: kill busn in acpi pci_root_info

arch/ia64/pci/pci.c | 2 +
arch/powerpc/include/asm/pci-bridge.h | 1 +
arch/powerpc/kernel/pci-common.c | 10 +-
arch/sparc/kernel/pci.c | 4 +
arch/sparc/kernel/pci_impl.h | 1 +
arch/x86/pci/acpi.c | 121 ++++---
arch/x86/pci/amd_bus.c | 88 ++----
arch/x86/pci/broadcom_bus.c | 17 +-
arch/x86/pci/bus_numa.c | 100 +++++--
arch/x86/pci/bus_numa.h | 23 +-
arch/x86/pci/common.c | 27 +--
arch/x86/pci/i386.c | 14 +
drivers/parisc/dino.c | 5 +
drivers/parisc/lba_pci.c | 3 +
drivers/pci/Makefile | 2 +-
drivers/pci/host-bridge.c | 97 ++++++
drivers/pci/hotplug/pciehp_pci.c | 12 +-
drivers/pci/probe.c | 601 ++++++++++++++++++++++-----------
drivers/pci/remove.c | 1 +
drivers/pcmcia/yenta_socket.c | 75 ----
include/linux/pci.h | 15 +-
21 files changed, 767 insertions(+), 452 deletions(-)
create mode 100644 drivers/pci/host-bridge.c

--
1.7.7


2012-02-29 23:08:20

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 07/39] x86, PCI: break down get_current_resource()

change it to probe_pci_root_info, aka only do one thing.

1. remove resource list head from pci_root_info
2. make get_current_resources() not pass resources
move out add_resources calling out of yet.
3. rename get_current_resourcs name to probe_pci_root_info

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 34 +++++++++++++---------------------
1 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 304ccf0..763f7bb 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,6 @@ struct pci_root_info {
char *name;
unsigned int res_num;
struct resource *res;
- struct list_head *resources;
int busnum;
};

@@ -277,7 +276,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
}
}

-static void add_resources(struct pci_root_info *info)
+static void add_resources(struct pci_root_info *info,
+ struct list_head *resources)
{
int i;
struct resource *res, *root, *conflict;
@@ -301,7 +301,7 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
else
- pci_add_resource(info->resources, res);
+ pci_add_resource(resources, res);
}
}

@@ -313,41 +313,30 @@ static void free_pci_root_info(struct pci_root_info *info)
}

static void
-get_current_resources(struct pci_root_info *info,
- struct acpi_device *device, int busnum,
- int domain, struct list_head *resources)
+probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
+ int busnum, int domain)
{
size_t size;

info->bridge = device;
info->res_num = 0;
- info->resources = resources;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
info);
if (!info->res_num)
return;

size = sizeof(*info->res) * info->res_num;
+ info->res_num = 0;
info->res = kmalloc(size, GFP_KERNEL);
if (!info->res)
return;

info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
if (!info->name)
- goto name_alloc_fail;
+ return;

- info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
-
- if (pci_use_crs) {
- add_resources(info);
-
- return;
- }
-
-name_alloc_fail:
- free_pci_root_info(info);
}

struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
@@ -412,15 +401,18 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else {
- get_current_resources(&info, device, busnum, domain,
- &resources);
+ probe_pci_root_info(&info, device, busnum, domain);

/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
- if (!pci_use_crs)
+ if (pci_use_crs)
+ add_resources(&info, &resources);
+ else {
+ free_pci_root_info(&info);
x86_pci_root_bus_resources(busnum, &resources);
+ }
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
--
1.7.7

2012-02-29 23:08:58

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 09/39] x86, PCI: embed name acpi version pci_root_info struct

Now We allocate info, and keep that in during whole life of hostbridge.

So don't allocate info->name seperately, just put name into struct.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index c7a230f..11c3ae7 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -9,7 +9,7 @@

struct pci_root_info {
struct acpi_device *bridge;
- char *name;
+ char name[16];
unsigned int res_num;
struct resource *res;
int busnum;
@@ -307,7 +307,6 @@ static void add_resources(struct pci_root_info *info,

static void free_pci_root_info_res(struct pci_root_info *info)
{
- kfree(info->name);
kfree(info->res);
info->res = NULL;
info->res_num = 0;
@@ -360,9 +359,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
if (!info->res)
return;

- info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
- if (!info->name)
- return;
+ sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);

acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
--
1.7.7

2012-02-29 23:09:21

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 21/39] PCI: Add busn_res operation functions

will use them insert/update busn res in pci_bus

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 3 +++
2 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a4a20d6..5efcf1a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1687,6 +1687,56 @@ err_out:
return NULL;
}

+void pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
+{
+ struct resource *res = &b->busn_res;
+ struct resource *parent_res;
+ int ret;
+
+ res->start = bus;
+ res->end = bus_max;
+ res->flags = IORESOURCE_BUS;
+
+ /* no parent for root bus' busn_res */
+ if (!pci_is_root_bus(b)) {
+ parent_res = &b->parent->busn_res;
+
+ ret = insert_resource(parent_res, res);
+
+ dev_printk(KERN_DEBUG, &b->dev,
+ "busn_res: %pR %s inserted under %pR\n",
+ res, ret ? "can not be" : "is", parent_res);
+ } else
+ dev_printk(KERN_DEBUG, &b->dev,
+ "busn_res: %pR for root bus\n",
+ res);
+}
+
+void pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
+{
+ struct resource *res = &b->busn_res;
+ struct resource old_res = *res;
+
+ res->end = bus_max;
+ dev_printk(KERN_DEBUG, &b->dev,
+ "busn_res: %pR end updated to %pR\n",
+ &old_res, res);
+}
+
+void pci_bus_release_busn_res(struct pci_bus *b)
+{
+ struct resource *res = &b->busn_res;
+ int ret;
+
+ if (!res->flags)
+ return;
+
+ ret = release_resource(res);
+ dev_printk(KERN_DEBUG, &b->dev,
+ "busn_res: %pR %s released\n",
+ res, ret ? "can not be" : "is");
+}
+
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 84eedff..40606c1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -671,6 +671,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
+void pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
+void pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
+void pci_bus_release_busn_res(struct pci_bus *b);
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
--
1.7.7

2012-02-29 23:09:44

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 28/39] PCI, powerpc: Register busn_res for root buses

Signed-off-by: Yinghai Lu <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: [email protected]
---
arch/powerpc/include/asm/pci-bridge.h | 1 +
arch/powerpc/kernel/pci-common.c | 10 +++++++++-
2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 5d48765..11cebf0 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -30,6 +30,7 @@ struct pci_controller {
int first_busno;
int last_busno;
int self_busno;
+ struct resource busn;

void __iomem *io_base_virt;
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 910b9de..ee8c0c9 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1648,6 +1648,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
/* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose, &resources);

+ hose->busn.start = hose->first_busno;
+ hose->busn.end = hose->last_busno;
+ hose->busn.flags = IORESOURCE_BUS;
+ pci_add_resource(&resources, &hose->busn);
+
/* Create an empty bus for the toplevel */
bus = pci_create_root_bus(hose->parent, hose->first_busno,
hose->ops, hose, &resources);
@@ -1670,8 +1675,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
of_scan_bus(node, bus);
}

- if (mode == PCI_PROBE_NORMAL)
+ if (mode == PCI_PROBE_NORMAL) {
+ pci_bus_update_busn_res_end(bus, 255);
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+ pci_bus_update_busn_res_end(bus, bus->subordinate);
+ }

/* Platform gets a chance to do some global fixups before
* we proceed to resource allocation
--
1.7.7

2012-02-29 23:09:41

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 26/39] PCI, ia64: Register busn_res for root buses

-v2: according to Bjorn, use root->secondary directly.

Signed-off-by: Yinghai Lu <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: [email protected]
---
arch/ia64/pci/pci.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index d1ce320..6c7c4ae 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -352,6 +352,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
#endif

INIT_LIST_HEAD(&info.resources);
+ /* insert busn resource at first */
+ pci_add_resource(&info.resources, &root->secondary);
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
&windows);
if (windows) {
--
1.7.7

2012-02-29 23:10:09

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 06/39] PCI: add host bridge release support

We need one hook to release host bridge resource that are created for host
bridge.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/host-bridge.c | 8 ++++++++
drivers/pci/probe.c | 3 ++-
include/linux/pci.h | 5 +++++
3 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 03d8db1..a710a60 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -27,6 +27,14 @@ static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
return to_pci_host_bridge(bus->bridge);
}

+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data)
+{
+ bridge->release_fn = release_fn;
+ bridge->release_data = release_data;
+}
+
static bool resource_contains(struct resource *res1, struct resource *res2)
{
return res1->start <= res2->start && res1->end >= res2->end;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fb3dd4b..675d7ed 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1136,7 +1136,8 @@ static void pci_release_bus_bridge_dev(struct device *dev)
{
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);

- /* TODO: need to free window->res */
+ if (bridge->release_fn)
+ bridge->release_fn(bridge);

pci_free_resource_list(&bridge->windows);

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 310610e..d93d3ae 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -378,9 +378,14 @@ struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* pci_host_bridge_windows */
+ void (*release_fn)(struct pci_host_bridge *);
+ void *release_data;
};

#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data);

/*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
--
1.7.7

2012-02-29 23:10:29

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 32/39] PCI: Strict checking of valid range for bridge

children bridges busn range should be able to be allocated from parent bus range.

to avoid overlapping between sibling bridges on same bus.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c540022..5c031f0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -801,6 +801,30 @@ reduce_needed_size:
return ret;
}

+static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
+ struct pci_dev *dev,
+ int secondary, int subordinate)
+{
+ int broken = 0;
+
+ struct resource busn_res;
+ int ret;
+
+ memset(&busn_res, 0, sizeof(struct resource));
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "check if busn %02x-%02x is in busn_res: %pR\n",
+ secondary, subordinate, &bus->busn_res);
+ ret = allocate_resource(&bus->busn_res, &busn_res,
+ (subordinate - secondary + 1),
+ secondary, subordinate,
+ 1, NULL, NULL);
+ if (ret)
+ broken = 1;
+ else
+ release_resource(&busn_res);
+
+ return broken;
+}
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
--
1.7.7

2012-02-29 23:10:56

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 20/39] PCI: Add busn_res into struct pci_bus.

will use it to have bus number resource tree.

Signed-off-by: Yinghai Lu <[email protected]>
Cc: Andrew Morton <[email protected]>
---
include/linux/pci.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index c40fc04..84eedff 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -421,6 +421,7 @@ struct pci_bus {
struct list_head slots; /* list of slots on this bus */
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources; /* address space routed to this bus */
+ struct resource busn_res; /* track registered bus num range */

struct pci_ops *ops; /* configuration access functions */
void *sysdata; /* hook for sys-specific extension */
--
1.7.7

2012-02-29 23:09:39

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 33/39] PCI: Allocate bus range instead of use max blindly

every bus have extra busn_res, and linked them toghter to iobusn_resource.

when need to find usable bus number range, try probe from iobusn_resource tree.

To avoid falling to small hole in the middle, we try from 8 spare bus.
if can not find 8 or more in the middle, will try to append 8 on top later.
then if can not append, will try to find 7 from the middle, then will try to append 7 on top.
then if can not append, will try to find 6 from the middle...

for cardbus will only find 4 spare.

if extend from top, at last will shrink back to really needed range...

-v4: fix checking with pci rescan. Found by Bjorn.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 100 ++++++++++++++++++++++++++++++---------------------
1 files changed, 59 insertions(+), 41 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5c031f0..f22a209 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -839,10 +839,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- u32 buses, i, j = 0;
+ u32 buses;
u16 bctl;
u8 primary, secondary, subordinate;
int broken = 0;
+ struct resource *parent_res = NULL;

pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
primary = buses & 0xFF;
@@ -859,10 +860,16 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,

/* Check if setup is sensible at all */
if (!pass &&
- (primary != bus->number || secondary <= bus->number)) {
- dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
+ (primary != bus->number || secondary <= bus->number))
broken = 1;
- }
+
+ /* more strict checking */
+ if (!pass && !broken && !dev->subordinate)
+ broken = pci_bridge_check_busn_broken(bus, dev,
+ secondary, subordinate);
+
+ if (broken)
+ dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");

/* Disable MasterAbortMode during probing to avoid reporting
of bus errors (in some architectures) */
@@ -895,6 +902,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
child->primary = primary;
child->subordinate = subordinate;
child->bridge_ctl = bctl;
+
+ pci_bus_insert_busn_res(child, secondary, subordinate);
}

cmax = pci_scan_child_bus(child);
@@ -907,6 +916,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
* We need to assign a number to this bus which we always
* do in the second pass.
*/
+ long shrink_size;
+ struct resource busn_res;
+ int ret = -ENOMEM;
+ int old_max = max;
+
if (!pass) {
if (pcibios_assign_all_busses() || broken)
/* Temporarily disable forwarding of the
@@ -923,20 +937,43 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);

- /* Prevent assigning a bus number that already exists.
- * This can happen when a bridge is hot-plugged, so in
- * this case we only re-scan this bus. */
- child = pci_find_bus(pci_domain_nr(bus), max+1);
- if (!child) {
- child = pci_add_new_bus(bus, dev, ++max);
- if (!child)
- goto out;
+ if (dev->subordinate) {
+ /* We get here only for cardbus */
+ child = dev->subordinate;
+ if (!is_cardbus)
+ dev_warn(&dev->dev,
+ "rescan scaned bridge as broken one again ?");
+
+ goto out;
}
+ /*
+ * For CardBus bridges, we leave 4 bus numbers
+ * as cards with a PCI-to-PCI bridge can be
+ * inserted later.
+ * other just allocate 8 bus to avoid we fall into
+ * small hole in the middle.
+ */
+ ret = pci_bridge_probe_busn_res(bus, dev, &busn_res,
+ is_cardbus ? (CARDBUS_RESERVE_BUSNR + 1) : 8,
+ &parent_res);
+
+ if (ret != 0)
+ goto out;
+
+ child = pci_add_new_bus(bus, dev, busn_res.start);
+ if (!child)
+ goto out;
+
+ child->subordinate = busn_res.end;
+ pci_bus_insert_busn_res(child, busn_res.start, busn_res.end);
+
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8)
| ((unsigned int)(child->subordinate) << 16);

+ max = child->subordinate;
+
/*
* yenta.c forces a secondary latency timer of 176.
* Copy that behaviour here.
@@ -967,43 +1004,24 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
* the real value of max.
*/
pci_fixup_parent_subordinate_busnr(child, max);
+
} else {
- /*
- * For CardBus bridges, we leave 4 bus numbers
- * as cards with a PCI-to-PCI bridge can be
- * inserted later.
- */
- for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) {
- struct pci_bus *parent = bus;
- if (pci_find_bus(pci_domain_nr(bus),
- max+i+1))
- break;
- while (parent->parent) {
- if ((!pcibios_assign_all_busses()) &&
- (parent->subordinate > max) &&
- (parent->subordinate <= max+i)) {
- j = 1;
- }
- parent = parent->parent;
- }
- if (j) {
- /*
- * Often, there are two cardbus bridges
- * -- try to leave one valid bus number
- * for each one.
- */
- i /= 2;
- break;
- }
- }
- max += i;
pci_fixup_parent_subordinate_busnr(child, max);
}
/*
* Set the subordinate bus number to its real value.
*/
+ shrink_size = child->subordinate - max;
child->subordinate = max;
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+ pci_bus_update_busn_res_end(child, max);
+
+ /* shrink some back, if we extend top before */
+ if (!is_cardbus && (shrink_size > 0) && parent_res)
+ pci_bus_shrink_top(bus, shrink_size, parent_res);
+
+ if (old_max > max)
+ max = old_max;
}

sprintf(child->name,
--
1.7.7

2012-02-29 23:09:37

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 25/39] PCI: add default res for pci_scan_bus

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1149109..1c07aba 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1784,6 +1784,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,

pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
+ pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b)
b->subordinate = pci_scan_child_bus(b);
@@ -1801,6 +1802,7 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,

pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
+ pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) {
b->subordinate = pci_scan_child_bus(b);
--
1.7.7

2012-02-29 23:11:32

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 35/39] PCI: Seperate child bus scanning to two passes overall

In extreme case: Two bridges are properly setup.
bridge A
bridge AA
bridge AB
bridge B
bridge BA
bridge BB
but AA, AB are not setup properly.
bridge A has small range, and bridge AB could need more, when do the
first pass0 for bridge A, it will do pass0 and pass1 for AA and AB,
during that process, it will extend range of A for AB blindly.
because bridge B is not registered yet.
that could overlap range that is used by bridge B.

Right way should be:
do pass0 for all good bridges at first.
So we could do pass0 for bridge B before pass1 for bridge AB.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 50 ++++++++++++++++++++++++++++++++++----------------
1 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ba51902..4a38ef4 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -809,6 +809,9 @@ static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,

return broken;
}
+
+static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
+ int pass);
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
@@ -865,11 +868,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
!is_cardbus && !broken) {
unsigned int cmax;
/*
- * Bus already configured by firmware, process it in the first
- * pass and just note the configuration.
+ * Bus already configured by firmware, still process it in two
+ * passes in extreme case like two adjaced bridges have children
+ * bridges that are not setup properly.
*/
- if (pass)
- goto out;

/*
* If we already got to this bus through a different bridge,
@@ -890,7 +892,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
pci_bus_insert_busn_res(child, secondary, subordinate);
}

- cmax = pci_scan_child_bus(child);
+ cmax = __pci_scan_child_bus(child, pass);
if (cmax > max)
max = cmax;
if (child->subordinate > max)
@@ -1704,12 +1706,13 @@ void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
}
EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);

-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
+ int pass)
{
- unsigned int devfn, pass, max = bus->secondary;
+ unsigned int devfn, max = bus->secondary;
struct pci_dev *dev;

- dev_dbg(&bus->dev, "scanning bus\n");
+ dev_dbg(&bus->dev, "scanning bus pass %d\n", pass);

/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8)
@@ -1723,18 +1726,16 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
* all PCI-to-PCI bridges on this bus.
*/
if (!bus->is_added) {
- dev_dbg(&bus->dev, "fixups for bus\n");
+ dev_dbg(&bus->dev, "fixups for bus pass %d\n", pass);
pcibios_fixup_bus(bus);
if (pci_is_root_bus(bus))
bus->is_added = 1;
}

- for (pass=0; pass < 2; pass++)
- list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
- max = pci_scan_bridge(bus, dev, max, pass);
- }
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ max = pci_scan_bridge(bus, dev, max, pass);

/*
* We've scanned the bus and so we know all about what's on
@@ -1743,7 +1744,24 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
*
* Return how far we've got finding sub-buses.
*/
- dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
+ dev_dbg(&bus->dev, "bus scan returning with max=%02x pass %d\n",
+ max, pass);
+
+ return max;
+}
+
+unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+{
+ int pass;
+ unsigned int max = 0, tmp;
+
+ for (pass = 0; pass < 2; pass++) {
+ tmp = __pci_scan_child_bus(bus, pass);
+
+ if (tmp > max)
+ max = tmp;
+ }
+
return max;
}

--
1.7.7

2012-02-29 23:11:53

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 15/39] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node

Those two almost the same.
Let pcibios_scan_root call pci_scan_bus_on_node instead.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/common.c | 27 ++++-----------------------
1 files changed, 4 insertions(+), 23 deletions(-)

diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 323481e..8e04ec5 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -430,9 +430,7 @@ void __init dmi_check_pciprobe(void)

struct pci_bus * __devinit pcibios_scan_root(int busnum)
{
- LIST_HEAD(resources);
struct pci_bus *bus = NULL;
- struct pci_sysdata *sd;

while ((bus = pci_find_next_bus(bus)) != NULL) {
if (bus->number == busnum) {
@@ -441,28 +439,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
}
}

- /* Allocate per-root-bus (not per bus) arch-specific data.
- * TODO: leak; this memory is never freed.
- * It's arguable whether it's worth the trouble to care.
- */
- sd = kzalloc(sizeof(*sd), GFP_KERNEL);
- if (!sd) {
- printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
- return NULL;
- }
-
- sd->node = get_mp_bus_to_node(busnum);
-
- printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
- x86_pci_root_bus_resources(busnum, &resources);
- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
- if (!bus) {
- pci_free_resource_list(&resources);
- kfree(sd);
- }
-
- return bus;
+ return pci_scan_bus_on_node(busnum, &pci_root_ops,
+ get_mp_bus_to_node(busnum));
}
+
void __init pcibios_set_cache_line_size(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -656,6 +636,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
}
sd->node = node;
x86_pci_root_bus_resources(busno, &resources);
+ printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
--
1.7.7

2012-02-29 23:11:56

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

Bjorn thought that we should just use that in acpi_root.

Suggested-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 19 ++++++-------------
1 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index ff5243e..5178917 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,6 @@ struct pci_root_info {
char name[16];
unsigned int res_num;
struct resource *res;
- struct resource busn;
struct pci_sysdata sd;
};

@@ -283,9 +282,6 @@ static void add_resources(struct pci_root_info *info,
int i;
struct resource *res, *root, *conflict;

- if (info->busn.flags & IORESOURCE_BUS)
- pci_add_resource(resources, &info->busn);
-
coalesce_windows(info, IORESOURCE_MEM);
coalesce_windows(info, IORESOURCE_IO);

@@ -346,16 +342,12 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)

static void
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
- int busnum, int busmax, int domain)
+ int busnum, int domain)
{
size_t size;

sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
info->bridge = device;
- info->busn.name = info->name;
- info->busn.start = busnum;
- info->busn.end = busmax;
- info->busn.flags = IORESOURCE_BUS;

info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
@@ -379,7 +371,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
- int busmax = root->secondary.end;
LIST_HEAD(resources);
struct pci_bus *bus;
struct pci_sysdata *sd;
@@ -432,15 +423,17 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(info);
} else {
- probe_pci_root_info(info, device, busnum, busmax, domain);
+ probe_pci_root_info(info, device, busnum, domain);

/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
- if (pci_use_crs)
+ if (pci_use_crs) {
+ /* insert busn res at first */
+ pci_add_resource(&resources, &root->secondary);
add_resources(info, &resources);
- else {
+ } else {
free_pci_root_info_res(info);
x86_pci_root_bus_resources(busnum, &resources);
}
--
1.7.7

2012-02-29 23:09:35

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 31/39] PCI: Probe safe range that we can use for unassigned bridge.

Try to allocate from parent bus busn_res. if can not find any big enough, will try
to extend parent bus top. even the extending is through allocating, after allocating
will pad the range to parent buses top.

When extending happens, We will record the parent_res, so could use it as stopper
for really extend/shrink top later.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 96259f8..c540022 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -691,6 +691,116 @@ static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
pci_bus_update_top(parent, -size, parent_res);
}

+static resource_size_t __devinit find_res_top_free_size(struct resource *res)
+{
+ resource_size_t n_size;
+ struct resource tmp_res;
+
+ /*
+ * find out number below res->end, that we can use at first
+ * res->start can not be used.
+ */
+ n_size = resource_size(res) - 1;
+ memset(&tmp_res, 0, sizeof(struct resource));
+ while (n_size > 0) {
+ int ret;
+
+ ret = allocate_resource(res, &tmp_res, n_size,
+ res->end - n_size + 1, res->end,
+ 1, NULL, NULL);
+ if (ret == 0) {
+ release_resource(&tmp_res);
+ break;
+ }
+ n_size--;
+ }
+
+ return n_size;
+}
+
+static int __devinit pci_bridge_probe_busn_res(struct pci_bus *bus,
+ struct pci_dev *dev, struct resource *busn_res,
+ resource_size_t needed_size, struct resource **p)
+{
+ int ret = -ENOMEM;
+ resource_size_t n_size;
+ struct pci_bus *parent;
+ struct resource *parent_res = NULL;
+ resource_size_t tmp = bus->busn_res.end + 1;
+ int free_sz = -1;
+
+again:
+ /*
+ * find bigest range in bus->busn_res that we can use in the middle
+ * and we can not use bus->busn_res.start.
+ */
+ n_size = resource_size(&bus->busn_res) - 1;
+ memset(busn_res, 0, sizeof(struct resource));
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "find free busn in busn_res: %pR\n", &bus->busn_res);
+ while (n_size >= needed_size) {
+ ret = allocate_resource(&bus->busn_res, busn_res, n_size,
+ bus->busn_res.start + 1, bus->busn_res.end,
+ 1, NULL, NULL);
+ if (ret == 0) {
+ /* found one, prepare to return */
+ release_resource(busn_res);
+
+ return ret;
+ }
+ n_size--;
+ }
+
+ /* try extend the top of parent bus, find free under top af first */
+ if (free_sz < 0) {
+ free_sz = find_res_top_free_size(&bus->busn_res);
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "found free busn %d in busn_res: %pR top\n",
+ free_sz, &bus->busn_res);
+ }
+ n_size = free_sz;
+
+ /* can not extend cross domain boundary */
+ if ((0xff - bus->busn_res.end) < (needed_size - n_size))
+ goto reduce_needed_size;
+
+ /* find exteded range */
+ memset(busn_res, 0, sizeof(struct resource));
+ parent = bus->parent;
+ while (parent) {
+ ret = allocate_resource(&parent->busn_res, busn_res,
+ needed_size - n_size,
+ tmp, tmp + needed_size - n_size - 1,
+ 1, NULL, NULL);
+ if (ret == 0)
+ break;
+ parent = parent->parent;
+ }
+
+reduce_needed_size:
+ if (ret != 0) {
+ needed_size--;
+ if (!needed_size)
+ return ret;
+
+ goto again;
+ }
+
+ /* save parent_res, we need it as stopper later */
+ parent_res = busn_res->parent;
+
+ /* prepare busn_res for return */
+ release_resource(busn_res);
+ busn_res->start -= n_size;
+
+ /* extend parent bus top*/
+ pci_bus_extend_top(bus, needed_size - n_size, parent_res);
+
+ *p = parent_res;
+
+ return ret;
+}
+
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
--
1.7.7

2012-02-29 23:12:54

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 14/39] x86, PCI: allocate temp range array in amd_bus pci_root_info probing

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/amd_bus.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 5f30a98..aff155d 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -30,7 +30,7 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
};

-#define RANGE_NUM 16
+#define RANGE_NUM 128

static struct pci_root_info __init *find_pci_root_info(int node, int link)
{
@@ -64,7 +64,7 @@ static int __init early_fill_mp_bus_info(void)
u32 reg;
u64 start;
u64 end;
- struct range range[RANGE_NUM];
+ struct range *range;
u64 val;
u32 address;
bool found;
@@ -125,7 +125,10 @@ static int __init early_fill_mp_bus_info(void)
reg = read_pci_config(bus, slot, 0, 0x64);
def_link = (reg >> 8) & 0x03;

- memset(range, 0, sizeof(range));
+ range = kcalloc(RANGE_NUM, sizeof(struct range), GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+
add_range(range, RANGE_NUM, 0, 0, 0xffff + 1);
/* io port resource */
for (i = 0; i < 4; i++) {
@@ -291,6 +294,8 @@ static int __init early_fill_mp_bus_info(void)
}
}

+ kfree(range);
+
print_all_pci_root_info("ht link", true);

return 0;
--
1.7.7

2012-02-29 23:09:34

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 34/39] PCI: kill pci_fixup_parent_subordinate_busnr()

Now we can safely extend parent top and shrink them according iobusn_resource tree.

Don't need that any more.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 32 --------------------------------
1 files changed, 0 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f22a209..ba51902 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -639,22 +639,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
return child;
}

-static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
-{
- struct pci_bus *parent = child->parent;
-
- /* Attempts to fix that up are really dangerous unless
- we're going to re-assign all bus numbers. */
- if (!pcibios_assign_all_busses())
- return;
-
- while (parent->parent && parent->subordinate < max) {
- parent->subordinate = max;
- pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
- parent = parent->parent;
- }
-}
-
static void __devinit pci_bus_update_top(struct pci_bus *parent,
long size, struct resource *parent_res)
{
@@ -990,23 +974,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,

if (!is_cardbus) {
child->bridge_ctl = bctl;
- /*
- * Adjust subordinate busnr in parent buses.
- * We do this before scanning for children because
- * some devices may not be detected if the bios
- * was lazy.
- */
- pci_fixup_parent_subordinate_busnr(child, max);
- /* Now we can scan all subordinate buses... */
max = pci_scan_child_bus(child);
- /*
- * now fix it up again since we have found
- * the real value of max.
- */
- pci_fixup_parent_subordinate_busnr(child, max);
-
- } else {
- pci_fixup_parent_subordinate_busnr(child, max);
}
/*
* Set the subordinate bus number to its real value.
--
1.7.7

2012-02-29 23:09:31

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 23/39] PCI: insert busn_res in pci_create_root_bus

that busn_res is from resources list

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5efcf1a..e32f1b7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1655,10 +1655,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
list_for_each_entry_safe(window, n, resources, list) {
list_move_tail(&window->list, &bridge->windows);
res = window->res;
- if (res->flags & IORESOURCE_BUS)
- continue;
offset = window->offset;
- pci_bus_add_resource(b, res, 0);
+ if (res->flags & IORESOURCE_BUS)
+ pci_bus_insert_busn_res(b, res->start, res->end);
+ else
+ pci_bus_add_resource(b, res, 0);
if (offset) {
if (resource_type(res) == IORESOURCE_IO)
fmt = " (bus address [%#06llx-%#06llx])";
--
1.7.7

2012-02-29 23:09:30

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 27/39] PCI, sparc: Register busn_res for root buses

Signed-off-by: Yinghai Lu <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: [email protected]
---
arch/sparc/kernel/pci.c | 4 ++++
arch/sparc/kernel/pci_impl.h | 1 +
2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 253e8ac..1687fed 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -695,6 +695,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
pbm->io_space.start);
pci_add_resource_offset(&resources, &pbm->mem_space,
pbm->mem_space.start);
+ pbm->busn.start = pbm->pci_first_busno;
+ pbm->busn.end = pbm->pci_last_busn;
+ pbm->busn.flags = IORESOURCE_BUS;
+ pci_add_resource(&resources, &pbm->busn);
bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
pbm, &resources);
if (!bus) {
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 6beb60d..918a203 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -97,6 +97,7 @@ struct pci_pbm_info {
/* PBM I/O and Memory space resources. */
struct resource io_space;
struct resource mem_space;
+ struct resource busn;

/* Base of PCI Config space, can be per-PBM or shared. */
unsigned long config_space;
--
1.7.7

2012-02-29 23:09:29

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 16/39] PCI: skip busn resource at first.

busn_alloc code is not there yet. so need to skip it.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 675d7ed..3bdc421 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1648,6 +1648,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
list_for_each_entry_safe(window, n, resources, list) {
list_move_tail(&window->list, &bridge->windows);
res = window->res;
+ if (res->flags & IORESOURCE_BUS)
+ continue;
offset = window->offset;
pci_bus_add_resource(b, res, 0);
if (offset) {
--
1.7.7

2012-02-29 23:14:05

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 37/39] PCI: Double checking setting for bus register and bus struct.

User could use setpci change bridge's bus register. that could make value of register
and struct is out of sync.
User later will use rescan to see the devices is moving.

In the rescaning, we need to double check the range and remove the old struct at first.

to make thing working user may need have script to remove children devices under bridge
at first, and then use setpci update bus register and then rescan.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 4a38ef4..67071b0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -850,6 +850,46 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
(primary != bus->number || secondary <= bus->number))
broken = 1;

+ if (!pass && dev->subordinate) {
+ child = dev->subordinate;
+ /*
+ * User could change bus register in bridge manually with
+ * setpci and rescan. So double check the setting, and remove
+ * old structs. Don't set broken yet, let following check
+ * to see if the new setting good.
+ */
+ if (primary != child->primary ||
+ secondary != child->secondary ||
+ subordinate != child->subordinate) {
+ dev_info(&dev->dev,
+ "someone changed bus register from pri:%02x, sec:%02x, sub:%02x to pri:%02x, sec:%02x, sub:%02x\n",
+ child->primary, child->secondary, child->subordinate,
+ primary, secondary, subordinate);
+ if (!list_empty(&dev->subordinate->devices)) {
+ u32 old_buses;
+
+ dev_info(&dev->dev,
+ "but children devices are not removed manually before that.\n");
+ /*
+ * Try best to remove left children devices
+ * but we need to set bus register back, otherwise
+ * We can not access children device and stop them
+ */
+ old_buses = (buses & 0xff000000)
+ | ((unsigned int)(child->primary) << 0)
+ | ((unsigned int)(child->secondary) << 8)
+ | ((unsigned int)(child->subordinate) << 16);
+ pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+ old_buses);
+ pci_stop_and_remove_behind_bridge(dev);
+ pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+ buses);
+ }
+ pci_remove_bus(dev->subordinate);
+ dev->subordinate = NULL;
+ }
+ }
+
/* more strict checking */
if (!pass && !broken && !dev->subordinate)
broken = pci_bridge_check_busn_broken(bus, dev,
--
1.7.7

2012-02-29 23:09:27

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 12/39] x86, PCI: Merge root info printing for nocrs path

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/amd_bus.c | 12 +-----------
arch/x86/pci/broadcom_bus.c | 9 +--------
arch/x86/pci/bus_numa.c | 17 +++++++++++++++++
arch/x86/pci/bus_numa.h | 1 +
4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 459a731..0b6abbe 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -291,17 +291,7 @@ static int __init early_fill_mp_bus_info(void)
}
}

- list_for_each_entry(info, &pci_root_infos, list) {
- int busnum;
- struct pci_root_res *root_res;
-
- busnum = info->bus_min;
- printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
- info->bus_min, info->bus_max, info->node, info->link);
- list_for_each_entry(root_res, &info->resources, list)
- printk(KERN_DEBUG "bus: %02x %pR\n",
- busnum, &root_res->res);
- }
+ print_pci_root_info(info, "bus:", true);

return 0;
}
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index 614392c..a03a14a 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -76,14 +76,7 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
update_res(info, res.start, res.end, res.flags, 0);
}

- /* print information about this host bridge */
- res.start = fbus;
- res.end = lbus;
- res.flags = IORESOURCE_BUS;
- printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
-
- list_for_each_entry(root_res, &info->resources, list)
- printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
+ print_pci_root_info(info, "host bridge windows: ", false);
}

static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 306579f..7251011 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -77,6 +77,23 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
return info;
}

+void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink)
+{
+ struct pci_root_res *root_res;
+ int busnum = info->bus_min;
+
+ if (!nodelink)
+ printk(KERN_DEBUG "%s: [%02x, %02x]\n", name,
+ info->bus_min, info->bus_max);
+ else
+ printk(KERN_DEBUG "%s: [%02x, %02x] on node %x link %x\n", name,
+ info->bus_min, info->bus_max, info->node, info->link);
+
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_DEBUG "%s: %02x %pR\n", name, busnum,
+ &root_res->res);
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 226a466..d19ac93 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -22,6 +22,7 @@ struct pci_root_info {
extern struct list_head pci_root_infos;
struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
int node, int link);
+void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
--
1.7.7

2012-02-29 23:14:43

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 13/39] x86, PCI: add print all root info for nocrs path

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/amd_bus.c | 2 +-
arch/x86/pci/bus_numa.c | 8 ++++++++
arch/x86/pci/bus_numa.h | 1 +
3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0b6abbe..5f30a98 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -291,7 +291,7 @@ static int __init early_fill_mp_bus_info(void)
}
}

- print_pci_root_info(info, "bus:", true);
+ print_all_pci_root_info("ht link", true);

return 0;
}
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 7251011..772949f 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -94,6 +94,14 @@ void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink)
&root_res->res);
}

+void print_all_pci_root_info(char *name, bool nodelink)
+{
+ struct pci_root_info *info;
+
+ list_for_each_entry(info, &pci_root_infos, list)
+ print_pci_root_info(info, name, nodelink);
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index d19ac93..deada6a 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -23,6 +23,7 @@ extern struct list_head pci_root_infos;
struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
int node, int link);
void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink);
+void print_all_pci_root_info(char *name, bool nodelink);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
--
1.7.7

2012-02-29 23:14:41

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 17/39] x86, PCI: put busn resource in pci_root_info for acpi path

will put it in resources list and pass it for create_root_bus

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 2331ccb..ff5243e 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,7 @@ struct pci_root_info {
char name[16];
unsigned int res_num;
struct resource *res;
- int busnum;
+ struct resource busn;
struct pci_sysdata sd;
};

@@ -283,6 +283,9 @@ static void add_resources(struct pci_root_info *info,
int i;
struct resource *res, *root, *conflict;

+ if (info->busn.flags & IORESOURCE_BUS)
+ pci_add_resource(resources, &info->busn);
+
coalesce_windows(info, IORESOURCE_MEM);
coalesce_windows(info, IORESOURCE_IO);

@@ -343,11 +346,17 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)

static void
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
- int busnum, int domain)
+ int busnum, int busmax, int domain)
{
size_t size;

+ sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
info->bridge = device;
+ info->busn.name = info->name;
+ info->busn.start = busnum;
+ info->busn.end = busmax;
+ info->busn.flags = IORESOURCE_BUS;
+
info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
info);
@@ -360,8 +369,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
if (!info->res)
return;

- sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
-
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
}
@@ -372,6 +379,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
+ int busmax = root->secondary.end;
LIST_HEAD(resources);
struct pci_bus *bus;
struct pci_sysdata *sd;
@@ -424,7 +432,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(info);
} else {
- probe_pci_root_info(info, device, busnum, domain);
+ probe_pci_root_info(info, device, busnum, busmax, domain);

/*
* _CRS with no apertures is normal, so only fall back to
--
1.7.7

2012-02-29 23:09:24

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 24/39] PCI: checking busn_res in pci_scan_root_bus

some calling may not have end decided yet, and may not pass busn_res in
resources list.

try to do insert big one and shrink.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e32f1b7..1149109 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1742,12 +1742,34 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
struct pci_bus *b;
+ struct pci_host_bridge_window *window, *n;
+ struct resource *res;
+ bool found;
+
+ list_for_each_entry_safe(window, n, resources, list) {
+ res = window->res;
+ if (res->flags & IORESOURCE_BUS) {
+ found = true;
+ break;
+ }
+ }

b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
if (!b)
return NULL;

+ if (!found) {
+ dev_info(&b->dev,
+ "No busn resource found for root bus, will use [%02x, ff]\n",
+ bus);
+ pci_bus_insert_busn_res(b, bus, 255);
+ }
+
b->subordinate = pci_scan_child_bus(b);
+
+ if (!found)
+ pci_bus_update_busn_res_end(b, b->subordinate);
+
pci_bus_add_devices(b);
return b;
}
--
1.7.7

2012-02-29 23:09:22

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 22/39] PCI: release busn when removing bus

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/remove.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index fd77e2b..04a4861 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)

down_write(&pci_bus_sem);
list_del(&pci_bus->node);
+ pci_bus_release_busn_res(pci_bus);
up_write(&pci_bus_sem);
if (!pci_bus->is_added)
return;
--
1.7.7

2012-02-29 23:09:19

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 08/39] x86, PCI: add host bridge resource release for using _CRS

1. allocate pci_root_info instead of use local stack. we need to pass around info
for release fn.
2. add release_pci_root_info
3. set x86 own host bridge release fn, so will make sure root bridge
related resources get freed during root bus removal.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 63 +++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 763f7bb..c7a230f 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,11 +305,40 @@ static void add_resources(struct pci_root_info *info,
}
}

-static void free_pci_root_info(struct pci_root_info *info)
+static void free_pci_root_info_res(struct pci_root_info *info)
{
kfree(info->name);
kfree(info->res);
- memset(info, 0, sizeof(struct pci_root_info));
+ info->res = NULL;
+ info->res_num = 0;
+}
+
+static void __release_pci_root_info(struct pci_root_info *info)
+{
+ int i;
+ struct resource *res;
+
+ for (i = 0; i < info->res_num; i++) {
+ res = &info->res[i];
+
+ if (!res->parent)
+ continue;
+
+ if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ continue;
+
+ release_resource(res);
+ }
+
+ free_pci_root_info_res(info);
+
+ kfree(info);
+}
+static void release_pci_root_info(struct pci_host_bridge *bridge)
+{
+ struct pci_root_info *info = bridge->release_data;
+
+ __release_pci_root_info(info);
}

static void
@@ -342,7 +371,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
- struct pci_root_info info;
+ struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
@@ -387,7 +416,13 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)

sd->domain = domain;
sd->node = node;
- memset(&info, 0, sizeof(struct pci_root_info));
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ kfree(sd);
+ printk(KERN_WARNING "pci_bus %04x:%02x: "
+ "ignored (out of memory)\n", domain, busnum);
+ return NULL;
+ }
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -399,29 +434,33 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
+ kfree(info);
kfree(sd);
} else {
- probe_pci_root_info(&info, device, busnum, domain);
+ probe_pci_root_info(info, device, busnum, domain);

/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
if (pci_use_crs)
- add_resources(&info, &resources);
+ add_resources(info, &resources);
else {
- free_pci_root_info(&info);
+ free_pci_root_info_res(info);
x86_pci_root_bus_resources(busnum, &resources);
}
+
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
- if (bus)
+ if (bus) {
bus->subordinate = pci_scan_child_bus(bus);
- else
+ pci_set_host_bridge_release(
+ to_pci_host_bridge(bus->bridge),
+ release_pci_root_info, info);
+ } else {
pci_free_resource_list(&resources);
-
- if (!bus && pci_use_crs)
- free_pci_root_info(&info);
+ __release_pci_root_info(info);
+ }
}

/* After the PCI-E bus has been walked and all devices discovered,
--
1.7.7

2012-02-29 23:09:18

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 10/39] x86, PCI: embed pci_sysdata into pci_root_info on acpi path

So that part memory will be released on remove path.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 21 ++++-----------------
1 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 11c3ae7..2331ccb 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -13,6 +13,7 @@ struct pci_root_info {
unsigned int res_num;
struct resource *res;
int busnum;
+ struct pci_sysdata sd;
};

static bool pci_use_crs = true;
@@ -400,26 +401,16 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != -1 && !node_online(node))
node = -1;

- /* Allocate per-root-bus (not per bus) arch-specific data.
- * TODO: leak; this memory is never freed.
- * It's arguable whether it's worth the trouble to care.
- */
- sd = kzalloc(sizeof(*sd), GFP_KERNEL);
- if (!sd) {
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL;
}

+ sd = &info->sd;
sd->domain = domain;
sd->node = node;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- kfree(sd);
- printk(KERN_WARNING "pci_bus %04x:%02x: "
- "ignored (out of memory)\n", domain, busnum);
- return NULL;
- }
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -432,7 +423,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(info);
- kfree(sd);
} else {
probe_pci_root_info(info, device, busnum, domain);

@@ -474,9 +464,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
}

- if (!bus)
- kfree(sd);
-
if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
--
1.7.7

2012-02-29 23:09:15

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 19/39] x86, PCI: put busn resource in pci_root_info for no_crs path

will put it in resources list and pass it for create_root_bus

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/amd_bus.c | 1 -
arch/x86/pci/bus_numa.c | 22 ++++++++++++++--------
arch/x86/pci/bus_numa.h | 3 +--
3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index aff155d..03397ea 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -116,7 +116,6 @@ static int __init early_fill_mp_bus_info(void)
link = (reg >> 8) & 0x03;

info = alloc_pci_root_info(min_bus, max_bus, node, link);
- sprintf(info->name, "PCI Bus #%02x", min_bus);
}

/* get the default node and link for left over res */
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 772949f..b5b9d91 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
return NULL;

list_for_each_entry(info, &pci_root_infos, list)
- if (info->bus_min == bus)
+ if (info->busn.start == bus)
return info;

return NULL;
@@ -31,6 +31,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
bus);

+ pci_add_resource(resources, &info->busn);
+
list_for_each_entry(root_res, &info->resources, list) {
struct resource *res;
struct resource *root;
@@ -54,6 +56,7 @@ default_resources:
printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
pci_add_resource(resources, &ioport_resource);
pci_add_resource(resources, &iomem_resource);
+ pci_add_resource(resources, &busn_resource);
}

struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
@@ -66,9 +69,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
if (!info)
return info;

+ sprintf(info->name, "PCI Bus #%02x", bus_min);
+
INIT_LIST_HEAD(&info->resources);
- info->bus_min = bus_min;
- info->bus_max = bus_max;
+ info->busn.name = info->name;
+ info->busn.start = bus_min;
+ info->busn.end = bus_max;
+ info->busn.flags = IORESOURCE_BUS;
info->node = node;
info->link = link;

@@ -80,14 +87,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink)
{
struct pci_root_res *root_res;
- int busnum = info->bus_min;
+ int busnum = info->busn.start;

if (!nodelink)
- printk(KERN_DEBUG "%s: [%02x, %02x]\n", name,
- info->bus_min, info->bus_max);
+ printk(KERN_DEBUG "%s: %pR\n", name, &info->busn);
else
- printk(KERN_DEBUG "%s: [%02x, %02x] on node %x link %x\n", name,
- info->bus_min, info->bus_max, info->node, info->link);
+ printk(KERN_DEBUG "%s: %pR on node %x link %x\n", name,
+ &info->busn, info->node, info->link);

list_for_each_entry(root_res, &info->resources, list)
printk(KERN_DEBUG "%s: %02x %pR\n", name, busnum,
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index deada6a..f9919c3 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -13,8 +13,7 @@ struct pci_root_info {
struct list_head list;
char name[12];
struct list_head resources;
- int bus_min;
- int bus_max;
+ struct resource busn;
int node;
int link;
};
--
1.7.7

2012-02-29 23:09:14

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 04/39] PCI: rename pci_host_bridge() to find_pci_root_bridge()

Separate find_pci_root_bus out.

-v2: according to Bjorn, remove extra null checking.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/host-bridge.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index dfaff3f..b3ddcc5 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -16,15 +16,22 @@ void add_to_pci_host_bridges(struct pci_host_bridge *bridge)
list_add_tail(&bridge->list, &pci_host_bridges);
}

-static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
+static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
{
struct pci_bus *bus;
- struct pci_host_bridge *bridge;

bus = dev->bus;
while (bus->parent)
bus = bus->parent;

+ return bus;
+}
+
+static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
+{
+ struct pci_bus *bus = find_pci_root_bus(dev);
+ struct pci_host_bridge *bridge;
+
list_for_each_entry(bridge, &pci_host_bridges, list) {
if (bridge->bus == bus)
return bridge;
@@ -42,7 +49,7 @@ void __weak pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region,
struct resource *res)
{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
struct pci_host_bridge_window *window;
resource_size_t offset = 0;

@@ -70,12 +77,13 @@ static bool region_contains(struct pci_bus_region *region1,
void __weak pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
struct pci_host_bridge_window *window;
- struct pci_bus_region bus_region;
resource_size_t offset = 0;

list_for_each_entry(window, &bridge->windows, list) {
+ struct pci_bus_region bus_region;
+
if (resource_type(res) != resource_type(window->res))
continue;

--
1.7.7

2012-02-29 23:17:26

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 01/39] PCI: Separate host_bridge code out from probe.c

-v2: Bjorn want add_to_pci_host_bridges to pass struct pci_host_bridge *
instead of list head pointer.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/Makefile | 2 +-
drivers/pci/host-bridge.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.h | 2 +
drivers/pci/probe.c | 81 +--------------------------------------
4 files changed, 97 insertions(+), 81 deletions(-)
create mode 100644 drivers/pci/host-bridge.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 083a49f..2c224ed 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PCI bus specific drivers.
#

-obj-y += access.o bus.o probe.o remove.o pci.o \
+obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
new file mode 100644
index 0000000..5ca4220
--- /dev/null
+++ b/drivers/pci/host-bridge.c
@@ -0,0 +1,93 @@
+/*
+ * host_bridge.c - host bridge related code
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+#include "pci.h"
+
+static LIST_HEAD(pci_host_bridges);
+
+void add_to_pci_host_bridges(struct pci_host_bridge *bridge)
+{
+ list_add_tail(&bridge->list, &pci_host_bridges);
+}
+
+static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
+{
+ struct pci_bus *bus;
+ struct pci_host_bridge *bridge;
+
+ bus = dev->bus;
+ while (bus->parent)
+ bus = bus->parent;
+
+ list_for_each_entry(bridge, &pci_host_bridges, list) {
+ if (bridge->bus == bus)
+ return bridge;
+ }
+
+ return NULL;
+}
+
+static bool resource_contains(struct resource *res1, struct resource *res2)
+{
+ return res1->start <= res2->start && res1->end >= res2->end;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ if (resource_contains(window->res, res)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+static bool region_contains(struct pci_bus_region *region1,
+ struct pci_bus_region *region2)
+{
+ return region1->start <= region2->start && region1->end >= region2->end;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ struct pci_bus_region bus_region;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ bus_region.start = window->res->start - window->offset;
+ bus_region.end = window->res->end - window->offset;
+
+ if (region_contains(&bus_region, region)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index e494347..c695a92 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -231,6 +231,8 @@ static inline int pci_ari_enabled(struct pci_bus *bus)
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
extern void pci_disable_bridge_window(struct pci_dev *dev);

+void add_to_pci_host_bridges(struct pci_host_bridge *bridge);
+
/* Single Root I/O Virtualization */
struct pci_sriov {
int pos; /* capability position */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 944e05a..89a82a3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,13 +15,10 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3

-static LIST_HEAD(pci_host_bridges);
-
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses);

-
static int find_anything(struct device *dev, void *data)
{
return 1;
@@ -44,82 +41,6 @@ int no_pci_devices(void)
}
EXPORT_SYMBOL(no_pci_devices);

-static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
-{
- struct pci_bus *bus;
- struct pci_host_bridge *bridge;
-
- bus = dev->bus;
- while (bus->parent)
- bus = bus->parent;
-
- list_for_each_entry(bridge, &pci_host_bridges, list) {
- if (bridge->bus == bus)
- return bridge;
- }
-
- return NULL;
-}
-
-static bool resource_contains(struct resource *res1, struct resource *res2)
-{
- return res1->start <= res2->start && res1->end >= res2->end;
-}
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- if (resource_contains(window->res, res)) {
- offset = window->offset;
- break;
- }
- }
-
- region->start = res->start - offset;
- region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-static bool region_contains(struct pci_bus_region *region1,
- struct pci_bus_region *region2)
-{
- return region1->start <= region2->start && region1->end >= region2->end;
-}
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- struct pci_bus_region bus_region;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- bus_region.start = window->res->start - window->offset;
- bus_region.end = window->res->end - window->offset;
-
- if (region_contains(&bus_region, region)) {
- offset = window->offset;
- break;
- }
- }
-
- res->start = region->start + offset;
- res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
/*
* PCI Bus Class
*/
@@ -1731,7 +1652,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}

down_write(&pci_bus_sem);
- list_add_tail(&bridge->list, &pci_host_bridges);
+ add_to_pci_host_bridges(bridge);
list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem);

--
1.7.7

2012-02-29 23:17:24

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 36/39] pcmcia: remove workaround for fixing pci parent bus subordinate

Now pci busn allocation code is there, and it will preallocate bus number and it
will make sure parent buses subordinate is right.

So remove workaround here.

Signed-off-by: Yinghai Lu <[email protected]>
Tested-by: Dominik Brodowski <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Mauro Carvalho Chehab <[email protected]>
Cc: [email protected]
---
drivers/pcmcia/yenta_socket.c | 75 -----------------------------------------
1 files changed, 0 insertions(+), 75 deletions(-)

diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 849c0c1..5757cae 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1064,79 +1064,6 @@ static void yenta_config_init(struct yenta_socket *socket)
config_writew(socket, CB_BRIDGE_CONTROL, bridge);
}

-/**
- * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge
- * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to
- *
- * Checks if devices on the bus which the CardBus bridge bridges to would be
- * invisible during PCI scans because of a misconfigured subordinate number
- * of the parent brige - some BIOSes seem to be too lazy to set it right.
- * Does the fixup carefully by checking how far it can go without conflicts.
- * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information.
- */
-static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
-{
- struct list_head *tmp;
- unsigned char upper_limit;
- /*
- * We only check and fix the parent bridge: All systems which need
- * this fixup that have been reviewed are laptops and the only bridge
- * which needed fixing was the parent bridge of the CardBus bridge:
- */
- struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
-
- /* Check bus numbers are already set up correctly: */
- if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
- return; /* The subordinate number is ok, nothing to do */
-
- if (!bridge_to_fix->parent)
- return; /* Root bridges are ok */
-
- /* stay within the limits of the bus range of the parent: */
- upper_limit = bridge_to_fix->parent->subordinate;
-
- /* check the bus ranges of all silbling bridges to prevent overlap */
- list_for_each(tmp, &bridge_to_fix->parent->children) {
- struct pci_bus *silbling = pci_bus_b(tmp);
- /*
- * If the silbling has a higher secondary bus number
- * and it's secondary is equal or smaller than our
- * current upper limit, set the new upper limit to
- * the bus number below the silbling's range:
- */
- if (silbling->secondary > bridge_to_fix->subordinate
- && silbling->secondary <= upper_limit)
- upper_limit = silbling->secondary - 1;
- }
-
- /* Show that the wanted subordinate number is not possible: */
- if (cardbus_bridge->subordinate > upper_limit)
- dev_printk(KERN_WARNING, &cardbus_bridge->dev,
- "Upper limit for fixing this "
- "bridge's parent bridge: #%02x\n", upper_limit);
-
- /* If we have room to increase the bridge's subordinate number, */
- if (bridge_to_fix->subordinate < upper_limit) {
-
- /* use the highest number of the hidden bus, within limits */
- unsigned char subordinate_to_assign =
- min(cardbus_bridge->subordinate, upper_limit);
-
- dev_printk(KERN_INFO, &bridge_to_fix->dev,
- "Raising subordinate bus# of parent "
- "bus (#%02x) from #%02x to #%02x\n",
- bridge_to_fix->number,
- bridge_to_fix->subordinate, subordinate_to_assign);
-
- /* Save the new subordinate in the bus struct of the bridge */
- bridge_to_fix->subordinate = subordinate_to_assign;
-
- /* and update the PCI config space with the new subordinate */
- pci_write_config_byte(bridge_to_fix->self,
- PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
- }
-}
-
/*
* Initialize a cardbus controller. Make sure we have a usable
* interrupt, and that we can map the cardbus area. Fill in the
@@ -1257,8 +1184,6 @@ static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id
dev_printk(KERN_INFO, &dev->dev,
"Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));

- yenta_fixup_parent_bridge(dev->subordinate);
-
/* Register it with the pcmcia layer.. */
ret = pcmcia_register_socket(&socket->socket);
if (ret == 0) {
--
1.7.7

2012-02-29 23:09:11

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 05/39] PCI: add generic device into pci_host_bridge struct

use that device for pci_root_bus bridge pointer.

With that make code more simple.

Also we can use pci_release_bus_bridge_dev() to release allocated
pci_host_bridge during removing path.

At last, we can use root bus bridge pointer to get host bridge pointer instead
of going over host bridge list, so could kill that host bridge list.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/host-bridge.c | 15 +---------
drivers/pci/pci.h | 2 -
drivers/pci/probe.c | 65 +++++++++++++++++++++++---------------------
include/linux/pci.h | 4 ++-
4 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index b3ddcc5..03d8db1 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -9,13 +9,6 @@

#include "pci.h"

-static LIST_HEAD(pci_host_bridges);
-
-void add_to_pci_host_bridges(struct pci_host_bridge *bridge)
-{
- list_add_tail(&bridge->list, &pci_host_bridges);
-}
-
static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
{
struct pci_bus *bus;
@@ -30,14 +23,8 @@ static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
{
struct pci_bus *bus = find_pci_root_bus(dev);
- struct pci_host_bridge *bridge;
-
- list_for_each_entry(bridge, &pci_host_bridges, list) {
- if (bridge->bus == bus)
- return bridge;
- }

- return NULL;
+ return to_pci_host_bridge(bus->bridge);
}

static bool resource_contains(struct resource *res1, struct resource *res2)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index c695a92..e494347 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -231,8 +231,6 @@ static inline int pci_ari_enabled(struct pci_bus *bus)
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
extern void pci_disable_bridge_window(struct pci_dev *dev);

-void add_to_pci_host_bridges(struct pci_host_bridge *bridge);
-
/* Single Root I/O Virtualization */
struct pci_sriov {
int pos; /* capability position */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 89a82a3..fb3dd4b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -421,6 +421,19 @@ static struct pci_bus * pci_alloc_bus(void)
return b;
}

+static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+{
+ struct pci_host_bridge *bridge;
+
+ bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+ if (bridge) {
+ INIT_LIST_HEAD(&bridge->windows);
+ bridge->bus = b;
+ }
+
+ return bridge;
+}
+
static unsigned char pcix_bus_speed[] = {
PCI_SPEED_UNKNOWN, /* 0 */
PCI_SPEED_66MHz_PCIX, /* 1 */
@@ -1121,7 +1134,13 @@ int pci_cfg_space_size(struct pci_dev *dev)

static void pci_release_bus_bridge_dev(struct device *dev)
{
- kfree(dev);
+ struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+ /* TODO: need to free window->res */
+
+ pci_free_resource_list(&bridge->windows);
+
+ kfree(bridge);
}

struct pci_dev *alloc_pci_dev(void)
@@ -1570,28 +1589,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int error;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct device *dev;
struct pci_host_bridge_window *window, *n;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
char *fmt;

- bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
- if (!bridge)
- return NULL;

b = pci_alloc_bus();
if (!b)
- goto err_bus;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- goto err_dev;
+ return NULL;

b->sysdata = sysdata;
b->ops = ops;
-
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1599,13 +1609,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
goto err_out;
}

- dev->parent = parent;
- dev->release = pci_release_bus_bridge_dev;
- dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus);
- error = device_register(dev);
+ bridge = pci_alloc_host_bridge(b);
+ if (!bridge)
+ goto err_out;
+
+ bridge->dev.parent = parent;
+ bridge->dev.release = pci_release_bus_bridge_dev;
+ dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ error = device_register(&bridge->dev);
if (error)
- goto dev_reg_err;
- b->bridge = get_device(dev);
+ goto bridge_dev_reg_err;
+ b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);

@@ -1624,9 +1638,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,

b->number = b->secondary = bus;

- bridge->bus = b;
- INIT_LIST_HEAD(&bridge->windows);
-
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else
@@ -1652,25 +1663,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}

down_write(&pci_bus_sem);
- add_to_pci_host_bridges(bridge);
list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem);

return b;

class_dev_reg_err:
- device_unregister(dev);
-dev_reg_err:
- down_write(&pci_bus_sem);
- list_del(&bridge->list);
- list_del(&b->node);
- up_write(&pci_bus_sem);
+ device_unregister(&bridge->dev);
+bridge_dev_reg_err:
+ kfree(bridge);
err_out:
- kfree(dev);
-err_dev:
kfree(b);
-err_bus:
- kfree(bridge);
return NULL;
}

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5584aac..310610e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -375,11 +375,13 @@ struct pci_host_bridge_window {
};

struct pci_host_bridge {
- struct list_head list;
+ struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* pci_host_bridge_windows */
};

+#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+
/*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
* to P2P or CardBus bridge windows) go in a table. Additional ones (for
--
1.7.7

2012-02-29 23:09:08

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 18/39] PCI: default busn_resource

We need to put into the resources list

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 7 +++++++
include/linux/pci.h | 2 ++
2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3bdc421..a4a20d6 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,6 +15,13 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3

+struct resource busn_resource = {
+ .name = "PCI busn",
+ .start = 0,
+ .end = 255,
+ .flags = IORESOURCE_BUS,
+};
+
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d93d3ae..c40fc04 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -368,6 +368,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
return (pdev->error_state != pci_channel_io_normal);
}

+extern struct resource busn_resource;
+
struct pci_host_bridge_window {
struct list_head list;
struct resource *res; /* host bridge aperture (CPU address) */
--
1.7.7

2012-02-29 23:09:04

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 03/39] x86, PCI: Fix memleak with get_current_resources

in pci_scan_acpi_root, when pci_use_crs is set, get_current_resources is used
to get pci_root_info, and it will allocate name and res array.

later if pci_create_root_bus can not create bus (could be already there...)
it will only free bus res list. but the name and res array is not freed.

let get_current_resource take info pointer instead have local info.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/acpi.c | 49 ++++++++++++++++++++++++++++++-------------------
1 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 7cc0a44..304ccf0 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,49 +305,55 @@ static void add_resources(struct pci_root_info *info)
}
}

+static void free_pci_root_info(struct pci_root_info *info)
+{
+ kfree(info->name);
+ kfree(info->res);
+ memset(info, 0, sizeof(struct pci_root_info));
+}
+
static void
-get_current_resources(struct acpi_device *device, int busnum,
+get_current_resources(struct pci_root_info *info,
+ struct acpi_device *device, int busnum,
int domain, struct list_head *resources)
{
- struct pci_root_info info;
size_t size;

- info.bridge = device;
- info.res_num = 0;
- info.resources = resources;
+ info->bridge = device;
+ info->res_num = 0;
+ info->resources = resources;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
- &info);
- if (!info.res_num)
+ info);
+ if (!info->res_num)
return;

- size = sizeof(*info.res) * info.res_num;
- info.res = kmalloc(size, GFP_KERNEL);
- if (!info.res)
+ size = sizeof(*info->res) * info->res_num;
+ info->res = kmalloc(size, GFP_KERNEL);
+ if (!info->res)
return;

- info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
- if (!info.name)
+ info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
+ if (!info->name)
goto name_alloc_fail;

- info.res_num = 0;
+ info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
- &info);
+ info);

if (pci_use_crs) {
- add_resources(&info);
+ add_resources(info);

return;
}

- kfree(info.name);
-
name_alloc_fail:
- kfree(info.res);
+ free_pci_root_info(info);
}

struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
+ struct pci_root_info info;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
@@ -392,6 +398,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)

sd->domain = domain;
sd->node = node;
+ memset(&info, 0, sizeof(struct pci_root_info));
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -405,7 +412,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else {
- get_current_resources(device, busnum, domain, &resources);
+ get_current_resources(&info, device, busnum, domain,
+ &resources);

/*
* _CRS with no apertures is normal, so only fall back to
@@ -419,6 +427,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
bus->subordinate = pci_scan_child_bus(bus);
else
pci_free_resource_list(&resources);
+
+ if (!bus && pci_use_crs)
+ free_pci_root_info(&info);
}

/* After the PCI-E bus has been walked and all devices discovered,
--
1.7.7

2012-02-29 23:09:01

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 11/39] x86, PCI: Allocating pci_root_info for not using _CRS path

so we could get ride of static allocation and hard limits.

We could save some bytes, and can handle system with more than 4
peer root buses.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/amd_bus.c | 76 +++++++++++++++---------------------------
arch/x86/pci/broadcom_bus.c | 12 ++----
arch/x86/pci/bus_numa.c | 69 ++++++++++++++++++++++++++------------
arch/x86/pci/bus_numa.h | 18 ++++++----
4 files changed, 88 insertions(+), 87 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0567df3..459a731 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -32,6 +32,18 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {

#define RANGE_NUM 16

+static struct pci_root_info __init *find_pci_root_info(int node, int link)
+{
+ struct pci_root_info *info;
+
+ /* find the position */
+ list_for_each_entry(info, &pci_root_infos, list)
+ if (info->node == node && info->link == link)
+ return info;
+
+ return NULL;
+}
+
/**
* early_fill_mp_bus_to_node()
* called before pcibios_scan_root and pci_scan_bus
@@ -50,7 +62,6 @@ static int __init early_fill_mp_bus_info(void)
int def_link;
struct pci_root_info *info;
u32 reg;
- struct resource *res;
u64 start;
u64 end;
struct range range[RANGE_NUM];
@@ -86,7 +97,6 @@ static int __init early_fill_mp_bus_info(void)
if (!found)
return 0;

- pci_root_num = 0;
for (i = 0; i < 4; i++) {
int min_bus;
int max_bus;
@@ -105,13 +115,8 @@ static int __init early_fill_mp_bus_info(void)
#endif
link = (reg >> 8) & 0x03;

- info = &pci_root_info[pci_root_num];
- info->bus_min = min_bus;
- info->bus_max = max_bus;
- info->node = node;
- info->link = link;
+ info = alloc_pci_root_info(min_bus, max_bus, node, link);
sprintf(info->name, "PCI Bus #%02x", min_bus);
- pci_root_num++;
}

/* get the default node and link for left over res */
@@ -134,16 +139,10 @@ static int __init early_fill_mp_bus_info(void)
link = (reg >> 4) & 0x03;
end = (reg & 0xfff000) | 0xfff;

- /* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == node && info->link == link)
- break;
- }
- if (j == pci_root_num)
+ info = find_pci_root_info(node, link);
+ if (!info)
continue; /* not found */

- info = &pci_root_info[j];
printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
node, link, start, end);

@@ -155,13 +154,8 @@ static int __init early_fill_mp_bus_info(void)
}
/* add left over io port range to def node/link, [0, 0xffff] */
/* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == def_node && info->link == def_link)
- break;
- }
- if (j < pci_root_num) {
- info = &pci_root_info[j];
+ info = find_pci_root_info(def_node, def_link);
+ if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
@@ -214,16 +208,10 @@ static int __init early_fill_mp_bus_info(void)
end <<= 8;
end |= 0xffff;

- /* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == node && info->link == link)
- break;
- }
- if (j == pci_root_num)
- continue; /* not found */
+ info = find_pci_root_info(node, link);

- info = &pci_root_info[j];
+ if (!info)
+ continue;

printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
node, link, start, end);
@@ -291,14 +279,8 @@ static int __init early_fill_mp_bus_info(void)
* add left over mmio range to def node/link ?
* that is tricky, just record range in from start_min to 4G
*/
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == def_node && info->link == def_link)
- break;
- }
- if (j < pci_root_num) {
- info = &pci_root_info[j];
-
+ info = find_pci_root_info(def_node, def_link);
+ if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
@@ -309,20 +291,16 @@ static int __init early_fill_mp_bus_info(void)
}
}

- for (i = 0; i < pci_root_num; i++) {
- int res_num;
+ list_for_each_entry(info, &pci_root_infos, list) {
int busnum;
+ struct pci_root_res *root_res;

- info = &pci_root_info[i];
- res_num = info->res_num;
busnum = info->bus_min;
printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
info->bus_min, info->bus_max, info->node, info->link);
- for (j = 0; j < res_num; j++) {
- res = &info->res[j];
- printk(KERN_DEBUG "bus: %02x index %x %pR\n",
- busnum, j, res);
- }
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_DEBUG "bus: %02x %pR\n",
+ busnum, &root_res->res);
}

return 0;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index f3a7c56..614392c 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -22,19 +22,15 @@
static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
{
struct pci_root_info *info;
+ struct pci_root_res *root_res;
struct resource res;
u16 word1, word2;
u8 fbus, lbus;
- int i;
-
- info = &pci_root_info[pci_root_num];
- pci_root_num++;

/* read the PCI bus numbers */
fbus = read_pci_config_byte(bus, slot, func, 0x44);
lbus = read_pci_config_byte(bus, slot, func, 0x45);
- info->bus_min = fbus;
- info->bus_max = lbus;
+ info = alloc_pci_root_info(fbus, lbus, 0, 0);

/*
* Add the legacy IDE ports on bus 0
@@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
res.flags = IORESOURCE_BUS;
printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);

- for (i = 0; i < info->res_num; i++)
- printk(KERN_INFO "host bridge window %pR\n", &info->res[i]);
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
}

static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index fd3f655..306579f 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -4,35 +4,38 @@

#include "bus_numa.h"

-int pci_root_num;
-struct pci_root_info pci_root_info[PCI_ROOT_NR];
+LIST_HEAD(pci_root_infos);

-void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+static struct pci_root_info *x86_find_pci_root_info(int bus)
{
- int i;
- int j;
struct pci_root_info *info;

- if (!pci_root_num)
- goto default_resources;
+ if (list_empty(&pci_root_infos))
+ return NULL;

- for (i = 0; i < pci_root_num; i++) {
- if (pci_root_info[i].bus_min == bus)
- break;
- }
+ list_for_each_entry(info, &pci_root_infos, list)
+ if (info->bus_min == bus)
+ return info;
+
+ return NULL;
+}

- if (i == pci_root_num)
+void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+{
+ struct pci_root_info *info = x86_find_pci_root_info(bus);
+ struct pci_root_res *root_res;
+
+ if (!info)
goto default_resources;

printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
bus);

- info = &pci_root_info[i];
- for (j = 0; j < info->res_num; j++) {
+ list_for_each_entry(root_res, &info->resources, list) {
struct resource *res;
struct resource *root;

- res = &info->res[j];
+ res = &root_res->res;
pci_add_resource(resources, res);
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
@@ -53,11 +56,32 @@ default_resources:
pci_add_resource(resources, &iomem_resource);
}

+struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link)
+{
+ struct pci_root_info *info;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+ if (!info)
+ return info;
+
+ INIT_LIST_HEAD(&info->resources);
+ info->bus_min = bus_min;
+ info->bus_max = bus_max;
+ info->node = node;
+ info->link = link;
+
+ list_add_tail(&info->list, &pci_root_infos);
+
+ return info;
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
- int i;
struct resource *res;
+ struct pci_root_res *root_res;

if (start > end)
return;
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
goto addit;

/* try to merge it with old one */
- for (i = 0; i < info->res_num; i++) {
+ list_for_each_entry(root_res, &info->resources, list) {
resource_size_t final_start, final_end;
resource_size_t common_start, common_end;

- res = &info->res[i];
+ res = &root_res->res;
if (res->flags != flags)
continue;

@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
addit:

/* need to add that */
- if (info->res_num >= RES_NUM)
+ root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
+ if (!root_res)
return;

- res = &info->res[info->res_num];
+ res = &root_res->res;
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
- res->child = NULL;
- info->res_num++;
+
+ list_add_tail(&root_res->list, &info->resources);
}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 804a4b4..226a466 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -4,22 +4,24 @@
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there.
*/
-#define RES_NUM 16
+struct pci_root_res {
+ struct list_head list;
+ struct resource res;
+};
+
struct pci_root_info {
+ struct list_head list;
char name[12];
- unsigned int res_num;
- struct resource res[RES_NUM];
+ struct list_head resources;
int bus_min;
int bus_max;
int node;
int link;
};

-/* 4 at this time, it may become to 32 */
-#define PCI_ROOT_NR 4
-extern int pci_root_num;
-extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
-
+extern struct list_head pci_root_infos;
+struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
--
1.7.7

2012-02-29 23:20:08

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 02/39] x86, PCI: have own version for pcibios_bus_to_resource

x86 does not need to offset the address. So we can skip that costing offset
searching.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/pci/i386.c | 14 ++++++++++++++
drivers/pci/host-bridge.c | 9 +++++----
2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 33e6a0b..eeed28e 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -335,6 +335,20 @@ void __init pcibios_resource_survey(void)
*/
fs_initcall(pcibios_assign_resources);

+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ region->start = res->start;
+ region->end = res->end;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ res->start = region->start;
+ res->end = region->end;
+}
+
static const struct vm_operations_struct pci_mmap_ops = {
.access = generic_access_phys,
};
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 5ca4220..dfaff3f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -38,8 +38,9 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
return res1->start <= res2->start && res1->end >= res2->end;
}

-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
+void __weak pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res)
{
struct pci_host_bridge *bridge = pci_host_bridge(dev);
struct pci_host_bridge_window *window;
@@ -66,8 +67,8 @@ static bool region_contains(struct pci_bus_region *region1,
return region1->start <= region2->start && region1->end >= region2->end;
}

-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
+void __weak pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
{
struct pci_host_bridge *bridge = pci_host_bridge(dev);
struct pci_host_bridge_window *window;
--
1.7.7

2012-02-29 23:20:32

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 02/39] x86, PCI: have own version for pcibios_bus_to_resource

On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
> x86 does not need to offset the address. So we can skip that costing offset
> searching.

I tried to start a discussion about this patch (and others), but I
don't think you responded:
http://marc.info/?l=linux-pci&m=133036414506921&w=2

It's discouraging to spend time reviewing all your patches and trying
to give useful feedback, when all I get in response is a deluge of
fresh patches.

Bjorn

> Signed-off-by: Yinghai Lu <[email protected]>
> ---
> ?arch/x86/pci/i386.c ? ? ? | ? 14 ++++++++++++++
> ?drivers/pci/host-bridge.c | ? ?9 +++++----
> ?2 files changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
> index 33e6a0b..eeed28e 100644
> --- a/arch/x86/pci/i386.c
> +++ b/arch/x86/pci/i386.c
> @@ -335,6 +335,20 @@ void __init pcibios_resource_survey(void)
> ?*/
> ?fs_initcall(pcibios_assign_resources);
>
> +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct resource *res)
> +{
> + ? ? ? region->start = res->start;
> + ? ? ? region->end = res->end;
> +}
> +
> +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct pci_bus_region *region)
> +{
> + ? ? ? res->start = region->start;
> + ? ? ? res->end = region->end;
> +}
> +
> ?static const struct vm_operations_struct pci_mmap_ops = {
> ? ? ? ?.access = generic_access_phys,
> ?};
> diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
> index 5ca4220..dfaff3f 100644
> --- a/drivers/pci/host-bridge.c
> +++ b/drivers/pci/host-bridge.c
> @@ -38,8 +38,9 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
> ? ? ? ?return res1->start <= res2->start && res1->end >= res2->end;
> ?}
>
> -void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct resource *res)
> +void __weak pcibios_resource_to_bus(struct pci_dev *dev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct pci_bus_region *region,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct resource *res)
> ?{
> ? ? ? ?struct pci_host_bridge *bridge = pci_host_bridge(dev);
> ? ? ? ?struct pci_host_bridge_window *window;
> @@ -66,8 +67,8 @@ static bool region_contains(struct pci_bus_region *region1,
> ? ? ? ?return region1->start <= region2->start && region1->end >= region2->end;
> ?}
>
> -void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct pci_bus_region *region)
> +void __weak pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct pci_bus_region *region)
> ?{
> ? ? ? ?struct pci_host_bridge *bridge = pci_host_bridge(dev);
> ? ? ? ?struct pci_host_bridge_window *window;
> --
> 1.7.7
>

2012-02-29 23:21:06

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 30/39] PCI: Add pci_bus_extend/shrink_top()

extend or shrink bus and parent buses top (subordinate)

extended range is verified safe range, and stop at recorded parent_res.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 36 ++++++++++++++++++++++++++++++++++++
1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1c07aba..96259f8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -655,6 +655,42 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
}
}

+static void __devinit pci_bus_update_top(struct pci_bus *parent,
+ long size, struct resource *parent_res)
+{
+ struct resource *res;
+
+ if (!size)
+ return;
+
+ while (parent) {
+ res = &parent->busn_res;
+ if (res == parent_res)
+ break;
+ res->end += size;
+ parent->subordinate += size;
+ pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS,
+ parent->subordinate);
+ dev_printk(KERN_DEBUG, &parent->dev,
+ "busn_res: %s %02lx to %pR\n",
+ (size > 0) ? "extended" : "shrunk",
+ abs(size), res);
+ parent = parent->parent;
+ }
+}
+
+static void __devinit pci_bus_extend_top(struct pci_bus *parent,
+ long size, struct resource *parent_res)
+{
+ pci_bus_update_top(parent, size, parent_res);
+}
+
+static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
+ long size, struct resource *parent_res)
+{
+ pci_bus_update_top(parent, -size, parent_res);
+}
+
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
--
1.7.7

2012-02-29 23:21:33

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 38/39] PCI, pciehp: Remove not needed bus number range checking

Found hotplug adding one EM with bridge fail, bios only leave one bus range
for slot.

[ 1169.621444] pciehp: No bus number available for hot-added bridge 0000:55:00.0
[ 1169.633277] pcieport 0000:40:03.0: PCI bridge to [bus 55-55]

With busn_res tracking and allocating, we don't need that checking anymore.

Parent bridges' bus number will be extended safely.

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/hotplug/pciehp_pci.c | 12 +-----------
1 files changed, 1 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 47d9dc0..e21171c 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -37,18 +37,8 @@
static int __ref pciehp_add_bridge(struct pci_dev *dev)
{
struct pci_bus *parent = dev->bus;
- int pass, busnr, start = parent->secondary;
- int end = parent->subordinate;
+ int pass, busnr = parent->secondary;

- for (busnr = start; busnr <= end; busnr++) {
- if (!pci_find_bus(pci_domain_nr(parent), busnr))
- break;
- }
- if (busnr-- > end) {
- err("No bus number available for hot-added bridge %s\n",
- pci_name(dev));
- return -1;
- }
for (pass = 0; pass < 2; pass++)
busnr = pci_scan_bridge(parent, dev, busnr, pass);
if (!dev->subordinate)
--
1.7.7

2012-02-29 23:21:51

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 29/39] PCI, parisc: Register busn_res for root buses

Signed-off-by: Yinghai Lu <[email protected]>
Cc: Kyle McMartin <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: [email protected]
---
drivers/parisc/dino.c | 5 +++++
drivers/parisc/lba_pci.c | 3 +++
2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 0610e91..def94af 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -984,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev)
if (dino_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.gmmio_space);

+ dino_dev->hba.bus_num.start = dino_current_bus;
+ dino_dev->hba.bus_num.end = 255;
+ dino_dev->hba.bus_num.flags |= IORESOURCE_BUS;
+ pci_add_resource(&resources, &dino_dev->hba.bus_num);
/*
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
@@ -999,6 +1003,7 @@ static int __init dino_probe(struct parisc_device *dev)
return 0;
}

+ pci_bus_update_busn_res_end(bus, bus->subordinate);
bus->subordinate = pci_scan_child_bus(bus);

/* This code *depends* on scanning being single threaded
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index e885764..df1e9f9 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1503,6 +1503,9 @@ lba_driver_probe(struct parisc_device *dev)
if (lba_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &lba_dev->hba.gmmio_space);

+ lba_dev->hba.bus_num.flags |= IORESOURCE_BUS;
+ pci_add_resource(&resources, &lba_dev->hba.bus_num);
+
dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
--
1.7.7

2012-02-29 23:32:54

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
> Bjorn thought that we should just use that in acpi_root.
>
> Suggested-by: Bjorn Helgaas <[email protected]>
> Signed-off-by: Yinghai Lu <[email protected]>
> ---
> ?arch/x86/pci/acpi.c | ? 19 ++++++-------------
> ?1 files changed, 6 insertions(+), 13 deletions(-)
>
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index ff5243e..5178917 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -12,7 +12,6 @@ struct pci_root_info {
> ? ? ? ?char name[16];
> ? ? ? ?unsigned int res_num;
> ? ? ? ?struct resource *res;
> - ? ? ? struct resource busn;
> ? ? ? ?struct pci_sysdata sd;
> ?};
>
> @@ -283,9 +282,6 @@ static void add_resources(struct pci_root_info *info,
> ? ? ? ?int i;
> ? ? ? ?struct resource *res, *root, *conflict;
>
> - ? ? ? if (info->busn.flags & IORESOURCE_BUS)
> - ? ? ? ? ? ? ? pci_add_resource(resources, &info->busn);
> -
> ? ? ? ?coalesce_windows(info, IORESOURCE_MEM);
> ? ? ? ?coalesce_windows(info, IORESOURCE_IO);
>
> @@ -346,16 +342,12 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
>
> ?static void
> ?probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
> - ? ? ? ? ? ? ? ? ? int busnum, int busmax, int domain)
> + ? ? ? ? ? ? ? ? ? int busnum, int domain)
> ?{
> ? ? ? ?size_t size;
>
> ? ? ? ?sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
> ? ? ? ?info->bridge = device;
> - ? ? ? info->busn.name = info->name;
> - ? ? ? info->busn.start = busnum;
> - ? ? ? info->busn.end = busmax;
> - ? ? ? info->busn.flags = IORESOURCE_BUS;

You just *added* this stuff in a prior patch that hasn't been merged
yet. Why can't you just fix that series rather than doing the
add/remove churn?

> ? ? ? ?info->res_num = 0;
> ? ? ? ?acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
> @@ -379,7 +371,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
> ? ? ? ?struct pci_root_info *info = NULL;
> ? ? ? ?int domain = root->segment;
> ? ? ? ?int busnum = root->secondary.start;
> - ? ? ? int busmax = root->secondary.end;
> ? ? ? ?LIST_HEAD(resources);
> ? ? ? ?struct pci_bus *bus;
> ? ? ? ?struct pci_sysdata *sd;
> @@ -432,15 +423,17 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
> ? ? ? ? ? ? ? ?memcpy(bus->sysdata, sd, sizeof(*sd));
> ? ? ? ? ? ? ? ?kfree(info);
> ? ? ? ?} else {
> - ? ? ? ? ? ? ? probe_pci_root_info(info, device, busnum, busmax, domain);
> + ? ? ? ? ? ? ? probe_pci_root_info(info, device, busnum, domain);
>
> ? ? ? ? ? ? ? ?/*
> ? ? ? ? ? ? ? ? * _CRS with no apertures is normal, so only fall back to
> ? ? ? ? ? ? ? ? * defaults or native bridge info if we're ignoring _CRS.
> ? ? ? ? ? ? ? ? */
> - ? ? ? ? ? ? ? if (pci_use_crs)
> + ? ? ? ? ? ? ? if (pci_use_crs) {
> + ? ? ? ? ? ? ? ? ? ? ? /* insert busn res at first */
> + ? ? ? ? ? ? ? ? ? ? ? pci_add_resource(&resources, ?&root->secondary);
> ? ? ? ? ? ? ? ? ? ? ? ?add_resources(info, &resources);
> - ? ? ? ? ? ? ? else {
> + ? ? ? ? ? ? ? } else {
> ? ? ? ? ? ? ? ? ? ? ? ?free_pci_root_info_res(info);
> ? ? ? ? ? ? ? ? ? ? ? ?x86_pci_root_bus_resources(busnum, &resources);
> ? ? ? ? ? ? ? ?}
> --
> 1.7.7
>

2012-02-29 23:33:40

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 02/39] x86, PCI: have own version for pcibios_bus_to_resource

On Wed, Feb 29, 2012 at 3:20 PM, Bjorn Helgaas <[email protected]> wrote:
> On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
>> x86 does not need to offset the address. So we can skip that costing offset
>> searching.
>
> I tried to start a discussion about this patch (and others), but I
> don't think you responded:
> http://marc.info/?l=linux-pci&m=133036414506921&w=2

this patch does reduce some not needed ops.

and it does not affects your effects, and it just make x86 not get punished.

let's let Jesse and x86 maintainers to decide if this patch is needed.

Thanks

Yinghai

2012-02-29 23:37:56

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

On Wed, Feb 29, 2012 at 3:32 PM, Bjorn Helgaas <[email protected]> wrote:
> On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
>> Bjorn thought that we should just use that in acpi_root.
>>
>> Suggested-by: Bjorn Helgaas <[email protected]>
>> Signed-off-by: Yinghai Lu <[email protected]>
>> ---
>> ?arch/x86/pci/acpi.c | ? 19 ++++++-------------
>> ?1 files changed, 6 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index ff5243e..5178917 100644
>> --- a/arch/x86/pci/acpi.c
>> +++ b/arch/x86/pci/acpi.c
>> @@ -12,7 +12,6 @@ struct pci_root_info {
>> ? ? ? ?char name[16];
>> ? ? ? ?unsigned int res_num;
>> ? ? ? ?struct resource *res;
>> - ? ? ? struct resource busn;
>> ? ? ? ?struct pci_sysdata sd;
>> ?};
>>
>> @@ -283,9 +282,6 @@ static void add_resources(struct pci_root_info *info,
>> ? ? ? ?int i;
>> ? ? ? ?struct resource *res, *root, *conflict;
>>
>> - ? ? ? if (info->busn.flags & IORESOURCE_BUS)
>> - ? ? ? ? ? ? ? pci_add_resource(resources, &info->busn);
>> -
>> ? ? ? ?coalesce_windows(info, IORESOURCE_MEM);
>> ? ? ? ?coalesce_windows(info, IORESOURCE_IO);
>>
>> @@ -346,16 +342,12 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
>>
>> ?static void
>> ?probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
>> - ? ? ? ? ? ? ? ? ? int busnum, int busmax, int domain)
>> + ? ? ? ? ? ? ? ? ? int busnum, int domain)
>> ?{
>> ? ? ? ?size_t size;
>>
>> ? ? ? ?sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
>> ? ? ? ?info->bridge = device;
>> - ? ? ? info->busn.name = info->name;
>> - ? ? ? info->busn.start = busnum;
>> - ? ? ? info->busn.end = busmax;
>> - ? ? ? info->busn.flags = IORESOURCE_BUS;
>
> You just *added* this stuff in a prior patch that hasn't been merged
> yet. ?Why can't you just fix that series rather than doing the
> add/remove churn?

as i said before, I'm not quite sure about the life cycle about that object.

still need to wait some months to verify that on system that does
support pci root bus hot plug etc.

or we can just this patch for now.

Yinghai

2012-02-29 23:53:07

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

On Wed, Feb 29, 2012 at 03:37:53PM -0800, Yinghai Lu wrote:
> On Wed, Feb 29, 2012 at 3:32 PM, Bjorn Helgaas <[email protected]> wrote:
> > On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
> >> Bjorn thought that we should just use that in acpi_root.
> >>
> >> Suggested-by: Bjorn Helgaas <[email protected]>
> >> Signed-off-by: Yinghai Lu <[email protected]>
> >> ---
> >> ?arch/x86/pci/acpi.c | ? 19 ++++++-------------
> >> ?1 files changed, 6 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> >> index ff5243e..5178917 100644
> >> --- a/arch/x86/pci/acpi.c
> >> +++ b/arch/x86/pci/acpi.c
> >> @@ -12,7 +12,6 @@ struct pci_root_info {
> >> ? ? ? ?char name[16];
> >> ? ? ? ?unsigned int res_num;
> >> ? ? ? ?struct resource *res;
> >> - ? ? ? struct resource busn;
> >> ? ? ? ?struct pci_sysdata sd;
> >> ?};
> >>
> >> @@ -283,9 +282,6 @@ static void add_resources(struct pci_root_info *info,
> >> ? ? ? ?int i;
> >> ? ? ? ?struct resource *res, *root, *conflict;
> >>
> >> - ? ? ? if (info->busn.flags & IORESOURCE_BUS)
> >> - ? ? ? ? ? ? ? pci_add_resource(resources, &info->busn);
> >> -
> >> ? ? ? ?coalesce_windows(info, IORESOURCE_MEM);
> >> ? ? ? ?coalesce_windows(info, IORESOURCE_IO);
> >>
> >> @@ -346,16 +342,12 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
> >>
> >> ?static void
> >> ?probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
> >> - ? ? ? ? ? ? ? ? ? int busnum, int busmax, int domain)
> >> + ? ? ? ? ? ? ? ? ? int busnum, int domain)
> >> ?{
> >> ? ? ? ?size_t size;
> >>
> >> ? ? ? ?sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
> >> ? ? ? ?info->bridge = device;
> >> - ? ? ? info->busn.name = info->name;
> >> - ? ? ? info->busn.start = busnum;
> >> - ? ? ? info->busn.end = busmax;
> >> - ? ? ? info->busn.flags = IORESOURCE_BUS;
> >
> > You just *added* this stuff in a prior patch that hasn't been merged
> > yet. ?Why can't you just fix that series rather than doing the
> > add/remove churn?
>
> as i said before, I'm not quite sure about the life cycle about that object.
>
> still need to wait some months to verify that on system that does
> support pci root bus hot plug etc.
>
> or we can just this patch for now.

A statement like that would cause all of these patches to be instantly
deleted from any queue that I had control over, and I strongly recommend
that Jesse just ignore them all.

If you don't know this thing, then you have no right to change it, flat
out. Why do we trust these patches from you? I sure don't.

greg k-h

2012-03-01 00:27:58

by Jesse Barnes

[permalink] [raw]
Subject: Re: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

On Wed, 29 Feb 2012 15:51:28 -0800
Greg KH <[email protected]> wrote:

> On Wed, Feb 29, 2012 at 03:37:53PM -0800, Yinghai Lu wrote:
> > On Wed, Feb 29, 2012 at 3:32 PM, Bjorn Helgaas

> > > You just *added* this stuff in a prior patch that hasn't been
> > > merged yet.  Why can't you just fix that series rather than doing
> > > the add/remove churn?
> >
> > as i said before, I'm not quite sure about the life cycle about
> > that object.

I thought Bjorn figured that out for you in the last thread?

> >
> > still need to wait some months to verify that on system that does
> > support pci root bus hot plug etc.
> >
> > or we can just this patch for now.
>
> A statement like that would cause all of these patches to be instantly
> deleted from any queue that I had control over, and I strongly
> recommend that Jesse just ignore them all.
>
> If you don't know this thing, then you have no right to change it,
> flat out. Why do we trust these patches from you? I sure don't.

Oh don't worry, this patch set isn't going upstream anytime soon.
Bjorn has raised several good points that Yinghai has yet to
address... I trust Bjorn's judgment on these, so until he's happy I
likely won't be merging them.

2012-03-01 00:43:04

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 02/39] x86, PCI: have own version for pcibios_bus_to_resource

On Wed, Feb 29, 2012 at 4:33 PM, Yinghai Lu <[email protected]> wrote:
> On Wed, Feb 29, 2012 at 3:20 PM, Bjorn Helgaas <[email protected]> wrote:
>> On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
>>> x86 does not need to offset the address. So we can skip that costing offset
>>> searching.
>>
>> I tried to start a discussion about this patch (and others), but I
>> don't think you responded:
>> http://marc.info/?l=linux-pci&m=133036414506921&w=2
>
> this patch does reduce some not needed ops.
>
> and it does not affects your effects,

It does affect my efforts in that this patch adds back x86 complexity
that I don't think is necessary.

And this patch makes it so the pci_add_resource_offset() interface
exists and appears to work on x86, but if somebody tries to use it, it
*doesn't* work. I don't like to write code like that. I think it's
poor style.

> and it just make x86 not get punished.

What punishment are you worried about? I really don't think you'll be
able to measure any performance impact.

I agree that the x86 code you add *is* simpler than the generic
version. But I think the *overall* complexity is higher because now
you have to look at two versions (generic and x86) and convince
yourself that it's safe to use the x86 version.

Bjorn

2012-03-01 02:54:38

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 02/39] x86, PCI: have own version for pcibios_bus_to_resource

On Wed, Feb 29, 2012 at 4:42 PM, Bjorn Helgaas <[email protected]> wrote:
> On Wed, Feb 29, 2012 at 4:33 PM, Yinghai Lu <[email protected]> wrote:
>> On Wed, Feb 29, 2012 at 3:20 PM, Bjorn Helgaas <[email protected]> wrote:
>>> On Wed, Feb 29, 2012 at 4:07 PM, Yinghai Lu <[email protected]> wrote:
>>>> x86 does not need to offset the address. So we can skip that costing offset
>>>> searching.
>>>
>>> I tried to start a discussion about this patch (and others), but I
>>> don't think you responded:
>>> http://marc.info/?l=linux-pci&m=133036414506921&w=2
>>
>> this patch does reduce some not needed ops.
>>
>> and it does not affects your effects,
>
> It does affect my efforts in that this patch adds back x86 complexity
> that I don't think is necessary.
>
> And this patch makes it so the pci_add_resource_offset() interface
> exists and appears to work on x86, but if somebody tries to use it, it
> *doesn't* work. ?I don't like to write code like that. ?I think it's
> poor style.
>
>> and it just make x86 not get punished.
>
> What punishment are you worried about? ?I really don't think you'll be
> able to measure any performance impact.
>
> I agree that the x86 code you add *is* simpler than the generic
> version. ?But I think the *overall* complexity is higher because now
> you have to look at two versions (generic and x86) and convince
> yourself that it's safe to use the x86 version.
>

fine, i will that patch.

Yinghai

2012-03-01 02:57:31

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 39/39] x86, PCI: kill busn in acpi pci_root_info

On Wed, Feb 29, 2012 at 4:27 PM, Jesse Barnes <[email protected]> wrote:
> On Wed, 29 Feb 2012 15:51:28 -0800
> Greg KH <[email protected]> wrote:
>
>> On Wed, Feb 29, 2012 at 03:37:53PM -0800, Yinghai Lu wrote:
>> > On Wed, Feb 29, 2012 at 3:32 PM, Bjorn Helgaas
>
>> > > You just *added* this stuff in a prior patch that hasn't been
>> > > merged yet. ?Why can't you just fix that series rather than doing
>> > > the add/remove churn?
>> >
>> > as i said before, I'm not quite sure about the life cycle about
>> > that object.
>
> I thought Bjorn figured that out for you in the last thread?
>
>> >
>> > still need to wait some months to verify that on system that does
>> > support pci root bus hot plug etc.
>> >
>> > or we can just this patch for now.
>>
>> A statement like that would cause all of these patches to be instantly
>> deleted from any queue that I had control over, and I strongly
>> recommend that Jesse just ignore them all.
>>
>> If you don't know this thing, then you have no right to change it,
>> flat out. ?Why do we trust these patches from you? ?I sure don't.
>
> Oh don't worry, this patch set isn't going upstream anytime soon.
> Bjorn has raised several good points that Yinghai has yet to
> address... ?I trust Bjorn's judgment on these, so until he's happy I
> likely won't be merging them.

Sorry for upsetting Greg.

will reorder patch sequence to mold that patch.

Yinghai