@@ -23,8 +23,8 @@ static void pci_release_host_bridge_dev(struct device *dev)
}
struct pci_host_bridge *pci_create_host_bridge(
- struct device *parent, u32 db,
- struct list_head *resources, void *sysdata)
+ struct device *parent, u32 db, struct list_head *resources,
+ void *sysdata, struct pci_host_bridge_ops *ops)
{
int error;
int bus = PCI_BUSNUM(db);
@@ -56,6 +56,7 @@ struct pci_host_bridge *pci_create_host_bridge(
}
mutex_unlock(&phb_mutex);
+ host->ops = ops;
host->dev.parent = parent;
INIT_LIST_HEAD(&host->windows);
host->dev.release = pci_release_host_bridge_dev;
@@ -63,6 +64,13 @@ struct pci_host_bridge *pci_create_host_bridge(
dev_set_name(&host->dev, "pci%04x:%02x", host->domain,
host->busnum);
+ if (host->ops && host->ops->prepare) {
+ error = host->ops->prepare(host);
+ if (error) {
+ kfree(host);
+ return NULL;
+ }
+ }
error = device_register(&host->dev);
if (error) {
put_device(&host->dev);
@@ -322,8 +322,8 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
#endif
struct pci_host_bridge *pci_create_host_bridge(
- struct device *parent, u32 dombus,
- struct list_head *resources, void *sysdata);
+ struct device *parent, u32 dombus, struct list_head *resources,
+ void *sysdata, struct pci_host_bridge_ops *ops);
void pci_free_host_bridge(struct pci_host_bridge *host);
#endif /* DRIVERS_PCI_H */
@@ -1888,6 +1888,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);
error = pcibios_root_bridge_prepare(bridge);
if (error)
goto err_out;
@@ -1953,7 +1955,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
{
struct pci_host_bridge *host;
- host = pci_create_host_bridge(parent, db, resources, sysdata);
+ host = pci_create_host_bridge(parent, db, resources, sysdata, NULL);
if (!host)
return NULL;
@@ -2050,10 +2052,13 @@ static struct pci_bus *__pci_scan_root_bus(
pci_bus_insert_busn_res(b, b->number, 255);
}
- max = pci_scan_child_bus(b);
-
- if (!found)
- pci_bus_update_busn_res_end(b, max);
+ if (host->ops && host->ops->scan_bus) {
+ host->ops->scan_bus(host);
+ } else {
+ max = pci_scan_child_bus(b);
+ if (!found)
+ pci_bus_update_busn_res_end(b, max);
+ }
return b;
}
@@ -2063,7 +2068,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
{
struct pci_host_bridge *host;
- host = pci_create_host_bridge(parent, db, resources, sysdata);
+ host = pci_create_host_bridge(parent, db, resources, sysdata, NULL);
if (!host)
return NULL;
@@ -400,6 +400,13 @@ 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 {
+ void (*set_root_bus_speed)(struct pci_host_bridge *host);
+ int (*prepare)(struct pci_host_bridge *host);
+ void (*scan_bus)(struct pci_host_bridge *);
+};
+
struct pci_host_bridge {
u16 domain;
u16 busnum;
@@ -407,6 +414,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;
};