diff options
-rw-r--r-- | drivers/pci/host-bridge.c | 15 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/probe.c | 66 | ||||
-rw-r--r-- | include/linux/pci.h | 4 |
4 files changed, 39 insertions, 48 deletions
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c index c49a1c482cfb..122df80592c3 100644 --- a/drivers/pci/host-bridge.c +++ b/drivers/pci/host-bridge.c | |||
@@ -9,13 +9,6 @@ | |||
9 | 9 | ||
10 | #include "pci.h" | 10 | #include "pci.h" |
11 | 11 | ||
12 | static LIST_HEAD(pci_host_bridges); | ||
13 | |||
14 | void add_to_pci_host_bridges(struct pci_host_bridge *bridge) | ||
15 | { | ||
16 | list_add_tail(&bridge->list, &pci_host_bridges); | ||
17 | } | ||
18 | |||
19 | static struct pci_bus *find_pci_root_bus(struct pci_dev *dev) | 12 | static struct pci_bus *find_pci_root_bus(struct pci_dev *dev) |
20 | { | 13 | { |
21 | struct pci_bus *bus; | 14 | struct pci_bus *bus; |
@@ -30,14 +23,8 @@ static struct pci_bus *find_pci_root_bus(struct pci_dev *dev) | |||
30 | static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev) | 23 | static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev) |
31 | { | 24 | { |
32 | struct pci_bus *bus = find_pci_root_bus(dev); | 25 | struct pci_bus *bus = find_pci_root_bus(dev); |
33 | struct pci_host_bridge *bridge; | ||
34 | |||
35 | list_for_each_entry(bridge, &pci_host_bridges, list) { | ||
36 | if (bridge->bus == bus) | ||
37 | return bridge; | ||
38 | } | ||
39 | 26 | ||
40 | return NULL; | 27 | return to_pci_host_bridge(bus->bridge); |
41 | } | 28 | } |
42 | 29 | ||
43 | static bool resource_contains(struct resource *res1, struct resource *res2) | 30 | static bool resource_contains(struct resource *res1, struct resource *res2) |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c695a92cca13..e4943479b234 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -231,8 +231,6 @@ static inline int pci_ari_enabled(struct pci_bus *bus) | |||
231 | void pci_reassigndev_resource_alignment(struct pci_dev *dev); | 231 | void pci_reassigndev_resource_alignment(struct pci_dev *dev); |
232 | extern void pci_disable_bridge_window(struct pci_dev *dev); | 232 | extern void pci_disable_bridge_window(struct pci_dev *dev); |
233 | 233 | ||
234 | void add_to_pci_host_bridges(struct pci_host_bridge *bridge); | ||
235 | |||
236 | /* Single Root I/O Virtualization */ | 234 | /* Single Root I/O Virtualization */ |
237 | struct pci_sriov { | 235 | struct pci_sriov { |
238 | int pos; /* capability position */ | 236 | int pos; /* capability position */ |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index bcea52b90e0d..8d291ee15257 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -422,6 +422,19 @@ static struct pci_bus * pci_alloc_bus(void) | |||
422 | return b; | 422 | return b; |
423 | } | 423 | } |
424 | 424 | ||
425 | static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) | ||
426 | { | ||
427 | struct pci_host_bridge *bridge; | ||
428 | |||
429 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); | ||
430 | if (bridge) { | ||
431 | INIT_LIST_HEAD(&bridge->windows); | ||
432 | bridge->bus = b; | ||
433 | } | ||
434 | |||
435 | return bridge; | ||
436 | } | ||
437 | |||
425 | static unsigned char pcix_bus_speed[] = { | 438 | static unsigned char pcix_bus_speed[] = { |
426 | PCI_SPEED_UNKNOWN, /* 0 */ | 439 | PCI_SPEED_UNKNOWN, /* 0 */ |
427 | PCI_SPEED_66MHz_PCIX, /* 1 */ | 440 | PCI_SPEED_66MHz_PCIX, /* 1 */ |
@@ -1122,7 +1135,13 @@ int pci_cfg_space_size(struct pci_dev *dev) | |||
1122 | 1135 | ||
1123 | static void pci_release_bus_bridge_dev(struct device *dev) | 1136 | static void pci_release_bus_bridge_dev(struct device *dev) |
1124 | { | 1137 | { |
1125 | kfree(dev); | 1138 | struct pci_host_bridge *bridge = to_pci_host_bridge(dev); |
1139 | |||
1140 | /* TODO: need to free window->res */ | ||
1141 | |||
1142 | pci_free_resource_list(&bridge->windows); | ||
1143 | |||
1144 | kfree(bridge); | ||
1126 | } | 1145 | } |
1127 | 1146 | ||
1128 | struct pci_dev *alloc_pci_dev(void) | 1147 | struct pci_dev *alloc_pci_dev(void) |
@@ -1571,28 +1590,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1571 | int error; | 1590 | int error; |
1572 | struct pci_host_bridge *bridge; | 1591 | struct pci_host_bridge *bridge; |
1573 | struct pci_bus *b, *b2; | 1592 | struct pci_bus *b, *b2; |
1574 | struct device *dev; | ||
1575 | struct pci_host_bridge_window *window, *n; | 1593 | struct pci_host_bridge_window *window, *n; |
1576 | struct resource *res; | 1594 | struct resource *res; |
1577 | resource_size_t offset; | 1595 | resource_size_t offset; |
1578 | char bus_addr[64]; | 1596 | char bus_addr[64]; |
1579 | char *fmt; | 1597 | char *fmt; |
1580 | 1598 | ||
1581 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); | ||
1582 | if (!bridge) | ||
1583 | return NULL; | ||
1584 | 1599 | ||
1585 | b = pci_alloc_bus(); | 1600 | b = pci_alloc_bus(); |
1586 | if (!b) | 1601 | if (!b) |
1587 | goto err_bus; | 1602 | return NULL; |
1588 | |||
1589 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1590 | if (!dev) | ||
1591 | goto err_dev; | ||
1592 | 1603 | ||
1593 | b->sysdata = sysdata; | 1604 | b->sysdata = sysdata; |
1594 | b->ops = ops; | 1605 | b->ops = ops; |
1595 | |||
1596 | b2 = pci_find_bus(pci_domain_nr(b), bus); | 1606 | b2 = pci_find_bus(pci_domain_nr(b), bus); |
1597 | if (b2) { | 1607 | if (b2) { |
1598 | /* If we already got to this bus through a different bridge, ignore it */ | 1608 | /* If we already got to this bus through a different bridge, ignore it */ |
@@ -1600,13 +1610,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1600 | goto err_out; | 1610 | goto err_out; |
1601 | } | 1611 | } |
1602 | 1612 | ||
1603 | dev->parent = parent; | 1613 | bridge = pci_alloc_host_bridge(b); |
1604 | dev->release = pci_release_bus_bridge_dev; | 1614 | if (!bridge) |
1605 | dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus); | 1615 | goto err_out; |
1606 | error = device_register(dev); | 1616 | |
1617 | bridge->dev.parent = parent; | ||
1618 | bridge->dev.release = pci_release_bus_bridge_dev; | ||
1619 | dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); | ||
1620 | error = device_register(&bridge->dev); | ||
1607 | if (error) | 1621 | if (error) |
1608 | goto dev_reg_err; | 1622 | goto bridge_dev_reg_err; |
1609 | b->bridge = get_device(dev); | 1623 | b->bridge = get_device(&bridge->dev); |
1610 | device_enable_async_suspend(b->bridge); | 1624 | device_enable_async_suspend(b->bridge); |
1611 | pci_set_bus_of_node(b); | 1625 | pci_set_bus_of_node(b); |
1612 | 1626 | ||
@@ -1625,9 +1639,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1625 | 1639 | ||
1626 | b->number = b->secondary = bus; | 1640 | b->number = b->secondary = bus; |
1627 | 1641 | ||
1628 | bridge->bus = b; | ||
1629 | INIT_LIST_HEAD(&bridge->windows); | ||
1630 | |||
1631 | if (parent) | 1642 | if (parent) |
1632 | dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); | 1643 | dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); |
1633 | else | 1644 | else |
@@ -1653,25 +1664,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1653 | } | 1664 | } |
1654 | 1665 | ||
1655 | down_write(&pci_bus_sem); | 1666 | down_write(&pci_bus_sem); |
1656 | add_to_pci_host_bridges(bridge); | ||
1657 | list_add_tail(&b->node, &pci_root_buses); | 1667 | list_add_tail(&b->node, &pci_root_buses); |
1658 | up_write(&pci_bus_sem); | 1668 | up_write(&pci_bus_sem); |
1659 | 1669 | ||
1660 | return b; | 1670 | return b; |
1661 | 1671 | ||
1662 | class_dev_reg_err: | 1672 | class_dev_reg_err: |
1663 | device_unregister(dev); | 1673 | put_device(&bridge->dev); |
1664 | dev_reg_err: | 1674 | device_unregister(&bridge->dev); |
1665 | down_write(&pci_bus_sem); | 1675 | bridge_dev_reg_err: |
1666 | list_del(&bridge->list); | 1676 | kfree(bridge); |
1667 | list_del(&b->node); | ||
1668 | up_write(&pci_bus_sem); | ||
1669 | err_out: | 1677 | err_out: |
1670 | kfree(dev); | ||
1671 | err_dev: | ||
1672 | kfree(b); | 1678 | kfree(b); |
1673 | err_bus: | ||
1674 | kfree(bridge); | ||
1675 | return NULL; | 1679 | return NULL; |
1676 | } | 1680 | } |
1677 | 1681 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index e444f5b49118..8f4f29d2b606 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -375,11 +375,13 @@ struct pci_host_bridge_window { | |||
375 | }; | 375 | }; |
376 | 376 | ||
377 | struct pci_host_bridge { | 377 | struct pci_host_bridge { |
378 | struct list_head list; | 378 | struct device dev; |
379 | struct pci_bus *bus; /* root bus */ | 379 | struct pci_bus *bus; /* root bus */ |
380 | struct list_head windows; /* pci_host_bridge_windows */ | 380 | struct list_head windows; /* pci_host_bridge_windows */ |
381 | }; | 381 | }; |
382 | 382 | ||
383 | #define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev) | ||
384 | |||
383 | /* | 385 | /* |
384 | * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond | 386 | * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond |
385 | * to P2P or CardBus bridge windows) go in a table. Additional ones (for | 387 | * to P2P or CardBus bridge windows) go in a table. Additional ones (for |