diff options
-rw-r--r-- | drivers/pci/Makefile | 2 | ||||
-rw-r--r-- | drivers/pci/host-bridge.c | 93 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/probe.c | 81 |
4 files changed, 97 insertions, 81 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 083a49fee56a..2c224edae1ac 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the PCI bus specific drivers. | 2 | # Makefile for the PCI bus specific drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += access.o bus.o probe.o remove.o pci.o \ | 5 | obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ |
6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ | 6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ |
7 | irq.o vpd.o | 7 | irq.o vpd.o |
8 | obj-$(CONFIG_PROC_FS) += proc.o | 8 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c new file mode 100644 index 000000000000..28b24a5375d4 --- /dev/null +++ b/drivers/pci/host-bridge.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * host bridge related code | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/pci.h> | ||
8 | #include <linux/module.h> | ||
9 | |||
10 | #include "pci.h" | ||
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_host_bridge *pci_host_bridge(struct pci_dev *dev) | ||
20 | { | ||
21 | struct pci_bus *bus; | ||
22 | struct pci_host_bridge *bridge; | ||
23 | |||
24 | bus = dev->bus; | ||
25 | while (bus->parent) | ||
26 | bus = bus->parent; | ||
27 | |||
28 | list_for_each_entry(bridge, &pci_host_bridges, list) { | ||
29 | if (bridge->bus == bus) | ||
30 | return bridge; | ||
31 | } | ||
32 | |||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | static bool resource_contains(struct resource *res1, struct resource *res2) | ||
37 | { | ||
38 | return res1->start <= res2->start && res1->end >= res2->end; | ||
39 | } | ||
40 | |||
41 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
42 | struct resource *res) | ||
43 | { | ||
44 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
45 | struct pci_host_bridge_window *window; | ||
46 | resource_size_t offset = 0; | ||
47 | |||
48 | list_for_each_entry(window, &bridge->windows, list) { | ||
49 | if (resource_type(res) != resource_type(window->res)) | ||
50 | continue; | ||
51 | |||
52 | if (resource_contains(window->res, res)) { | ||
53 | offset = window->offset; | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | region->start = res->start - offset; | ||
59 | region->end = res->end - offset; | ||
60 | } | ||
61 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
62 | |||
63 | static bool region_contains(struct pci_bus_region *region1, | ||
64 | struct pci_bus_region *region2) | ||
65 | { | ||
66 | return region1->start <= region2->start && region1->end >= region2->end; | ||
67 | } | ||
68 | |||
69 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
70 | struct pci_bus_region *region) | ||
71 | { | ||
72 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
73 | struct pci_host_bridge_window *window; | ||
74 | struct pci_bus_region bus_region; | ||
75 | resource_size_t offset = 0; | ||
76 | |||
77 | list_for_each_entry(window, &bridge->windows, list) { | ||
78 | if (resource_type(res) != resource_type(window->res)) | ||
79 | continue; | ||
80 | |||
81 | bus_region.start = window->res->start - window->offset; | ||
82 | bus_region.end = window->res->end - window->offset; | ||
83 | |||
84 | if (region_contains(&bus_region, region)) { | ||
85 | offset = window->offset; | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | res->start = region->start + offset; | ||
91 | res->end = region->end + offset; | ||
92 | } | ||
93 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e4943479b234..c695a92cca13 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -231,6 +231,8 @@ static inline int pci_ari_enabled(struct pci_bus *bus) | |||
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 | |||
234 | /* Single Root I/O Virtualization */ | 236 | /* Single Root I/O Virtualization */ |
235 | struct pci_sriov { | 237 | struct pci_sriov { |
236 | int pos; /* capability position */ | 238 | int pos; /* capability position */ |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5e1ca3c58a7d..bcea52b90e0d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -15,13 +15,10 @@ | |||
15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ | 15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ |
16 | #define CARDBUS_RESERVE_BUSNR 3 | 16 | #define CARDBUS_RESERVE_BUSNR 3 |
17 | 17 | ||
18 | static LIST_HEAD(pci_host_bridges); | ||
19 | |||
20 | /* Ugh. Need to stop exporting this to modules. */ | 18 | /* Ugh. Need to stop exporting this to modules. */ |
21 | LIST_HEAD(pci_root_buses); | 19 | LIST_HEAD(pci_root_buses); |
22 | EXPORT_SYMBOL(pci_root_buses); | 20 | EXPORT_SYMBOL(pci_root_buses); |
23 | 21 | ||
24 | |||
25 | static int find_anything(struct device *dev, void *data) | 22 | static int find_anything(struct device *dev, void *data) |
26 | { | 23 | { |
27 | return 1; | 24 | return 1; |
@@ -44,82 +41,6 @@ int no_pci_devices(void) | |||
44 | } | 41 | } |
45 | EXPORT_SYMBOL(no_pci_devices); | 42 | EXPORT_SYMBOL(no_pci_devices); |
46 | 43 | ||
47 | static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev) | ||
48 | { | ||
49 | struct pci_bus *bus; | ||
50 | struct pci_host_bridge *bridge; | ||
51 | |||
52 | bus = dev->bus; | ||
53 | while (bus->parent) | ||
54 | bus = bus->parent; | ||
55 | |||
56 | list_for_each_entry(bridge, &pci_host_bridges, list) { | ||
57 | if (bridge->bus == bus) | ||
58 | return bridge; | ||
59 | } | ||
60 | |||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | static bool resource_contains(struct resource *res1, struct resource *res2) | ||
65 | { | ||
66 | return res1->start <= res2->start && res1->end >= res2->end; | ||
67 | } | ||
68 | |||
69 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
70 | struct resource *res) | ||
71 | { | ||
72 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
73 | struct pci_host_bridge_window *window; | ||
74 | resource_size_t offset = 0; | ||
75 | |||
76 | list_for_each_entry(window, &bridge->windows, list) { | ||
77 | if (resource_type(res) != resource_type(window->res)) | ||
78 | continue; | ||
79 | |||
80 | if (resource_contains(window->res, res)) { | ||
81 | offset = window->offset; | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | region->start = res->start - offset; | ||
87 | region->end = res->end - offset; | ||
88 | } | ||
89 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
90 | |||
91 | static bool region_contains(struct pci_bus_region *region1, | ||
92 | struct pci_bus_region *region2) | ||
93 | { | ||
94 | return region1->start <= region2->start && region1->end >= region2->end; | ||
95 | } | ||
96 | |||
97 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
98 | struct pci_bus_region *region) | ||
99 | { | ||
100 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
101 | struct pci_host_bridge_window *window; | ||
102 | struct pci_bus_region bus_region; | ||
103 | resource_size_t offset = 0; | ||
104 | |||
105 | list_for_each_entry(window, &bridge->windows, list) { | ||
106 | if (resource_type(res) != resource_type(window->res)) | ||
107 | continue; | ||
108 | |||
109 | bus_region.start = window->res->start - window->offset; | ||
110 | bus_region.end = window->res->end - window->offset; | ||
111 | |||
112 | if (region_contains(&bus_region, region)) { | ||
113 | offset = window->offset; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | res->start = region->start + offset; | ||
119 | res->end = region->end + offset; | ||
120 | } | ||
121 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
122 | |||
123 | /* | 44 | /* |
124 | * PCI Bus Class | 45 | * PCI Bus Class |
125 | */ | 46 | */ |
@@ -1732,7 +1653,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1732 | } | 1653 | } |
1733 | 1654 | ||
1734 | down_write(&pci_bus_sem); | 1655 | down_write(&pci_bus_sem); |
1735 | list_add_tail(&bridge->list, &pci_host_bridges); | 1656 | add_to_pci_host_bridges(bridge); |
1736 | list_add_tail(&b->node, &pci_root_buses); | 1657 | list_add_tail(&b->node, &pci_root_buses); |
1737 | up_write(&pci_bus_sem); | 1658 | up_write(&pci_bus_sem); |
1738 | 1659 | ||