aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/rpaphp_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/rpaphp_pci.c')
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c142
1 files changed, 1 insertions, 141 deletions
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index f16d0f9240ee..1a12ebd10e34 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -101,140 +101,6 @@ exit:
101 return rc; 101 return rc;
102} 102}
103 103
104/* Must be called before pci_bus_add_devices */
105void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
106{
107 struct pci_dev *dev;
108
109 list_for_each_entry(dev, &bus->devices, bus_list) {
110 /*
111 * Skip already-present devices (which are on the
112 * global device list.)
113 */
114 if (list_empty(&dev->global_list)) {
115 int i;
116
117 /* Need to setup IOMMU tables */
118 ppc_md.iommu_dev_setup(dev);
119
120 if(fix_bus)
121 pcibios_fixup_device_resources(dev, bus);
122 pci_read_irq_line(dev);
123 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
124 struct resource *r = &dev->resource[i];
125
126 if (r->parent || !r->start || !r->flags)
127 continue;
128 pci_claim_resource(dev, i);
129 }
130 }
131 }
132}
133
134static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
135{
136 struct pci_dev *dev;
137
138 list_for_each_entry(dev, &bus->devices, bus_list) {
139 eeh_add_device_late(dev);
140 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
141 struct pci_bus *subbus = dev->subordinate;
142 if (subbus)
143 rpaphp_eeh_add_bus_device (subbus);
144 }
145 }
146}
147
148static int rpaphp_pci_config_bridge(struct pci_dev *dev)
149{
150 u8 sec_busno;
151 struct pci_bus *child_bus;
152 struct pci_dev *child_dev;
153
154 dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
155
156 /* get busno of downstream bus */
157 pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
158
159 /* add to children of PCI bridge dev->bus */
160 child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
161 if (!child_bus) {
162 err("%s: could not add second bus\n", __FUNCTION__);
163 return -EIO;
164 }
165 sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
166 /* do pci_scan_child_bus */
167 pci_scan_child_bus(child_bus);
168
169 list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
170 eeh_add_device_late(child_dev);
171 }
172
173 /* fixup new pci devices without touching bus struct */
174 rpaphp_fixup_new_pci_devices(child_bus, 0);
175
176 /* Make the discovered devices available */
177 pci_bus_add_devices(child_bus);
178 return 0;
179}
180
181void rpaphp_init_new_devs(struct pci_bus *bus)
182{
183 rpaphp_fixup_new_pci_devices(bus, 0);
184 rpaphp_eeh_add_bus_device(bus);
185}
186EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
187
188/*****************************************************************************
189 rpaphp_pci_config_slot() will configure all devices under the
190 given slot->dn and return the the first pci_dev.
191 *****************************************************************************/
192static struct pci_dev *
193rpaphp_pci_config_slot(struct pci_bus *bus)
194{
195 struct device_node *dn = pci_bus_to_OF_node(bus);
196 struct pci_dev *dev = NULL;
197 int slotno;
198 int num;
199
200 dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
201 if (!dn || !dn->child)
202 return NULL;
203
204 if (_machine == PLATFORM_PSERIES_LPAR) {
205 of_scan_bus(dn, bus);
206 if (list_empty(&bus->devices)) {
207 err("%s: No new device found\n", __FUNCTION__);
208 return NULL;
209 }
210
211 rpaphp_init_new_devs(bus);
212 pci_bus_add_devices(bus);
213 dev = list_entry(&bus->devices, struct pci_dev, bus_list);
214 } else {
215 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
216
217 /* pci_scan_slot should find all children */
218 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
219 if (num) {
220 rpaphp_fixup_new_pci_devices(bus, 1);
221 pci_bus_add_devices(bus);
222 }
223 if (list_empty(&bus->devices)) {
224 err("%s: No new device found\n", __FUNCTION__);
225 return NULL;
226 }
227 list_for_each_entry(dev, &bus->devices, bus_list) {
228 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
229 rpaphp_pci_config_bridge(dev);
230
231 rpaphp_eeh_add_bus_device(bus);
232 }
233 }
234
235 return dev;
236}
237
238static void print_slot_pci_funcs(struct pci_bus *bus) 104static void print_slot_pci_funcs(struct pci_bus *bus)
239{ 105{
240 struct device_node *dn; 106 struct device_node *dn;
@@ -253,19 +119,13 @@ static void print_slot_pci_funcs(struct pci_bus *bus)
253int rpaphp_config_pci_adapter(struct pci_bus *bus) 119int rpaphp_config_pci_adapter(struct pci_bus *bus)
254{ 120{
255 struct device_node *dn = pci_bus_to_OF_node(bus); 121 struct device_node *dn = pci_bus_to_OF_node(bus);
256 struct pci_dev *dev;
257 int rc = -ENODEV; 122 int rc = -ENODEV;
258 123
259 dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name); 124 dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
260 if (!dn) 125 if (!dn)
261 goto exit; 126 goto exit;
262 127
263 eeh_add_device_tree_early(dn); 128 pcibios_add_pci_devices(bus);
264 dev = rpaphp_pci_config_slot(bus);
265 if (!dev) {
266 err("%s: can't find any devices.\n", __FUNCTION__);
267 goto exit;
268 }
269 print_slot_pci_funcs(bus); 129 print_slot_pci_funcs(bus);
270 rc = 0; 130 rc = 0;
271exit: 131exit: