diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 21:41:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 21:41:42 -0500 |
commit | 977127174a7dff52d17faeeb4c4949a54221881f (patch) | |
tree | b05b9d18a1256d7ed97bdfb537213a8d70ccca57 /drivers/pci | |
parent | 80c0531514516e43ae118ddf38424e06e5c3cb3c (diff) | |
parent | 93b47684f60cf25e8cefe19a21d94aa0257fdf36 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp.h | 8 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 127 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_ctrl.c | 28 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 138 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_pci.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 92 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 19 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 52 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehprm_acpi.c | 13 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 27 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp_pci.c | 47 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 16 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 37 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 138 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 19 | ||||
-rw-r--r-- | drivers/pci/pci.c | 7 | ||||
-rw-r--r-- | drivers/pci/pci.h | 5 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 4 | ||||
-rw-r--r-- | drivers/pci/probe.c | 49 | ||||
-rw-r--r-- | drivers/pci/proc.c | 3 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 26 | ||||
-rw-r--r-- | drivers/pci/remove.c | 3 |
24 files changed, 523 insertions, 347 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 8e21f6ab89a1..509a5b3ae998 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -794,12 +794,14 @@ static int enable_device(struct acpiphp_slot *slot) | |||
794 | if (PCI_SLOT(dev->devfn) != slot->device) | 794 | if (PCI_SLOT(dev->devfn) != slot->device) |
795 | continue; | 795 | continue; |
796 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 796 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
797 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 797 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
798 | max = pci_scan_bridge(bus, dev, max, pass); | 798 | max = pci_scan_bridge(bus, dev, max, pass); |
799 | if (pass && dev->subordinate) | ||
800 | pci_bus_size_bridges(dev->subordinate); | ||
801 | } | ||
799 | } | 802 | } |
800 | } | 803 | } |
801 | 804 | ||
802 | pci_bus_size_bridges(bus); | ||
803 | pci_bus_assign_resources(bus); | 805 | pci_bus_assign_resources(bus); |
804 | acpiphp_sanitize_bus(bus); | 806 | acpiphp_sanitize_bus(bus); |
805 | pci_enable_bridges(bus); | 807 | pci_enable_bridges(bus); |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 092491e25ef2..cb88404c89fe 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -317,6 +317,7 @@ struct controller { | |||
317 | u16 vendor_id; | 317 | u16 vendor_id; |
318 | struct work_struct int_task_event; | 318 | struct work_struct int_task_event; |
319 | wait_queue_head_t queue; /* sleep & wake process */ | 319 | wait_queue_head_t queue; /* sleep & wake process */ |
320 | struct dentry *dentry; /* debugfs dentry */ | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | struct irq_mapping { | 323 | struct irq_mapping { |
@@ -399,8 +400,11 @@ struct resource_lists { | |||
399 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 400 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" |
400 | 401 | ||
401 | 402 | ||
402 | /* sysfs functions for the hotplug controller info */ | 403 | /* debugfs functions for the hotplug controller info */ |
403 | extern void cpqhp_create_ctrl_files (struct controller *ctrl); | 404 | extern void cpqhp_initialize_debugfs (void); |
405 | extern void cpqhp_shutdown_debugfs (void); | ||
406 | extern void cpqhp_create_debugfs_files (struct controller *ctrl); | ||
407 | extern void cpqhp_remove_debugfs_files (struct controller *ctrl); | ||
404 | 408 | ||
405 | /* controller functions */ | 409 | /* controller functions */ |
406 | extern void cpqhp_pushbutton_thread (unsigned long event_pointer); | 410 | extern void cpqhp_pushbutton_thread (unsigned long event_pointer); |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 9aed8efe6a11..b3659ffccac9 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -327,7 +327,9 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
327 | void __iomem *smbios_start, | 327 | void __iomem *smbios_start, |
328 | void __iomem *smbios_table) | 328 | void __iomem *smbios_table) |
329 | { | 329 | { |
330 | struct slot *new_slot; | 330 | struct slot *slot; |
331 | struct hotplug_slot *hotplug_slot; | ||
332 | struct hotplug_slot_info *hotplug_slot_info; | ||
331 | u8 number_of_slots; | 333 | u8 number_of_slots; |
332 | u8 slot_device; | 334 | u8 slot_device; |
333 | u8 slot_number; | 335 | u8 slot_number; |
@@ -345,93 +347,105 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
345 | slot_number = ctrl->first_slot; | 347 | slot_number = ctrl->first_slot; |
346 | 348 | ||
347 | while (number_of_slots) { | 349 | while (number_of_slots) { |
348 | new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); | 350 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); |
349 | if (!new_slot) | 351 | if (!slot) |
350 | goto error; | 352 | goto error; |
351 | 353 | ||
352 | memset(new_slot, 0, sizeof(struct slot)); | 354 | memset(slot, 0, sizeof(struct slot)); |
353 | new_slot->hotplug_slot = kmalloc(sizeof(*(new_slot->hotplug_slot)), | 355 | slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)), |
354 | GFP_KERNEL); | 356 | GFP_KERNEL); |
355 | if (!new_slot->hotplug_slot) | 357 | if (!slot->hotplug_slot) |
356 | goto error_slot; | 358 | goto error_slot; |
357 | memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); | 359 | hotplug_slot = slot->hotplug_slot; |
360 | memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); | ||
358 | 361 | ||
359 | new_slot->hotplug_slot->info = | 362 | hotplug_slot->info = |
360 | kmalloc(sizeof(*(new_slot->hotplug_slot->info)), | 363 | kmalloc(sizeof(*(hotplug_slot->info)), |
361 | GFP_KERNEL); | 364 | GFP_KERNEL); |
362 | if (!new_slot->hotplug_slot->info) | 365 | if (!hotplug_slot->info) |
363 | goto error_hpslot; | 366 | goto error_hpslot; |
364 | memset(new_slot->hotplug_slot->info, 0, | 367 | hotplug_slot_info = hotplug_slot->info; |
368 | memset(hotplug_slot_info, 0, | ||
365 | sizeof(struct hotplug_slot_info)); | 369 | sizeof(struct hotplug_slot_info)); |
366 | new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | 370 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
367 | if (!new_slot->hotplug_slot->name) | 371 | |
372 | if (!hotplug_slot->name) | ||
368 | goto error_info; | 373 | goto error_info; |
369 | 374 | ||
370 | new_slot->ctrl = ctrl; | 375 | slot->ctrl = ctrl; |
371 | new_slot->bus = ctrl->bus; | 376 | slot->bus = ctrl->bus; |
372 | new_slot->device = slot_device; | 377 | slot->device = slot_device; |
373 | new_slot->number = slot_number; | 378 | slot->number = slot_number; |
374 | dbg("slot->number = %d\n",new_slot->number); | 379 | dbg("slot->number = %d\n", slot->number); |
375 | 380 | ||
376 | slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, | 381 | slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, |
377 | slot_entry); | 382 | slot_entry); |
378 | 383 | ||
379 | while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) { | 384 | while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != |
385 | slot->number)) { | ||
380 | slot_entry = get_SMBIOS_entry(smbios_start, | 386 | slot_entry = get_SMBIOS_entry(smbios_start, |
381 | smbios_table, 9, slot_entry); | 387 | smbios_table, 9, slot_entry); |
382 | } | 388 | } |
383 | 389 | ||
384 | new_slot->p_sm_slot = slot_entry; | 390 | slot->p_sm_slot = slot_entry; |
385 | 391 | ||
386 | init_timer(&new_slot->task_event); | 392 | init_timer(&slot->task_event); |
387 | new_slot->task_event.expires = jiffies + 5 * HZ; | 393 | slot->task_event.expires = jiffies + 5 * HZ; |
388 | new_slot->task_event.function = cpqhp_pushbutton_thread; | 394 | slot->task_event.function = cpqhp_pushbutton_thread; |
389 | 395 | ||
390 | //FIXME: these capabilities aren't used but if they are | 396 | //FIXME: these capabilities aren't used but if they are |
391 | // they need to be correctly implemented | 397 | // they need to be correctly implemented |
392 | new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; | 398 | slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; |
393 | new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; | 399 | slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; |
394 | 400 | ||
395 | if (is_slot64bit(new_slot)) | 401 | if (is_slot64bit(slot)) |
396 | new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | 402 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; |
397 | if (is_slot66mhz(new_slot)) | 403 | if (is_slot66mhz(slot)) |
398 | new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | 404 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; |
399 | if (ctrl->speed == PCI_SPEED_66MHz) | 405 | if (ctrl->speed == PCI_SPEED_66MHz) |
400 | new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | 406 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; |
401 | 407 | ||
402 | ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); | 408 | ctrl_slot = |
409 | slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); | ||
403 | 410 | ||
404 | // Check presence | 411 | // Check presence |
405 | new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; | 412 | slot->capabilities |= |
413 | ((((~tempdword) >> 23) | | ||
414 | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; | ||
406 | // Check the switch state | 415 | // Check the switch state |
407 | new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; | 416 | slot->capabilities |= |
417 | ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; | ||
408 | // Check the slot enable | 418 | // Check the slot enable |
409 | new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; | 419 | slot->capabilities |= |
420 | ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; | ||
410 | 421 | ||
411 | /* register this slot with the hotplug pci core */ | 422 | /* register this slot with the hotplug pci core */ |
412 | new_slot->hotplug_slot->release = &release_slot; | 423 | hotplug_slot->release = &release_slot; |
413 | new_slot->hotplug_slot->private = new_slot; | 424 | hotplug_slot->private = slot; |
414 | make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); | 425 | make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot); |
415 | new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops; | 426 | hotplug_slot->ops = &cpqphp_hotplug_slot_ops; |
416 | 427 | ||
417 | new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot); | 428 | hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot); |
418 | new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot); | 429 | hotplug_slot_info->attention_status = |
419 | new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot); | 430 | cpq_get_attention_status(ctrl, slot); |
420 | new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot); | 431 | hotplug_slot_info->latch_status = |
432 | cpq_get_latch_status(ctrl, slot); | ||
433 | hotplug_slot_info->adapter_status = | ||
434 | get_presence_status(ctrl, slot); | ||
421 | 435 | ||
422 | dbg ("registering bus %d, dev %d, number %d, " | 436 | dbg("registering bus %d, dev %d, number %d, " |
423 | "ctrl->slot_device_offset %d, slot %d\n", | 437 | "ctrl->slot_device_offset %d, slot %d\n", |
424 | new_slot->bus, new_slot->device, | 438 | slot->bus, slot->device, |
425 | new_slot->number, ctrl->slot_device_offset, | 439 | slot->number, ctrl->slot_device_offset, |
426 | slot_number); | 440 | slot_number); |
427 | result = pci_hp_register (new_slot->hotplug_slot); | 441 | result = pci_hp_register(hotplug_slot); |
428 | if (result) { | 442 | if (result) { |
429 | err ("pci_hp_register failed with error %d\n", result); | 443 | err("pci_hp_register failed with error %d\n", result); |
430 | goto error_name; | 444 | goto error_name; |
431 | } | 445 | } |
432 | 446 | ||
433 | new_slot->next = ctrl->slot; | 447 | slot->next = ctrl->slot; |
434 | ctrl->slot = new_slot; | 448 | ctrl->slot = slot; |
435 | 449 | ||
436 | number_of_slots--; | 450 | number_of_slots--; |
437 | slot_device++; | 451 | slot_device++; |
@@ -439,15 +453,14 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
439 | } | 453 | } |
440 | 454 | ||
441 | return 0; | 455 | return 0; |
442 | |||
443 | error_name: | 456 | error_name: |
444 | kfree(new_slot->hotplug_slot->name); | 457 | kfree(hotplug_slot->name); |
445 | error_info: | 458 | error_info: |
446 | kfree(new_slot->hotplug_slot->info); | 459 | kfree(hotplug_slot_info); |
447 | error_hpslot: | 460 | error_hpslot: |
448 | kfree(new_slot->hotplug_slot); | 461 | kfree(hotplug_slot); |
449 | error_slot: | 462 | error_slot: |
450 | kfree(new_slot); | 463 | kfree(slot); |
451 | error: | 464 | error: |
452 | return result; | 465 | return result; |
453 | } | 466 | } |
@@ -466,6 +479,8 @@ static int ctrl_slot_cleanup (struct controller * ctrl) | |||
466 | old_slot = next_slot; | 479 | old_slot = next_slot; |
467 | } | 480 | } |
468 | 481 | ||
482 | cpqhp_remove_debugfs_files(ctrl); | ||
483 | |||
469 | //Free IRQ associated with hot plug device | 484 | //Free IRQ associated with hot plug device |
470 | free_irq(ctrl->interrupt, ctrl); | 485 | free_irq(ctrl->interrupt, ctrl); |
471 | //Unmap the memory | 486 | //Unmap the memory |
@@ -1262,7 +1277,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1262 | // Done with exclusive hardware access | 1277 | // Done with exclusive hardware access |
1263 | up(&ctrl->crit_sect); | 1278 | up(&ctrl->crit_sect); |
1264 | 1279 | ||
1265 | cpqhp_create_ctrl_files(ctrl); | 1280 | cpqhp_create_debugfs_files(ctrl); |
1266 | 1281 | ||
1267 | return 0; | 1282 | return 0; |
1268 | 1283 | ||
@@ -1502,6 +1517,7 @@ static int __init cpqhpc_init(void) | |||
1502 | cpqhp_debug = debug; | 1517 | cpqhp_debug = debug; |
1503 | 1518 | ||
1504 | info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 1519 | info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
1520 | cpqhp_initialize_debugfs(); | ||
1505 | result = pci_register_driver(&cpqhpc_driver); | 1521 | result = pci_register_driver(&cpqhpc_driver); |
1506 | dbg("pci_register_driver = %d\n", result); | 1522 | dbg("pci_register_driver = %d\n", result); |
1507 | return result; | 1523 | return result; |
@@ -1515,6 +1531,7 @@ static void __exit cpqhpc_cleanup(void) | |||
1515 | 1531 | ||
1516 | dbg("pci_unregister_driver\n"); | 1532 | dbg("pci_unregister_driver\n"); |
1517 | pci_unregister_driver(&cpqhpc_driver); | 1533 | pci_unregister_driver(&cpqhpc_driver); |
1534 | cpqhp_shutdown_debugfs(); | ||
1518 | } | 1535 | } |
1519 | 1536 | ||
1520 | 1537 | ||
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 10a5a7674a8a..771ed34b1819 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -2630,29 +2630,15 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func | |||
2630 | hold_mem_node = NULL; | 2630 | hold_mem_node = NULL; |
2631 | } | 2631 | } |
2632 | 2632 | ||
2633 | /* If we have prefetchable memory resources copy them and | 2633 | memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); |
2634 | * fill in the bridge's memory range registers. Otherwise, | 2634 | p_mem_node->next = NULL; |
2635 | * fill in the range registers with values that disable them. */ | ||
2636 | if (p_mem_node) { | ||
2637 | memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); | ||
2638 | p_mem_node->next = NULL; | ||
2639 | |||
2640 | /* set Pre Mem base and Limit registers */ | ||
2641 | temp_word = p_mem_node->base >> 16; | ||
2642 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); | ||
2643 | |||
2644 | temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16; | ||
2645 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | ||
2646 | } else { | ||
2647 | temp_word = 0xFFFF; | ||
2648 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); | ||
2649 | 2635 | ||
2650 | temp_word = 0x0000; | 2636 | /* set Pre Mem base and Limit registers */ |
2651 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | 2637 | temp_word = p_mem_node->base >> 16; |
2638 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); | ||
2652 | 2639 | ||
2653 | kfree(hold_p_mem_node); | 2640 | temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16; |
2654 | hold_p_mem_node = NULL; | 2641 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); |
2655 | } | ||
2656 | 2642 | ||
2657 | /* Adjust this to compensate for extra adjustment in first loop */ | 2643 | /* Adjust this to compensate for extra adjustment in first loop */ |
2658 | irqs.barber_pole--; | 2644 | irqs.barber_pole--; |
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 4c11048ad51b..bbfeed767ff1 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
@@ -33,22 +33,15 @@ | |||
33 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/debugfs.h> | ||
36 | #include "cpqphp.h" | 37 | #include "cpqphp.h" |
37 | 38 | ||
38 | 39 | static int show_ctrl (struct controller *ctrl, char *buf) | |
39 | /* A few routines that create sysfs entries for the hot plug controller */ | ||
40 | |||
41 | static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf) | ||
42 | { | 40 | { |
43 | struct pci_dev *pci_dev; | 41 | char *out = buf; |
44 | struct controller *ctrl; | ||
45 | char * out = buf; | ||
46 | int index; | 42 | int index; |
47 | struct pci_resource *res; | 43 | struct pci_resource *res; |
48 | 44 | ||
49 | pci_dev = container_of (dev, struct pci_dev, dev); | ||
50 | ctrl = pci_get_drvdata(pci_dev); | ||
51 | |||
52 | out += sprintf(buf, "Free resources: memory\n"); | 45 | out += sprintf(buf, "Free resources: memory\n"); |
53 | index = 11; | 46 | index = 11; |
54 | res = ctrl->mem_head; | 47 | res = ctrl->mem_head; |
@@ -80,22 +73,16 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
80 | 73 | ||
81 | return out - buf; | 74 | return out - buf; |
82 | } | 75 | } |
83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); | ||
84 | 76 | ||
85 | static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf) | 77 | static int show_dev (struct controller *ctrl, char *buf) |
86 | { | 78 | { |
87 | struct pci_dev *pci_dev; | ||
88 | struct controller *ctrl; | ||
89 | char * out = buf; | 79 | char * out = buf; |
90 | int index; | 80 | int index; |
91 | struct pci_resource *res; | 81 | struct pci_resource *res; |
92 | struct pci_func *new_slot; | 82 | struct pci_func *new_slot; |
93 | struct slot *slot; | 83 | struct slot *slot; |
94 | 84 | ||
95 | pci_dev = container_of (dev, struct pci_dev, dev); | 85 | slot = ctrl->slot; |
96 | ctrl = pci_get_drvdata(pci_dev); | ||
97 | |||
98 | slot=ctrl->slot; | ||
99 | 86 | ||
100 | while (slot) { | 87 | while (slot) { |
101 | new_slot = cpqhp_slot_find(slot->bus, slot->device, 0); | 88 | new_slot = cpqhp_slot_find(slot->bus, slot->device, 0); |
@@ -134,10 +121,117 @@ static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char | |||
134 | 121 | ||
135 | return out - buf; | 122 | return out - buf; |
136 | } | 123 | } |
137 | static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL); | ||
138 | 124 | ||
139 | void cpqhp_create_ctrl_files (struct controller *ctrl) | 125 | static int spew_debug_info(struct controller *ctrl, char *data, int size) |
140 | { | 126 | { |
141 | device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); | 127 | int used; |
142 | device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev); | 128 | |
129 | used = size - show_ctrl(ctrl, data); | ||
130 | used = (size - used) - show_dev(ctrl, &data[used]); | ||
131 | return used; | ||
132 | } | ||
133 | |||
134 | struct ctrl_dbg { | ||
135 | int size; | ||
136 | char *data; | ||
137 | struct controller *ctrl; | ||
138 | }; | ||
139 | |||
140 | #define MAX_OUTPUT (4*PAGE_SIZE) | ||
141 | |||
142 | static int open(struct inode *inode, struct file *file) | ||
143 | { | ||
144 | struct controller *ctrl = inode->u.generic_ip; | ||
145 | struct ctrl_dbg *dbg; | ||
146 | int retval = -ENOMEM; | ||
147 | |||
148 | lock_kernel(); | ||
149 | dbg = kmalloc(sizeof(*dbg), GFP_KERNEL); | ||
150 | if (!dbg) | ||
151 | goto exit; | ||
152 | dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); | ||
153 | if (!dbg->data) { | ||
154 | kfree(dbg); | ||
155 | goto exit; | ||
156 | } | ||
157 | dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT); | ||
158 | file->private_data = dbg; | ||
159 | retval = 0; | ||
160 | exit: | ||
161 | unlock_kernel(); | ||
162 | return retval; | ||
163 | } | ||
164 | |||
165 | static loff_t lseek(struct file *file, loff_t off, int whence) | ||
166 | { | ||
167 | struct ctrl_dbg *dbg; | ||
168 | loff_t new = -1; | ||
169 | |||
170 | lock_kernel(); | ||
171 | dbg = file->private_data; | ||
172 | |||
173 | switch (whence) { | ||
174 | case 0: | ||
175 | new = off; | ||
176 | break; | ||
177 | case 1: | ||
178 | new = file->f_pos + off; | ||
179 | break; | ||
180 | } | ||
181 | if (new < 0 || new > dbg->size) { | ||
182 | unlock_kernel(); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | unlock_kernel(); | ||
186 | return (file->f_pos = new); | ||
143 | } | 187 | } |
188 | |||
189 | static ssize_t read(struct file *file, char __user *buf, | ||
190 | size_t nbytes, loff_t *ppos) | ||
191 | { | ||
192 | struct ctrl_dbg *dbg = file->private_data; | ||
193 | return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size); | ||
194 | } | ||
195 | |||
196 | static int release(struct inode *inode, struct file *file) | ||
197 | { | ||
198 | struct ctrl_dbg *dbg = file->private_data; | ||
199 | |||
200 | kfree(dbg->data); | ||
201 | kfree(dbg); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static struct file_operations debug_ops = { | ||
206 | .owner = THIS_MODULE, | ||
207 | .open = open, | ||
208 | .llseek = lseek, | ||
209 | .read = read, | ||
210 | .release = release, | ||
211 | }; | ||
212 | |||
213 | static struct dentry *root; | ||
214 | |||
215 | void cpqhp_initialize_debugfs(void) | ||
216 | { | ||
217 | if (!root) | ||
218 | root = debugfs_create_dir("cpqhp", NULL); | ||
219 | } | ||
220 | |||
221 | void cpqhp_shutdown_debugfs(void) | ||
222 | { | ||
223 | debugfs_remove(root); | ||
224 | } | ||
225 | |||
226 | void cpqhp_create_debugfs_files(struct controller *ctrl) | ||
227 | { | ||
228 | ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops); | ||
229 | } | ||
230 | |||
231 | void cpqhp_remove_debugfs_files(struct controller *ctrl) | ||
232 | { | ||
233 | if (ctrl->dentry) | ||
234 | debugfs_remove(ctrl->dentry); | ||
235 | ctrl->dentry = NULL; | ||
236 | } | ||
237 | |||
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index b1ba429e0a2d..155133fe5c12 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c | |||
@@ -969,7 +969,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
969 | debug ("io 32\n"); | 969 | debug ("io 32\n"); |
970 | need_io_upper = TRUE; | 970 | need_io_upper = TRUE; |
971 | } | 971 | } |
972 | if ((io_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { | 972 | if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { |
973 | debug ("pfmem 64\n"); | 973 | debug ("pfmem 64\n"); |
974 | need_pfmem_upper = TRUE; | 974 | need_pfmem_upper = TRUE; |
975 | } | 975 | } |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 8df704860348..4fb569018a24 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -103,7 +103,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
103 | 103 | ||
104 | static int init_slots(struct controller *ctrl) | 104 | static int init_slots(struct controller *ctrl) |
105 | { | 105 | { |
106 | struct slot *new_slot; | 106 | struct slot *slot; |
107 | struct hpc_ops *hpc_ops; | ||
108 | struct hotplug_slot *hotplug_slot; | ||
109 | struct hotplug_slot_info *hotplug_slot_info; | ||
107 | u8 number_of_slots; | 110 | u8 number_of_slots; |
108 | u8 slot_device; | 111 | u8 slot_device; |
109 | u32 slot_number; | 112 | u32 slot_number; |
@@ -114,59 +117,66 @@ static int init_slots(struct controller *ctrl) | |||
114 | slot_number = ctrl->first_slot; | 117 | slot_number = ctrl->first_slot; |
115 | 118 | ||
116 | while (number_of_slots) { | 119 | while (number_of_slots) { |
117 | new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); | 120 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); |
118 | if (!new_slot) | 121 | if (!slot) |
119 | goto error; | 122 | goto error; |
120 | 123 | ||
121 | memset(new_slot, 0, sizeof(struct slot)); | 124 | memset(slot, 0, sizeof(struct slot)); |
122 | new_slot->hotplug_slot = | 125 | slot->hotplug_slot = |
123 | kmalloc(sizeof(*(new_slot->hotplug_slot)), | 126 | kmalloc(sizeof(*(slot->hotplug_slot)), |
124 | GFP_KERNEL); | 127 | GFP_KERNEL); |
125 | if (!new_slot->hotplug_slot) | 128 | if (!slot->hotplug_slot) |
126 | goto error_slot; | 129 | goto error_slot; |
127 | memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); | 130 | hotplug_slot = slot->hotplug_slot; |
131 | memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); | ||
128 | 132 | ||
129 | new_slot->hotplug_slot->info = | 133 | hotplug_slot->info = |
130 | kmalloc(sizeof(*(new_slot->hotplug_slot->info)), | 134 | kmalloc(sizeof(*(hotplug_slot->info)), |
131 | GFP_KERNEL); | 135 | GFP_KERNEL); |
132 | if (!new_slot->hotplug_slot->info) | 136 | if (!hotplug_slot->info) |
133 | goto error_hpslot; | 137 | goto error_hpslot; |
134 | memset(new_slot->hotplug_slot->info, 0, | 138 | hotplug_slot_info = hotplug_slot->info; |
139 | memset(hotplug_slot_info, 0, | ||
135 | sizeof(struct hotplug_slot_info)); | 140 | sizeof(struct hotplug_slot_info)); |
136 | new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, | 141 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
137 | GFP_KERNEL); | 142 | if (!hotplug_slot->name) |
138 | if (!new_slot->hotplug_slot->name) | ||
139 | goto error_info; | 143 | goto error_info; |
140 | 144 | ||
141 | new_slot->ctrl = ctrl; | 145 | slot->ctrl = ctrl; |
142 | new_slot->bus = ctrl->slot_bus; | 146 | slot->bus = ctrl->slot_bus; |
143 | new_slot->device = slot_device; | 147 | slot->device = slot_device; |
144 | new_slot->hpc_ops = ctrl->hpc_ops; | 148 | slot->hpc_ops = hpc_ops = ctrl->hpc_ops; |
145 | 149 | ||
146 | new_slot->number = ctrl->first_slot; | 150 | slot->number = ctrl->first_slot; |
147 | new_slot->hp_slot = slot_device - ctrl->slot_device_offset; | 151 | slot->hp_slot = slot_device - ctrl->slot_device_offset; |
148 | 152 | ||
149 | /* register this slot with the hotplug pci core */ | 153 | /* register this slot with the hotplug pci core */ |
150 | new_slot->hotplug_slot->private = new_slot; | 154 | hotplug_slot->private = slot; |
151 | new_slot->hotplug_slot->release = &release_slot; | 155 | hotplug_slot->release = &release_slot; |
152 | make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); | 156 | make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot); |
153 | new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops; | 157 | hotplug_slot->ops = &pciehp_hotplug_slot_ops; |
154 | 158 | ||
155 | new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); | 159 | hpc_ops->get_power_status(slot, |
156 | new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); | 160 | &(hotplug_slot_info->power_status)); |
157 | new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); | 161 | hpc_ops->get_attention_status(slot, |
158 | new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); | 162 | &(hotplug_slot_info->attention_status)); |
159 | 163 | hpc_ops->get_latch_status(slot, | |
160 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", | 164 | &(hotplug_slot_info->latch_status)); |
161 | new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); | 165 | hpc_ops->get_adapter_status(slot, |
162 | result = pci_hp_register (new_slot->hotplug_slot); | 166 | &(hotplug_slot_info->adapter_status)); |
167 | |||
168 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " | ||
169 | "slot_device_offset=%x\n", | ||
170 | slot->bus, slot->device, slot->hp_slot, slot->number, | ||
171 | ctrl->slot_device_offset); | ||
172 | result = pci_hp_register(hotplug_slot); | ||
163 | if (result) { | 173 | if (result) { |
164 | err ("pci_hp_register failed with error %d\n", result); | 174 | err ("pci_hp_register failed with error %d\n", result); |
165 | goto error_name; | 175 | goto error_name; |
166 | } | 176 | } |
167 | 177 | ||
168 | new_slot->next = ctrl->slot; | 178 | slot->next = ctrl->slot; |
169 | ctrl->slot = new_slot; | 179 | ctrl->slot = slot; |
170 | 180 | ||
171 | number_of_slots--; | 181 | number_of_slots--; |
172 | slot_device++; | 182 | slot_device++; |
@@ -176,13 +186,13 @@ static int init_slots(struct controller *ctrl) | |||
176 | return 0; | 186 | return 0; |
177 | 187 | ||
178 | error_name: | 188 | error_name: |
179 | kfree(new_slot->hotplug_slot->name); | 189 | kfree(hotplug_slot->name); |
180 | error_info: | 190 | error_info: |
181 | kfree(new_slot->hotplug_slot->info); | 191 | kfree(hotplug_slot_info); |
182 | error_hpslot: | 192 | error_hpslot: |
183 | kfree(new_slot->hotplug_slot); | 193 | kfree(hotplug_slot); |
184 | error_slot: | 194 | error_slot: |
185 | kfree(new_slot); | 195 | kfree(slot); |
186 | error: | 196 | error: |
187 | return result; | 197 | return result; |
188 | } | 198 | } |
@@ -502,7 +512,7 @@ static void __exit unload_pciehpd(void) | |||
502 | 512 | ||
503 | } | 513 | } |
504 | 514 | ||
505 | int hpdriver_context = 0; | 515 | static int hpdriver_context = 0; |
506 | 516 | ||
507 | static void pciehp_remove (struct pcie_device *device) | 517 | static void pciehp_remove (struct pcie_device *device) |
508 | { | 518 | { |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index ac1e495c314e..77e530321de2 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -787,8 +787,13 @@ static int hpc_power_on_slot(struct slot * slot) | |||
787 | 787 | ||
788 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; | 788 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; |
789 | 789 | ||
790 | /* Enable detection that we turned off at slot power-off time */ | ||
790 | if (!pciehp_poll_mode) | 791 | if (!pciehp_poll_mode) |
791 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 792 | slot_cmd = slot_cmd | |
793 | PWR_FAULT_DETECT_ENABLE | | ||
794 | MRL_DETECT_ENABLE | | ||
795 | PRSN_DETECT_ENABLE | | ||
796 | HP_INTR_ENABLE; | ||
792 | 797 | ||
793 | retval = pcie_write_cmd(slot, slot_cmd); | 798 | retval = pcie_write_cmd(slot, slot_cmd); |
794 | 799 | ||
@@ -833,8 +838,18 @@ static int hpc_power_off_slot(struct slot * slot) | |||
833 | 838 | ||
834 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; | 839 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; |
835 | 840 | ||
841 | /* | ||
842 | * If we get MRL or presence detect interrupts now, the isr | ||
843 | * will notice the sticky power-fault bit too and issue power | ||
844 | * indicator change commands. This will lead to an endless loop | ||
845 | * of command completions, since the power-fault bit remains on | ||
846 | * till the slot is powered on again. | ||
847 | */ | ||
836 | if (!pciehp_poll_mode) | 848 | if (!pciehp_poll_mode) |
837 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 849 | slot_cmd = (slot_cmd & |
850 | ~PWR_FAULT_DETECT_ENABLE & | ||
851 | ~MRL_DETECT_ENABLE & | ||
852 | ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; | ||
838 | 853 | ||
839 | retval = pcie_write_cmd(slot, slot_cmd); | 854 | retval = pcie_write_cmd(slot, slot_cmd); |
840 | 855 | ||
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 647673a7d224..4017fb03a0b8 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -34,6 +34,31 @@ | |||
34 | #include "../pci.h" | 34 | #include "../pci.h" |
35 | #include "pciehp.h" | 35 | #include "pciehp.h" |
36 | 36 | ||
37 | static int pciehp_add_bridge(struct pci_dev *dev) | ||
38 | { | ||
39 | struct pci_bus *parent = dev->bus; | ||
40 | int pass, busnr, start = parent->secondary; | ||
41 | int end = parent->subordinate; | ||
42 | |||
43 | for (busnr = start; busnr <= end; busnr++) { | ||
44 | if (!pci_find_bus(pci_domain_nr(parent), busnr)) | ||
45 | break; | ||
46 | } | ||
47 | if (busnr-- > end) { | ||
48 | err("No bus number available for hot-added bridge %s\n", | ||
49 | pci_name(dev)); | ||
50 | return -1; | ||
51 | } | ||
52 | for (pass = 0; pass < 2; pass++) | ||
53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); | ||
54 | if (!dev->subordinate) | ||
55 | return -1; | ||
56 | pci_bus_size_bridges(dev->subordinate); | ||
57 | pci_bus_assign_resources(parent); | ||
58 | pci_enable_bridges(parent); | ||
59 | pci_bus_add_devices(parent); | ||
60 | return 0; | ||
61 | } | ||
37 | 62 | ||
38 | int pciehp_configure_device(struct slot *p_slot) | 63 | int pciehp_configure_device(struct slot *p_slot) |
39 | { | 64 | { |
@@ -55,8 +80,8 @@ int pciehp_configure_device(struct slot *p_slot) | |||
55 | } | 80 | } |
56 | 81 | ||
57 | for (fn = 0; fn < 8; fn++) { | 82 | for (fn = 0; fn < 8; fn++) { |
58 | if (!(dev = pci_find_slot(p_slot->bus, | 83 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); |
59 | PCI_DEVFN(p_slot->device, fn)))) | 84 | if (!dev) |
60 | continue; | 85 | continue; |
61 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | 86 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { |
62 | err("Cannot hot-add display device %s\n", | 87 | err("Cannot hot-add display device %s\n", |
@@ -65,27 +90,7 @@ int pciehp_configure_device(struct slot *p_slot) | |||
65 | } | 90 | } |
66 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 91 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
67 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 92 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
68 | /* Find an unused bus number for the new bridge */ | 93 | pciehp_add_bridge(dev); |
69 | struct pci_bus *child; | ||
70 | unsigned char busnr, start = parent->secondary; | ||
71 | unsigned char end = parent->subordinate; | ||
72 | for (busnr = start; busnr <= end; busnr++) { | ||
73 | if (!pci_find_bus(pci_domain_nr(parent), | ||
74 | busnr)) | ||
75 | break; | ||
76 | } | ||
77 | if (busnr >= end) { | ||
78 | err("No free bus for hot-added bridge\n"); | ||
79 | continue; | ||
80 | } | ||
81 | child = pci_add_new_bus(parent, dev, busnr); | ||
82 | if (!child) { | ||
83 | err("Cannot add new bus for %s\n", | ||
84 | pci_name(dev)); | ||
85 | continue; | ||
86 | } | ||
87 | child->subordinate = pci_do_scan_bus(child); | ||
88 | pci_bus_size_bridges(child); | ||
89 | } | 94 | } |
90 | /* TBD: program firmware provided _HPP values */ | 95 | /* TBD: program firmware provided _HPP values */ |
91 | /* program_fw_provided_values(dev); */ | 96 | /* program_fw_provided_values(dev); */ |
@@ -93,7 +98,6 @@ int pciehp_configure_device(struct slot *p_slot) | |||
93 | 98 | ||
94 | pci_bus_assign_resources(parent); | 99 | pci_bus_assign_resources(parent); |
95 | pci_bus_add_devices(parent); | 100 | pci_bus_add_devices(parent); |
96 | pci_enable_bridges(parent); | ||
97 | return 0; | 101 | return 0; |
98 | } | 102 | } |
99 | 103 | ||
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index ae244e218620..2bdb30f68bf8 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c | |||
@@ -174,7 +174,9 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
174 | acpi_status status; | 174 | acpi_status status; |
175 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | 175 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); |
176 | struct pci_dev *pdev = dev; | 176 | struct pci_dev *pdev = dev; |
177 | struct pci_bus *parent; | ||
177 | u8 *path_name; | 178 | u8 *path_name; |
179 | |||
178 | /* | 180 | /* |
179 | * Per PCI firmware specification, we should run the ACPI _OSC | 181 | * Per PCI firmware specification, we should run the ACPI _OSC |
180 | * method to get control of hotplug hardware before using it. | 182 | * method to get control of hotplug hardware before using it. |
@@ -190,17 +192,18 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
190 | */ | 192 | */ |
191 | if (!pdev || !pdev->bus->parent) | 193 | if (!pdev || !pdev->bus->parent) |
192 | break; | 194 | break; |
195 | parent = pdev->bus->parent; | ||
193 | dbg("Could not find %s in acpi namespace, trying parent\n", | 196 | dbg("Could not find %s in acpi namespace, trying parent\n", |
194 | pci_name(pdev)); | 197 | pci_name(pdev)); |
195 | if (!pdev->bus->parent->self) | 198 | if (!parent->self) |
196 | /* Parent must be a host bridge */ | 199 | /* Parent must be a host bridge */ |
197 | handle = acpi_get_pci_rootbridge_handle( | 200 | handle = acpi_get_pci_rootbridge_handle( |
198 | pci_domain_nr(pdev->bus->parent), | 201 | pci_domain_nr(parent), |
199 | pdev->bus->parent->number); | 202 | parent->number); |
200 | else | 203 | else |
201 | handle = DEVICE_ACPI_HANDLE( | 204 | handle = DEVICE_ACPI_HANDLE( |
202 | &(pdev->bus->parent->self->dev)); | 205 | &(parent->self->dev)); |
203 | pdev = pdev->bus->parent->self; | 206 | pdev = parent->self; |
204 | } | 207 | } |
205 | 208 | ||
206 | while (handle) { | 209 | while (handle) { |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index cc03609f45d0..7d93dbaf628d 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -112,28 +112,6 @@ static struct slot *find_slot(struct device_node *dn) | |||
112 | return NULL; | 112 | return NULL; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void rpadlpar_claim_one_bus(struct pci_bus *b) | ||
116 | { | ||
117 | struct list_head *ld; | ||
118 | struct pci_bus *child_bus; | ||
119 | |||
120 | for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { | ||
121 | struct pci_dev *dev = pci_dev_b(ld); | ||
122 | int i; | ||
123 | |||
124 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
125 | struct resource *r = &dev->resource[i]; | ||
126 | |||
127 | if (r->parent || !r->start || !r->flags) | ||
128 | continue; | ||
129 | rpaphp_claim_resource(dev, i); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | list_for_each_entry(child_bus, &b->children, node) | ||
134 | rpadlpar_claim_one_bus(child_bus); | ||
135 | } | ||
136 | |||
137 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, | 115 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, |
138 | struct device_node *dev_dn) | 116 | struct device_node *dev_dn) |
139 | { | 117 | { |
@@ -154,7 +132,8 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | |||
154 | struct pci_controller *phb = pdn->phb; | 132 | struct pci_controller *phb = pdn->phb; |
155 | struct pci_dev *dev = NULL; | 133 | struct pci_dev *dev = NULL; |
156 | 134 | ||
157 | rpaphp_eeh_init_nodes(dn); | 135 | eeh_add_device_tree_early(dn); |
136 | |||
158 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ | 137 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ |
159 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); | 138 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); |
160 | if (!dev) { | 139 | if (!dev) { |
@@ -170,7 +149,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | |||
170 | rpaphp_init_new_devs(dev->subordinate); | 149 | rpaphp_init_new_devs(dev->subordinate); |
171 | 150 | ||
172 | /* Claim new bus resources */ | 151 | /* Claim new bus resources */ |
173 | rpadlpar_claim_one_bus(dev->bus); | 152 | pcibios_claim_one_bus(dev->bus); |
174 | 153 | ||
175 | /* ioremap() for child bus, which may or may not succeed */ | 154 | /* ioremap() for child bus, which may or may not succeed */ |
176 | (void) remap_bus_range(dev->bus); | 155 | (void) remap_bus_range(dev->bus); |
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 4b35097b3d9f..396b54b0c847 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -62,28 +62,6 @@ struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) | |||
62 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus); | 63 | EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus); |
64 | 64 | ||
65 | int rpaphp_claim_resource(struct pci_dev *dev, int resource) | ||
66 | { | ||
67 | struct resource *res = &dev->resource[resource]; | ||
68 | struct resource *root = pci_find_parent_resource(dev, res); | ||
69 | char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge"; | ||
70 | int err = -EINVAL; | ||
71 | |||
72 | if (root != NULL) { | ||
73 | err = request_resource(root, res); | ||
74 | } | ||
75 | |||
76 | if (err) { | ||
77 | err("PCI: %s region %d of %s %s [%lx:%lx]\n", | ||
78 | root ? "Address space collision on" : | ||
79 | "No parent found for", | ||
80 | resource, dtype, pci_name(dev), res->start, res->end); | ||
81 | } | ||
82 | return err; | ||
83 | } | ||
84 | |||
85 | EXPORT_SYMBOL_GPL(rpaphp_claim_resource); | ||
86 | |||
87 | static int rpaphp_get_sensor_state(struct slot *slot, int *state) | 65 | static int rpaphp_get_sensor_state(struct slot *slot, int *state) |
88 | { | 66 | { |
89 | int rc; | 67 | int rc; |
@@ -177,7 +155,7 @@ void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
177 | 155 | ||
178 | if (r->parent || !r->start || !r->flags) | 156 | if (r->parent || !r->start || !r->flags) |
179 | continue; | 157 | continue; |
180 | rpaphp_claim_resource(dev, i); | 158 | pci_claim_resource(dev, i); |
181 | } | 159 | } |
182 | } | 160 | } |
183 | } | 161 | } |
@@ -287,18 +265,6 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
287 | return dev; | 265 | return dev; |
288 | } | 266 | } |
289 | 267 | ||
290 | void rpaphp_eeh_init_nodes(struct device_node *dn) | ||
291 | { | ||
292 | struct device_node *sib; | ||
293 | |||
294 | for (sib = dn->child; sib; sib = sib->sibling) | ||
295 | rpaphp_eeh_init_nodes(sib); | ||
296 | eeh_add_device_early(dn); | ||
297 | return; | ||
298 | |||
299 | } | ||
300 | EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); | ||
301 | |||
302 | static void print_slot_pci_funcs(struct pci_bus *bus) | 268 | static void print_slot_pci_funcs(struct pci_bus *bus) |
303 | { | 269 | { |
304 | struct device_node *dn; | 270 | struct device_node *dn; |
@@ -324,7 +290,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) | |||
324 | if (!dn) | 290 | if (!dn) |
325 | goto exit; | 291 | goto exit; |
326 | 292 | ||
327 | rpaphp_eeh_init_nodes(dn); | 293 | eeh_add_device_tree_early(dn); |
328 | dev = rpaphp_pci_config_slot(bus); | 294 | dev = rpaphp_pci_config_slot(bus); |
329 | if (!dev) { | 295 | if (!dev) { |
330 | err("%s: can't find any devices.\n", __FUNCTION__); | 296 | err("%s: can't find any devices.\n", __FUNCTION__); |
@@ -370,13 +336,14 @@ EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); | |||
370 | 336 | ||
371 | static int setup_pci_hotplug_slot_info(struct slot *slot) | 337 | static int setup_pci_hotplug_slot_info(struct slot *slot) |
372 | { | 338 | { |
339 | struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; | ||
340 | |||
373 | dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", | 341 | dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", |
374 | __FUNCTION__); | 342 | __FUNCTION__); |
375 | rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status); | 343 | rpaphp_get_power_status(slot, &hotplug_slot_info->power_status); |
376 | rpaphp_get_pci_adapter_status(slot, 1, | 344 | rpaphp_get_pci_adapter_status(slot, 1, |
377 | &slot->hotplug_slot->info-> | 345 | &hotplug_slot_info->adapter_status); |
378 | adapter_status); | 346 | if (hotplug_slot_info->adapter_status == NOT_VALID) { |
379 | if (slot->hotplug_slot->info->adapter_status == NOT_VALID) { | ||
380 | err("%s: NOT_VALID: skip dn->full_name=%s\n", | 347 | err("%s: NOT_VALID: skip dn->full_name=%s\n", |
381 | __FUNCTION__, slot->dn->full_name); | 348 | __FUNCTION__, slot->dn->full_name); |
382 | return -EINVAL; | 349 | return -EINVAL; |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 08ad26a0cae7..ce0e9b6ce833 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -98,6 +98,10 @@ struct controller { | |||
98 | enum pci_bus_speed speed; | 98 | enum pci_bus_speed speed; |
99 | u32 first_slot; /* First physical slot number */ | 99 | u32 first_slot; /* First physical slot number */ |
100 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ | 100 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ |
101 | u32 cap_offset; | ||
102 | unsigned long mmio_base; | ||
103 | unsigned long mmio_size; | ||
104 | volatile int cmd_busy; | ||
101 | }; | 105 | }; |
102 | 106 | ||
103 | struct hotplug_params { | 107 | struct hotplug_params { |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 63628e01dd43..a2b3f0010cec 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -65,6 +65,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
68 | static int get_address (struct hotplug_slot *slot, u32 *value); | ||
68 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | 69 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); |
69 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | 70 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); |
70 | 71 | ||
@@ -77,6 +78,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | |||
77 | .get_attention_status = get_attention_status, | 78 | .get_attention_status = get_attention_status, |
78 | .get_latch_status = get_latch_status, | 79 | .get_latch_status = get_latch_status, |
79 | .get_adapter_status = get_adapter_status, | 80 | .get_adapter_status = get_adapter_status, |
81 | .get_address = get_address, | ||
80 | .get_max_bus_speed = get_max_bus_speed, | 82 | .get_max_bus_speed = get_max_bus_speed, |
81 | .get_cur_bus_speed = get_cur_bus_speed, | 83 | .get_cur_bus_speed = get_cur_bus_speed, |
82 | }; | 84 | }; |
@@ -314,6 +316,18 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
314 | return 0; | 316 | return 0; |
315 | } | 317 | } |
316 | 318 | ||
319 | static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) | ||
320 | { | ||
321 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | ||
322 | struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; | ||
323 | |||
324 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | ||
325 | |||
326 | *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
317 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 331 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) |
318 | { | 332 | { |
319 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 333 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); |
@@ -377,8 +391,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
377 | goto err_out_free_ctrl; | 391 | goto err_out_free_ctrl; |
378 | } | 392 | } |
379 | 393 | ||
380 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ | ||
381 | |||
382 | pci_set_drvdata(pdev, ctrl); | 394 | pci_set_drvdata(pdev, ctrl); |
383 | 395 | ||
384 | ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); | 396 | ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 58619359ad08..25ccb0e47593 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -248,7 +248,6 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
248 | up(&ctrl->crit_sect); | 248 | up(&ctrl->crit_sect); |
249 | return WRONG_BUS_FREQUENCY; | 249 | return WRONG_BUS_FREQUENCY; |
250 | } | 250 | } |
251 | wait_for_ctrl_irq (ctrl); | ||
252 | 251 | ||
253 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 252 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
254 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | 253 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", |
@@ -330,9 +329,6 @@ static int board_added(struct slot *p_slot) | |||
330 | up(&ctrl->crit_sect); | 329 | up(&ctrl->crit_sect); |
331 | return -1; | 330 | return -1; |
332 | } | 331 | } |
333 | |||
334 | /* Wait for the command to complete */ | ||
335 | wait_for_ctrl_irq (ctrl); | ||
336 | 332 | ||
337 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 333 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
338 | if (rc) { | 334 | if (rc) { |
@@ -352,7 +348,6 @@ static int board_added(struct slot *p_slot) | |||
352 | up(&ctrl->crit_sect); | 348 | up(&ctrl->crit_sect); |
353 | return WRONG_BUS_FREQUENCY; | 349 | return WRONG_BUS_FREQUENCY; |
354 | } | 350 | } |
355 | wait_for_ctrl_irq (ctrl); | ||
356 | 351 | ||
357 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 352 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
358 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | 353 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", |
@@ -367,7 +362,6 @@ static int board_added(struct slot *p_slot) | |||
367 | up(&ctrl->crit_sect); | 362 | up(&ctrl->crit_sect); |
368 | return rc; | 363 | return rc; |
369 | } | 364 | } |
370 | wait_for_ctrl_irq (ctrl); | ||
371 | 365 | ||
372 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 366 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
373 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | 367 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); |
@@ -494,7 +488,6 @@ static int board_added(struct slot *p_slot) | |||
494 | up(&ctrl->crit_sect); | 488 | up(&ctrl->crit_sect); |
495 | return rc; | 489 | return rc; |
496 | } | 490 | } |
497 | wait_for_ctrl_irq (ctrl); | ||
498 | 491 | ||
499 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 492 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
500 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | 493 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); |
@@ -532,9 +525,6 @@ static int board_added(struct slot *p_slot) | |||
532 | 525 | ||
533 | p_slot->hpc_ops->green_led_on(p_slot); | 526 | p_slot->hpc_ops->green_led_on(p_slot); |
534 | 527 | ||
535 | /* Wait for the command to complete */ | ||
536 | wait_for_ctrl_irq (ctrl); | ||
537 | |||
538 | /* Done with exclusive hardware access */ | 528 | /* Done with exclusive hardware access */ |
539 | up(&ctrl->crit_sect); | 529 | up(&ctrl->crit_sect); |
540 | 530 | ||
@@ -552,8 +542,6 @@ err_exit: | |||
552 | up(&ctrl->crit_sect); | 542 | up(&ctrl->crit_sect); |
553 | return rc; | 543 | return rc; |
554 | } | 544 | } |
555 | /* Wait for the command to complete */ | ||
556 | wait_for_ctrl_irq (ctrl); | ||
557 | 545 | ||
558 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 546 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
559 | if (rc) { | 547 | if (rc) { |
@@ -603,8 +591,6 @@ static int remove_board(struct slot *p_slot) | |||
603 | up(&ctrl->crit_sect); | 591 | up(&ctrl->crit_sect); |
604 | return rc; | 592 | return rc; |
605 | } | 593 | } |
606 | /* Wait for the command to complete */ | ||
607 | wait_for_ctrl_irq (ctrl); | ||
608 | 594 | ||
609 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 595 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
610 | if (rc) { | 596 | if (rc) { |
@@ -621,8 +607,6 @@ static int remove_board(struct slot *p_slot) | |||
621 | up(&ctrl->crit_sect); | 607 | up(&ctrl->crit_sect); |
622 | return rc; | 608 | return rc; |
623 | } | 609 | } |
624 | /* Wait for the command to complete */ | ||
625 | wait_for_ctrl_irq (ctrl); | ||
626 | 610 | ||
627 | /* Done with exclusive hardware access */ | 611 | /* Done with exclusive hardware access */ |
628 | up(&ctrl->crit_sect); | 612 | up(&ctrl->crit_sect); |
@@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (unsigned long slot) | |||
676 | 660 | ||
677 | p_slot->hpc_ops->green_led_off(p_slot); | 661 | p_slot->hpc_ops->green_led_off(p_slot); |
678 | 662 | ||
679 | /* Wait for the command to complete */ | ||
680 | wait_for_ctrl_irq (p_slot->ctrl); | ||
681 | |||
682 | /* Done with exclusive hardware access */ | 663 | /* Done with exclusive hardware access */ |
683 | up(&p_slot->ctrl->crit_sect); | 664 | up(&p_slot->ctrl->crit_sect); |
684 | } | 665 | } |
@@ -790,14 +771,9 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
790 | down(&ctrl->crit_sect); | 771 | down(&ctrl->crit_sect); |
791 | 772 | ||
792 | p_slot->hpc_ops->green_led_on(p_slot); | 773 | p_slot->hpc_ops->green_led_on(p_slot); |
793 | /* Wait for the command to complete */ | ||
794 | wait_for_ctrl_irq (ctrl); | ||
795 | 774 | ||
796 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 775 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
797 | 776 | ||
798 | /* Wait for the command to complete */ | ||
799 | wait_for_ctrl_irq (ctrl); | ||
800 | |||
801 | /* Done with exclusive hardware access */ | 777 | /* Done with exclusive hardware access */ |
802 | up(&ctrl->crit_sect); | 778 | up(&ctrl->crit_sect); |
803 | break; | 779 | break; |
@@ -806,12 +782,8 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
806 | down(&ctrl->crit_sect); | 782 | down(&ctrl->crit_sect); |
807 | 783 | ||
808 | p_slot->hpc_ops->green_led_off(p_slot); | 784 | p_slot->hpc_ops->green_led_off(p_slot); |
809 | /* Wait for the command to complete */ | ||
810 | wait_for_ctrl_irq (ctrl); | ||
811 | 785 | ||
812 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 786 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
813 | /* Wait for the command to complete */ | ||
814 | wait_for_ctrl_irq (ctrl); | ||
815 | 787 | ||
816 | /* Done with exclusive hardware access */ | 788 | /* Done with exclusive hardware access */ |
817 | up(&ctrl->crit_sect); | 789 | up(&ctrl->crit_sect); |
@@ -845,14 +817,9 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
845 | 817 | ||
846 | /* blink green LED and turn off amber */ | 818 | /* blink green LED and turn off amber */ |
847 | p_slot->hpc_ops->green_led_blink(p_slot); | 819 | p_slot->hpc_ops->green_led_blink(p_slot); |
848 | /* Wait for the command to complete */ | ||
849 | wait_for_ctrl_irq (ctrl); | ||
850 | 820 | ||
851 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 821 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
852 | 822 | ||
853 | /* Wait for the command to complete */ | ||
854 | wait_for_ctrl_irq (ctrl); | ||
855 | |||
856 | /* Done with exclusive hardware access */ | 823 | /* Done with exclusive hardware access */ |
857 | up(&ctrl->crit_sect); | 824 | up(&ctrl->crit_sect); |
858 | 825 | ||
@@ -870,12 +837,8 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
870 | down(&ctrl->crit_sect); | 837 | down(&ctrl->crit_sect); |
871 | 838 | ||
872 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 839 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
873 | /* Wait for the command to complete */ | ||
874 | wait_for_ctrl_irq (ctrl); | ||
875 | 840 | ||
876 | p_slot->hpc_ops->green_led_off(p_slot); | 841 | p_slot->hpc_ops->green_led_off(p_slot); |
877 | /* Wait for the command to complete */ | ||
878 | wait_for_ctrl_irq (ctrl); | ||
879 | 842 | ||
880 | /* Done with exclusive hardware access */ | 843 | /* Done with exclusive hardware access */ |
881 | up(&ctrl->crit_sect); | 844 | up(&ctrl->crit_sect); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 9987a6fd65b8..b4226ff3a854 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) | |||
275 | return; | 275 | return; |
276 | } | 276 | } |
277 | 277 | ||
278 | static inline int shpc_wait_cmd(struct controller *ctrl) | ||
279 | { | ||
280 | int retval = 0; | ||
281 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | ||
282 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | ||
283 | int rc = wait_event_interruptible_timeout(ctrl->queue, | ||
284 | !ctrl->cmd_busy, timeout); | ||
285 | if (!rc) { | ||
286 | retval = -EIO; | ||
287 | err("Command not completed in %d msec\n", timeout_msec); | ||
288 | } else if (rc < 0) { | ||
289 | retval = -EINTR; | ||
290 | info("Command was interrupted by a signal\n"); | ||
291 | } | ||
292 | ctrl->cmd_busy = 0; | ||
293 | |||
294 | return retval; | ||
295 | } | ||
296 | |||
278 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | 297 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) |
279 | { | 298 | { |
280 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 299 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
314 | /* To make sure the Controller Busy bit is 0 before we send out the | 333 | /* To make sure the Controller Busy bit is 0 before we send out the |
315 | * command. | 334 | * command. |
316 | */ | 335 | */ |
336 | slot->ctrl->cmd_busy = 1; | ||
317 | writew(temp_word, php_ctlr->creg + CMD); | 337 | writew(temp_word, php_ctlr->creg + CMD); |
318 | 338 | ||
339 | /* | ||
340 | * Wait for command completion. | ||
341 | */ | ||
342 | retval = shpc_wait_cmd(slot->ctrl); | ||
343 | |||
319 | DBG_LEAVE_ROUTINE | 344 | DBG_LEAVE_ROUTINE |
320 | return retval; | 345 | return retval; |
321 | } | 346 | } |
@@ -604,7 +629,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) | |||
604 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); | 629 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); |
605 | 630 | ||
606 | if (pi == 2) { | 631 | if (pi == 2) { |
607 | *mode = (sec_bus_status & 0x0100) >> 7; | 632 | *mode = (sec_bus_status & 0x0100) >> 8; |
608 | } else { | 633 | } else { |
609 | retval = -1; | 634 | retval = -1; |
610 | } | 635 | } |
@@ -791,7 +816,7 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
791 | } | 816 | } |
792 | if (php_ctlr->pci_dev) { | 817 | if (php_ctlr->pci_dev) { |
793 | iounmap(php_ctlr->creg); | 818 | iounmap(php_ctlr->creg); |
794 | release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0)); | 819 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
795 | php_ctlr->pci_dev = NULL; | 820 | php_ctlr->pci_dev = NULL; |
796 | } | 821 | } |
797 | 822 | ||
@@ -1058,12 +1083,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1058 | if (intr_loc & 0x0001) { | 1083 | if (intr_loc & 0x0001) { |
1059 | /* | 1084 | /* |
1060 | * Command Complete Interrupt Pending | 1085 | * Command Complete Interrupt Pending |
1061 | * RO only - clear by writing 0 to the Command Completion | 1086 | * RO only - clear by writing 1 to the Command Completion |
1062 | * Detect bit in Controller SERR-INT register | 1087 | * Detect bit in Controller SERR-INT register |
1063 | */ | 1088 | */ |
1064 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); | 1089 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); |
1065 | temp_dword &= 0xfffeffff; | 1090 | temp_dword &= 0xfffdffff; |
1066 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); | 1091 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); |
1092 | ctrl->cmd_busy = 0; | ||
1067 | wake_up_interruptible(&ctrl->queue); | 1093 | wake_up_interruptible(&ctrl->queue); |
1068 | } | 1094 | } |
1069 | 1095 | ||
@@ -1121,7 +1147,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
1121 | int retval = 0; | 1147 | int retval = 0; |
1122 | u8 pi; | 1148 | u8 pi; |
1123 | u32 slot_avail1, slot_avail2; | 1149 | u32 slot_avail1, slot_avail2; |
1124 | int slot_num; | ||
1125 | 1150 | ||
1126 | DBG_ENTER_ROUTINE | 1151 | DBG_ENTER_ROUTINE |
1127 | 1152 | ||
@@ -1140,39 +1165,39 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
1140 | slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); | 1165 | slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); |
1141 | 1166 | ||
1142 | if (pi == 2) { | 1167 | if (pi == 2) { |
1143 | if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 ) | 1168 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) |
1144 | bus_speed = PCIX_133MHZ_533; | 1169 | bus_speed = PCIX_133MHZ_533; |
1145 | else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 ) | 1170 | else if (slot_avail2 & SLOT_100MHZ_PCIX_533) |
1146 | bus_speed = PCIX_100MHZ_533; | 1171 | bus_speed = PCIX_100MHZ_533; |
1147 | else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 ) | 1172 | else if (slot_avail2 & SLOT_66MHZ_PCIX_533) |
1148 | bus_speed = PCIX_66MHZ_533; | 1173 | bus_speed = PCIX_66MHZ_533; |
1149 | else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 ) | 1174 | else if (slot_avail2 & SLOT_133MHZ_PCIX_266) |
1150 | bus_speed = PCIX_133MHZ_266; | 1175 | bus_speed = PCIX_133MHZ_266; |
1151 | else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 ) | 1176 | else if (slot_avail2 & SLOT_100MHZ_PCIX_266) |
1152 | bus_speed = PCIX_100MHZ_266; | 1177 | bus_speed = PCIX_100MHZ_266; |
1153 | else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 ) | 1178 | else if (slot_avail2 & SLOT_66MHZ_PCIX_266) |
1154 | bus_speed = PCIX_66MHZ_266; | 1179 | bus_speed = PCIX_66MHZ_266; |
1155 | else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) | 1180 | else if (slot_avail1 & SLOT_133MHZ_PCIX) |
1156 | bus_speed = PCIX_133MHZ; | 1181 | bus_speed = PCIX_133MHZ; |
1157 | else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) | 1182 | else if (slot_avail1 & SLOT_100MHZ_PCIX) |
1158 | bus_speed = PCIX_100MHZ; | 1183 | bus_speed = PCIX_100MHZ; |
1159 | else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) | 1184 | else if (slot_avail1 & SLOT_66MHZ_PCIX) |
1160 | bus_speed = PCIX_66MHZ; | 1185 | bus_speed = PCIX_66MHZ; |
1161 | else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) | 1186 | else if (slot_avail2 & SLOT_66MHZ) |
1162 | bus_speed = PCI_66MHZ; | 1187 | bus_speed = PCI_66MHZ; |
1163 | else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) | 1188 | else if (slot_avail1 & SLOT_33MHZ) |
1164 | bus_speed = PCI_33MHZ; | 1189 | bus_speed = PCI_33MHZ; |
1165 | else bus_speed = PCI_SPEED_UNKNOWN; | 1190 | else bus_speed = PCI_SPEED_UNKNOWN; |
1166 | } else { | 1191 | } else { |
1167 | if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) | 1192 | if (slot_avail1 & SLOT_133MHZ_PCIX) |
1168 | bus_speed = PCIX_133MHZ; | 1193 | bus_speed = PCIX_133MHZ; |
1169 | else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) | 1194 | else if (slot_avail1 & SLOT_100MHZ_PCIX) |
1170 | bus_speed = PCIX_100MHZ; | 1195 | bus_speed = PCIX_100MHZ; |
1171 | else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) | 1196 | else if (slot_avail1 & SLOT_66MHZ_PCIX) |
1172 | bus_speed = PCIX_66MHZ; | 1197 | bus_speed = PCIX_66MHZ; |
1173 | else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) | 1198 | else if (slot_avail2 & SLOT_66MHZ) |
1174 | bus_speed = PCI_66MHZ; | 1199 | bus_speed = PCI_66MHZ; |
1175 | else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) | 1200 | else if (slot_avail1 & SLOT_33MHZ) |
1176 | bus_speed = PCI_33MHZ; | 1201 | bus_speed = PCI_33MHZ; |
1177 | else bus_speed = PCI_SPEED_UNKNOWN; | 1202 | else bus_speed = PCI_SPEED_UNKNOWN; |
1178 | } | 1203 | } |
@@ -1321,19 +1346,34 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
1321 | .check_cmd_status = hpc_check_cmd_status, | 1346 | .check_cmd_status = hpc_check_cmd_status, |
1322 | }; | 1347 | }; |
1323 | 1348 | ||
1349 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, | ||
1350 | u32 *value) | ||
1351 | { | ||
1352 | int rc; | ||
1353 | u32 cap_offset = ctrl->cap_offset; | ||
1354 | struct pci_dev *pdev = ctrl->pci_dev; | ||
1355 | |||
1356 | rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); | ||
1357 | if (rc) | ||
1358 | return rc; | ||
1359 | return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); | ||
1360 | } | ||
1361 | |||
1324 | int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | 1362 | int shpc_init(struct controller * ctrl, struct pci_dev * pdev) |
1325 | { | 1363 | { |
1326 | struct php_ctlr_state_s *php_ctlr, *p; | 1364 | struct php_ctlr_state_s *php_ctlr, *p; |
1327 | void *instance_id = ctrl; | 1365 | void *instance_id = ctrl; |
1328 | int rc; | 1366 | int rc, num_slots = 0; |
1329 | u8 hp_slot; | 1367 | u8 hp_slot; |
1330 | static int first = 1; | 1368 | static int first = 1; |
1331 | u32 shpc_cap_offset, shpc_base_offset; | 1369 | u32 shpc_base_offset; |
1332 | u32 tempdword, slot_reg; | 1370 | u32 tempdword, slot_reg; |
1333 | u8 i; | 1371 | u8 i; |
1334 | 1372 | ||
1335 | DBG_ENTER_ROUTINE | 1373 | DBG_ENTER_ROUTINE |
1336 | 1374 | ||
1375 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ | ||
1376 | |||
1337 | spin_lock_init(&list_lock); | 1377 | spin_lock_init(&list_lock); |
1338 | php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); | 1378 | php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); |
1339 | 1379 | ||
@@ -1348,41 +1388,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1348 | 1388 | ||
1349 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == | 1389 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == |
1350 | PCI_DEVICE_ID_AMD_GOLAM_7450)) { | 1390 | PCI_DEVICE_ID_AMD_GOLAM_7450)) { |
1351 | shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */ | 1391 | /* amd shpc driver doesn't use Base Offset; assume 0 */ |
1392 | ctrl->mmio_base = pci_resource_start(pdev, 0); | ||
1393 | ctrl->mmio_size = pci_resource_len(pdev, 0); | ||
1352 | } else { | 1394 | } else { |
1353 | if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) { | 1395 | ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); |
1354 | err("%s : shpc_cap_offset == 0\n", __FUNCTION__); | 1396 | if (!ctrl->cap_offset) { |
1397 | err("%s : cap_offset == 0\n", __FUNCTION__); | ||
1355 | goto abort_free_ctlr; | 1398 | goto abort_free_ctlr; |
1356 | } | 1399 | } |
1357 | dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset); | 1400 | dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); |
1358 | 1401 | ||
1359 | rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET); | 1402 | rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); |
1360 | if (rc) { | 1403 | if (rc) { |
1361 | err("%s : pci_word_config_byte failed\n", __FUNCTION__); | 1404 | err("%s: cannot read base_offset\n", __FUNCTION__); |
1362 | goto abort_free_ctlr; | 1405 | goto abort_free_ctlr; |
1363 | } | 1406 | } |
1364 | 1407 | ||
1365 | rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset); | 1408 | rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); |
1366 | if (rc) { | 1409 | if (rc) { |
1367 | err("%s : pci_read_config_dword failed\n", __FUNCTION__); | 1410 | err("%s: cannot read slot config\n", __FUNCTION__); |
1368 | goto abort_free_ctlr; | 1411 | goto abort_free_ctlr; |
1369 | } | 1412 | } |
1413 | num_slots = tempdword & SLOT_NUM; | ||
1414 | dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); | ||
1370 | 1415 | ||
1371 | for (i = 0; i <= 14; i++) { | 1416 | for (i = 0; i < 9 + num_slots; i++) { |
1372 | rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i); | 1417 | rc = shpc_indirect_creg_read(ctrl, i, &tempdword); |
1373 | if (rc) { | ||
1374 | err("%s : pci_word_config_byte failed\n", __FUNCTION__); | ||
1375 | goto abort_free_ctlr; | ||
1376 | } | ||
1377 | |||
1378 | rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword); | ||
1379 | if (rc) { | 1418 | if (rc) { |
1380 | err("%s : pci_read_config_dword failed\n", __FUNCTION__); | 1419 | err("%s: cannot read creg (index = %d)\n", |
1420 | __FUNCTION__, i); | ||
1381 | goto abort_free_ctlr; | 1421 | goto abort_free_ctlr; |
1382 | } | 1422 | } |
1383 | dbg("%s: offset %d: value %x\n", __FUNCTION__,i, | 1423 | dbg("%s: offset %d: value %x\n", __FUNCTION__,i, |
1384 | tempdword); | 1424 | tempdword); |
1385 | } | 1425 | } |
1426 | |||
1427 | ctrl->mmio_base = | ||
1428 | pci_resource_start(pdev, 0) + shpc_base_offset; | ||
1429 | ctrl->mmio_size = 0x24 + 0x4 * num_slots; | ||
1386 | } | 1430 | } |
1387 | 1431 | ||
1388 | if (first) { | 1432 | if (first) { |
@@ -1396,16 +1440,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1396 | if (pci_enable_device(pdev)) | 1440 | if (pci_enable_device(pdev)) |
1397 | goto abort_free_ctlr; | 1441 | goto abort_free_ctlr; |
1398 | 1442 | ||
1399 | if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { | 1443 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { |
1400 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); | 1444 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); |
1401 | goto abort_free_ctlr; | 1445 | goto abort_free_ctlr; |
1402 | } | 1446 | } |
1403 | 1447 | ||
1404 | php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); | 1448 | php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); |
1405 | if (!php_ctlr->creg) { | 1449 | if (!php_ctlr->creg) { |
1406 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), | 1450 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, |
1407 | pci_resource_start(pdev, 0) + shpc_base_offset); | 1451 | ctrl->mmio_size, ctrl->mmio_base); |
1408 | release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); | 1452 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
1409 | goto abort_free_ctlr; | 1453 | goto abort_free_ctlr; |
1410 | } | 1454 | } |
1411 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1455 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 38009bc0fd5d..19e1a5e1e30b 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -89,10 +89,11 @@ int shpchp_configure_device(struct slot *p_slot) | |||
89 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; | 89 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; |
90 | int num, fn; | 90 | int num, fn; |
91 | 91 | ||
92 | dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); | 92 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
93 | if (dev) { | 93 | if (dev) { |
94 | err("Device %s already exists at %x:%x, cannot hot-add\n", | 94 | err("Device %s already exists at %x:%x, cannot hot-add\n", |
95 | pci_name(dev), p_slot->bus, p_slot->device); | 95 | pci_name(dev), p_slot->bus, p_slot->device); |
96 | pci_dev_put(dev); | ||
96 | return -EINVAL; | 97 | return -EINVAL; |
97 | } | 98 | } |
98 | 99 | ||
@@ -103,12 +104,13 @@ int shpchp_configure_device(struct slot *p_slot) | |||
103 | } | 104 | } |
104 | 105 | ||
105 | for (fn = 0; fn < 8; fn++) { | 106 | for (fn = 0; fn < 8; fn++) { |
106 | if (!(dev = pci_find_slot(p_slot->bus, | 107 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); |
107 | PCI_DEVFN(p_slot->device, fn)))) | 108 | if (!dev) |
108 | continue; | 109 | continue; |
109 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | 110 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { |
110 | err("Cannot hot-add display device %s\n", | 111 | err("Cannot hot-add display device %s\n", |
111 | pci_name(dev)); | 112 | pci_name(dev)); |
113 | pci_dev_put(dev); | ||
112 | continue; | 114 | continue; |
113 | } | 115 | } |
114 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 116 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
@@ -124,18 +126,21 @@ int shpchp_configure_device(struct slot *p_slot) | |||
124 | } | 126 | } |
125 | if (busnr >= end) { | 127 | if (busnr >= end) { |
126 | err("No free bus for hot-added bridge\n"); | 128 | err("No free bus for hot-added bridge\n"); |
129 | pci_dev_put(dev); | ||
127 | continue; | 130 | continue; |
128 | } | 131 | } |
129 | child = pci_add_new_bus(parent, dev, busnr); | 132 | child = pci_add_new_bus(parent, dev, busnr); |
130 | if (!child) { | 133 | if (!child) { |
131 | err("Cannot add new bus for %s\n", | 134 | err("Cannot add new bus for %s\n", |
132 | pci_name(dev)); | 135 | pci_name(dev)); |
136 | pci_dev_put(dev); | ||
133 | continue; | 137 | continue; |
134 | } | 138 | } |
135 | child->subordinate = pci_do_scan_bus(child); | 139 | child->subordinate = pci_do_scan_bus(child); |
136 | pci_bus_size_bridges(child); | 140 | pci_bus_size_bridges(child); |
137 | } | 141 | } |
138 | program_fw_provided_values(dev); | 142 | program_fw_provided_values(dev); |
143 | pci_dev_put(dev); | ||
139 | } | 144 | } |
140 | 145 | ||
141 | pci_bus_assign_resources(parent); | 146 | pci_bus_assign_resources(parent); |
@@ -149,17 +154,19 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
149 | int rc = 0; | 154 | int rc = 0; |
150 | int j; | 155 | int j; |
151 | u8 bctl = 0; | 156 | u8 bctl = 0; |
152 | 157 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; | |
158 | |||
153 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); | 159 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); |
154 | 160 | ||
155 | for (j=0; j<8 ; j++) { | 161 | for (j=0; j<8 ; j++) { |
156 | struct pci_dev* temp = pci_find_slot(p_slot->bus, | 162 | struct pci_dev* temp = pci_get_slot(parent, |
157 | (p_slot->device << 3) | j); | 163 | (p_slot->device << 3) | j); |
158 | if (!temp) | 164 | if (!temp) |
159 | continue; | 165 | continue; |
160 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | 166 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { |
161 | err("Cannot remove display device %s\n", | 167 | err("Cannot remove display device %s\n", |
162 | pci_name(temp)); | 168 | pci_name(temp)); |
169 | pci_dev_put(temp); | ||
163 | continue; | 170 | continue; |
164 | } | 171 | } |
165 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 172 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
@@ -167,10 +174,12 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
167 | if (bctl & PCI_BRIDGE_CTL_VGA) { | 174 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
168 | err("Cannot remove display device %s\n", | 175 | err("Cannot remove display device %s\n", |
169 | pci_name(temp)); | 176 | pci_name(temp)); |
177 | pci_dev_put(temp); | ||
170 | continue; | 178 | continue; |
171 | } | 179 | } |
172 | } | 180 | } |
173 | pci_remove_bus_device(temp); | 181 | pci_remove_bus_device(temp); |
182 | pci_dev_put(temp); | ||
174 | } | 183 | } |
175 | return rc; | 184 | return rc; |
176 | } | 185 | } |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8e287a828d5d..d2a633efa10a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 19 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
20 | #include "pci.h" | 20 | #include "pci.h" |
21 | 21 | ||
22 | #if 0 | ||
22 | 23 | ||
23 | /** | 24 | /** |
24 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children | 25 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children |
@@ -63,6 +64,8 @@ pci_max_busnr(void) | |||
63 | return max; | 64 | return max; |
64 | } | 65 | } |
65 | 66 | ||
67 | #endif /* 0 */ | ||
68 | |||
66 | static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) | 69 | static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) |
67 | { | 70 | { |
68 | u8 id; | 71 | u8 id; |
@@ -587,7 +590,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) | |||
587 | { | 590 | { |
588 | u8 pin; | 591 | u8 pin; |
589 | 592 | ||
590 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 593 | pin = dev->pin; |
591 | if (!pin) | 594 | if (!pin) |
592 | return -1; | 595 | return -1; |
593 | pin--; | 596 | pin--; |
@@ -917,8 +920,6 @@ EXPORT_SYMBOL_GPL(pci_restore_bars); | |||
917 | EXPORT_SYMBOL(pci_enable_device_bars); | 920 | EXPORT_SYMBOL(pci_enable_device_bars); |
918 | EXPORT_SYMBOL(pci_enable_device); | 921 | EXPORT_SYMBOL(pci_enable_device); |
919 | EXPORT_SYMBOL(pci_disable_device); | 922 | EXPORT_SYMBOL(pci_disable_device); |
920 | EXPORT_SYMBOL(pci_max_busnr); | ||
921 | EXPORT_SYMBOL(pci_bus_max_busnr); | ||
922 | EXPORT_SYMBOL(pci_find_capability); | 923 | EXPORT_SYMBOL(pci_find_capability); |
923 | EXPORT_SYMBOL(pci_bus_find_capability); | 924 | EXPORT_SYMBOL(pci_bus_find_capability); |
924 | EXPORT_SYMBOL(pci_release_regions); | 925 | EXPORT_SYMBOL(pci_release_regions); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 294849d24590..a6dfee2f6d2b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -26,20 +26,15 @@ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val); | |||
26 | #ifdef CONFIG_PROC_FS | 26 | #ifdef CONFIG_PROC_FS |
27 | extern int pci_proc_attach_device(struct pci_dev *dev); | 27 | extern int pci_proc_attach_device(struct pci_dev *dev); |
28 | extern int pci_proc_detach_device(struct pci_dev *dev); | 28 | extern int pci_proc_detach_device(struct pci_dev *dev); |
29 | extern int pci_proc_attach_bus(struct pci_bus *bus); | ||
30 | extern int pci_proc_detach_bus(struct pci_bus *bus); | 29 | extern int pci_proc_detach_bus(struct pci_bus *bus); |
31 | #else | 30 | #else |
32 | static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; } | 31 | static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; } |
33 | static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; } | 32 | static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; } |
34 | static inline int pci_proc_attach_bus(struct pci_bus *bus) { return 0; } | ||
35 | static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } | 33 | static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } |
36 | #endif | 34 | #endif |
37 | 35 | ||
38 | /* Functions for PCI Hotplug drivers to use */ | 36 | /* Functions for PCI Hotplug drivers to use */ |
39 | extern unsigned int pci_do_scan_bus(struct pci_bus *bus); | 37 | extern unsigned int pci_do_scan_bus(struct pci_bus *bus); |
40 | extern int pci_remove_device_safe(struct pci_dev *dev); | ||
41 | extern unsigned char pci_max_busnr(void); | ||
42 | extern unsigned char pci_bus_max_busnr(struct pci_bus *bus); | ||
43 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); | 38 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); |
44 | 39 | ||
45 | extern void pci_remove_legacy_files(struct pci_bus *bus); | 40 | extern void pci_remove_legacy_files(struct pci_bus *bus); |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 467a4ceccf10..e4e5f1e8d816 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -238,8 +238,8 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | |||
238 | device->driver = NULL; | 238 | device->driver = NULL; |
239 | device->driver_data = NULL; | 239 | device->driver_data = NULL; |
240 | device->release = release_pcie_device; /* callback to free pcie dev */ | 240 | device->release = release_pcie_device; /* callback to free pcie dev */ |
241 | sprintf(&device->bus_id[0], "pcie%02x", | 241 | snprintf(device->bus_id, sizeof(device->bus_id), "%s:pcie%02x", |
242 | get_descriptor_id(port_type, service_type)); | 242 | pci_name(parent), get_descriptor_id(port_type, service_type)); |
243 | device->parent = &parent->dev; | 243 | device->parent = &parent->dev; |
244 | } | 244 | } |
245 | 245 | ||
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index fce2cb2112d8..adfad4fd6a13 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -264,8 +264,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
264 | 264 | ||
265 | if (base <= limit) { | 265 | if (base <= limit) { |
266 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; | 266 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; |
267 | res->start = base; | 267 | if (!res->start) |
268 | res->end = limit + 0xfff; | 268 | res->start = base; |
269 | if (!res->end) | ||
270 | res->end = limit + 0xfff; | ||
269 | } | 271 | } |
270 | 272 | ||
271 | res = child->resource[1]; | 273 | res = child->resource[1]; |
@@ -431,7 +433,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
431 | { | 433 | { |
432 | struct pci_bus *child; | 434 | struct pci_bus *child; |
433 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); | 435 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); |
434 | u32 buses, i; | 436 | u32 buses, i, j = 0; |
435 | u16 bctl; | 437 | u16 bctl; |
436 | 438 | ||
437 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); | 439 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); |
@@ -541,10 +543,29 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
541 | * as cards with a PCI-to-PCI bridge can be | 543 | * as cards with a PCI-to-PCI bridge can be |
542 | * inserted later. | 544 | * inserted later. |
543 | */ | 545 | */ |
544 | for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) | 546 | for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) { |
547 | struct pci_bus *parent = bus; | ||
545 | if (pci_find_bus(pci_domain_nr(bus), | 548 | if (pci_find_bus(pci_domain_nr(bus), |
546 | max+i+1)) | 549 | max+i+1)) |
547 | break; | 550 | break; |
551 | while (parent->parent) { | ||
552 | if ((!pcibios_assign_all_busses()) && | ||
553 | (parent->subordinate > max) && | ||
554 | (parent->subordinate <= max+i)) { | ||
555 | j = 1; | ||
556 | } | ||
557 | parent = parent->parent; | ||
558 | } | ||
559 | if (j) { | ||
560 | /* | ||
561 | * Often, there are two cardbus bridges | ||
562 | * -- try to leave one valid bus number | ||
563 | * for each one. | ||
564 | */ | ||
565 | i /= 2; | ||
566 | break; | ||
567 | } | ||
568 | } | ||
548 | max += i; | 569 | max += i; |
549 | pci_fixup_parent_subordinate_busnr(child, max); | 570 | pci_fixup_parent_subordinate_busnr(child, max); |
550 | } | 571 | } |
@@ -559,6 +580,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
559 | 580 | ||
560 | sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); | 581 | sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); |
561 | 582 | ||
583 | while (bus->parent) { | ||
584 | if ((child->subordinate > bus->subordinate) || | ||
585 | (child->number > bus->subordinate) || | ||
586 | (child->number < bus->number) || | ||
587 | (child->subordinate < bus->number)) { | ||
588 | printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be " | ||
589 | "hidden behind%s bridge #%02x (-#%02x)%s\n", | ||
590 | child->number, child->subordinate, | ||
591 | bus->self->transparent ? " transparent" : " ", | ||
592 | bus->number, bus->subordinate, | ||
593 | pcibios_assign_all_busses() ? " " : | ||
594 | " (try 'pci=assign-busses')"); | ||
595 | } | ||
596 | bus = bus->parent; | ||
597 | } | ||
598 | |||
562 | return max; | 599 | return max; |
563 | } | 600 | } |
564 | 601 | ||
@@ -571,6 +608,7 @@ static void pci_read_irq(struct pci_dev *dev) | |||
571 | unsigned char irq; | 608 | unsigned char irq; |
572 | 609 | ||
573 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); | 610 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); |
611 | dev->pin = irq; | ||
574 | if (irq) | 612 | if (irq) |
575 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | 613 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); |
576 | dev->irq = irq; | 614 | dev->irq = irq; |
@@ -624,6 +662,7 @@ static int pci_setup_device(struct pci_dev * dev) | |||
624 | /* The PCI-to-PCI bridge spec requires that subtractive | 662 | /* The PCI-to-PCI bridge spec requires that subtractive |
625 | decoding (i.e. transparent) bridge must have programming | 663 | decoding (i.e. transparent) bridge must have programming |
626 | interface code of 0x01. */ | 664 | interface code of 0x01. */ |
665 | pci_read_irq(dev); | ||
627 | dev->transparent = ((dev->class & 0xff) == 1); | 666 | dev->transparent = ((dev->class & 0xff) == 1); |
628 | pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); | 667 | pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); |
629 | break; | 668 | break; |
@@ -678,7 +717,7 @@ static void pci_release_dev(struct device *dev) | |||
678 | * reading the dword at 0x100 which must either be 0 or a valid extended | 717 | * reading the dword at 0x100 which must either be 0 or a valid extended |
679 | * capability header. | 718 | * capability header. |
680 | */ | 719 | */ |
681 | static int pci_cfg_space_size(struct pci_dev *dev) | 720 | int pci_cfg_space_size(struct pci_dev *dev) |
682 | { | 721 | { |
683 | int pos; | 722 | int pos; |
684 | u32 status; | 723 | u32 status; |
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 9cb6dd0834be..92a885760832 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c | |||
@@ -431,6 +431,7 @@ int pci_proc_detach_device(struct pci_dev *dev) | |||
431 | return 0; | 431 | return 0; |
432 | } | 432 | } |
433 | 433 | ||
434 | #if 0 | ||
434 | int pci_proc_attach_bus(struct pci_bus* bus) | 435 | int pci_proc_attach_bus(struct pci_bus* bus) |
435 | { | 436 | { |
436 | struct proc_dir_entry *de = bus->procdir; | 437 | struct proc_dir_entry *de = bus->procdir; |
@@ -447,6 +448,7 @@ int pci_proc_attach_bus(struct pci_bus* bus) | |||
447 | } | 448 | } |
448 | return 0; | 449 | return 0; |
449 | } | 450 | } |
451 | #endif /* 0 */ | ||
450 | 452 | ||
451 | int pci_proc_detach_bus(struct pci_bus* bus) | 453 | int pci_proc_detach_bus(struct pci_bus* bus) |
452 | { | 454 | { |
@@ -612,7 +614,6 @@ __initcall(pci_proc_init); | |||
612 | 614 | ||
613 | #ifdef CONFIG_HOTPLUG | 615 | #ifdef CONFIG_HOTPLUG |
614 | EXPORT_SYMBOL(pci_proc_attach_device); | 616 | EXPORT_SYMBOL(pci_proc_attach_device); |
615 | EXPORT_SYMBOL(pci_proc_attach_bus); | ||
616 | EXPORT_SYMBOL(pci_proc_detach_bus); | 617 | EXPORT_SYMBOL(pci_proc_detach_bus); |
617 | #endif | 618 | #endif |
618 | 619 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f28ebdd3958a..605f0df0bfba 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -1342,6 +1342,32 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) | |||
1342 | pci_do_fixups(dev, start, end); | 1342 | pci_do_fixups(dev, start, end); |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | /* Enable 1k I/O space granularity on the Intel P64H2 */ | ||
1346 | static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) | ||
1347 | { | ||
1348 | u16 en1k; | ||
1349 | u8 io_base_lo, io_limit_lo; | ||
1350 | unsigned long base, limit; | ||
1351 | struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; | ||
1352 | |||
1353 | pci_read_config_word(dev, 0x40, &en1k); | ||
1354 | |||
1355 | if (en1k & 0x200) { | ||
1356 | printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n"); | ||
1357 | |||
1358 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); | ||
1359 | pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); | ||
1360 | base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; | ||
1361 | limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8; | ||
1362 | |||
1363 | if (base <= limit) { | ||
1364 | res->start = base; | ||
1365 | res->end = limit + 0x3ff; | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); | ||
1370 | |||
1345 | EXPORT_SYMBOL(pcie_mch_quirk); | 1371 | EXPORT_SYMBOL(pcie_mch_quirk); |
1346 | #ifdef CONFIG_HOTPLUG | 1372 | #ifdef CONFIG_HOTPLUG |
1347 | EXPORT_SYMBOL(pci_fixup_device); | 1373 | EXPORT_SYMBOL(pci_fixup_device); |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 27a294b6965d..1a6bf9de166f 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -48,6 +48,7 @@ static void pci_destroy_dev(struct pci_dev *dev) | |||
48 | * in question is not being used by a driver. | 48 | * in question is not being used by a driver. |
49 | * Returns 0 on success. | 49 | * Returns 0 on success. |
50 | */ | 50 | */ |
51 | #if 0 | ||
51 | int pci_remove_device_safe(struct pci_dev *dev) | 52 | int pci_remove_device_safe(struct pci_dev *dev) |
52 | { | 53 | { |
53 | if (pci_dev_driver(dev)) | 54 | if (pci_dev_driver(dev)) |
@@ -55,7 +56,7 @@ int pci_remove_device_safe(struct pci_dev *dev) | |||
55 | pci_destroy_dev(dev); | 56 | pci_destroy_dev(dev); |
56 | return 0; | 57 | return 0; |
57 | } | 58 | } |
58 | EXPORT_SYMBOL(pci_remove_device_safe); | 59 | #endif /* 0 */ |
59 | 60 | ||
60 | void pci_remove_bus(struct pci_bus *pci_bus) | 61 | void pci_remove_bus(struct pci_bus *pci_bus) |
61 | { | 62 | { |