diff options
Diffstat (limited to 'drivers/pci/hotplug/rpaphp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/rpaphp_pci.c | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index f7c12d7dfcfc..4b35097b3d9f 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -154,8 +154,7 @@ exit: | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* Must be called before pci_bus_add_devices */ | 156 | /* Must be called before pci_bus_add_devices */ |
157 | static void | 157 | void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) |
158 | rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | ||
159 | { | 158 | { |
160 | struct pci_dev *dev; | 159 | struct pci_dev *dev; |
161 | 160 | ||
@@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
184 | } | 183 | } |
185 | } | 184 | } |
186 | 185 | ||
186 | static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) | ||
187 | { | ||
188 | struct pci_dev *dev; | ||
189 | |||
190 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
191 | eeh_add_device_late(dev); | ||
192 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
193 | struct pci_bus *subbus = dev->subordinate; | ||
194 | if (subbus) | ||
195 | rpaphp_eeh_add_bus_device (subbus); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | |||
187 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) | 200 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) |
188 | { | 201 | { |
189 | u8 sec_busno; | 202 | u8 sec_busno; |
@@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) | |||
217 | return 0; | 230 | return 0; |
218 | } | 231 | } |
219 | 232 | ||
233 | void rpaphp_init_new_devs(struct pci_bus *bus) | ||
234 | { | ||
235 | rpaphp_fixup_new_pci_devices(bus, 0); | ||
236 | rpaphp_eeh_add_bus_device(bus); | ||
237 | } | ||
238 | EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); | ||
239 | |||
220 | /***************************************************************************** | 240 | /***************************************************************************** |
221 | rpaphp_pci_config_slot() will configure all devices under the | 241 | rpaphp_pci_config_slot() will configure all devices under the |
222 | given slot->dn and return the the first pci_dev. | 242 | given slot->dn and return the the first pci_dev. |
@@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
233 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
234 | return NULL; | 254 | return NULL; |
235 | 255 | ||
236 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 256 | if (_machine == PLATFORM_PSERIES_LPAR) { |
257 | of_scan_bus(dn, bus); | ||
258 | if (list_empty(&bus->devices)) { | ||
259 | err("%s: No new device found\n", __FUNCTION__); | ||
260 | return NULL; | ||
261 | } | ||
237 | 262 | ||
238 | /* pci_scan_slot should find all children */ | 263 | rpaphp_init_new_devs(bus); |
239 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | ||
240 | if (num) { | ||
241 | rpaphp_fixup_new_pci_devices(bus, 1); | ||
242 | pci_bus_add_devices(bus); | 264 | pci_bus_add_devices(bus); |
243 | } | 265 | dev = list_entry(&bus->devices, struct pci_dev, bus_list); |
244 | if (list_empty(&bus->devices)) { | 266 | } else { |
245 | err("%s: No new device found\n", __FUNCTION__); | 267 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
246 | return NULL; | 268 | |
247 | } | 269 | /* pci_scan_slot should find all children */ |
248 | list_for_each_entry(dev, &bus->devices, bus_list) { | 270 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
249 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | 271 | if (num) { |
250 | rpaphp_pci_config_bridge(dev); | 272 | rpaphp_fixup_new_pci_devices(bus, 1); |
273 | pci_bus_add_devices(bus); | ||
274 | } | ||
275 | if (list_empty(&bus->devices)) { | ||
276 | err("%s: No new device found\n", __FUNCTION__); | ||
277 | return NULL; | ||
278 | } | ||
279 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
280 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
281 | rpaphp_pci_config_bridge(dev); | ||
282 | |||
283 | rpaphp_eeh_add_bus_device(bus); | ||
284 | } | ||
251 | } | 285 | } |
252 | 286 | ||
253 | return dev; | 287 | return dev; |
254 | } | 288 | } |
255 | 289 | ||
256 | static void enable_eeh(struct device_node *dn) | 290 | void rpaphp_eeh_init_nodes(struct device_node *dn) |
257 | { | 291 | { |
258 | struct device_node *sib; | 292 | struct device_node *sib; |
259 | 293 | ||
260 | for (sib = dn->child; sib; sib = sib->sibling) | 294 | for (sib = dn->child; sib; sib = sib->sibling) |
261 | enable_eeh(sib); | 295 | rpaphp_eeh_init_nodes(sib); |
262 | eeh_add_device_early(dn); | 296 | eeh_add_device_early(dn); |
263 | return; | 297 | return; |
264 | 298 | ||
265 | } | 299 | } |
300 | EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); | ||
266 | 301 | ||
267 | static void print_slot_pci_funcs(struct pci_bus *bus) | 302 | static void print_slot_pci_funcs(struct pci_bus *bus) |
268 | { | 303 | { |
@@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) | |||
289 | if (!dn) | 324 | if (!dn) |
290 | goto exit; | 325 | goto exit; |
291 | 326 | ||
292 | enable_eeh(dn); | 327 | rpaphp_eeh_init_nodes(dn); |
293 | dev = rpaphp_pci_config_slot(bus); | 328 | dev = rpaphp_pci_config_slot(bus); |
294 | if (!dev) { | 329 | if (!dev) { |
295 | err("%s: can't find any devices.\n", __FUNCTION__); | 330 | err("%s: can't find any devices.\n", __FUNCTION__); |
@@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) | |||
331 | } | 366 | } |
332 | return 0; | 367 | return 0; |
333 | } | 368 | } |
369 | EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); | ||
334 | 370 | ||
335 | static int setup_pci_hotplug_slot_info(struct slot *slot) | 371 | static int setup_pci_hotplug_slot_info(struct slot *slot) |
336 | { | 372 | { |
@@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot) | |||
444 | retval = rpaphp_config_pci_adapter(slot->bus); | 480 | retval = rpaphp_config_pci_adapter(slot->bus); |
445 | if (!retval) { | 481 | if (!retval) { |
446 | slot->state = CONFIGURED; | 482 | slot->state = CONFIGURED; |
447 | dbg("%s: PCI devices in slot[%s] has been configured\n", | 483 | info("%s: devices in slot[%s] configured\n", |
448 | __FUNCTION__, slot->name); | 484 | __FUNCTION__, slot->name); |
449 | } else { | 485 | } else { |
450 | slot->state = NOT_CONFIGURED; | 486 | slot->state = NOT_CONFIGURED; |
451 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", | 487 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", |