Commit 97ad2bdc authored by Lorenzo Pieralisi's avatar Lorenzo Pieralisi Committed by Bjorn Helgaas

ARM/PCI: Convert PCI scan API to pci_scan_root_bus_bridge()

The introduction of pci_scan_root_bus_bridge() provides a PCI core API to
scan a PCI root bus backed by an already initialized struct pci_host_bridge
object, which simplifies the bus scan interface and makes the PCI scan root
bus interface easier to generalize as members are added to the struct
pci_host_bridge.

Convert ARM bios32 code to pci_scan_root_bus_bridge() to improve the PCI
root bus scanning interface.
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
[bhelgaas: fold in warning fix from Arnd Bergmann <arnd@arndb.de>:
http://lkml.kernel.org/r/20170621215323.3921382-1-arnd@arndb.de]
[bhelgaas: set bridge->ops for mv78xx0]
[bhelgaas: fold in fixes from Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>:
http://lkml.kernel.org/r/20170701135457.GB8977@red-moon]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
parent cea9bc0b
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
struct pci_sys_data; struct pci_sys_data;
struct pci_ops; struct pci_ops;
struct pci_bus; struct pci_bus;
struct pci_host_bridge;
struct device; struct device;
struct hw_pci { struct hw_pci {
...@@ -25,7 +26,7 @@ struct hw_pci { ...@@ -25,7 +26,7 @@ struct hw_pci {
unsigned int io_optional:1; unsigned int io_optional:1;
void **private_data; void **private_data;
int (*setup)(int nr, struct pci_sys_data *); int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *); int (*scan)(int nr, struct pci_host_bridge *);
void (*preinit)(void); void (*preinit)(void);
void (*postinit)(void); void (*postinit)(void);
u8 (*swizzle)(struct pci_dev *dev, u8 *pin); u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
......
...@@ -458,10 +458,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -458,10 +458,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
int nr, busnr; int nr, busnr;
for (nr = busnr = 0; nr < hw->nr_controllers; nr++) { for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL); struct pci_host_bridge *bridge;
if (WARN(!sys, "PCI: unable to allocate sys data!"))
bridge = pci_alloc_host_bridge(sizeof(struct pci_sys_data));
if (WARN(!bridge, "PCI: unable to allocate bridge!"))
break; break;
sys = pci_host_bridge_priv(bridge);
sys->busnr = busnr; sys->busnr = busnr;
sys->swizzle = hw->swizzle; sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq; sys->map_irq = hw->map_irq;
...@@ -473,7 +477,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -473,7 +477,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
ret = hw->setup(nr, sys); ret = hw->setup(nr, sys);
if (ret > 0) { if (ret > 0) {
struct pci_host_bridge *host_bridge;
ret = pcibios_init_resource(nr, sys, hw->io_optional); ret = pcibios_init_resource(nr, sys, hw->io_optional);
if (ret) { if (ret) {
...@@ -482,25 +485,33 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -482,25 +485,33 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
} }
if (hw->scan) if (hw->scan)
sys->bus = hw->scan(nr, sys); ret = hw->scan(nr, bridge);
else else {
sys->bus = pci_scan_root_bus_msi(parent, list_splice_init(&sys->resources,
sys->busnr, hw->ops, sys, &bridge->windows);
&sys->resources, hw->msi_ctrl); bridge->dev.parent = parent;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = hw->ops;
bridge->msi = hw->msi_ctrl;
bridge->align_resource =
hw->align_resource;
ret = pci_scan_root_bus_bridge(bridge);
}
if (WARN(!sys->bus, "PCI: unable to scan bus!")) { if (WARN(ret < 0, "PCI: unable to scan bus!")) {
kfree(sys); pci_free_host_bridge(bridge);
break; break;
} }
sys->bus = bridge->bus;
busnr = sys->bus->busn_res.end + 1; busnr = sys->bus->busn_res.end + 1;
list_add(&sys->node, head); list_add(&sys->node, head);
host_bridge = pci_find_host_bridge(sys->bus);
host_bridge->align_resource = hw->align_resource;
} else { } else {
kfree(sys); pci_free_host_bridge(bridge);
if (ret < 0) if (ret < 0)
break; break;
} }
......
...@@ -152,16 +152,23 @@ static void rc_pci_fixup(struct pci_dev *dev) ...@@ -152,16 +152,23 @@ static void rc_pci_fixup(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init * static int __init
dove_pcie_scan_bus(int nr, struct pci_sys_data *sys) dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) { if (nr >= num_pcie_ports) {
BUG(); BUG();
return NULL; return -EINVAL;
} }
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys, list_splice_init(&sys->resources, &bridge->windows);
&sys->resources); bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
} }
static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
...@@ -504,10 +504,10 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -504,10 +504,10 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
/* Scan an IOP13XX PCI bus. nr selects which ATU we use. /* Scan an IOP13XX PCI bus. nr selects which ATU we use.
*/ */
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
int which_atu; int which_atu, ret;
struct pci_bus *bus = NULL; struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
switch (init_atu) { switch (init_atu) {
case IOP13XX_INIT_ATU_ATUX: case IOP13XX_INIT_ATU_ATUX:
...@@ -525,9 +525,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) ...@@ -525,9 +525,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
if (!which_atu) { if (!which_atu) {
BUG(); BUG();
return NULL; return -ENODEV;
} }
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
switch (which_atu) { switch (which_atu) {
case IOP13XX_INIT_ATU_ATUX: case IOP13XX_INIT_ATU_ATUX:
if (time_after_eq(jiffies + msecs_to_jiffies(1000), if (time_after_eq(jiffies + msecs_to_jiffies(1000),
...@@ -535,18 +540,22 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) ...@@ -535,18 +540,22 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
while(time_before(jiffies, atux_trhfa_timeout)) while(time_before(jiffies, atux_trhfa_timeout))
udelay(100); udelay(100);
bus = pci_bus_atux = pci_scan_root_bus(NULL, sys->busnr, bridge->ops = &iop13xx_atux_ops;
&iop13xx_atux_ops, ret = pci_scan_root_bus_bridge(bridge);
sys, &sys->resources); if (!ret)
pci_bus_atux = bridge->bus;
break; break;
case IOP13XX_INIT_ATU_ATUE: case IOP13XX_INIT_ATU_ATUE:
bus = pci_bus_atue = pci_scan_root_bus(NULL, sys->busnr, bridge->ops = &iop13xx_atue_ops;
&iop13xx_atue_ops, ret = pci_scan_root_bus_bridge(bridge);
sys, &sys->resources); if (!ret)
pci_bus_atue = bridge->bus;
break; break;
default:
ret = -EINVAL;
} }
return bus; return ret;
} }
/* This function is called from iop13xx_pci_init() after assigning valid /* This function is called from iop13xx_pci_init() after assigning valid
......
...@@ -11,9 +11,10 @@ extern size_t iop13xx_atue_mem_size; ...@@ -11,9 +11,10 @@ extern size_t iop13xx_atue_mem_size;
extern size_t iop13xx_atux_mem_size; extern size_t iop13xx_atux_mem_size;
struct pci_sys_data; struct pci_sys_data;
struct pci_host_bridge;
struct hw_pci; struct hw_pci;
int iop13xx_pci_setup(int nr, struct pci_sys_data *sys); int iop13xx_pci_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *); int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge);
void iop13xx_atu_select(struct hw_pci *plat_pci); void iop13xx_atu_select(struct hw_pci *plat_pci);
void iop13xx_pci_init(void); void iop13xx_pci_init(void);
void iop13xx_map_pci_memory(void); void iop13xx_map_pci_memory(void);
......
...@@ -194,16 +194,22 @@ static void rc_pci_fixup(struct pci_dev *dev) ...@@ -194,16 +194,22 @@ static void rc_pci_fixup(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init * static int __init mv78xx0_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
{ {
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) { if (nr >= num_pcie_ports) {
BUG(); BUG();
return NULL; return -EINVAL;
} }
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys, list_splice_init(&sys->resources, &bridge->windows);
&sys->resources); bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
} }
static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot, static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
......
...@@ -54,6 +54,7 @@ void orion5x_restart(enum reboot_mode, const char *); ...@@ -54,6 +54,7 @@ void orion5x_restart(enum reboot_mode, const char *);
* PCIe/PCI functions. * PCIe/PCI functions.
*/ */
struct pci_bus; struct pci_bus;
struct pci_host_bridge;
struct pci_sys_data; struct pci_sys_data;
struct pci_dev; struct pci_dev;
...@@ -61,7 +62,7 @@ void orion5x_pcie_id(u32 *dev, u32 *rev); ...@@ -61,7 +62,7 @@ void orion5x_pcie_id(u32 *dev, u32 *rev);
void orion5x_pci_disable(void); void orion5x_pci_disable(void);
void orion5x_pci_set_cardbus_mode(void); void orion5x_pci_set_cardbus_mode(void);
int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge);
int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
struct tag; struct tag;
......
...@@ -555,18 +555,27 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys) ...@@ -555,18 +555,27 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
return 0; return 0;
} }
struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys) int __init orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
if (nr == 0) struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
if (nr == 1 && !orion5x_pci_disabled) list_splice_init(&sys->resources, &bridge->windows);
return pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys, bridge->dev.parent = NULL;
&sys->resources); bridge->sysdata = sys;
bridge->busnr = sys->busnr;
if (nr == 0) {
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
}
if (nr == 1 && !orion5x_pci_disabled) {
bridge->ops = &pci_ops;
return pci_scan_root_bus_bridge(bridge);
}
BUG(); BUG();
return NULL; return -ENODEV;
} }
int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment