aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorJohn Rose <johnrose@austin.ibm.com>2005-07-25 12:13:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 17:57:22 -0400
commit9c209c919df95f83aa042b3352c43841ad15a02b (patch)
tree9be41a91d2da30893cc4e5b88fa02ea36f756598 /drivers/pci/hotplug
parent5eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14 (diff)
[PATCH] PCI Hotplug: rpaphp: Change slot pci reference
The slot structure in the rpaphp module currently references the PCI contents of the slot using the PCI device of the parent bridge. This is unnecessary, since the module is actually interested in the subordinate bus of the bridge. The dependency on a PCI bridge device also prohibits the module from registering hotplug slots that have a root bridge as a parent, since root bridges on PPC64 don't have PCI devices. This patch changes struct slot to reference the PCI subsystem using a pci_bus rather than a pci_dev. Signed-off-by: John Rose <johnrose@austin.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c44
-rw-r--r--drivers/pci/hotplug/rpaphp.h7
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c141
3 files changed, 75 insertions, 117 deletions
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index d7f1319f167a..7f868edaa72d 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -198,28 +198,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
198 return dev; 198 return dev;
199} 199}
200 200
201static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
202{
203 struct pci_bus *secondary_bus;
204
205 if (!bridge_dev) {
206 printk(KERN_ERR "%s: unexpected null device\n",
207 __FUNCTION__);
208 return -EINVAL;
209 }
210
211 secondary_bus = bridge_dev->subordinate;
212
213 if (unmap_bus_range(secondary_bus)) {
214 printk(KERN_ERR "%s: failed to unmap bus range\n",
215 __FUNCTION__);
216 return -ERANGE;
217 }
218
219 pci_remove_bus_device(bridge_dev);
220 return 0;
221}
222
223static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) 201static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
224{ 202{
225 struct pci_dev *dev; 203 struct pci_dev *dev;
@@ -415,14 +393,7 @@ static int dlpar_remove_vio_slot(struct device_node *dn, char *drc_name)
415 */ 393 */
416int dlpar_remove_pci_slot(struct slot *slot, char *drc_name) 394int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
417{ 395{
418 struct pci_dev *bridge_dev; 396 struct pci_bus *bus = slot->bus;
419
420 bridge_dev = slot->bridge;
421 if (!bridge_dev) {
422 printk(KERN_ERR "%s: unexpected null bridge device\n",
423 __FUNCTION__);
424 return -EIO;
425 }
426 397
427 /* Remove hotplug slot */ 398 /* Remove hotplug slot */
428 if (rpaphp_remove_slot(slot)) { 399 if (rpaphp_remove_slot(slot)) {
@@ -431,13 +402,14 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
431 return -EIO; 402 return -EIO;
432 } 403 }
433 404
434 /* Remove pci bus */ 405 if (unmap_bus_range(bus)) {
435 406 printk(KERN_ERR "%s: failed to unmap bus range\n",
436 if (dlpar_pci_remove_bus(bridge_dev)) { 407 __FUNCTION__);
437 printk(KERN_ERR "%s: unable to remove pci bus %s\n", 408 return -ERANGE;
438 __FUNCTION__, drc_name);
439 return -EIO;
440 } 409 }
410
411 BUG_ON(!bus->self);
412 pci_remove_bus_device(bus->self);
441 return 0; 413 return 0;
442} 414}
443 415
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 2d9f420dfa4f..9f050fde80c2 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -80,10 +80,9 @@ struct slot {
80 char *name; 80 char *name;
81 char *location; 81 char *location;
82 u8 removable; 82 u8 removable;
83 struct device_node *dn; /* slot's device_node in OFDT */ 83 struct device_node *dn;
84 /* dn has phb info */ 84 struct pci_bus *bus;
85 struct pci_dev *bridge; /* slot's pci_dev in pci_devices */ 85 struct list_head *pci_devs;
86 struct list_head *pci_devs; /* pci_devs in PCI slot */
87 struct hotplug_slot *hotplug_slot; 86 struct hotplug_slot *hotplug_slot;
88}; 87};
89 88
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 30d10fcc24b2..54fff5fb0094 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -45,6 +45,32 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
45 return dev; 45 return dev;
46} 46}
47 47
48struct pci_bus *find_bus_among_children(struct pci_bus *bus,
49 struct device_node *dn)
50{
51 struct pci_bus *child = NULL;
52 struct list_head *tmp;
53 struct device_node *busdn;
54
55 busdn = pci_bus_to_OF_node(bus);
56 if (busdn == dn)
57 return bus;
58
59 list_for_each(tmp, &bus->children) {
60 child = find_bus_among_children(pci_bus_b(tmp), dn);
61 if (child)
62 break;
63 }
64 return child;
65}
66
67struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
68{
69 BUG_ON(!dn->phb || !dn->phb->bus);
70
71 return find_bus_among_children(dn->phb->bus, dn);
72}
73
48EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); 74EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev);
49 75
50int rpaphp_claim_resource(struct pci_dev *dev, int resource) 76int rpaphp_claim_resource(struct pci_dev *dev, int resource)
@@ -69,11 +95,6 @@ int rpaphp_claim_resource(struct pci_dev *dev, int resource)
69 95
70EXPORT_SYMBOL_GPL(rpaphp_claim_resource); 96EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
71 97
72static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
73{
74 return rpaphp_find_pci_dev(slot->dn);
75}
76
77static int rpaphp_get_sensor_state(struct slot *slot, int *state) 98static int rpaphp_get_sensor_state(struct slot *slot, int *state)
78{ 99{
79 int rc; 100 int rc;
@@ -226,20 +247,22 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev)
226static struct pci_dev * 247static struct pci_dev *
227rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) 248rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus)
228{ 249{
229 struct device_node *eads_first_child = dn->child;
230 struct pci_dev *dev = NULL; 250 struct pci_dev *dev = NULL;
251 int slotno;
231 int num; 252 int num;
232 253
233 dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); 254 dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
234 255
235 if (eads_first_child) { 256 if (dn->child) {
236 /* pci_scan_slot should find all children of EADs */ 257 slotno = PCI_SLOT(dn->child->devfn);
237 num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); 258
259 /* pci_scan_slot should find all children */
260 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
238 if (num) { 261 if (num) {
239 rpaphp_fixup_new_pci_devices(bus, 1); 262 rpaphp_fixup_new_pci_devices(bus, 1);
240 pci_bus_add_devices(bus); 263 pci_bus_add_devices(bus);
241 } 264 }
242 dev = rpaphp_find_pci_dev(eads_first_child); 265 dev = rpaphp_find_pci_dev(dn->child);
243 if (!dev) { 266 if (!dev) {
244 err("No new device found\n"); 267 err("No new device found\n");
245 return NULL; 268 return NULL;
@@ -273,31 +296,19 @@ static void print_slot_pci_funcs(struct slot *slot)
273 296
274static int rpaphp_config_pci_adapter(struct slot *slot) 297static int rpaphp_config_pci_adapter(struct slot *slot)
275{ 298{
276 struct pci_bus *pci_bus;
277 struct pci_dev *dev; 299 struct pci_dev *dev;
278 int rc = -ENODEV; 300 int rc = -ENODEV;
279 301
280 dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); 302 dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
281 303
282 if (slot->bridge) { 304 enable_eeh(slot->dn);
283 305 dev = rpaphp_pci_config_slot(slot->dn, slot->bus);
284 pci_bus = slot->bridge->subordinate; 306 if (!dev) {
285 if (!pci_bus) { 307 err("%s: can't find any devices.\n", __FUNCTION__);
286 err("%s: can't find bus structure\n", __FUNCTION__); 308 goto exit;
287 goto exit;
288 }
289 enable_eeh(slot->dn);
290 dev = rpaphp_pci_config_slot(slot->dn, pci_bus);
291 if (!dev) {
292 err("%s: can't find any devices.\n", __FUNCTION__);
293 goto exit;
294 }
295 print_slot_pci_funcs(slot);
296 rc = 0;
297 } else {
298 /* slot is not enabled */
299 err("slot doesn't have pci_dev structure\n");
300 } 309 }
310 print_slot_pci_funcs(slot);
311 rc = 0;
301exit: 312exit:
302 dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); 313 dbg("Exit %s: rc=%d\n", __FUNCTION__, rc);
303 return rc; 314 return rc;
@@ -323,13 +334,14 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
323 334
324int rpaphp_unconfig_pci_adapter(struct slot *slot) 335int rpaphp_unconfig_pci_adapter(struct slot *slot)
325{ 336{
326 struct pci_dev *dev; 337 struct pci_dev *dev, *tmp;
327 int retval = 0; 338 int retval = 0;
328 339
329 list_for_each_entry(dev, slot->pci_devs, bus_list) 340 list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
330 rpaphp_eeh_remove_bus_device(dev); 341 rpaphp_eeh_remove_bus_device(dev);
342 pci_remove_bus_device(dev);
343 }
331 344
332 pci_remove_behind_bridge(slot->bridge);
333 slot->state = NOT_CONFIGURED; 345 slot->state = NOT_CONFIGURED;
334 info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, 346 info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
335 slot->name); 347 slot->name);
@@ -352,66 +364,41 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
352 return 0; 364 return 0;
353} 365}
354 366
355static int set_phb_slot_name(struct slot *slot) 367static void set_slot_name(struct slot *slot)
356{ 368{
357 struct device_node *dn; 369 struct pci_bus *bus = slot->bus;
358 struct pci_controller *phb; 370 struct pci_dev *bridge;
359 struct pci_bus *bus;
360
361 dn = slot->dn;
362 if (!dn) {
363 return -EINVAL;
364 }
365 phb = dn->phb;
366 if (!phb) {
367 return -EINVAL;
368 }
369 bus = phb->bus;
370 if (!bus) {
371 return -EINVAL;
372 }
373 371
374 sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus), 372 bridge = bus->self;
375 bus->number, 0, 0); 373 if (bridge)
376 return 0; 374 strcpy(slot->name, pci_name(bridge));
375 else
376 sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
377 bus->number);
377} 378}
378 379
379static int setup_pci_slot(struct slot *slot) 380static int setup_pci_slot(struct slot *slot)
380{ 381{
382 struct device_node *dn = slot->dn;
381 struct pci_bus *bus; 383 struct pci_bus *bus;
382 int rc;
383 384
384 if (slot->type == PHB) { 385 BUG_ON(!dn);
385 rc = set_phb_slot_name(slot); 386 bus = rpaphp_find_pci_bus(dn);
386 if (rc < 0) { 387 if (!bus) {
387 err("%s: failed to set phb slot name\n", __FUNCTION__); 388 err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
388 goto exit_rc; 389 goto exit_rc;
389 }
390 } else {
391 slot->bridge = rpaphp_find_bridge_pdev(slot);
392 if (!slot->bridge) {
393 /* slot being added doesn't have pci_dev yet */
394 err("%s: no pci_dev for bridge dn %s\n",
395 __FUNCTION__, slot->name);
396 goto exit_rc;
397 }
398
399 bus = slot->bridge->subordinate;
400 if (!bus)
401 goto exit_rc;
402 slot->pci_devs = &bus->devices;
403
404 dbg("%s set slot->name to %s\n", __FUNCTION__,
405 pci_name(slot->bridge));
406 strcpy(slot->name, pci_name(slot->bridge));
407 } 390 }
408 391
392 slot->bus = bus;
393 slot->pci_devs = &bus->devices;
394 set_slot_name(slot);
395
409 /* find slot's pci_dev if it's not empty */ 396 /* find slot's pci_dev if it's not empty */
410 if (slot->hotplug_slot->info->adapter_status == EMPTY) { 397 if (slot->hotplug_slot->info->adapter_status == EMPTY) {
411 slot->state = EMPTY; /* slot is empty */ 398 slot->state = EMPTY; /* slot is empty */
412 } else { 399 } else {
413 /* slot is occupied */ 400 /* slot is occupied */
414 if (!(slot->dn->child)) { 401 if (!dn->child) {
415 /* non-empty slot has to have child */ 402 /* non-empty slot has to have child */
416 err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 403 err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
417 __FUNCTION__, slot->name); 404 __FUNCTION__, slot->name);