2015-04-21 11:38:38

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 00/29] Refine PCI scan interfaces and make generic pci host bridge

This series could be pulled from:
https://github.com/YijingWang/linux-pci.git enumer10

v9->v10:
Dynamically allocate busn resource if callers don't supply.
Try to adjust busn resource if host bridge busn resource conlict.
Rebase whole series on Bjorn's latest pci-next branch.
Major v9->v10 changes are in patch 5,6,7,10.
v8->v9:
Add Thierry's Acked-by and Tested-by.
Fix the building error for powerpc found by Daniel.
Change pci_host_assign_domain_nr() to static.
v7->v8:
Fix some cross building errors found by kbuild test.
Drop the rename patch for find_pci_host_bridge().
v6->v7:
Drop previous patch which combined the domain and bus in one argument.
Make the pci_host_bridge hold the default busn resource, so we could
check whether new host busn resource is conflict with existing ones.
Move pci_host_assign_domain_nr() to drivers/pci/host-bridge.c
Other changes suggested by Bjorn and Suravee.
v5->v6:
Fix cross building errors found by kbuild test.
Export busn_resource to Xen pcifront driver.
v4->v5:
Fix some code style issues and rename some functions suggested by Bjorn.
Fix some code flaw(Eg. call pci_bus_add_devices() before resources claim
or lack the return checking).
v3->v4:
Fix the rebase issue.
v2->v3:
Rebase this series on v4.0-rc1.
v1->v2:
Split pci_host_bridge_list into a new patch, remove .phb_probe_mode
and rework powerpc .phb_of_scan_bus() for simpilicty suggested by
Arnd. Refresh some patch description log, and add a new patch to fix
build warning in ia64.

This series is based on Bjorn's pci/enumeration branch.
You could pull it from https://github.com/YijingWang/linux-pci.git enumer9

Now in kernel, we scan pci bus use the following ways:
1. pci_scan_bus.
parent = NULL, default io/mem/bus resources
call pci_bus_add_devices()

2. pci_scan_bus_parented() + pci_bus_add_devices()
default io/mem/bus resources, only used by xen

3. pci_scan_root_bus() + pci_bus_add_devices()

4. pci_create_root_bus() + pci_scan_child_bus() + pci_bus_add_devices()

5. pci_create_root_bus() + xx_of_scan_bus() + pci_bus_add_devices()

And we have a lot of arch specific pci_domain_nr() and other platform
specific weak function like pcibios_root_bridge_prepare().

After applied this series, we have following scan interfaces:

1. pci_scan_bus()
parent = NULL, default io/mem/bus resources.
for legacy pci scan

2. pci_scan_root_bus()
for callers provide its own parent and io/mem/bus resources
but no platform specific pci_host_bridge operations

3. pci_scan_host_bridge()
for callers provide its own parent and io/mem/bus resources



Arnd Bergmann (1):
xen/PCI: Don't use deprecated function pci_scan_bus_parented()

Yijing Wang (28):
PCI: Remove deprecated pci_scan_bus_parented()
PCI: Save domain in pci_host_bridge
PCI: Move pci_bus_assign_domain_nr() declaration into
drivers/pci/pci.h
PCI: Remove argument bus for pci_create_root_bus()
PCI: Alloc busn resource dynamically for pci_scan_bus()
PCI: Allocate busn resource for pci_scan_root_bus()
PCI: Introduce pci_host_assign_domain_nr() to assign domain
PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
PCI: Introduce pci_host_bridge_list to manage host bridges
PCI: Save sysdata in pci_host_bridge drvdata
powerpc/PCI: Rename pcibios_root_bridge_prepare() to
pcibios_set_root_bus_speed()
PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()
PCI: Introduce pci_host_bridge_ops to support host specific
operations
PCI: Introduce new scan function pci_scan_host_bridge()
PCI: Introduce pci_bus_child_max_busnr()
x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
powerpc/pci: Use pci_scan_host_bridge() for simplicity
PCI: Remove pcibios_root_bridge_prepare() and
pcibos_set_root_bus_speed()
sparc/PCI: Use pci_scan_host_bridge() for simplicity
parisc/PCI: Use pci_scan_root_bus() for simplicity
PCI/mvebu: Use pci_common_init_dev() to simplify code
PCI/tegra: Remove redundant tegra_pcie_scan_bus()
PCI/designware: Use pci_scan_root_bus() for simplicity
PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()
PCI: Rename __pci_create_root_bus() to pci_create_root_bus()
PCI: Remove platform specific pci_domain_nr()
PCI: Remove pci_bus_assign_domain_nr()

arch/alpha/include/asm/pci.h | 2 -
arch/alpha/kernel/pci.c | 4 +-
arch/alpha/kernel/sys_nautilus.c | 2 +-
arch/arm/kernel/bios32.c | 2 +-
arch/arm/mach-dove/pcie.c | 2 +-
arch/arm/mach-iop13xx/pci.c | 4 +-
arch/arm/mach-mv78xx0/pcie.c | 2 +-
arch/arm/mach-orion5x/pci.c | 4 +-
arch/frv/mb93090-mb00/pci-vdk.c | 3 +-
arch/ia64/include/asm/pci.h | 1 -
arch/ia64/pci/pci.c | 35 ++--
arch/ia64/sn/kernel/io_init.c | 4 +-
arch/m68k/coldfire/pci.c | 2 +-
arch/microblaze/pci/pci-common.c | 15 +--
arch/mips/include/asm/pci.h | 2 -
arch/mips/pci/pci.c | 4 +-
arch/mn10300/unit-asb2305/pci.c | 3 +-
arch/powerpc/include/asm/machdep.h | 2 +-
arch/powerpc/kernel/pci-common.c | 79 +++++-----
arch/powerpc/platforms/pseries/pci.c | 8 +-
arch/powerpc/platforms/pseries/pseries.h | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
arch/s390/pci/pci.c | 10 +-
arch/sh/drivers/pci/pci.c | 4 +-
arch/sh/include/asm/pci.h | 2 -
arch/sparc/kernel/leon_pci.c | 2 +-
arch/sparc/kernel/pci.c | 45 +++---
arch/sparc/kernel/pcic.c | 2 +-
arch/tile/include/asm/pci.h | 2 -
arch/tile/kernel/pci.c | 4 +-
arch/tile/kernel/pci_gx.c | 4 +-
arch/unicore32/kernel/pci.c | 2 +-
arch/x86/include/asm/pci.h | 6 -
arch/x86/pci/acpi.c | 37 +++--
arch/x86/pci/common.c | 2 +-
arch/xtensa/kernel/pci.c | 2 +-
drivers/parisc/dino.c | 6 +-
drivers/parisc/lba_pci.c | 6 +-
drivers/pci/host-bridge.c | 223 +++++++++++++++++++++++++
drivers/pci/host/pci-mvebu.c | 18 +--
drivers/pci/host/pci-tegra.c | 16 --
drivers/pci/host/pci-versatile.c | 3 +-
drivers/pci/host/pci-xgene.c | 5 +-
drivers/pci/host/pcie-designware.c | 6 +-
drivers/pci/host/pcie-xilinx.c | 2 +-
drivers/pci/hotplug/acpiphp_glue.c | 29 +---
drivers/pci/hotplug/ibmphp_core.c | 2 +-
drivers/pci/pci.c | 85 +++-------
drivers/pci/pci.h | 5 +
drivers/pci/probe.c | 265 ++++++++++++++---------------
drivers/pci/xen-pcifront.c | 16 ++-
include/linux/pci.h | 45 +++---
52 files changed, 573 insertions(+), 467 deletions(-)


2015-04-21 11:38:09

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 01/29] xen/PCI: Don't use deprecated function pci_scan_bus_parented()

From: Arnd Bergmann <[email protected]>

Use pci_scan_root_bus() instead of deprecated function
pci_scan_bus_parented().

Signed-off-by: Arnd Bergmann <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
CC: Konrad Rzeszutek Wilk <[email protected]>
CC: [email protected]
---
drivers/pci/xen-pcifront.c | 16 +++++++++++++---
1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index b1ffebe..a69e529 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -446,9 +446,15 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
unsigned int domain, unsigned int bus)
{
struct pci_bus *b;
+ LIST_HEAD(resources);
struct pcifront_sd *sd = NULL;
struct pci_bus_entry *bus_entry = NULL;
int err = 0;
+ static struct resource busn_res = {
+ .start = 0,
+ .end = 255,
+ .flags = IORESOURCE_BUS,
+ };

#ifndef CONFIG_PCI_DOMAINS
if (domain != 0) {
@@ -470,17 +476,21 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
err = -ENOMEM;
goto err_out;
}
+ pci_add_resource(&resources, &ioport_resource);
+ pci_add_resource(&resources, &iomem_resource);
+ pci_add_resource(&resources, &busn_res);
pcifront_init_sd(sd, domain, bus, pdev);

pci_lock_rescan_remove();

- b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
- &pcifront_bus_ops, sd);
+ b = pci_scan_root_bus(&pdev->xdev->dev, bus,
+ &pcifront_bus_ops, sd, &resources);
if (!b) {
dev_err(&pdev->xdev->dev,
"Error creating PCI Frontend Bus!\n");
err = -ENOMEM;
pci_unlock_rescan_remove();
+ pci_free_resource_list(&resources);
goto err_out;
}

@@ -488,7 +498,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,

list_add(&bus_entry->list, &pdev->root_buses);

- /* pci_scan_bus_parented skips devices which do not have a have
+ /* pci_scan_root_bus skips devices which do not have a
* devfn==0. The pcifront_scan_bus enumerates all devfn. */
err = pcifront_scan_bus(pdev, domain, bus, b);

--
1.7.1

2015-04-21 11:39:04

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 02/29] PCI: Remove deprecated pci_scan_bus_parented()

No one uses pci_scan_bus_parented() any more,
remove it.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/probe.c | 19 -------------------
include/linux/pci.h | 2 --
2 files changed, 0 insertions(+), 21 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6675a7a..7d6a61c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2094,25 +2094,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
}
EXPORT_SYMBOL(pci_scan_root_bus);

-/* Deprecated; use pci_scan_root_bus() instead */
-struct pci_bus *pci_scan_bus_parented(struct device *parent,
- int bus, struct pci_ops *ops, void *sysdata)
-{
- LIST_HEAD(resources);
- struct pci_bus *b;
-
- 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)
- pci_scan_child_bus(b);
- else
- pci_free_resource_list(&resources);
- return b;
-}
-EXPORT_SYMBOL(pci_scan_bus_parented);
-
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
void *sysdata)
{
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e63112f..f0b4f7b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -773,8 +773,6 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
void pcibios_scan_specific_bus(int busn);
struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
-struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata);
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,
--
1.7.1

2015-04-21 11:48:04

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 03/29] PCI: Save domain in pci_host_bridge

Save domain in pci_host_bridge, so we could get domain
from pci_host_bridge, and at the end of series, we could
clean up the arch specific pci_domain_nr(). For arm/arm64,
the domain argument is pointless, because they enable
CONFIG_PCI_DOMAINS_GENERIC, PCI core would assign domain
number for them, so we pass meaningless -1 as the domain
number.

Tested-by: Gregory CLEMENT <[email protected]> #mvebu part
Signed-off-by: Yijing Wang <[email protected]>
---
arch/alpha/kernel/pci.c | 4 ++--
arch/alpha/kernel/sys_nautilus.c | 2 +-
arch/arm/kernel/bios32.c | 2 +-
arch/arm/mach-dove/pcie.c | 2 +-
arch/arm/mach-iop13xx/pci.c | 4 ++--
arch/arm/mach-mv78xx0/pcie.c | 2 +-
arch/arm/mach-orion5x/pci.c | 4 ++--
arch/frv/mb93090-mb00/pci-vdk.c | 3 ++-
arch/ia64/pci/pci.c | 4 ++--
arch/ia64/sn/kernel/io_init.c | 4 ++--
arch/m68k/coldfire/pci.c | 2 +-
arch/microblaze/pci/pci-common.c | 4 ++--
arch/mips/pci/pci.c | 4 ++--
arch/mn10300/unit-asb2305/pci.c | 3 ++-
arch/powerpc/kernel/pci-common.c | 4 ++--
arch/s390/pci/pci.c | 4 ++--
arch/sh/drivers/pci/pci.c | 4 ++--
arch/sparc/kernel/leon_pci.c | 2 +-
arch/sparc/kernel/pci.c | 4 ++--
arch/sparc/kernel/pcic.c | 2 +-
arch/tile/kernel/pci.c | 4 ++--
arch/tile/kernel/pci_gx.c | 4 ++--
arch/unicore32/kernel/pci.c | 2 +-
arch/x86/pci/acpi.c | 4 ++--
arch/x86/pci/common.c | 2 +-
arch/xtensa/kernel/pci.c | 2 +-
drivers/parisc/dino.c | 2 +-
drivers/parisc/lba_pci.c | 2 +-
drivers/pci/host/pci-mvebu.c | 2 +-
drivers/pci/host/pci-tegra.c | 4 ++--
drivers/pci/host/pci-versatile.c | 3 ++-
drivers/pci/host/pci-xgene.c | 2 +-
drivers/pci/host/pcie-designware.c | 2 +-
drivers/pci/host/pcie-xilinx.c | 2 +-
drivers/pci/hotplug/ibmphp_core.c | 2 +-
drivers/pci/probe.c | 21 +++++++++++++--------
drivers/pci/xen-pcifront.c | 2 +-
include/linux/pci.h | 8 +++++---
38 files changed, 72 insertions(+), 62 deletions(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 82f738e..2b0bce9 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -336,8 +336,8 @@ common_init_pci(void)
pci_add_resource_offset(&resources, hose->mem_space,
hose->mem_space->start);

- bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
- hose, &resources);
+ bus = pci_scan_root_bus(NULL, hose->index, next_busno,
+ alpha_mv.pci_ops, hose, &resources);
if (!bus)
continue;
hose->bus = bus;
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 700686d..9614e4e 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -206,7 +206,7 @@ nautilus_init_pci(void)
unsigned long memtop = max_low_pfn << PAGE_SHIFT;

/* Scan our single hose. */
- bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+ bus = pci_scan_bus(hose->index, 0, alpha_mv.pci_ops, hose);
if (!bus)
return;

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index ab19b7c..fec2c90 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -486,7 +486,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
if (hw->scan)
sys->bus = hw->scan(nr, sys);
else
- sys->bus = pci_scan_root_bus(parent, sys->busnr,
+ sys->bus = pci_scan_root_bus(parent, -1, sys->busnr,
hw->ops, sys, &sys->resources);

if (!sys->bus)
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 91fe971..a379287 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -160,7 +160,7 @@ dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
return NULL;
}

- return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+ return pci_scan_root_bus(NULL, -1, sys->busnr, &pcie_ops, sys,
&sys->resources);
}

diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index 9082b84..bc4ba7e 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -535,12 +535,12 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
while(time_before(jiffies, atux_trhfa_timeout))
udelay(100);

- bus = pci_bus_atux = pci_scan_root_bus(NULL, sys->busnr,
+ bus = pci_bus_atux = pci_scan_root_bus(NULL, -1, sys->busnr,
&iop13xx_atux_ops,
sys, &sys->resources);
break;
case IOP13XX_INIT_ATU_ATUE:
- bus = pci_bus_atue = pci_scan_root_bus(NULL, sys->busnr,
+ bus = pci_bus_atue = pci_scan_root_bus(NULL, -1, sys->busnr,
&iop13xx_atue_ops,
sys, &sys->resources);
break;
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index 097ea4c..4010a95 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -202,7 +202,7 @@ mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
return NULL;
}

- return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+ return pci_scan_root_bus(NULL, -1, sys->busnr, &pcie_ops, sys,
&sys->resources);
}

diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index b02f394..83898cc 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -558,11 +558,11 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
{
if (nr == 0)
- return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+ return pci_scan_root_bus(NULL, -1, sys->busnr, &pcie_ops, sys,
&sys->resources);

if (nr == 1 && !orion5x_pci_disabled)
- return pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
+ return pci_scan_root_bus(NULL, -1, sys->busnr, &pci_ops, sys,
&sys->resources);

BUG();
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index f211839..719fb75 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -384,7 +384,8 @@ int __init pcibios_init(void)
printk("PCI: Probing PCI hardware\n");
pci_add_resource(&resources, &pci_ioport_resource);
pci_add_resource(&resources, &pci_iomem_resource);
- bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
+ bus = pci_scan_root_bus(NULL, 0, 0, pci_root_ops, NULL,
+ &resources);

pcibios_irq_init();
pcibios_fixup_irqs();
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 48cc657..c642bc8 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -465,8 +465,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
* should handle the case here, but it appears that IA64 hasn't
* such quirk. So we just ignore the case now.
*/
- pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
- &info->resources);
+ pbus = pci_create_root_bus(NULL, domain, bus, &pci_root_ops,
+ controller, &info->resources);
if (!pbus) {
pci_free_resource_list(&info->resources);
__release_pci_root_info(info);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 1be65eb..d528814 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -266,8 +266,8 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
pci_add_resource_offset(&resources, &res[1],
prom_bussoft_ptr->bs_legacy_mem);

- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
- &resources);
+ bus = pci_scan_root_bus(NULL, controller->segment, busnum,
+ &pci_root_ops, controller, &resources);
if (bus == NULL) {
kfree(res);
kfree(controller);
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index 821de92..63c0c2f 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -312,7 +312,7 @@ static int __init mcf_pci_init(void)
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(msecs_to_jiffies(200));

- rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL);
+ rootbus = pci_scan_bus(0, 0, &mcf_pci_ops, NULL);
if (!rootbus)
return -ENODEV;

diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index ae838ed..d232c8a 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1350,8 +1350,8 @@ static void pcibios_scan_phb(struct pci_controller *hose)

pcibios_setup_phb_resources(hose, &resources);

- bus = pci_scan_root_bus(hose->parent, hose->first_busno,
- hose->ops, hose, &resources);
+ bus = pci_scan_root_bus(hose->parent, hose->global_number,
+ hose->first_busno, hose->ops, hose, &resources);
if (bus == NULL) {
pr_err("Failed to create bus for PCI domain %04x\n",
hose->global_number);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 8bb13a4..d6361d5 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -92,8 +92,8 @@ static void pcibios_scanbus(struct pci_controller *hose)
pci_add_resource_offset(&resources,
hose->mem_resource, hose->mem_offset);
pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset);
- bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
- &resources);
+ bus = pci_scan_root_bus(NULL, hose->index, next_busno,
+ hose->pci_ops, hose, &resources);
hose->bus = bus;

need_domain_info = need_domain_info || hose->index;
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 3dfe2d3..a298172 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -372,7 +372,8 @@ static int __init pcibios_init(void)

pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
- bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+ bus = pci_scan_root_bus(NULL, 0, 0, &pci_direct_ampci,
+ NULL, &resources);
if (!bus)
return 0;

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2a525c9..9913f6c 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1612,8 +1612,8 @@ void pcibios_scan_phb(struct pci_controller *hose)
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);
+ bus = pci_create_root_bus(hose->parent, hose->global_number,
+ hose->first_busno, hose->ops, hose, &resources);
if (bus == NULL) {
pr_err("Failed to create bus for PCI domain %04x\n",
hose->global_number);
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index b2c76f6..d70b2db 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -774,8 +774,8 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
if (ret)
return ret;

- zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
- zdev, &resources);
+ zdev->bus = pci_scan_root_bus(NULL, zdev->domain, ZPCI_BUS_NR,
+ &pci_root_ops, zdev, &resources);
if (!zdev->bus) {
zpci_cleanup_bus_resources(zdev);
return -EIO;
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index d5462b7..293249a 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -52,8 +52,8 @@ static void pcibios_scanbus(struct pci_channel *hose)
pci_add_resource_offset(&resources, res, offset);
}

- bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
- &resources);
+ bus = pci_scan_root_bus(NULL, hose->index, next_busno,
+ hose->pci_ops, hose, &resources);
hose->bus = bus;

need_domain_info = need_domain_info || hose->index;
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 4371f72..36d702d 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -32,7 +32,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
info->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &info->busn);

- root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
+ root_bus = pci_scan_root_bus(&ofdev->dev, 0, 0, info->ops, info,
&resources);
if (!root_bus) {
pci_free_resource_list(&resources);
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 9e267ca..e40e456 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -667,8 +667,8 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
pbm->busn.end = pbm->pci_last_busno;
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);
+ bus = pci_create_root_bus(parent, pbm->index, pbm->pci_first_busno,
+ pbm->pci_ops, pbm, &resources);
if (!bus) {
printk(KERN_ERR "Failed to create bus for %s\n",
node->full_name);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 24384e1..7e86410 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -390,7 +390,7 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
{
struct linux_pbm_info *pbm = &pcic->pbm;

- pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+ pbm->pci_bus = pci_scan_bus(0, pbm->pci_first_busno, &pcic_ops, pbm);
if (!pbm->pci_bus)
return;

diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 9475a74..6ae0871 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -306,8 +306,8 @@ int __init pcibios_init(void)

pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
- bus = pci_scan_root_bus(NULL, 0, controller->ops,
- controller, &resources);
+ bus = pci_scan_root_bus(NULL, controller->index, 0,
+ controller->ops, controller, &resources);
controller->root_bus = bus;
controller->last_busno = bus->busn_res.end;
}
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index b1df847..d47a698 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -881,8 +881,8 @@ int __init pcibios_init(void)
controller->mem_offset);
pci_add_resource(&resources, &controller->io_space);
controller->first_busno = next_busno;
- bus = pci_scan_root_bus(NULL, next_busno, controller->ops,
- controller, &resources);
+ bus = pci_scan_root_bus(NULL, controller->index, next_busno,
+ controller->ops, controller, &resources);
controller->root_bus = bus;
next_busno = bus->busn_res.end + 1;
}
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index d45fa5f..ef9be16 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -258,7 +258,7 @@ static int __init pci_common_init(void)

pci_puv3_preinit();

- puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+ puv3_bus = pci_scan_bus(0, 0, &pci_puv3_ops, NULL);

if (!puv3_bus)
panic("PCI: unable to scan bus!");
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index e469598..7563855 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -430,8 +430,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
(u8)root->secondary.end, root->mcfg_addr))
- bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
- sd, &resources);
+ bus = pci_create_root_bus(NULL, domain, busnum,
+ &pci_root_ops, sd, &resources);

if (bus) {
pci_scan_child_bus(bus);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 95a0ba7..9813266 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -486,7 +486,7 @@ void pcibios_scan_root(int busnum)
sd->node = x86_pci_root_bus_node(busnum);
x86_pci_root_bus_resources(busnum, &resources);
printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
+ bus = pci_scan_root_bus(NULL, 0, busnum, &pci_root_ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
kfree(sd);
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index b848cc3..66da4c3 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -183,7 +183,7 @@ static int __init pcibios_init(void)
pci_ctrl->last_busno = 0xff;
INIT_LIST_HEAD(&resources);
pci_controller_apertures(pci_ctrl, &resources);
- bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
+ bus = pci_scan_root_bus(NULL, 0, pci_ctrl->first_busno,
pci_ctrl->ops, pci_ctrl, &resources);
if (!bus)
continue;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index a0580af..f375252 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -986,7 +986,7 @@ static int __init dino_probe(struct parisc_device *dev)
** with configuration accessor functions.
*/
dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
- dino_current_bus, &dino_cfg_ops, NULL, &resources);
+ 0, dino_current_bus, &dino_cfg_ops, NULL, &resources);
if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index dceb9dd..2949030 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1563,7 +1563,7 @@ lba_driver_probe(struct parisc_device *dev)

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,
+ pci_create_root_bus(&dev->dev, 0, lba_dev->hba.bus_num.start,
cfg_ops, NULL, &resources);
if (!lba_bus) {
pci_free_resource_list(&resources);
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 1ab8635..bc4c6c0 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -756,7 +756,7 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct mvebu_pcie *pcie = sys_to_pcie(sys);
struct pci_bus *bus;

- bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
+ bus = pci_create_root_bus(&pcie->pdev->dev, -1, sys->busnr,
&mvebu_pcie_ops, sys, &sys->resources);
if (!bus)
return NULL;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 00e9272..94e9362 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -635,8 +635,8 @@ static struct pci_bus *tegra_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct tegra_pcie *pcie = sys_to_pcie(sys);
struct pci_bus *bus;

- bus = pci_create_root_bus(pcie->dev, sys->busnr, &tegra_pcie_ops, sys,
- &sys->resources);
+ bus = pci_create_root_bus(pcie->dev, -1, sys->busnr, &tegra_pcie_ops,
+ sys, &sys->resources);
if (!bus)
return NULL;

diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c
index 0863d9c..b9fdb6b 100644
--- a/drivers/pci/host/pci-versatile.c
+++ b/drivers/pci/host/pci-versatile.c
@@ -208,7 +208,8 @@ static int versatile_pci_probe(struct platform_device *pdev)
pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);

- bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, &sys, &pci_res);
+ bus = pci_scan_root_bus(&pdev->dev, -1, 0, &pci_versatile_ops,
+ &sys, &pci_res);
if (!bus)
return -ENOMEM;

diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index ee082c0..c048e03 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -499,7 +499,7 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret)
return ret;

- bus = pci_create_root_bus(&pdev->dev, 0,
+ bus = pci_create_root_bus(&pdev->dev, -1, 0,
&xgene_pcie_ops, port, &res);
if (!bus)
return -ENOMEM;
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 1f4ea6f..93778b9 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -728,7 +728,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pcie_port *pp = sys_to_pcie(sys);

pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
+ bus = pci_create_root_bus(pp->dev, -1, sys->busnr,
&dw_pcie_ops, sys, &sys->resources);
if (!bus)
return NULL;
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index f1a06a0..b5a72a5 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -647,7 +647,7 @@ static struct pci_bus *xilinx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pci_bus *bus;

port->root_busno = sys->busnr;
- bus = pci_scan_root_bus(port->dev, sys->busnr, &xilinx_pcie_ops,
+ bus = pci_scan_root_bus(port->dev, -1, sys->busnr, &xilinx_pcie_ops,
sys, &sys->resources);

return bus;
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 1530247..db6240e 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -765,7 +765,7 @@ static u8 bus_structure_fixup(u8 busno)
(l != 0x0000) && (l != 0xffff)) {
debug("%s - Inside bus_structure_fixup()\n",
__func__);
- b = pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+ b = pci_scan_bus(0, busno, ibmphp_pci_bus->ops, NULL);
if (!b)
continue;

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 7d6a61c..9f9445e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1891,8 +1891,9 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
{
}

-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
+ int bus, struct pci_ops *ops, void *sysdata,
+ struct list_head *resources)
{
int error;
struct pci_host_bridge *bridge;
@@ -1922,6 +1923,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
if (!bridge)
goto err_out;

+ bridge->domain = domain;
bridge->dev.parent = parent;
bridge->dev.release = pci_release_host_bridge_dev;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
@@ -2060,8 +2062,9 @@ void pci_bus_release_busn_res(struct pci_bus *b)
res, ret ? "can not be" : "is");
}

-struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
+ int bus, struct pci_ops *ops, void *sysdata,
+ struct list_head *resources)
{
struct resource_entry *window;
bool found = false;
@@ -2074,7 +2077,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
break;
}

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

@@ -2094,8 +2098,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
}
EXPORT_SYMBOL(pci_scan_root_bus);

-struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
- void *sysdata)
+struct pci_bus *pci_scan_bus(int domain, int bus,
+ struct pci_ops *ops, void *sysdata)
{
LIST_HEAD(resources);
struct pci_bus *b;
@@ -2103,7 +2107,8 @@ struct pci_bus *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);
+ b = pci_create_root_bus(NULL, domain, bus, ops, sysdata,
+ &resources);
if (b) {
pci_scan_child_bus(b);
} else {
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index a69e529..830a31e 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -483,7 +483,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,

pci_lock_rescan_remove();

- b = pci_scan_root_bus(&pdev->xdev->dev, bus,
+ b = pci_scan_root_bus(&pdev->xdev->dev, sd->domain, bus,
&pcifront_bus_ops, sd, &resources);
if (!b) {
dev_err(&pdev->xdev->dev,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f0b4f7b..1a0f8d2 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -401,6 +401,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
}

struct pci_host_bridge {
+ int domain;
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* resource_entry */
@@ -773,14 +774,15 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
void pcibios_scan_specific_bus(int busn);
struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
-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_bus *pci_scan_bus(int domain, int bus, struct pci_ops *ops,
+ void *sysdata);
+struct pci_bus *pci_create_root_bus(struct device *parent, int domain, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int 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 *pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, int domain, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
--
1.7.1

2015-04-21 11:38:18

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 04/29] PCI: Move pci_bus_assign_domain_nr() declaration into drivers/pci/pci.h

pci_bus_assign_domain_nr() is only called in probe.c,
Move pci_bus_assign_domain_nr() declaration into
drivers/pci/pci.h.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/pci.h | 9 +++++++++
include/linux/pci.h | 6 ------
2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d72f849..dbf1ac0 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -323,4 +323,13 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)

struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);

+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
+#else
+static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
+ struct device *parent)
+{
+}
+#endif
+
#endif /* DRIVERS_PCI_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1a0f8d2..0bdc639 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1331,12 +1331,6 @@ static inline int pci_domain_nr(struct pci_bus *bus)
{
return bus->domain_nr;
}
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
-#else
-static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
- struct device *parent)
-{
-}
#endif

/* some architectures require additional setup to direct VGA traffic */
--
1.7.1

2015-04-21 11:38:33

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 05/29] PCI: Remove argument bus for pci_create_root_bus()

All pci_create_root_bus() callers have supplied
busn resource, the argument bus is equal to
busn_res->start, clean up the redundant argument
bus for simplicity.

Signed-off-by: Yijing Wang <[email protected]>
---
arch/ia64/pci/pci.c | 3 +--
arch/powerpc/kernel/pci-common.c | 2 +-
arch/sparc/kernel/pci.c | 2 +-
arch/x86/pci/acpi.c | 4 ++--
drivers/parisc/dino.c | 2 +-
drivers/parisc/lba_pci.c | 3 +--
drivers/pci/host/pci-mvebu.c | 2 +-
drivers/pci/host/pci-tegra.c | 2 +-
drivers/pci/host/pci-xgene.c | 2 +-
drivers/pci/host/pcie-designware.c | 4 ++--
drivers/pci/probe.c | 26 ++++++++++++++++++++------
include/linux/pci.h | 2 +-
12 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index c642bc8..84f1eb8 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -424,7 +424,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
int domain = root->segment;
- int bus = root->secondary.start;
struct pci_controller *controller;
struct pci_root_info *info = NULL;
int busnum = root->secondary.start;
@@ -465,7 +464,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
* should handle the case here, but it appears that IA64 hasn't
* such quirk. So we just ignore the case now.
*/
- pbus = pci_create_root_bus(NULL, domain, bus, &pci_root_ops,
+ pbus = pci_create_root_bus(NULL, domain, &pci_root_ops,
controller, &info->resources);
if (!pbus) {
pci_free_resource_list(&info->resources);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9913f6c..9acc08d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1613,7 +1613,7 @@ void pcibios_scan_phb(struct pci_controller *hose)

/* Create an empty bus for the toplevel */
bus = pci_create_root_bus(hose->parent, hose->global_number,
- hose->first_busno, hose->ops, hose, &resources);
+ hose->ops, hose, &resources);
if (bus == NULL) {
pr_err("Failed to create bus for PCI domain %04x\n",
hose->global_number);
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index e40e456..6ff363c 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -667,7 +667,7 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
pbm->busn.end = pbm->pci_last_busno;
pbm->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &pbm->busn);
- bus = pci_create_root_bus(parent, pbm->index, pbm->pci_first_busno,
+ bus = pci_create_root_bus(parent, pbm->index,
pbm->pci_ops, pbm, &resources);
if (!bus) {
printk(KERN_ERR "Failed to create bus for %s\n",
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 7563855..d6aab1c 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -430,8 +430,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
(u8)root->secondary.end, root->mcfg_addr))
- bus = pci_create_root_bus(NULL, domain, busnum,
- &pci_root_ops, sd, &resources);
+ bus = pci_create_root_bus(NULL, domain, &pci_root_ops,
+ sd, &resources);

if (bus) {
pci_scan_child_bus(bus);
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index f375252..56abc43 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -986,7 +986,7 @@ static int __init dino_probe(struct parisc_device *dev)
** with configuration accessor functions.
*/
dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
- 0, dino_current_bus, &dino_cfg_ops, NULL, &resources);
+ 0, &dino_cfg_ops, NULL, &resources);
if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 2949030..0b9ed96 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1563,8 +1563,7 @@ lba_driver_probe(struct parisc_device *dev)

dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
- pci_create_root_bus(&dev->dev, 0, lba_dev->hba.bus_num.start,
- cfg_ops, NULL, &resources);
+ pci_create_root_bus(&dev->dev, 0, cfg_ops, NULL, &resources);
if (!lba_bus) {
pci_free_resource_list(&resources);
return 0;
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index bc4c6c0..c91a8b4 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -756,7 +756,7 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct mvebu_pcie *pcie = sys_to_pcie(sys);
struct pci_bus *bus;

- bus = pci_create_root_bus(&pcie->pdev->dev, -1, sys->busnr,
+ bus = pci_create_root_bus(&pcie->pdev->dev, -1,
&mvebu_pcie_ops, sys, &sys->resources);
if (!bus)
return NULL;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 94e9362..3e45142 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -635,7 +635,7 @@ static struct pci_bus *tegra_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct tegra_pcie *pcie = sys_to_pcie(sys);
struct pci_bus *bus;

- bus = pci_create_root_bus(pcie->dev, -1, sys->busnr, &tegra_pcie_ops,
+ bus = pci_create_root_bus(pcie->dev, -1, &tegra_pcie_ops,
sys, &sys->resources);
if (!bus)
return NULL;
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index c048e03..f11e77b 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -499,7 +499,7 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret)
return ret;

- bus = pci_create_root_bus(&pdev->dev, -1, 0,
+ bus = pci_create_root_bus(&pdev->dev, -1,
&xgene_pcie_ops, port, &res);
if (!bus)
return -ENOMEM;
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 93778b9..8854d25 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -728,8 +728,8 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pcie_port *pp = sys_to_pcie(sys);

pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, -1, sys->busnr,
- &dw_pcie_ops, sys, &sys->resources);
+ bus = pci_create_root_bus(pp->dev, -1, &dw_pcie_ops, sys,
+ &sys->resources);
if (!bus)
return NULL;

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 9f9445e..52b9257 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -59,6 +59,17 @@ static struct resource *get_pci_domain_busn_res(int domain_nr)
return &r->res;
}

+static struct resource_entry *pci_busn_resource(
+ struct list_head *resources)
+{
+ struct resource_entry *entry;
+
+ resource_list_for_each_entry(entry, resources)
+ if (entry->res->flags & IORESOURCE_BUS)
+ return entry;
+ return NULL;
+}
+
static int find_anything(struct device *dev, void *data)
{
return 1;
@@ -1892,18 +1903,21 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
}

struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
- int bus, struct pci_ops *ops, void *sysdata,
- struct list_head *resources)
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
- int error;
+ int error, bus;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct resource_entry *window, *n;
+ struct resource_entry *window, *n, *busn_res;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
char *fmt;

+ busn_res = pci_busn_resource(resources);
+ if (!busn_res)
+ return NULL;
+ bus = busn_res->res->start;
b = pci_alloc_bus(NULL);
if (!b)
return NULL;
@@ -2077,7 +2091,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
break;
}

- b = pci_create_root_bus(parent, domain, bus, ops,
+ b = pci_create_root_bus(parent, domain, ops,
sysdata, resources);
if (!b)
return NULL;
@@ -2107,7 +2121,7 @@ struct pci_bus *pci_scan_bus(int domain, int bus,
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
- b = pci_create_root_bus(NULL, domain, bus, ops, sysdata,
+ b = pci_create_root_bus(NULL, domain, ops, sysdata,
&resources);
if (b) {
pci_scan_child_bus(b);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0bdc639..df77a62 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -776,7 +776,7 @@ struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
struct pci_bus *pci_scan_bus(int domain, int bus, struct pci_ops *ops,
void *sysdata);
-struct pci_bus *pci_create_root_bus(struct device *parent, int domain, int bus,
+struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
--
1.7.1

2015-04-21 11:49:53

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 06/29] PCI: Alloc busn resource dynamically for pci_scan_bus()

Pci_scan_bus() always add the global busn_resource[00-FF],
the busn resource added is not accurate, if root bus number
is not equal to zero, the bus range bellow root bus number
is pointless, and this inaccurate busn resource would make
host bridge confuse, this patch dynamically allocate busn
resource instead of default global one, and add a flag
to pci_host_bridge, so when pci_host_bridge go to free,
the dynamic busn resource could also be freed properly.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/probe.c | 27 +++++++++++++++++++--------
include/linux/pci.h | 1 +
2 files changed, 20 insertions(+), 8 deletions(-)

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

-static 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);
@@ -516,11 +509,17 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)

static void pci_release_host_bridge_dev(struct device *dev)
{
+ struct resource_entry *entry;
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);

if (bridge->release_fn)
bridge->release_fn(bridge);

+ if (bridge->dynamic_busn) {
+ entry = pci_busn_resource(&bridge->windows);
+ kfree(entry->res);
+ }
+
pci_free_resource_list(&bridge->windows);

kfree(bridge);
@@ -2117,15 +2116,27 @@ struct pci_bus *pci_scan_bus(int domain, int bus,
{
LIST_HEAD(resources);
struct pci_bus *b;
+ struct resource *busn_resource;
+ struct pci_host_bridge *host;
+
+ busn_resource = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!busn_resource)
+ return NULL;

+ busn_resource->start = bus;
+ busn_resource->end = 255;
+ busn_resource->flags = IORESOURCE_BUS;
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
- pci_add_resource(&resources, &busn_resource);
+ pci_add_resource(&resources, busn_resource);
b = pci_create_root_bus(NULL, domain, ops, sysdata,
&resources);
if (b) {
+ host = to_pci_host_bridge(b->bridge);
+ host->dynamic_busn = true;
pci_scan_child_bus(b);
} else {
+ kfree(busn_resource);
pci_free_resource_list(&resources);
}
return b;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index df77a62..0716158 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,6 +402,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)

struct pci_host_bridge {
int domain;
+ bool dynamic_busn;
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* resource_entry */
--
1.7.1

2015-04-21 11:49:07

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 07/29] PCI: Allocate busn resource for pci_scan_root_bus()

Some pci_scan_root_bus() callers don't supply the busn
resource, because they don't know the max bus number.
Currently we insert default busn resource[bus-FF] to root bus,
and update the max bus number after pci_scan_child_bus().
We could dynamically allocate busn resource and add it
to pci_host_bridge, in the later patch, it would be easy
to check whether new pci_host_bridge busn resource conflict.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/probe.c | 43 ++++++++++++++++++++++++++++++-------------
1 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c425755..0eafda2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2041,6 +2041,8 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)

int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
{
+ struct resource_entry *entry;
+ struct pci_host_bridge *host;
struct resource *res = &b->busn_res;
struct resource old_res = *res;
resource_size_t size;
@@ -2058,6 +2060,14 @@ int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
if (!ret && !res->parent)
pci_bus_insert_busn_res(b, res->start, res->end);

+ if (!ret && pci_is_root_bus(b)) {
+ host = to_pci_host_bridge(b->bridge);
+ if (host->dynamic_busn) {
+ entry = pci_busn_resource(&host->windows);
+ entry->res->end = bus_max;
+ }
+ }
+
return ret;
}

@@ -2079,32 +2089,39 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
int bus, struct pci_ops *ops, void *sysdata,
struct list_head *resources)
{
- struct resource_entry *window;
- bool found = false;
+ struct resource_entry *entry;
+ struct resource *busn_resource = NULL;
+ struct pci_host_bridge *host;
struct pci_bus *b;
int max;

- resource_list_for_each_entry(window, resources)
- if (window->res->flags & IORESOURCE_BUS) {
- found = true;
- break;
- }
+ entry = pci_busn_resource(resources);
+ if (!entry) {
+ busn_resource = kzalloc(sizeof (struct resource), GFP_KERNEL);
+ if (!busn_resource)
+ return NULL;
+ busn_resource->start = bus;
+ busn_resource->end = 255;
+ busn_resource->flags = IORESOURCE_BUS;
+ pci_add_resource(resources, busn_resource);
+ pr_info(
+ "No busn resource found for root bus, will use [bus %02x-ff]\n",
+ bus);
+ }

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

- if (!found) {
- dev_info(&b->dev,
- "No busn resource found for root bus, will use [bus %02x-ff]\n",
- bus);
- pci_bus_insert_busn_res(b, bus, 255);
+ if (busn_resource) {
+ host = to_pci_host_bridge(b->bridge);
+ host->dynamic_busn = true;
}

max = pci_scan_child_bus(b);

- if (!found)
+ if (busn_resource)
pci_bus_update_busn_res_end(b, max);

return b;
--
1.7.1

2015-04-21 11:38:44

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 08/29] PCI: Introduce pci_host_assign_domain_nr() to assign domain

Introduce pci_host_assign_domain_nr() to assign domain
number for pci_host_bridge. In the later patch, we would
assign domain in pci_create_host_bridge, clean up the
pci_bus_assign_domain_nr() and move this function into
drivers/pci/host-bridge.c.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/pci.c | 24 +++++++++++++++++++-----
drivers/pci/pci.h | 1 +
2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index acc4b6e..95ea445 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4506,10 +4506,10 @@ int pci_get_new_domain_nr(void)
}

#ifdef CONFIG_PCI_DOMAINS_GENERIC
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+static int pci_assign_domain_nr(struct device *dev)
{
static int use_dt_domains = -1;
- int domain = of_get_pci_domain_nr(parent->of_node);
+ int domain = of_get_pci_domain_nr(dev->of_node);

/*
* Check DT domain and use_dt_domains values.
@@ -4543,16 +4543,30 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
use_dt_domains = 0;
domain = pci_get_new_domain_nr();
} else {
- dev_err(parent, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
- parent->of_node->full_name);
+ dev_err(dev, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
+ dev->of_node->full_name);
domain = -1;
}

- bus->domain_nr = domain;
+ return domain;
+}
+
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+ bus->domain_nr = pci_assign_domain_nr(parent);
}
#endif
#endif

+void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain)
+{
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+ host->domain = pci_assign_domain_nr(host->dev.parent);
+#else
+ host->domain = domain;
+#endif
+}
+
/**
* pci_ext_cfg_avail - can we access extended PCI config space?
*
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index dbf1ac0..1e291e4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -332,4 +332,5 @@ static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
}
#endif

+void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain);
#endif /* DRIVERS_PCI_H */
--
1.7.1

2015-04-21 11:38:47

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 09/29] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

This patch separate pci_host_bridge creation out
of pci_create_root_bus(), and try to make a generic
pci_host_bridge, then we could make it hold host
bridge specific operations like
pcibios_root_bridge_prepare(). The changes are
transparent to platform host bridge drivers.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 58 +++++++++++++++++++++
drivers/pci/pci.h | 5 ++-
drivers/pci/probe.c | 126 ++++++++++++++++++++-------------------------
3 files changed, 118 insertions(+), 71 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 5f4a2e0..78a30c2 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,64 @@

#include "pci.h"

+static void pci_release_host_bridge_dev(struct device *dev)
+{
+ struct resource_entry *entry;
+ struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+ if (bridge->release_fn)
+ bridge->release_fn(bridge);
+
+ if (bridge->dynamic_busn) {
+ entry = pci_busn_resource(&bridge->windows);
+ kfree(entry->res);
+ }
+
+ pci_free_resource_list(&bridge->windows);
+ kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+ struct device *parent, int domain,
+ struct list_head *resources)
+{
+ int error, bus;
+ struct pci_host_bridge *host;
+ struct resource_entry *window, *n, *busn_res;
+
+ busn_res = pci_busn_resource(resources);
+ if (!busn_res)
+ return NULL;
+
+ bus = busn_res->res->start;
+ host = kzalloc(sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return NULL;
+
+ INIT_LIST_HEAD(&host->windows);
+ resource_list_for_each_entry_safe(window, n, resources)
+ list_move_tail(&window->node, &host->windows);
+
+ host->dev.parent = parent;
+ pci_host_assign_domain_nr(host, domain);
+ host->dev.release = pci_release_host_bridge_dev;
+ dev_set_name(&host->dev, "pci%04x:%02x",
+ host->domain, bus);
+
+ error = device_register(&host->dev);
+ if (error) {
+ put_device(&host->dev);
+ return NULL;
+ }
+
+ return host;
+}
+
+void pci_free_host_bridge(struct pci_host_bridge *host)
+{
+ device_unregister(&host->dev);
+}
+
static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
{
while (bus->parent)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 1e291e4..947c05a 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -331,6 +331,9 @@ static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
{
}
#endif
-
+struct resource_entry *pci_busn_resource(struct list_head *resources);
void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain);
+struct pci_host_bridge *pci_create_host_bridge(struct device *parent,
+ int domain, struct list_head *resources);
+void pci_free_host_bridge(struct pci_host_bridge *host);
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0eafda2..0b80ecb 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -52,7 +52,7 @@ static struct resource *get_pci_domain_busn_res(int domain_nr)
return &r->res;
}

-static struct resource_entry *pci_busn_resource(
+struct resource_entry *pci_busn_resource(
struct list_head *resources)
{
struct resource_entry *entry;
@@ -507,37 +507,6 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
return b;
}

-static void pci_release_host_bridge_dev(struct device *dev)
-{
- struct resource_entry *entry;
- struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
-
- if (bridge->release_fn)
- bridge->release_fn(bridge);
-
- if (bridge->dynamic_busn) {
- entry = pci_busn_resource(&bridge->windows);
- kfree(entry->res);
- }
-
- pci_free_resource_list(&bridge->windows);
-
- kfree(bridge);
-}
-
-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)
- return NULL;
-
- INIT_LIST_HEAD(&bridge->windows);
- bridge->bus = b;
- return bridge;
-}
-
static const unsigned char pcix_bus_speed[] = {
PCI_SPEED_UNKNOWN, /* 0 */
PCI_SPEED_66MHz_PCIX, /* 1 */
@@ -1901,22 +1870,24 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
{
}

-struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
- struct pci_ops *ops, void *sysdata, struct list_head *resources)
+static struct pci_bus *__pci_create_root_bus(
+ struct pci_host_bridge *bridge, struct pci_ops *ops,
+ void *sysdata)
{
int error, bus;
- struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct resource_entry *window, *n, *busn_res;
+ struct resource_entry *window, *busn_res;
+ struct device *parent;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
char *fmt;

- busn_res = pci_busn_resource(resources);
+ busn_res = pci_busn_resource(&bridge->windows);
if (!busn_res)
return NULL;
bus = busn_res->res->start;
+ parent = bridge->dev.parent;
b = pci_alloc_bus(NULL);
if (!b)
return NULL;
@@ -1932,26 +1903,12 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
goto err_out;
}

- bridge = pci_alloc_host_bridge(b);
- if (!bridge)
- goto err_out;
-
- bridge->domain = domain;
- bridge->dev.parent = parent;
- bridge->dev.release = pci_release_host_bridge_dev;
- dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ bridge->bus = b;
+ b->bridge = get_device(&bridge->dev);
error = pcibios_root_bridge_prepare(bridge);
- if (error) {
- kfree(bridge);
- goto err_out;
- }
+ if (error)
+ goto put_bridge;

- error = device_register(&bridge->dev);
- if (error) {
- put_device(&bridge->dev);
- goto err_out;
- }
- b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);

@@ -1960,10 +1917,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int domain,

b->dev.class = &pcibus_class;
b->dev.parent = b->bridge;
- dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+ dev_set_name(&b->dev, "%04x:%02x", bridge->domain, bus);
error = device_register(&b->dev);
if (error)
- goto class_dev_reg_err;
+ goto put_bridge;

pcibios_add_bus(b);

@@ -1976,8 +1933,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));

/* Add initial resources to the bus */
- resource_list_for_each_entry_safe(window, n, resources) {
- list_move_tail(&window->node, &bridge->windows);
+ resource_list_for_each_entry(window, &bridge->windows) {
res = window->res;
offset = window->offset;
if (res->flags & IORESOURCE_BUS)
@@ -2003,15 +1959,41 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int domain,

return b;

-class_dev_reg_err:
+put_bridge:
put_device(&bridge->dev);
- device_unregister(&bridge->dev);
err_out:
kfree(b);
return NULL;
}
EXPORT_SYMBOL_GPL(pci_create_root_bus);

+struct pci_bus *pci_create_root_bus(struct device *parent,
+ int domain, struct pci_ops *ops, void *sysdata,
+ struct list_head *resources)
+{
+ struct resource_entry *busn_res;
+ struct pci_host_bridge *host;
+
+ busn_res = pci_busn_resource(resources);
+ if (!busn_res) {
+ pr_err("No busn resource found\n");
+ return NULL;
+ }
+
+ host = pci_create_host_bridge(parent, domain, resources);
+ if (!host)
+ return NULL;
+
+ host->bus = __pci_create_root_bus(host, ops, sysdata);
+ if (!host->bus) {
+ pci_free_host_bridge(host);
+ return NULL;
+ }
+
+ return host->bus;
+}
+
+
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
{
struct resource *res = &b->busn_res;
@@ -2092,7 +2074,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
struct resource_entry *entry;
struct resource *busn_resource = NULL;
struct pci_host_bridge *host;
- struct pci_bus *b;
int max;

entry = pci_busn_resource(resources);
@@ -2109,22 +2090,27 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
bus);
}

- b = pci_create_root_bus(parent, domain, ops,
- sysdata, resources);
- if (!b)
+ host = pci_create_host_bridge(parent, domain, resources);
+ if (!host) {
+ kfree(busn_resource);
return NULL;
+ }

- if (busn_resource) {
- host = to_pci_host_bridge(b->bridge);
+ if (busn_resource)
host->dynamic_busn = true;
+
+ host->bus = __pci_create_root_bus(host, ops, sysdata);
+ if (!host->bus) {
+ pci_free_host_bridge(host);
+ return NULL;
}

- max = pci_scan_child_bus(b);
+ max = pci_scan_child_bus(host->bus);

if (busn_resource)
- pci_bus_update_busn_res_end(b, max);
+ pci_bus_update_busn_res_end(host->bus, max);

- return b;
+ return host->bus;
}
EXPORT_SYMBOL(pci_scan_root_bus);

--
1.7.1

2015-04-21 11:38:51

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 10/29] PCI: Introduce pci_host_bridge_list to manage host bridges

Introduce pci_host_bridge_list to manage pci host
bridges in system, this make us have the ability
to check whether the new host would conflict with
existing one. Then we could remove bus alreay exist
check in __pci_create_root_bus().

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/pci/probe.c | 9 +-----
include/linux/pci.h | 1 +
3 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 78a30c2..e05d8fc 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,9 @@

#include "pci.h"

+static LIST_HEAD(pci_host_bridge_list);
+static DEFINE_MUTEX(pci_host_mutex);
+
static void pci_release_host_bridge_dev(struct device *dev)
{
struct resource_entry *entry;
@@ -25,12 +28,64 @@ static void pci_release_host_bridge_dev(struct device *dev)
kfree(bridge);
}

+static int pci_host_busn_res_check(
+ struct pci_host_bridge *new, struct pci_host_bridge *old)
+{
+ int i;
+ bool conflict;
+ struct resource_entry *entry;
+ struct resource *res_new = NULL, *res_old = NULL;
+
+ entry = pci_busn_resource(&old->windows);
+ res_old = entry->res;
+ entry = pci_busn_resource(&new->windows);
+ res_new = entry->res;
+
+ conflict = resource_overlaps(res_new, res_old);
+ if (conflict) {
+ /*
+ * We hope every host bridge has its own exclusive
+ * busn resource, then if new host bridge's busn
+ * resource conflicts with existing host bridge,
+ * we could fail it. But in reality, firmware may
+ * doesn't supply busn resource to every host bridge.
+ * Or worse, supply the wrong busn resource to
+ * host bridge. In order to avoid the introduction of
+ * regression, we try to adjust busn resource for
+ * both new and existing host bridges. But if root
+ * bus number conflicts, must fail it.
+ */
+ pr_warn("pci%04x:%02x %pR conflicts with pci%04x:%02x %pR\n",
+ new->domain, (int)res_new->start, res_new,
+ old->domain, (int)res_old->start, res_old);
+ if (res_new->start == res_old->start)
+ return -ENOSPC;
+
+ if (res_new->start < res_old->start) {
+ res_new->end = res_old->start - 1;
+ pr_warn("pci%04x:%02x busn resource update to %pR\n",
+ new->domain, (int)res_new->start, res_new);
+ } else {
+ for (i = res_new->start;
+ i < (res_old->end - res_new->start + 1); i++) {
+ if (pci_find_bus(new->domain, i))
+ return -ENOSPC;
+ }
+ res_old->end = res_new->start - 1;
+ pr_warn("pci%04x:%02x busn resource update to %pR\n",
+ old->domain, (int)res_old->start, res_old);
+ }
+ }
+
+ return 0;
+}
+
struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain,
struct list_head *resources)
{
int error, bus;
- struct pci_host_bridge *host;
+ struct pci_host_bridge *host, *tmp;
struct resource_entry *window, *n, *busn_res;

busn_res = pci_busn_resource(resources);
@@ -48,6 +103,20 @@ struct pci_host_bridge *pci_create_host_bridge(

host->dev.parent = parent;
pci_host_assign_domain_nr(host, domain);
+
+ mutex_lock(&pci_host_mutex);
+ list_for_each_entry(tmp, &pci_host_bridge_list, list) {
+ if (tmp->domain == host->domain
+ && pci_host_busn_res_check(host, tmp)) {
+ mutex_unlock(&pci_host_mutex);
+ pci_free_resource_list(&host->windows);
+ kfree(host);
+ return NULL;
+ }
+ }
+ list_add_tail(&host->list, &pci_host_bridge_list);
+ mutex_unlock(&pci_host_mutex);
+
host->dev.release = pci_release_host_bridge_dev;
dev_set_name(&host->dev, "pci%04x:%02x",
host->domain, bus);
@@ -63,6 +132,10 @@ struct pci_host_bridge *pci_create_host_bridge(

void pci_free_host_bridge(struct pci_host_bridge *host)
{
+ mutex_lock(&pci_host_mutex);
+ list_del(&host->list);
+ mutex_unlock(&pci_host_mutex);
+
device_unregister(&host->dev);
}

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0b80ecb..d8c4da8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1875,7 +1875,7 @@ static struct pci_bus *__pci_create_root_bus(
void *sysdata)
{
int error, bus;
- struct pci_bus *b, *b2;
+ struct pci_bus *b;
struct resource_entry *window, *busn_res;
struct device *parent;
struct resource *res;
@@ -1896,12 +1896,6 @@ static struct pci_bus *__pci_create_root_bus(
b->ops = ops;
b->number = b->busn_res.start = bus;
pci_bus_assign_domain_nr(b, parent);
- b2 = pci_find_bus(pci_domain_nr(b), bus);
- if (b2) {
- /* If we already got to this bus through a different bridge, ignore it */
- dev_dbg(&b2->dev, "bus already known\n");
- goto err_out;
- }

bridge->bus = b;
b->bridge = get_device(&bridge->dev);
@@ -1961,7 +1955,6 @@ static struct pci_bus *__pci_create_root_bus(

put_bridge:
put_device(&bridge->dev);
-err_out:
kfree(b);
return NULL;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0716158..9a8a223 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -406,6 +406,7 @@ struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* resource_entry */
+ struct list_head list;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
unsigned int ignore_reset_delay:1; /* for entire hierarchy */
--
1.7.1

2015-04-21 11:39:27

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 11/29] PCI: Save sysdata in pci_host_bridge drvdata

Save platform specific sysdata in pci_host_bridge
drvdata, host bridge specific operation need to
access it before the pci bus creation.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 3 ++-
drivers/pci/pci.h | 2 +-
drivers/pci/probe.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index e05d8fc..b1cc6ef 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -81,7 +81,7 @@ static int pci_host_busn_res_check(
}

struct pci_host_bridge *pci_create_host_bridge(
- struct device *parent, int domain,
+ struct device *parent, int domain, void *sysdata,
struct list_head *resources)
{
int error, bus;
@@ -118,6 +118,7 @@ struct pci_host_bridge *pci_create_host_bridge(
mutex_unlock(&pci_host_mutex);

host->dev.release = pci_release_host_bridge_dev;
+ dev_set_drvdata(&host->dev, sysdata);
dev_set_name(&host->dev, "pci%04x:%02x",
host->domain, bus);

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 947c05a..3d6f455 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -334,6 +334,6 @@ static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
struct resource_entry *pci_busn_resource(struct list_head *resources);
void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain);
struct pci_host_bridge *pci_create_host_bridge(struct device *parent,
- int domain, struct list_head *resources);
+ int domain, void *sysdata, struct list_head *resources);
void pci_free_host_bridge(struct pci_host_bridge *host);
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index d8c4da8..cba3474 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1871,8 +1871,7 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
}

static struct pci_bus *__pci_create_root_bus(
- struct pci_host_bridge *bridge, struct pci_ops *ops,
- void *sysdata)
+ struct pci_host_bridge *bridge, struct pci_ops *ops)
{
int error, bus;
struct pci_bus *b;
@@ -1892,7 +1891,7 @@ static struct pci_bus *__pci_create_root_bus(
if (!b)
return NULL;

- b->sysdata = sysdata;
+ b->sysdata = dev_get_drvdata(&bridge->dev);
b->ops = ops;
b->number = b->busn_res.start = bus;
pci_bus_assign_domain_nr(b, parent);
@@ -1973,11 +1972,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent,
return NULL;
}

- host = pci_create_host_bridge(parent, domain, resources);
+ host = pci_create_host_bridge(parent, domain, sysdata, resources);
if (!host)
return NULL;

- host->bus = __pci_create_root_bus(host, ops, sysdata);
+ host->bus = __pci_create_root_bus(host, ops);
if (!host->bus) {
pci_free_host_bridge(host);
return NULL;
@@ -2083,7 +2082,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
bus);
}

- host = pci_create_host_bridge(parent, domain, resources);
+ host = pci_create_host_bridge(parent, domain, sysdata, resources);
if (!host) {
kfree(busn_resource);
return NULL;
@@ -2092,7 +2091,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
if (busn_resource)
host->dynamic_busn = true;

- host->bus = __pci_create_root_bus(host, ops, sysdata);
+ host->bus = __pci_create_root_bus(host, ops);
if (!host->bus) {
pci_free_host_bridge(host);
return NULL;
--
1.7.1

2015-04-21 11:38:25

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 12/29] powerpc/PCI: Rename pcibios_root_bridge_prepare() to pcibios_set_root_bus_speed()

pcibios_root_bridge_prepare() in powerpc set
root bus speed, it's not the preparation for
pci host bridge. Rename it for better readability,
and we could move pcibios_root_bridge_prepare()
to pci_create_host_bridge(), in which root bus
is not created. We will clean up these weak functions,
and add pci_host_bridge_ops to do the same thing
in later patch.

Signed-off-by: Yijing Wang <[email protected]>
---
arch/powerpc/include/asm/machdep.h | 2 +-
arch/powerpc/kernel/pci-common.c | 8 +++-----
arch/powerpc/platforms/pseries/pci.c | 8 ++++----
arch/powerpc/platforms/pseries/pseries.h | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
drivers/pci/probe.c | 5 +++++
6 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index c8175a3..b811d12 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -129,7 +129,7 @@ struct machdep_calls {
void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev);
- int (*pcibios_root_bridge_prepare)(struct pci_host_bridge
+ void (*pcibios_set_root_bus_speed)(struct pci_host_bridge
*bridge);

/* To setup PHBs when using automatic OF platform driver for PCI */
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9acc08d..630cac6 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -767,12 +767,10 @@ int pci_proc_domain(struct pci_bus *bus)
return 1;
}

-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+void pcibios_set_root_bus_speed(struct pci_host_bridge *bridge)
{
- if (ppc_md.pcibios_root_bridge_prepare)
- return ppc_md.pcibios_root_bridge_prepare(bridge);
-
- return 0;
+ if (ppc_md.pcibios_set_root_bus_speed)
+ return ppc_md.pcibios_set_root_bus_speed(bridge);
}

/* This header fixup will do the resource fixup for all devices as they are
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index fe16a50..89ff79c 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -110,7 +110,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_winbond_82c105);

-int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
+void pseries_set_root_bus_speed(struct pci_host_bridge *bridge)
{
struct device_node *dn, *pdn;
struct pci_bus *bus;
@@ -121,7 +121,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)

dn = pcibios_get_phb_of_node(bus);
if (!dn)
- return 0;
+ return;

for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
rc = of_property_read_u32_array(pdn,
@@ -135,7 +135,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)

if (rc) {
pr_debug("no ibm,pcie-link-speed-stats property\n");
- return 0;
+ return;
}

switch (pcie_link_speed_stats[0]) {
@@ -168,5 +168,5 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
break;
}

- return 0;
+ return;
}
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 1796c54..9aa9c13 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -63,7 +63,7 @@ extern int dlpar_detach_node(struct device_node *);

/* PCI root bridge prepare function override for pseries */
struct pci_host_bridge;
-int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
+void pseries_set_root_bus_speed(struct pci_host_bridge *bridge);

unsigned long pseries_memory_block_size(void);

diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index e445b67..b196c0d 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -496,7 +496,7 @@ static void __init pSeries_setup_arch(void)
ppc_md.enable_pmcs = power4_enable_pmcs;
}

- ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
+ ppc_md.pcibios_set_root_bus_speed = pseries_set_root_bus_speed;

if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
long rc;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cba3474..3c53fe7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1862,6 +1862,10 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
return 0;
}

+void __weak pcibios_set_root_bus_speed(struct pci_host_bridge *bridge)
+{
+}
+
void __weak pcibios_add_bus(struct pci_bus *bus)
{
}
@@ -1902,6 +1906,7 @@ static struct pci_bus *__pci_create_root_bus(
if (error)
goto put_bridge;

+ pcibios_set_root_bus_speed(bridge);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);

--
1.7.1

2015-04-21 11:39:24

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 13/29] PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()

Move pcibios_root_bridge_prepare() to pci_create_host_bridge().

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 16 +++++++++++++---
drivers/pci/probe.c | 3 ---
2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index b1cc6ef..6309970 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -109,9 +109,7 @@ struct pci_host_bridge *pci_create_host_bridge(
if (tmp->domain == host->domain
&& pci_host_busn_res_check(host, tmp)) {
mutex_unlock(&pci_host_mutex);
- pci_free_resource_list(&host->windows);
- kfree(host);
- return NULL;
+ goto free_res;
}
}
list_add_tail(&host->list, &pci_host_bridge_list);
@@ -122,6 +120,10 @@ struct pci_host_bridge *pci_create_host_bridge(
dev_set_name(&host->dev, "pci%04x:%02x",
host->domain, bus);

+ error = pcibios_root_bridge_prepare(host);
+ if (error)
+ goto list_del;
+
error = device_register(&host->dev);
if (error) {
put_device(&host->dev);
@@ -129,6 +131,14 @@ struct pci_host_bridge *pci_create_host_bridge(
}

return host;
+list_del:
+ mutex_lock(&pci_host_mutex);
+ list_del(&host->list);
+ mutex_unlock(&pci_host_mutex);
+free_res:
+ pci_free_resource_list(&host->windows);
+ kfree(host);
+ return NULL;
}

void pci_free_host_bridge(struct pci_host_bridge *host)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3c53fe7..e75b27c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1902,9 +1902,6 @@ static struct pci_bus *__pci_create_root_bus(

bridge->bus = b;
b->bridge = get_device(&bridge->dev);
- error = pcibios_root_bridge_prepare(bridge);
- if (error)
- goto put_bridge;

pcibios_set_root_bus_speed(bridge);
device_enable_async_suspend(b->bridge);
--
1.7.1

2015-04-21 11:39:08

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 14/29] PCI: Introduce pci_host_bridge_ops to support host specific operations

Now we have weak functions like pcibios_root_bridge_prepare()
to setup pci host bridge, We could introduce pci_host_bridge_ops
which contain host bridge specific ops to setup pci_host_bridge.
Then host bridge driver could add pci_host_bridge_ops hooks
intead of weak function to setup pci_host_bridge.
This patch add following pci_host_bridge_ops hooks:

pci_host_bridge_ops {
struct pci_ops *pci_ops;
/* set root bus speed, some platform need this like powerpc */
void (*set_root_bus_speed)(struct pci_host_bridge *host);
/* setup pci_host_bridge before pci_host_bridge be added to driver core */
int (*prepare)(struct pci_host_bridge *host);
/* platform specific of scan hook to scan pci device */
int (*scan_bus)(struct pci_host_bridge *);
}
We could easily extend it to support different host bridge
specific operations.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 9 ++++++++-
drivers/pci/pci.h | 3 ++-
drivers/pci/probe.c | 8 ++++++--
include/linux/pci.h | 9 +++++++++
4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 6309970..7e25f53 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -82,7 +82,8 @@ static int pci_host_busn_res_check(

struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain, void *sysdata,
- struct list_head *resources)
+ struct list_head *resources,
+ struct pci_host_bridge_ops *ops)
{
int error, bus;
struct pci_host_bridge *host, *tmp;
@@ -115,10 +116,16 @@ struct pci_host_bridge *pci_create_host_bridge(
list_add_tail(&host->list, &pci_host_bridge_list);
mutex_unlock(&pci_host_mutex);

+ host->ops = ops;
host->dev.release = pci_release_host_bridge_dev;
dev_set_drvdata(&host->dev, sysdata);
dev_set_name(&host->dev, "pci%04x:%02x",
host->domain, bus);
+ if (host->ops && host->ops->prepare) {
+ error = host->ops->prepare(host);
+ if (error)
+ goto list_del;
+ }

error = pcibios_root_bridge_prepare(host);
if (error)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3d6f455..0432889 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -334,6 +334,7 @@ static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
struct resource_entry *pci_busn_resource(struct list_head *resources);
void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain);
struct pci_host_bridge *pci_create_host_bridge(struct device *parent,
- int domain, void *sysdata, struct list_head *resources);
+ int domain, void *sysdata, struct list_head *resources,
+ struct pci_host_bridge_ops *ops);
void pci_free_host_bridge(struct pci_host_bridge *host);
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e75b27c..83cf7c6 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1903,6 +1903,8 @@ static struct pci_bus *__pci_create_root_bus(
bridge->bus = b;
b->bridge = get_device(&bridge->dev);

+ if (bridge->ops && bridge->ops->set_root_bus_speed)
+ bridge->ops->set_root_bus_speed(bridge);
pcibios_set_root_bus_speed(bridge);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);
@@ -1974,7 +1976,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent,
return NULL;
}

- host = pci_create_host_bridge(parent, domain, sysdata, resources);
+ host = pci_create_host_bridge(parent, domain, sysdata,
+ resources, NULL);
if (!host)
return NULL;

@@ -2084,7 +2087,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
bus);
}

- host = pci_create_host_bridge(parent, domain, sysdata, resources);
+ host = pci_create_host_bridge(parent, domain, sysdata,
+ resources, NULL);
if (!host) {
kfree(busn_resource);
return NULL;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9a8a223..91fde6a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -400,6 +400,14 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
return (pdev->error_state != pci_channel_io_normal);
}

+struct pci_host_bridge;
+struct pci_host_bridge_ops {
+ struct pci_ops *pci_ops;
+ int (*prepare)(struct pci_host_bridge *host);
+ void (*set_root_bus_speed)(struct pci_host_bridge *host);
+ int (*scan_bus)(struct pci_host_bridge *host);
+};
+
struct pci_host_bridge {
int domain;
bool dynamic_busn;
@@ -407,6 +415,7 @@ struct pci_host_bridge {
struct pci_bus *bus; /* root bus */
struct list_head windows; /* resource_entry */
struct list_head list;
+ struct pci_host_bridge_ops *ops;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
unsigned int ignore_reset_delay:1; /* for entire hierarchy */
--
1.7.1

2015-04-21 11:38:59

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 15/29] PCI: Introduce new scan function pci_scan_host_bridge()

Introduce new scan function pci_scan_host_bridge() to
support host bridge drivers that need to provide platform
own pci_host_bridge_ops.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 83cf7c6..708bcf1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2064,6 +2064,29 @@ void pci_bus_release_busn_res(struct pci_bus *b)
res, ret ? "can not be" : "is");
}

+struct pci_host_bridge *pci_scan_host_bridge(
+ struct device *parent, int domain,
+ void *sysdata, struct list_head *resources,
+ struct pci_host_bridge_ops *ops)
+{
+ struct pci_host_bridge *host;
+
+ host = pci_create_host_bridge(parent, domain, sysdata,
+ resources, ops);
+ if (!host)
+ return NULL;
+
+ host->bus = __pci_create_root_bus(host, ops->pci_ops);
+ if (!host->bus) {
+ pci_free_host_bridge(host);
+ return NULL;
+ }
+
+ pci_scan_child_bus(host->bus);
+ return host;
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
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 91fde6a..13edbf1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -796,6 +796,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
struct pci_bus *pci_scan_root_bus(struct device *parent, int domain, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+ int domain, void *sysdata, struct list_head *resources,
+ struct pci_host_bridge_ops *ops);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
int busnr);
void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
--
1.7.1

2015-04-21 11:39:14

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 16/29] PCI: Introduce pci_bus_child_max_busnr()

Sometimes, we want to know the highest reserved
busnr for children bus. Because parent's bus->busn_res
may have padding in it. For example, some host drivers
don't know the bus end, so they supply the bus
resource (root_bus, 255), they want to update the
max bus number after pci scan complete. But pci scan
functions won't return the actual max bus number.
So we could use pci_bus_child_max_busnr() to find
that.

Signed-off-by: Fengguang Wu <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/hotplug/acpiphp_glue.c | 29 +----------------------------
drivers/pci/pci.c | 27 +++++++++++++++++++++++++--
include/linux/pci.h | 2 +-
3 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index bcb90e4..84f2584 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -397,33 +397,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
acpi_unlock_hp_context();
}

-/**
- * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
- * @bus: bus to start search with
- */
-static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
-{
- struct pci_bus *tmp;
- unsigned char max, n;
-
- /*
- * pci_bus_max_busnr will return the highest
- * reserved busnr for all these children.
- * that is equivalent to the bus->subordinate
- * value. We don't want to use the parent's
- * bus->subordinate value because it could have
- * padding in it.
- */
- max = bus->busn_res.start;
-
- list_for_each_entry(tmp, &bus->children, node) {
- n = pci_bus_max_busnr(tmp);
- if (n > max)
- max = n;
- }
- return max;
-}
-
static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
{
struct acpiphp_func *func;
@@ -489,7 +462,7 @@ static void enable_slot(struct acpiphp_slot *slot)
LIST_HEAD(add_list);

acpiphp_rescan_slot(slot);
- max = acpiphp_max_busnr(bus);
+ max = pci_bus_child_max_busnr(bus);
for (pass = 0; pass < 2; pass++) {
list_for_each_entry(dev, &bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != slot->device)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 95ea445..d5cbea8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -108,7 +108,7 @@ static bool pcie_ari_disabled;
* Given a PCI bus, returns the highest PCI bus number present in the set
* including the given PCI bus and its list of child PCI buses.
*/
-unsigned char pci_bus_max_busnr(struct pci_bus *bus)
+static unsigned char pci_bus_max_busnr(struct pci_bus *bus)
{
struct pci_bus *tmp;
unsigned char max, n;
@@ -121,7 +121,30 @@ unsigned char pci_bus_max_busnr(struct pci_bus *bus)
}
return max;
}
-EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
+
+unsigned char pci_bus_child_max_busnr(struct pci_bus *bus)
+{
+ struct pci_bus *tmp;
+ unsigned char max, n;
+
+ /*
+ * pci_bus_max_busnr will return the highest
+ * reserved busnr for all these children.
+ * that is equivalent to the bus->subordinate
+ * value. We don't want to use the parent's
+ * bus->subordinate value because it could have
+ * padding in it.
+ */
+ max = bus->busn_res.start;
+
+ list_for_each_entry(tmp, &bus->children, node) {
+ n = pci_bus_max_busnr(tmp);
+ if (n > max)
+ max = n;
+ }
+ return max;
+}
+EXPORT_SYMBOL_GPL(pci_bus_child_max_busnr);

#ifdef CONFIG_HAS_IOMEM
void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 13edbf1..a82595a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
void *userdata);
int pci_cfg_space_size(struct pci_dev *dev);
-unsigned char pci_bus_max_busnr(struct pci_bus *bus);
+unsigned char pci_bus_child_max_busnr(struct pci_bus *bus);
void pci_setup_bridge(struct pci_bus *bus);
resource_size_t pcibios_window_alignment(struct pci_bus *bus,
unsigned long type);
--
1.7.1

2015-04-21 11:39:36

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 17/29] x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge

Signed-off-by: Yijing Wang <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: [email protected]
---
arch/x86/pci/acpi.c | 37 +++++++++++++++++++++----------------
1 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index d6aab1c..ec16499 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -354,6 +354,19 @@ static void probe_pci_root_info(struct pci_root_info *info,
}
}

+static int pci_host_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct pci_sysdata *sd = dev_get_drvdata(&bridge->dev);
+
+ ACPI_COMPANION_SET(&bridge->dev, sd->companion);
+ return 0;
+}
+
+static struct pci_host_bridge_ops pci_host_ops = {
+ .pci_ops = &pci_root_ops,
+ .prepare = pci_host_bridge_prepare,
+};
+
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
@@ -364,6 +377,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
LIST_HEAD(crs_res);
LIST_HEAD(resources);
struct pci_bus *bus;
+ struct pci_host_bridge *host = NULL;
struct pci_sysdata *sd;
int node;

@@ -430,14 +444,13 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
(u8)root->secondary.end, root->mcfg_addr))
- bus = pci_create_root_bus(NULL, domain, &pci_root_ops,
- sd, &resources);
-
- if (bus) {
- pci_scan_child_bus(bus);
- pci_set_host_bridge_release(
- to_pci_host_bridge(bus->bridge),
- release_pci_root_info, info);
+ host = pci_scan_host_bridge(NULL, domain, sd, &resources,
+ &pci_host_ops);
+
+ if (host) {
+ bus = host->bus;
+ pci_set_host_bridge_release(host,
+ release_pci_root_info, info);
} else {
resource_list_free(&resources);
teardown_mcfg_map(info);
@@ -460,14 +473,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
return bus;
}

-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
- struct pci_sysdata *sd = bridge->bus->sysdata;
-
- ACPI_COMPANION_SET(&bridge->dev, sd->companion);
- return 0;
-}
-
int __init pci_acpi_init(void)
{
struct pci_dev *dev = NULL;
--
1.7.1

2015-04-21 11:39:20

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 18/29] ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge

From: Yijing Wang <[email protected]>

Signed-off-by: Yijing Wang <[email protected]>
CC: Tony Luck <[email protected]>
CC: Fenghua Yu <[email protected]>
CC: [email protected]
---
arch/ia64/pci/pci.c | 34 +++++++++++++++++++---------------
1 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 84f1eb8..7f3b9fb 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -420,6 +420,19 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
return 0;
}

+static int pci_host_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct pci_controller *controller = bridge->bus->sysdata;
+
+ ACPI_COMPANION_SET(&bridge->dev, controller->companion);
+ return 0;
+}
+
+static struct pci_host_bridge_ops pci_host_ops = {
+ .pci_ops = &pci_root_ops,
+ .prepare = pci_host_bridge_prepare,
+};
+
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
@@ -427,7 +440,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
struct pci_controller *controller;
struct pci_root_info *info = NULL;
int busnum = root->secondary.start;
- struct pci_bus *pbus;
+ struct pci_host_bridge *host;
int ret;

controller = alloc_pci_controller(domain);
@@ -464,26 +477,17 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
* should handle the case here, but it appears that IA64 hasn't
* such quirk. So we just ignore the case now.
*/
- pbus = pci_create_root_bus(NULL, domain, &pci_root_ops,
- controller, &info->resources);
- if (!pbus) {
+ host = pci_scan_host_bridge(NULL, domain, controller,
+ &info->resources, &pci_host_ops);
+ if (!host) {
pci_free_resource_list(&info->resources);
__release_pci_root_info(info);
return NULL;
}

- pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge),
+ pci_set_host_bridge_release(host,
release_pci_root_info, info);
- pci_scan_child_bus(pbus);
- return pbus;
-}
-
-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
- struct pci_controller *controller = bridge->bus->sysdata;
-
- ACPI_COMPANION_SET(&bridge->dev, controller->companion);
- return 0;
+ return host->bus;
}

void pcibios_fixup_device_resources(struct pci_dev *dev)
--
1.7.1

2015-04-21 11:47:03

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 19/29] powerpc/pci: Use pci_scan_host_bridge() for simplicity

Now we could use pci_scan_host_bridge() to scan
pci buses, provide powerpc specific pci_host_bridge_ops.

Tested-by: Daniel Axtens <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
Reviewed-by: Daniel Axtens <[email protected]>
CC: Benjamin Herrenschmidt <[email protected]>
CC: [email protected]
---
arch/powerpc/kernel/pci-common.c | 62 +++++++++++++++++++++++--------------
1 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 630cac6..3210495 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -773,6 +773,29 @@ void pcibios_set_root_bus_speed(struct pci_host_bridge *bridge)
return ppc_md.pcibios_set_root_bus_speed(bridge);
}

+static int pci_host_scan_bus(struct pci_host_bridge *host)
+{
+ int mode = PCI_PROBE_NORMAL;
+ struct pci_bus *bus = host->bus;
+ struct pci_controller *hose = dev_get_drvdata(&host->dev);
+
+ /* Get probe mode and perform scan */
+ if (hose->dn && ppc_md.pci_probe_mode)
+ mode = ppc_md.pci_probe_mode(bus);
+
+ pr_debug(" probe mode: %d\n", mode);
+ if (mode == PCI_PROBE_DEVTREE)
+ of_scan_bus(hose->dn, bus);
+
+ if (mode == PCI_PROBE_NORMAL) {
+ pci_bus_update_busn_res_end(bus, 255);
+ hose->last_busno = pci_scan_child_bus(bus);
+ pci_bus_update_busn_res_end(bus, hose->last_busno);
+ }
+
+ return pci_bus_child_max_busnr(bus);
+}
+
/* This header fixup will do the resource fixup for all devices as they are
* probed, but not for bridge ranges
*/
@@ -1585,6 +1608,11 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
return of_node_get(hose->dn);
}

+static struct pci_host_bridge_ops pci_host_ops = {
+ .set_root_bus_speed = pcibios_set_root_bus_speed,
+ .scan_bus = pci_host_scan_bus,
+};
+
/**
* pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
* @hose: Pointer to the PCI host controller instance structure
@@ -1592,9 +1620,8 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
void pcibios_scan_phb(struct pci_controller *hose)
{
LIST_HEAD(resources);
- struct pci_bus *bus;
+ struct pci_host_bridge *host;
struct device_node *node = hose->dn;
- int mode;

pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));

@@ -1609,30 +1636,17 @@ void pcibios_scan_phb(struct pci_controller *hose)
hose->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &hose->busn);

+ pci_host_ops.pci_ops = hose->ops;
/* Create an empty bus for the toplevel */
- bus = pci_create_root_bus(hose->parent, hose->global_number,
- hose->ops, hose, &resources);
- if (bus == NULL) {
- pr_err("Failed to create bus for PCI domain %04x\n",
- hose->global_number);
+ host = pci_scan_host_bridge(hose->parent, hose->global_number,
+ hose, &resources, &pci_host_ops);
+ if (host == NULL) {
+ pr_err("Failed to create host bridge for pci%04x:%02x\n",
+ hose->global_number, hose->first_busno);
pci_free_resource_list(&resources);
return;
}
- hose->bus = bus;
-
- /* Get probe mode and perform scan */
- mode = PCI_PROBE_NORMAL;
- if (node && ppc_md.pci_probe_mode)
- mode = ppc_md.pci_probe_mode(bus);
- pr_debug(" probe mode: %d\n", mode);
- if (mode == PCI_PROBE_DEVTREE)
- of_scan_bus(node, bus);
-
- if (mode == PCI_PROBE_NORMAL) {
- pci_bus_update_busn_res_end(bus, 255);
- hose->last_busno = pci_scan_child_bus(bus);
- pci_bus_update_busn_res_end(bus, hose->last_busno);
- }
+ hose->bus = host->bus;

/* Platform gets a chance to do some global fixups before
* we proceed to resource allocation
@@ -1641,9 +1655,9 @@ void pcibios_scan_phb(struct pci_controller *hose)
ppc_md.pcibios_fixup_phb(hose);

/* Configure PCI Express settings */
- if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+ if (host->bus && !pci_has_flag(PCI_PROBE_ONLY)) {
struct pci_bus *child;
- list_for_each_entry(child, &bus->children, node)
+ list_for_each_entry(child, &host->bus->children, node)
pcie_bus_configure_settings(child);
}
}
--
1.7.1

2015-04-21 11:48:45

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 20/29] PCI: Remove pcibios_root_bridge_prepare() and pcibos_set_root_bus_speed()

Now no one use weak pcibios_root_bridge_prepare() and
pcibios_set_root_bus_speed, we could clean up them.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 4 ----
drivers/pci/probe.c | 18 +-----------------
include/linux/pci.h | 2 --
3 files changed, 1 insertions(+), 23 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 7e25f53..af539c4 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -127,10 +127,6 @@ struct pci_host_bridge *pci_create_host_bridge(
goto list_del;
}

- error = pcibios_root_bridge_prepare(host);
- if (error)
- goto list_del;
-
error = device_register(&host->dev);
if (error) {
put_device(&host->dev);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 708bcf1..2ba6754 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1850,22 +1850,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pci_scan_child_bus);

-/**
- * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
- * @bridge: Host bridge to set up.
- *
- * Default empty implementation. Replace with an architecture-specific setup
- * routine, if necessary.
- */
-int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
- return 0;
-}
-
-void __weak pcibios_set_root_bus_speed(struct pci_host_bridge *bridge)
-{
-}
-
void __weak pcibios_add_bus(struct pci_bus *bus)
{
}
@@ -1905,7 +1889,7 @@ static struct pci_bus *__pci_create_root_bus(

if (bridge->ops && bridge->ops->set_root_bus_speed)
bridge->ops->set_root_bus_speed(bridge);
- pcibios_set_root_bus_speed(bridge);
+
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);

diff --git a/include/linux/pci.h b/include/linux/pci.h
index a82595a..41eb672 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -426,8 +426,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
void (*release_fn)(struct pci_host_bridge *),
void *release_data);

-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
/*
* 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.1

2015-04-21 11:39:30

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 21/29] sparc/PCI: Use pci_scan_host_bridge() for simplicity

Now we could use pci_scan_host_bridge() to scan
pci buses, provide sparc specific pci_host_bridge_ops.

Signed-off-by: Yijing Wang <[email protected]>
CC: "David S. Miller" <[email protected]>
CC: [email protected]
---
arch/sparc/kernel/pci.c | 28 ++++++++++++++++++++++------
1 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 6ff363c..9feaa77 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -650,12 +650,27 @@ static void pci_claim_bus_resources(struct pci_bus *bus)
pci_claim_bus_resources(child_bus);
}

+static int pci_host_of_scan_bus(
+ struct pci_host_bridge *host)
+{
+ struct pci_pbm_info *pbm = dev_get_drvdata(&host->dev);
+ struct device_node *node = pbm->op->dev.of_node;
+
+ pci_of_scan_bus(pbm, node, host->bus);
+ return pci_bus_child_max_busnr(host->bus);
+}
+
+static struct pci_host_bridge_ops pci_host_ops = {
+ .scan_bus = pci_host_of_scan_bus,
+};
+
struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
struct device *parent)
{
LIST_HEAD(resources);
struct device_node *node = pbm->op->dev.of_node;
struct pci_bus *bus;
+ struct pci_host_bridge *host;

printk("PCI: Scanning PBM %s\n", node->full_name);

@@ -667,16 +682,17 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
pbm->busn.end = pbm->pci_last_busno;
pbm->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &pbm->busn);
- bus = pci_create_root_bus(parent, pbm->index,
- pbm->pci_ops, pbm, &resources);
- if (!bus) {
- printk(KERN_ERR "Failed to create bus for %s\n",
- node->full_name);
+ pci_host_ops.pci_ops = pbm->pci_ops;
+ host = pci_scan_host_bridge(parent, pbm->index,
+ pbm, &resources, &pci_host_ops);
+ if (!host) {
+ pr_err("Failed to create host bridge pci%04x:%02x for %s\n",
+ pbm->index, pbm->pci_first_busno, node->full_name);
pci_free_resource_list(&resources);
return NULL;
}

- pci_of_scan_bus(pbm, node, bus);
+ bus = host->bus;
pci_bus_register_of_sysfs(bus);

pci_claim_bus_resources(bus);
--
1.7.1

2015-04-21 11:39:33

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 22/29] parisc/PCI: Use pci_scan_root_bus() for simplicity

From: Yijing Wang <[email protected]>

Now pci_bus_add_devices() has been ripped out
from pci_scan_root_bus(), we could use pci_scan_root_bus()
instead of pci_create_root_bus() + pci_scan_child_bus()
for simplicity.

Signed-off-by: Yijing Wang <[email protected]>
CC: "James E.J. Bottomley" <[email protected]>
CC: [email protected]
---
drivers/parisc/dino.c | 6 +++---
drivers/parisc/lba_pci.c | 5 +++--
2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 56abc43..146c3ff 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -985,8 +985,8 @@ static int __init dino_probe(struct parisc_device *dev)
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
*/
- dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
- 0, &dino_cfg_ops, NULL, &resources);
+ dino_dev->hba.hba_bus = bus = pci_scan_root_bus(&dev->dev,
+ 0, dino_current_bus, &dino_cfg_ops, NULL, &resources);
if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
@@ -996,7 +996,7 @@ static int __init dino_probe(struct parisc_device *dev)
return 0;
}

- max = pci_scan_child_bus(bus);
+ max = pci_bus_child_max_busnr(bus);
pci_bus_update_busn_res_end(bus, max);

/* This code *depends* on scanning being single threaded
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 0b9ed96..24e42bf 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1563,13 +1563,14 @@ lba_driver_probe(struct parisc_device *dev)

dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
- pci_create_root_bus(&dev->dev, 0, cfg_ops, NULL, &resources);
+ pci_scan_root_bus(&dev->dev, 0, lba_dev->hba.bus_num.start,
+ cfg_ops, NULL, &resources);
if (!lba_bus) {
pci_free_resource_list(&resources);
return 0;
}

- max = pci_scan_child_bus(lba_bus);
+ max = pci_bus_child_max_busnr(lba_bus);

/* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
--
1.7.1

2015-04-21 11:39:42

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 23/29] PCI/mvebu: Use pci_common_init_dev() to simplify code

Mvebu_pcie_scan_bus() is not necessary, we could use
pci_common_init_dev() instead of pci_common_init(),
and pass the device pointer as the parent. Then
pci_scan_root_bus() will be called to scan the pci busses.

Tested-by: Gregory CLEMENT <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
Reviewed-by: Gregory CLEMENT <[email protected]>
CC: Thomas Petazzoni <[email protected]>
CC: Jason Cooper <[email protected]>
---
drivers/pci/host/pci-mvebu.c | 18 +-----------------
1 files changed, 1 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index c91a8b4..70aa095 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -751,21 +751,6 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}

-static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
- struct mvebu_pcie *pcie = sys_to_pcie(sys);
- struct pci_bus *bus;
-
- bus = pci_create_root_bus(&pcie->pdev->dev, -1,
- &mvebu_pcie_ops, sys, &sys->resources);
- if (!bus)
- return NULL;
-
- pci_scan_child_bus(bus);
-
- return bus;
-}
-
static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
const struct resource *res,
resource_size_t start,
@@ -809,12 +794,11 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
hw.nr_controllers = 1;
hw.private_data = (void **)&pcie;
hw.setup = mvebu_pcie_setup;
- hw.scan = mvebu_pcie_scan_bus;
hw.map_irq = of_irq_parse_and_map_pci;
hw.ops = &mvebu_pcie_ops;
hw.align_resource = mvebu_pcie_align_resource;

- pci_common_init(&hw);
+ pci_common_init_dev(&pcie->pdev->dev, &hw);
}

/*
--
1.7.1

2015-04-21 11:39:52

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 24/29] PCI/tegra: Remove redundant tegra_pcie_scan_bus()

Now pci_scan_root_bus() is almost similar to
pci_create_root_bus() + pci_scan_child_bus().
So we could use common pci_scan_root_bus() in
pci_common_init_dev() to scan pci busses.
tegra_pcie_scan_bus() is redundant, remove it.

Tested-by: Thierry Reding <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
Acked-by: Thierry Reding <[email protected]>
CC: Thierry Reding <[email protected]>
CC: [email protected]
---
drivers/pci/host/pci-tegra.c | 16 ----------------
1 files changed, 0 insertions(+), 16 deletions(-)

diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 3e45142..10c0571 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -630,21 +630,6 @@ static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
return irq;
}

-static struct pci_bus *tegra_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
- struct tegra_pcie *pcie = sys_to_pcie(sys);
- struct pci_bus *bus;
-
- bus = pci_create_root_bus(pcie->dev, -1, &tegra_pcie_ops,
- sys, &sys->resources);
- if (!bus)
- return NULL;
-
- pci_scan_child_bus(bus);
-
- return bus;
-}
-
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
const char *err_msg[] = {
@@ -1831,7 +1816,6 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie)
hw.private_data = (void **)&pcie;
hw.setup = tegra_pcie_setup;
hw.map_irq = tegra_pcie_map_irq;
- hw.scan = tegra_pcie_scan_bus;
hw.ops = &tegra_pcie_ops;

pci_common_init_dev(pcie->dev, &hw);
--
1.7.1

2015-04-21 11:47:07

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 25/29] PCI/designware: Use pci_scan_root_bus() for simplicity

Use pci_scan_root_bus() instead of pci_create_root_bus() +
pci_scan_child_bus() for simplicity.

Signed-off-by: Yijing Wang <[email protected]>
CC: Mohit Kumar <[email protected]>
CC: Jingoo Han <[email protected]>
---
drivers/pci/host/pcie-designware.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 8854d25..f8d3424 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -728,13 +728,11 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pcie_port *pp = sys_to_pcie(sys);

pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, -1, &dw_pcie_ops, sys,
+ bus = pci_scan_root_bus(pp->dev, -1, sys->busnr, &dw_pcie_ops, sys,
&sys->resources);
if (!bus)
return NULL;

- pci_scan_child_bus(bus);
-
if (bus && pp->ops->scan_bus)
pp->ops->scan_bus(pp);

--
1.7.1

2015-04-21 11:39:47

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 26/29] PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()

Use pci_scan_root_bus() instead of pci_create_root_bus() +
pci_scan_child_bus() for simplicity.

Signed-off-by: Yijing Wang <[email protected]>
CC: Tanmay Inamdar <[email protected]>
---
drivers/pci/host/pci-xgene.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index f11e77b..a91a739 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -499,12 +499,11 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret)
return ret;

- bus = pci_create_root_bus(&pdev->dev, -1,
- &xgene_pcie_ops, port, &res);
+ bus = pci_scan_root_bus(&pdev->dev, -1, &xgene_pcie_ops,
+ port, &res);
if (!bus)
return -ENOMEM;

- pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
pci_bus_add_devices(bus);

--
1.7.1

2015-04-21 11:39:58

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 27/29] PCI: Rename __pci_create_root_bus() to pci_create_root_bus()

Now no one use pci_create_root_bus(), we could remove it
and rename __pci_create_root_bus() to pci_create_root_bus().

Signed-off-by: [email protected]
---
drivers/pci/probe.c | 57 +++++++++++++++-----------------------------------
include/linux/pci.h | 3 --
2 files changed, 17 insertions(+), 43 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2ba6754..c9bee34 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1858,7 +1858,7 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
{
}

-static struct pci_bus *__pci_create_root_bus(
+static struct pci_bus *pci_create_root_bus(
struct pci_host_bridge *bridge, struct pci_ops *ops)
{
int error, bus;
@@ -1947,34 +1947,6 @@ put_bridge:
}
EXPORT_SYMBOL_GPL(pci_create_root_bus);

-struct pci_bus *pci_create_root_bus(struct device *parent,
- int domain, struct pci_ops *ops, void *sysdata,
- struct list_head *resources)
-{
- struct resource_entry *busn_res;
- struct pci_host_bridge *host;
-
- busn_res = pci_busn_resource(resources);
- if (!busn_res) {
- pr_err("No busn resource found\n");
- return NULL;
- }
-
- host = pci_create_host_bridge(parent, domain, sysdata,
- resources, NULL);
- if (!host)
- return NULL;
-
- host->bus = __pci_create_root_bus(host, ops);
- if (!host->bus) {
- pci_free_host_bridge(host);
- return NULL;
- }
-
- return host->bus;
-}
-
-
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
{
struct resource *res = &b->busn_res;
@@ -2060,7 +2032,7 @@ struct pci_host_bridge *pci_scan_host_bridge(
if (!host)
return NULL;

- host->bus = __pci_create_root_bus(host, ops->pci_ops);
+ host->bus = pci_create_root_bus(host, ops->pci_ops);
if (!host->bus) {
pci_free_host_bridge(host);
return NULL;
@@ -2104,7 +2076,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int domain,
if (busn_resource)
host->dynamic_busn = true;

- host->bus = __pci_create_root_bus(host, ops);
+ host->bus = pci_create_root_bus(host, ops);
if (!host->bus) {
pci_free_host_bridge(host);
return NULL;
@@ -2123,7 +2095,6 @@ struct pci_bus *pci_scan_bus(int domain, int bus,
struct pci_ops *ops, void *sysdata)
{
LIST_HEAD(resources);
- struct pci_bus *b;
struct resource *busn_resource;
struct pci_host_bridge *host;

@@ -2137,17 +2108,23 @@ struct pci_bus *pci_scan_bus(int domain, int bus,
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, busn_resource);
- b = pci_create_root_bus(NULL, domain, ops, sysdata,
- &resources);
- if (b) {
- host = to_pci_host_bridge(b->bridge);
- host->dynamic_busn = true;
- pci_scan_child_bus(b);
- } else {
+ host = pci_create_host_bridge(NULL, domain, sysdata,
+ &resources, NULL);
+ if (!host) {
kfree(busn_resource);
pci_free_resource_list(&resources);
+ return NULL;
}
- return b;
+
+ host->dynamic_busn = true;
+ host->bus = pci_create_root_bus(host, ops);
+ if (!host->bus) {
+ pci_free_host_bridge(host);
+ return NULL;
+ }
+
+ pci_scan_child_bus(host->bus);
+ return host->bus;
}
EXPORT_SYMBOL(pci_scan_bus);

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 41eb672..7a9bd2d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -785,9 +785,6 @@ struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
struct pci_bus *pci_scan_bus(int domain, int bus, struct pci_ops *ops,
void *sysdata);
-struct pci_bus *pci_create_root_bus(struct device *parent, int domain,
- struct pci_ops *ops, void *sysdata,
- struct list_head *resources);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

2015-04-21 11:39:55

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 28/29] PCI: Remove platform specific pci_domain_nr()

Now pci_host_bridge holds the domain number,
so we could eliminate all platform specific
pci_domain_nr().

Signed-off-by: Yijing Wang <[email protected]>
---
arch/alpha/include/asm/pci.h | 2 --
arch/ia64/include/asm/pci.h | 1 -
arch/microblaze/pci/pci-common.c | 11 -----------
arch/mips/include/asm/pci.h | 2 --
arch/powerpc/kernel/pci-common.c | 11 -----------
arch/s390/pci/pci.c | 6 ------
arch/sh/include/asm/pci.h | 2 --
arch/sparc/kernel/pci.c | 17 -----------------
arch/tile/include/asm/pci.h | 2 --
arch/x86/include/asm/pci.h | 6 ------
drivers/pci/host-bridge.c | 10 ++++++++++
include/linux/pci.h | 7 +------
12 files changed, 11 insertions(+), 66 deletions(-)

diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index f7f680f..63a9a1e 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -95,8 +95,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? 15 : 14;
}

-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
static inline int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = bus->sysdata;
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed..1dcea49 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -99,7 +99,6 @@ struct pci_controller {


#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
-#define pci_domain_nr(busdev) (PCI_CONTROLLER(busdev)->segment)

extern struct pci_ops pci_root_ops;

diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index d232c8a..6f64908 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -123,17 +123,6 @@ unsigned long pci_address_to_pio(phys_addr_t address)
}
EXPORT_SYMBOL_GPL(pci_address_to_pio);

-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
-
- return hose->global_number;
-}
-EXPORT_SYMBOL(pci_domain_nr);
-
/* This routine is meant to be used early during boot, when the
* PCI bus numbers have not yet been assigned, and you need to
* issue PCI config cycles to an OF device.
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 193b4c6..2e4d808 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -122,8 +122,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
#endif

#ifdef CONFIG_PCI_DOMAINS
-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
static inline int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = bus->sysdata;
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 3210495..a746ef5 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -181,17 +181,6 @@ unsigned long pci_address_to_pio(phys_addr_t address)
}
EXPORT_SYMBOL_GPL(pci_address_to_pio);

-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
-
- return hose->global_number;
-}
-EXPORT_SYMBOL(pci_domain_nr);
-
/* This routine is meant to be used early during boot, when the
* PCI bus numbers have not yet been assigned, and you need to
* issue PCI config cycles to an OF device.
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index d70b2db..13a242b 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -101,12 +101,6 @@ static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
}

-int pci_domain_nr(struct pci_bus *bus)
-{
- return ((struct zpci_dev *) bus->sysdata)->domain;
-}
-EXPORT_SYMBOL_GPL(pci_domain_nr);
-
int pci_proc_domain(struct pci_bus *bus)
{
return pci_domain_nr(bus);
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 5b45115..4dc3ad6 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -109,8 +109,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
/* Board-specific fixup routines. */
int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin);

-#define pci_domain_nr(bus) ((struct pci_channel *)(bus)->sysdata)->index
-
static inline int pci_proc_domain(struct pci_bus *bus)
{
struct pci_channel *hose = bus->sysdata;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 9feaa77..389b889 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -905,23 +905,6 @@ int pcibus_to_node(struct pci_bus *pbus)
EXPORT_SYMBOL(pcibus_to_node);
#endif

-/* Return the domain number for this pci bus */
-
-int pci_domain_nr(struct pci_bus *pbus)
-{
- struct pci_pbm_info *pbm = pbus->sysdata;
- int ret;
-
- if (!pbm) {
- ret = -ENXIO;
- } else {
- ret = pbm->index;
- }
-
- return ret;
-}
-EXPORT_SYMBOL(pci_domain_nr);
-
#ifdef CONFIG_PCI_MSI
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index dfedd7a..23a726e 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -199,8 +199,6 @@ int __init pcibios_init(void);

void pcibios_fixup_bus(struct pci_bus *bus);

-#define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
-
/*
* This decides whether to display the domain number in /proc.
*/
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 4e370a5..4fe0458 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -29,12 +29,6 @@ extern int noioapicreroute;
#ifdef CONFIG_PCI

#ifdef CONFIG_PCI_DOMAINS
-static inline int pci_domain_nr(struct pci_bus *bus)
-{
- struct pci_sysdata *sd = bus->sysdata;
- return sd->domain;
-}
-
static inline int pci_proc_domain(struct pci_bus *bus)
{
return pci_domain_nr(bus);
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index af539c4..5ae9ab8 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -182,6 +182,16 @@ void pci_put_host_bridge_device(struct device *dev)
kobject_put(&dev->kobj);
}

+#ifdef CONFIG_PCI_DOMAINS
+int pci_domain_nr(struct pci_bus *bus)
+{
+ struct pci_host_bridge *host = pci_find_host_bridge(bus);
+
+ return host->domain;
+}
+EXPORT_SYMBOL(pci_domain_nr);
+#endif
+
void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
void (*release_fn)(struct pci_host_bridge *),
void *release_data)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7a9bd2d..1ea69c7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1323,6 +1323,7 @@ void pci_cfg_access_unlock(struct pci_dev *dev);
#ifdef CONFIG_PCI_DOMAINS
extern int pci_domains_supported;
int pci_get_new_domain_nr(void);
+int pci_domain_nr(struct pci_bus *bus);
#else
enum { pci_domains_supported = 0 };
static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
@@ -1335,12 +1336,6 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
* architecture does not need custom management of PCI
* domains then this implementation will be used
*/
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
-static inline int pci_domain_nr(struct pci_bus *bus)
-{
- return bus->domain_nr;
-}
-#endif

/* some architectures require additional setup to direct VGA traffic */
typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
--
1.7.1

2015-04-21 11:40:06

by Yijing Wang

[permalink] [raw]
Subject: [PATCH v10 29/29] PCI: Remove pci_bus_assign_domain_nr()

Now we save the domain number in pci_host_bridge,
we could remove pci_bus_assign_domain_nr() and
clean the domain member in pci_bus. Also move
pci_host_assign_domain_nr() to drivers/pci/host-bridge.c
for simplicity.

Signed-off-by: Yijing Wang <[email protected]>
---
drivers/pci/host-bridge.c | 68 ++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.c | 72 ---------------------------------------------
drivers/pci/pci.h | 9 -----
drivers/pci/probe.c | 11 ++-----
include/linux/pci.h | 3 --
5 files changed, 71 insertions(+), 92 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 5ae9ab8..1b5b27d 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -5,12 +5,80 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>

#include "pci.h"

static LIST_HEAD(pci_host_bridge_list);
static DEFINE_MUTEX(pci_host_mutex);

+#ifdef CONFIG_PCI_DOMAINS
+static atomic_t __domain_nr = ATOMIC_INIT(-1);
+
+int pci_get_new_domain_nr(void)
+{
+ return atomic_inc_return(&__domain_nr);
+}
+
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+static int pci_assign_domain_nr(struct device *dev)
+{
+ static int use_dt_domains = -1;
+ int domain = of_get_pci_domain_nr(dev->of_node);
+
+ /*
+ * Check DT domain and use_dt_domains values.
+ *
+ * If DT domain property is valid (domain >= 0) and
+ * use_dt_domains != 0, the DT assignment is valid since this means
+ * we have not previously allocated a domain number by using
+ * pci_get_new_domain_nr(); we should also update use_dt_domains to
+ * 1, to indicate that we have just assigned a domain number from
+ * DT.
+ *
+ * If DT domain property value is not valid (ie domain < 0), and we
+ * have not previously assigned a domain number from DT
+ * (use_dt_domains != 1) we should assign a domain number by
+ * using the:
+ *
+ * pci_get_new_domain_nr()
+ *
+ * API and update the use_dt_domains value to keep track of method we
+ * are using to assign domain numbers (use_dt_domains = 0).
+ *
+ * All other combinations imply we have a platform that is trying
+ * to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
+ * which is a recipe for domain mishandling and it is prevented by
+ * invalidating the domain value (domain = -1) and printing a
+ * corresponding error.
+ */
+ if (domain >= 0 && use_dt_domains) {
+ use_dt_domains = 1;
+ } else if (domain < 0 && use_dt_domains != 1) {
+ use_dt_domains = 0;
+ domain = pci_get_new_domain_nr();
+ } else {
+ dev_err(dev, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
+ dev->of_node->full_name);
+ domain = -1;
+ }
+
+ return domain;
+}
+#endif
+#endif
+
+static void pci_host_assign_domain_nr(struct pci_host_bridge *host,
+ int domain)
+{
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+ host->domain = pci_assign_domain_nr(host->dev.parent);
+#else
+ host->domain = domain;
+#endif
+}
+
static void pci_release_host_bridge_dev(struct device *dev)
{
struct resource_entry *entry;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d5cbea8..1538a74 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -10,8 +10,6 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -4520,76 +4518,6 @@ static void pci_no_domains(void)
#endif
}

-#ifdef CONFIG_PCI_DOMAINS
-static atomic_t __domain_nr = ATOMIC_INIT(-1);
-
-int pci_get_new_domain_nr(void)
-{
- return atomic_inc_return(&__domain_nr);
-}
-
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
-static int pci_assign_domain_nr(struct device *dev)
-{
- static int use_dt_domains = -1;
- int domain = of_get_pci_domain_nr(dev->of_node);
-
- /*
- * Check DT domain and use_dt_domains values.
- *
- * If DT domain property is valid (domain >= 0) and
- * use_dt_domains != 0, the DT assignment is valid since this means
- * we have not previously allocated a domain number by using
- * pci_get_new_domain_nr(); we should also update use_dt_domains to
- * 1, to indicate that we have just assigned a domain number from
- * DT.
- *
- * If DT domain property value is not valid (ie domain < 0), and we
- * have not previously assigned a domain number from DT
- * (use_dt_domains != 1) we should assign a domain number by
- * using the:
- *
- * pci_get_new_domain_nr()
- *
- * API and update the use_dt_domains value to keep track of method we
- * are using to assign domain numbers (use_dt_domains = 0).
- *
- * All other combinations imply we have a platform that is trying
- * to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
- * which is a recipe for domain mishandling and it is prevented by
- * invalidating the domain value (domain = -1) and printing a
- * corresponding error.
- */
- if (domain >= 0 && use_dt_domains) {
- use_dt_domains = 1;
- } else if (domain < 0 && use_dt_domains != 1) {
- use_dt_domains = 0;
- domain = pci_get_new_domain_nr();
- } else {
- dev_err(dev, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
- dev->of_node->full_name);
- domain = -1;
- }
-
- return domain;
-}
-
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
-{
- bus->domain_nr = pci_assign_domain_nr(parent);
-}
-#endif
-#endif
-
-void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain)
-{
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
- host->domain = pci_assign_domain_nr(host->dev.parent);
-#else
- host->domain = domain;
-#endif
-}
-
/**
* pci_ext_cfg_avail - can we access extended PCI config space?
*
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0432889..e279147 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -323,16 +323,7 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)

struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);

-#ifdef CONFIG_PCI_DOMAINS_GENERIC
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
-#else
-static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
- struct device *parent)
-{
-}
-#endif
struct resource_entry *pci_busn_resource(struct list_head *resources);
-void pci_host_assign_domain_nr(struct pci_host_bridge *host, int domain);
struct pci_host_bridge *pci_create_host_bridge(struct device *parent,
int domain, void *sysdata, struct list_head *resources,
struct pci_host_bridge_ops *ops);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c9bee34..164225e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
}
}

-static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
+static struct pci_bus *pci_alloc_bus(void)
{
struct pci_bus *b;

@@ -500,10 +500,6 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
INIT_LIST_HEAD(&b->resources);
b->max_bus_speed = PCI_SPEED_UNKNOWN;
b->cur_bus_speed = PCI_SPEED_UNKNOWN;
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
- if (parent)
- b->domain_nr = parent->domain_nr;
-#endif
return b;
}

@@ -650,7 +646,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
/*
* Allocate a new bus, and inherit stuff from the parent..
*/
- child = pci_alloc_bus(parent);
+ child = pci_alloc_bus();
if (!child)
return NULL;

@@ -1875,14 +1871,13 @@ static struct pci_bus *pci_create_root_bus(
return NULL;
bus = busn_res->res->start;
parent = bridge->dev.parent;
- b = pci_alloc_bus(NULL);
+ b = pci_alloc_bus();
if (!b)
return NULL;

b->sysdata = dev_get_drvdata(&bridge->dev);
b->ops = ops;
b->number = b->busn_res.start = bus;
- pci_bus_assign_domain_nr(b, parent);

bridge->bus = b;
b->bridge = get_device(&bridge->dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1ea69c7..c167503 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -469,9 +469,6 @@ struct pci_bus {
unsigned char primary; /* number of primary bridge */
unsigned char max_bus_speed; /* enum pci_bus_speed */
unsigned char cur_bus_speed; /* enum pci_bus_speed */
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
- int domain_nr;
-#endif

char name[48];

--
1.7.1

2015-04-27 04:09:29

by Daniel Axtens

[permalink] [raw]
Subject: Re: [PATCH v10 00/29] Refine PCI scan interfaces and make generic pci host bridge

Hi Yijing,

I'm wondering if you might get some more momentum on these changes if
we could split them into a few smaller patch sets. I think we might
then be able to start getting bits of this in for 4.2, which should help
with getting the rest of it in.

I think there are a few things that would be easy to pull out.

* #1 (xen/PCI: Don't use deprecated function
pci_scan_bus_parented()) can go directly to Xen people and should
be easy to merge. #2 (PCI: Remove deprecated
pci_scan_bus_parented()) is then an easy fixup.

* I think #12 (powerpc/PCI: Rename pcibios_root_bridge_prepare() to
pcibios_set_root_bus_speed()) could go to the PowerPC folks
individually. I'm not sure, however, that it's worth renaming it
and creating another function and another hook when no other arch
uses it. If mpe and benh don't want to pick it up, it'd be pretty
easy to take out set_root_bus_speed from the host_bridge_ops
struct, and this way we can still advance other parts of the
series.

* #16 (PCI: Introduce pci_bus_child_max_busnr()) is self-contained
and already has a user, so that should go in easily.

* The domain/bus numbering cleanup stuff could be broken out:
#3 (PCI: Save domain in pci_host_bridge)
#4 (PCI: Move pci_bus_assign_domain_nr() declaration into
drivers/pci/pci.h)
#8 (PCI: Introduce pci_host_assign_domain_nr() to assign domain),
#28 (PCI: Remove platform specific pci_domain_nr())
#29 (PCI: Remove pci_bus_assign_domain_nr())



I've done a bunch of rebasing and compiles to try to make sure all of
these proposed divisions work and there are no dependencies that I've
missed. It it's helpful, you can see what I've done at
https://github.com/daxtens/linux in the YijingWang-enumer10
branch. Feel free to use it as you wish.

I think the remaining 20 patches could probably be split again at least
once - it looks like the bus/bus numbering stuff might be easy to split
out? I might have a look again in a few days.

Regards,
Daniel

My final set of series, using your original patch names:

Set 1 (Xen cleanup):
xen/PCI: Don't use deprecated function pci_scan_bus_parented()
PCI: Remove deprecated pci_scan_bus_parented()

Set 2 (PowerPC cleanup):
powerpc/PCI: Rename pcibios_root_bridge_prepare() to
pcibios_set_root_bus_speed()

Set 3: (could possibly be merged with set 4)
PCI: Introduce pci_bus_child_max_busnr()

Set 4: (_nr and friends)
PCI: Save domain in pci_host_bridge
PCI: Move pci_bus_assign_domain_nr() declaration into
drivers/pci/pci.h
PCI: Introduce pci_host_assign_domain_nr() to assign domain
PCI: Remove platform specific pci_domain_nr()
PCI: Remove pci_bus_assign_domain_nr()

Remainder:
PCI: Remove argument bus for pci_create_root_bus()
PCI: Alloc busn resource dynamically for pci_scan_bus()
PCI: Allocate busn resource for pci_scan_root_bus()
PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
PCI: Introduce pci_host_bridge_list to manage host bridges
PCI: Save sysdata in pci_host_bridge drvdata
PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()
PCI: Introduce pci_host_bridge_ops to support host specific
operations
PCI: Introduce new scan function pci_scan_host_bridge()
x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
powerpc/pci: Use pci_scan_host_bridge() for simplicity
PCI: Remove pcibios_root_bridge_prepare() and
pcibos_set_root_bus_speed()
sparc/PCI: Use pci_scan_host_bridge() for simplicity
parisc/PCI: Use pci_scan_root_bus() for simplicity
PCI/mvebu: Use pci_common_init_dev() to simplify code
PCI/tegra: Remove redundant tegra_pcie_scan_bus()
PCI/designware: Use pci_scan_root_bus() for simplicity
PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()
PCI: Rename __pci_create_root_bus() to pci_create_root_bus()

On Tue, 2015-04-21 at 19:34 +0800, Yijing Wang wrote:
> This series could be pulled from:
> https://github.com/YijingWang/linux-pci.git enumer10
>
> v9->v10:
> Dynamically allocate busn resource if callers don't supply.
> Try to adjust busn resource if host bridge busn resource conlict.
> Rebase whole series on Bjorn's latest pci-next branch.
> Major v9->v10 changes are in patch 5,6,7,10.
> v8->v9:
> Add Thierry's Acked-by and Tested-by.
> Fix the building error for powerpc found by Daniel.
> Change pci_host_assign_domain_nr() to static.
> v7->v8:
> Fix some cross building errors found by kbuild test.
> Drop the rename patch for find_pci_host_bridge().
> v6->v7:
> Drop previous patch which combined the domain and bus in one argument.
> Make the pci_host_bridge hold the default busn resource, so we could
> check whether new host busn resource is conflict with existing ones.
> Move pci_host_assign_domain_nr() to drivers/pci/host-bridge.c
> Other changes suggested by Bjorn and Suravee.
> v5->v6:
> Fix cross building errors found by kbuild test.
> Export busn_resource to Xen pcifront driver.
> v4->v5:
> Fix some code style issues and rename some functions suggested by Bjorn.
> Fix some code flaw(Eg. call pci_bus_add_devices() before resources claim
> or lack the return checking).
> v3->v4:
> Fix the rebase issue.
> v2->v3:
> Rebase this series on v4.0-rc1.
> v1->v2:
> Split pci_host_bridge_list into a new patch, remove .phb_probe_mode
> and rework powerpc .phb_of_scan_bus() for simpilicty suggested by
> Arnd. Refresh some patch description log, and add a new patch to fix
> build warning in ia64.
>
> This series is based on Bjorn's pci/enumeration branch.
> You could pull it from https://github.com/YijingWang/linux-pci.git enumer9
>
> Now in kernel, we scan pci bus use the following ways:
> 1. pci_scan_bus.
> parent = NULL, default io/mem/bus resources
> call pci_bus_add_devices()
>
> 2. pci_scan_bus_parented() + pci_bus_add_devices()
> default io/mem/bus resources, only used by xen
>
> 3. pci_scan_root_bus() + pci_bus_add_devices()
>
> 4. pci_create_root_bus() + pci_scan_child_bus() + pci_bus_add_devices()
>
> 5. pci_create_root_bus() + xx_of_scan_bus() + pci_bus_add_devices()
>
> And we have a lot of arch specific pci_domain_nr() and other platform
> specific weak function like pcibios_root_bridge_prepare().
>
> After applied this series, we have following scan interfaces:
>
> 1. pci_scan_bus()
> parent = NULL, default io/mem/bus resources.
> for legacy pci scan
>
> 2. pci_scan_root_bus()
> for callers provide its own parent and io/mem/bus resources
> but no platform specific pci_host_bridge operations
>
> 3. pci_scan_host_bridge()
> for callers provide its own parent and io/mem/bus resources
>
>
>
> Arnd Bergmann (1):
> xen/PCI: Don't use deprecated function pci_scan_bus_parented()
>
> Yijing Wang (28):
> PCI: Remove deprecated pci_scan_bus_parented()
> PCI: Save domain in pci_host_bridge
> PCI: Move pci_bus_assign_domain_nr() declaration into
> drivers/pci/pci.h
> PCI: Remove argument bus for pci_create_root_bus()
> PCI: Alloc busn resource dynamically for pci_scan_bus()
> PCI: Allocate busn resource for pci_scan_root_bus()
> PCI: Introduce pci_host_assign_domain_nr() to assign domain
> PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
> PCI: Introduce pci_host_bridge_list to manage host bridges
> PCI: Save sysdata in pci_host_bridge drvdata
> powerpc/PCI: Rename pcibios_root_bridge_prepare() to
> pcibios_set_root_bus_speed()
> PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()
> PCI: Introduce pci_host_bridge_ops to support host specific
> operations
> PCI: Introduce new scan function pci_scan_host_bridge()
> PCI: Introduce pci_bus_child_max_busnr()
> x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
> ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
> powerpc/pci: Use pci_scan_host_bridge() for simplicity
> PCI: Remove pcibios_root_bridge_prepare() and
> pcibos_set_root_bus_speed()
> sparc/PCI: Use pci_scan_host_bridge() for simplicity
> parisc/PCI: Use pci_scan_root_bus() for simplicity
> PCI/mvebu: Use pci_common_init_dev() to simplify code
> PCI/tegra: Remove redundant tegra_pcie_scan_bus()
> PCI/designware: Use pci_scan_root_bus() for simplicity
> PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()
> PCI: Rename __pci_create_root_bus() to pci_create_root_bus()
> PCI: Remove platform specific pci_domain_nr()
> PCI: Remove pci_bus_assign_domain_nr()
>
> arch/alpha/include/asm/pci.h | 2 -
> arch/alpha/kernel/pci.c | 4 +-
> arch/alpha/kernel/sys_nautilus.c | 2 +-
> arch/arm/kernel/bios32.c | 2 +-
> arch/arm/mach-dove/pcie.c | 2 +-
> arch/arm/mach-iop13xx/pci.c | 4 +-
> arch/arm/mach-mv78xx0/pcie.c | 2 +-
> arch/arm/mach-orion5x/pci.c | 4 +-
> arch/frv/mb93090-mb00/pci-vdk.c | 3 +-
> arch/ia64/include/asm/pci.h | 1 -
> arch/ia64/pci/pci.c | 35 ++--
> arch/ia64/sn/kernel/io_init.c | 4 +-
> arch/m68k/coldfire/pci.c | 2 +-
> arch/microblaze/pci/pci-common.c | 15 +--
> arch/mips/include/asm/pci.h | 2 -
> arch/mips/pci/pci.c | 4 +-
> arch/mn10300/unit-asb2305/pci.c | 3 +-
> arch/powerpc/include/asm/machdep.h | 2 +-
> arch/powerpc/kernel/pci-common.c | 79 +++++-----
> arch/powerpc/platforms/pseries/pci.c | 8 +-
> arch/powerpc/platforms/pseries/pseries.h | 2 +-
> arch/powerpc/platforms/pseries/setup.c | 2 +-
> arch/s390/pci/pci.c | 10 +-
> arch/sh/drivers/pci/pci.c | 4 +-
> arch/sh/include/asm/pci.h | 2 -
> arch/sparc/kernel/leon_pci.c | 2 +-
> arch/sparc/kernel/pci.c | 45 +++---
> arch/sparc/kernel/pcic.c | 2 +-
> arch/tile/include/asm/pci.h | 2 -
> arch/tile/kernel/pci.c | 4 +-
> arch/tile/kernel/pci_gx.c | 4 +-
> arch/unicore32/kernel/pci.c | 2 +-
> arch/x86/include/asm/pci.h | 6 -
> arch/x86/pci/acpi.c | 37 +++--
> arch/x86/pci/common.c | 2 +-
> arch/xtensa/kernel/pci.c | 2 +-
> drivers/parisc/dino.c | 6 +-
> drivers/parisc/lba_pci.c | 6 +-
> drivers/pci/host-bridge.c | 223 +++++++++++++++++++++++++
> drivers/pci/host/pci-mvebu.c | 18 +--
> drivers/pci/host/pci-tegra.c | 16 --
> drivers/pci/host/pci-versatile.c | 3 +-
> drivers/pci/host/pci-xgene.c | 5 +-
> drivers/pci/host/pcie-designware.c | 6 +-
> drivers/pci/host/pcie-xilinx.c | 2 +-
> drivers/pci/hotplug/acpiphp_glue.c | 29 +---
> drivers/pci/hotplug/ibmphp_core.c | 2 +-
> drivers/pci/pci.c | 85 +++-------
> drivers/pci/pci.h | 5 +
> drivers/pci/probe.c | 265 ++++++++++++++---------------
> drivers/pci/xen-pcifront.c | 16 ++-
> include/linux/pci.h | 45 +++---
> 52 files changed, 573 insertions(+), 467 deletions(-)
>


Attachments:
signature.asc (860.00 B)
This is a digitally signed message part

2015-04-27 06:26:16

by Yijing Wang

[permalink] [raw]
Subject: Re: [PATCH v10 00/29] Refine PCI scan interfaces and make generic pci host bridge

On 2015/4/27 12:09, Daniel Axtens wrote:
> Hi Yijing,
>
> I'm wondering if you might get some more momentum on these changes if
> we could split them into a few smaller patch sets. I think we might
> then be able to start getting bits of this in for 4.2, which should help
> with getting the rest of it in.

Yes, I think this is a good idea, the whole series maybe a bit heavy,
split it to several parts make it easier for folks to review and test the patchset.

>
> I think there are a few things that would be easy to pull out.
>
> * #1 (xen/PCI: Don't use deprecated function
> pci_scan_bus_parented()) can go directly to Xen people and should
> be easy to merge. #2 (PCI: Remove deprecated
> pci_scan_bus_parented()) is then an easy fixup.

I will poke Konrad to try to get some feedback.

>
> * I think #12 (powerpc/PCI: Rename pcibios_root_bridge_prepare() to
> pcibios_set_root_bus_speed()) could go to the PowerPC folks
> individually. I'm not sure, however, that it's worth renaming it
> and creating another function and another hook when no other arch
> uses it. If mpe and benh don't want to pick it up, it'd be pretty
> easy to take out set_root_bus_speed from the host_bridge_ops
> struct, and this way we can still advance other parts of the
> series.
>
> * #16 (PCI: Introduce pci_bus_child_max_busnr()) is self-contained
> and already has a user, so that should go in easily.
>
> * The domain/bus numbering cleanup stuff could be broken out:
> #3 (PCI: Save domain in pci_host_bridge)
> #4 (PCI: Move pci_bus_assign_domain_nr() declaration into
> drivers/pci/pci.h)
> #8 (PCI: Introduce pci_host_assign_domain_nr() to assign domain),
> #28 (PCI: Remove platform specific pci_domain_nr())
> #29 (PCI: Remove pci_bus_assign_domain_nr())
>

The domain number related changes could be pulled out first, in this part,
try to remove arch spec pci_domain_nr().

>
>
> I've done a bunch of rebasing and compiles to try to make sure all of
> these proposed divisions work and there are no dependencies that I've
> missed. It it's helpful, you can see what I've done at
> https://github.com/daxtens/linux in the YijingWang-enumer10
> branch. Feel free to use it as you wish.
>
> I think the remaining 20 patches could probably be split again at least
> once - it looks like the bus/bus numbering stuff might be easy to split
> out? I might have a look again in a few days.

Hi Daniel, thanks very much!
I will try to reorganize these patches in two days.

Thanks!
Yijing.

>
> Regards,
> Daniel
>
> My final set of series, using your original patch names:
>
> Set 1 (Xen cleanup):
> xen/PCI: Don't use deprecated function pci_scan_bus_parented()
> PCI: Remove deprecated pci_scan_bus_parented()
>
> Set 2 (PowerPC cleanup):
> powerpc/PCI: Rename pcibios_root_bridge_prepare() to
> pcibios_set_root_bus_speed()
>
> Set 3: (could possibly be merged with set 4)
> PCI: Introduce pci_bus_child_max_busnr()
>
> Set 4: (_nr and friends)
> PCI: Save domain in pci_host_bridge
> PCI: Move pci_bus_assign_domain_nr() declaration into
> drivers/pci/pci.h
> PCI: Introduce pci_host_assign_domain_nr() to assign domain
> PCI: Remove platform specific pci_domain_nr()
> PCI: Remove pci_bus_assign_domain_nr()
>
> Remainder:
> PCI: Remove argument bus for pci_create_root_bus()
> PCI: Alloc busn resource dynamically for pci_scan_bus()
> PCI: Allocate busn resource for pci_scan_root_bus()
> PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
> PCI: Introduce pci_host_bridge_list to manage host bridges
> PCI: Save sysdata in pci_host_bridge drvdata
> PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()
> PCI: Introduce pci_host_bridge_ops to support host specific
> operations
> PCI: Introduce new scan function pci_scan_host_bridge()
> x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
> ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
> powerpc/pci: Use pci_scan_host_bridge() for simplicity
> PCI: Remove pcibios_root_bridge_prepare() and
> pcibos_set_root_bus_speed()
> sparc/PCI: Use pci_scan_host_bridge() for simplicity
> parisc/PCI: Use pci_scan_root_bus() for simplicity
> PCI/mvebu: Use pci_common_init_dev() to simplify code
> PCI/tegra: Remove redundant tegra_pcie_scan_bus()
> PCI/designware: Use pci_scan_root_bus() for simplicity
> PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()
> PCI: Rename __pci_create_root_bus() to pci_create_root_bus()
>
> On Tue, 2015-04-21 at 19:34 +0800, Yijing Wang wrote:
>> This series could be pulled from:
>> https://github.com/YijingWang/linux-pci.git enumer10
>>
>> v9->v10:
>> Dynamically allocate busn resource if callers don't supply.
>> Try to adjust busn resource if host bridge busn resource conlict.
>> Rebase whole series on Bjorn's latest pci-next branch.
>> Major v9->v10 changes are in patch 5,6,7,10.
>> v8->v9:
>> Add Thierry's Acked-by and Tested-by.
>> Fix the building error for powerpc found by Daniel.
>> Change pci_host_assign_domain_nr() to static.
>> v7->v8:
>> Fix some cross building errors found by kbuild test.
>> Drop the rename patch for find_pci_host_bridge().
>> v6->v7:
>> Drop previous patch which combined the domain and bus in one argument.
>> Make the pci_host_bridge hold the default busn resource, so we could
>> check whether new host busn resource is conflict with existing ones.
>> Move pci_host_assign_domain_nr() to drivers/pci/host-bridge.c
>> Other changes suggested by Bjorn and Suravee.
>> v5->v6:
>> Fix cross building errors found by kbuild test.
>> Export busn_resource to Xen pcifront driver.
>> v4->v5:
>> Fix some code style issues and rename some functions suggested by Bjorn.
>> Fix some code flaw(Eg. call pci_bus_add_devices() before resources claim
>> or lack the return checking).
>> v3->v4:
>> Fix the rebase issue.
>> v2->v3:
>> Rebase this series on v4.0-rc1.
>> v1->v2:
>> Split pci_host_bridge_list into a new patch, remove .phb_probe_mode
>> and rework powerpc .phb_of_scan_bus() for simpilicty suggested by
>> Arnd. Refresh some patch description log, and add a new patch to fix
>> build warning in ia64.
>>
>> This series is based on Bjorn's pci/enumeration branch.
>> You could pull it from https://github.com/YijingWang/linux-pci.git enumer9
>>
>> Now in kernel, we scan pci bus use the following ways:
>> 1. pci_scan_bus.
>> parent = NULL, default io/mem/bus resources
>> call pci_bus_add_devices()
>>
>> 2. pci_scan_bus_parented() + pci_bus_add_devices()
>> default io/mem/bus resources, only used by xen
>>
>> 3. pci_scan_root_bus() + pci_bus_add_devices()
>>
>> 4. pci_create_root_bus() + pci_scan_child_bus() + pci_bus_add_devices()
>>
>> 5. pci_create_root_bus() + xx_of_scan_bus() + pci_bus_add_devices()
>>
>> And we have a lot of arch specific pci_domain_nr() and other platform
>> specific weak function like pcibios_root_bridge_prepare().
>>
>> After applied this series, we have following scan interfaces:
>>
>> 1. pci_scan_bus()
>> parent = NULL, default io/mem/bus resources.
>> for legacy pci scan
>>
>> 2. pci_scan_root_bus()
>> for callers provide its own parent and io/mem/bus resources
>> but no platform specific pci_host_bridge operations
>>
>> 3. pci_scan_host_bridge()
>> for callers provide its own parent and io/mem/bus resources
>>
>>
>>
>> Arnd Bergmann (1):
>> xen/PCI: Don't use deprecated function pci_scan_bus_parented()
>>
>> Yijing Wang (28):
>> PCI: Remove deprecated pci_scan_bus_parented()
>> PCI: Save domain in pci_host_bridge
>> PCI: Move pci_bus_assign_domain_nr() declaration into
>> drivers/pci/pci.h
>> PCI: Remove argument bus for pci_create_root_bus()
>> PCI: Alloc busn resource dynamically for pci_scan_bus()
>> PCI: Allocate busn resource for pci_scan_root_bus()
>> PCI: Introduce pci_host_assign_domain_nr() to assign domain
>> PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
>> PCI: Introduce pci_host_bridge_list to manage host bridges
>> PCI: Save sysdata in pci_host_bridge drvdata
>> powerpc/PCI: Rename pcibios_root_bridge_prepare() to
>> pcibios_set_root_bus_speed()
>> PCI: Move pcibios_root_bridge_prepare() to pci_create_host_bridge()
>> PCI: Introduce pci_host_bridge_ops to support host specific
>> operations
>> PCI: Introduce new scan function pci_scan_host_bridge()
>> PCI: Introduce pci_bus_child_max_busnr()
>> x86/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
>> ia64/PCI: Refine pci_acpi_scan_root() with generic pci_host_bridge
>> powerpc/pci: Use pci_scan_host_bridge() for simplicity
>> PCI: Remove pcibios_root_bridge_prepare() and
>> pcibos_set_root_bus_speed()
>> sparc/PCI: Use pci_scan_host_bridge() for simplicity
>> parisc/PCI: Use pci_scan_root_bus() for simplicity
>> PCI/mvebu: Use pci_common_init_dev() to simplify code
>> PCI/tegra: Remove redundant tegra_pcie_scan_bus()
>> PCI/designware: Use pci_scan_root_bus() for simplicity
>> PCI/xgene: Use pci_scan_root_bus() instead of pci_create_root_bus()
>> PCI: Rename __pci_create_root_bus() to pci_create_root_bus()
>> PCI: Remove platform specific pci_domain_nr()
>> PCI: Remove pci_bus_assign_domain_nr()
>>
>> arch/alpha/include/asm/pci.h | 2 -
>> arch/alpha/kernel/pci.c | 4 +-
>> arch/alpha/kernel/sys_nautilus.c | 2 +-
>> arch/arm/kernel/bios32.c | 2 +-
>> arch/arm/mach-dove/pcie.c | 2 +-
>> arch/arm/mach-iop13xx/pci.c | 4 +-
>> arch/arm/mach-mv78xx0/pcie.c | 2 +-
>> arch/arm/mach-orion5x/pci.c | 4 +-
>> arch/frv/mb93090-mb00/pci-vdk.c | 3 +-
>> arch/ia64/include/asm/pci.h | 1 -
>> arch/ia64/pci/pci.c | 35 ++--
>> arch/ia64/sn/kernel/io_init.c | 4 +-
>> arch/m68k/coldfire/pci.c | 2 +-
>> arch/microblaze/pci/pci-common.c | 15 +--
>> arch/mips/include/asm/pci.h | 2 -
>> arch/mips/pci/pci.c | 4 +-
>> arch/mn10300/unit-asb2305/pci.c | 3 +-
>> arch/powerpc/include/asm/machdep.h | 2 +-
>> arch/powerpc/kernel/pci-common.c | 79 +++++-----
>> arch/powerpc/platforms/pseries/pci.c | 8 +-
>> arch/powerpc/platforms/pseries/pseries.h | 2 +-
>> arch/powerpc/platforms/pseries/setup.c | 2 +-
>> arch/s390/pci/pci.c | 10 +-
>> arch/sh/drivers/pci/pci.c | 4 +-
>> arch/sh/include/asm/pci.h | 2 -
>> arch/sparc/kernel/leon_pci.c | 2 +-
>> arch/sparc/kernel/pci.c | 45 +++---
>> arch/sparc/kernel/pcic.c | 2 +-
>> arch/tile/include/asm/pci.h | 2 -
>> arch/tile/kernel/pci.c | 4 +-
>> arch/tile/kernel/pci_gx.c | 4 +-
>> arch/unicore32/kernel/pci.c | 2 +-
>> arch/x86/include/asm/pci.h | 6 -
>> arch/x86/pci/acpi.c | 37 +++--
>> arch/x86/pci/common.c | 2 +-
>> arch/xtensa/kernel/pci.c | 2 +-
>> drivers/parisc/dino.c | 6 +-
>> drivers/parisc/lba_pci.c | 6 +-
>> drivers/pci/host-bridge.c | 223 +++++++++++++++++++++++++
>> drivers/pci/host/pci-mvebu.c | 18 +--
>> drivers/pci/host/pci-tegra.c | 16 --
>> drivers/pci/host/pci-versatile.c | 3 +-
>> drivers/pci/host/pci-xgene.c | 5 +-
>> drivers/pci/host/pcie-designware.c | 6 +-
>> drivers/pci/host/pcie-xilinx.c | 2 +-
>> drivers/pci/hotplug/acpiphp_glue.c | 29 +---
>> drivers/pci/hotplug/ibmphp_core.c | 2 +-
>> drivers/pci/pci.c | 85 +++-------
>> drivers/pci/pci.h | 5 +
>> drivers/pci/probe.c | 265 ++++++++++++++---------------
>> drivers/pci/xen-pcifront.c | 16 ++-
>> include/linux/pci.h | 45 +++---
>> 52 files changed, 573 insertions(+), 467 deletions(-)
>>
>


--
Thanks!
Yijing