diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/pci/hotplug | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/pci/hotplug')
32 files changed, 382 insertions, 1008 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3625b094bf7e..6cd9f3c9887d 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
@@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o | |||
6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o | 6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o |
7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o | 7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o |
8 | 8 | ||
9 | # pciehp should be linked before acpiphp in order to allow the native driver | 9 | # native drivers should be linked before acpiphp in order to allow the |
10 | # to attempt to bind first. We can then fall back to generic support. | 10 | # native driver to attempt to bind first. We can then fall back to |
11 | # generic support. | ||
11 | 12 | ||
12 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o | 13 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o |
13 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o | ||
14 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o | ||
15 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o | 14 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o |
16 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o | 15 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o |
17 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o | 16 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o |
18 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o | 17 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o |
19 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o | 18 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o |
20 | obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o | 19 | obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o |
20 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o | ||
21 | |||
22 | # acpiphp_ibm extends acpiphp, so should be linked afterwards. | ||
23 | |||
24 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o | ||
21 | 25 | ||
22 | # Link this last so it doesn't claim devices that have a real hotplug driver | 26 | # Link this last so it doesn't claim devices that have a real hotplug driver |
23 | obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o | 27 | obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index a73028ec52e5..45fcc1e96df9 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/pci_hotplug.h> | 32 | #include <linux/pci_hotplug.h> |
33 | #include <linux/acpi.h> | 33 | #include <linux/acpi.h> |
34 | #include <linux/pci-acpi.h> | 34 | #include <linux/pci-acpi.h> |
35 | #include <linux/slab.h> | ||
35 | 36 | ||
36 | #define MY_NAME "acpi_pcihp" | 37 | #define MY_NAME "acpi_pcihp" |
37 | 38 | ||
@@ -362,6 +363,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
362 | status = acpi_pci_osc_control_set(handle, flags); | 363 | status = acpi_pci_osc_control_set(handle, flags); |
363 | if (ACPI_SUCCESS(status)) | 364 | if (ACPI_SUCCESS(status)) |
364 | goto got_one; | 365 | goto got_one; |
366 | if (status == AE_SUPPORT) | ||
367 | goto no_control; | ||
365 | kfree(string.pointer); | 368 | kfree(string.pointer); |
366 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; | 369 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; |
367 | } | 370 | } |
@@ -394,10 +397,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
394 | if (ACPI_FAILURE(status)) | 397 | if (ACPI_FAILURE(status)) |
395 | break; | 398 | break; |
396 | } | 399 | } |
397 | 400 | no_control: | |
398 | dbg("Cannot get control of hotplug hardware for pci %s\n", | 401 | dbg("Cannot get control of hotplug hardware for pci %s\n", |
399 | pci_name(pdev)); | 402 | pci_name(pdev)); |
400 | |||
401 | kfree(string.pointer); | 403 | kfree(string.pointer); |
402 | return -ENODEV; | 404 | return -ENODEV; |
403 | got_one: | 405 | got_one: |
@@ -471,7 +473,7 @@ int acpi_pci_detect_ejectable(acpi_handle handle) | |||
471 | return found; | 473 | return found; |
472 | 474 | ||
473 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | 475 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, |
474 | check_hotplug, (void *)&found, NULL); | 476 | check_hotplug, NULL, (void *)&found, NULL); |
475 | return found; | 477 | return found; |
476 | } | 478 | } |
477 | EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable); | 479 | EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable); |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7d938df79206..bab52047baa8 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -146,12 +146,6 @@ struct acpiphp_attention_info | |||
146 | struct module *owner; | 146 | struct module *owner; |
147 | }; | 147 | }; |
148 | 148 | ||
149 | struct acpiphp_ioapic { | ||
150 | struct pci_dev *dev; | ||
151 | u32 gsi_base; | ||
152 | struct list_head list; | ||
153 | }; | ||
154 | |||
155 | /* PCI bus bridge HID */ | 149 | /* PCI bus bridge HID */ |
156 | #define ACPI_PCI_HOST_HID "PNP0A03" | 150 | #define ACPI_PCI_HOST_HID "PNP0A03" |
157 | 151 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 4dd7114964ac..efa9f2de51c1 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -332,8 +332,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
332 | slot->hotplug_slot->info->attention_status = 0; | 332 | slot->hotplug_slot->info->attention_status = 0; |
333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); | 333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); |
334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); | 334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); |
335 | slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
336 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
337 | 335 | ||
338 | acpiphp_slot->slot = slot; | 336 | acpiphp_slot->slot = slot; |
339 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); | 337 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 58d25a163a8b..cb23aa2ebf96 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -47,13 +47,12 @@ | |||
47 | #include <linux/pci_hotplug.h> | 47 | #include <linux/pci_hotplug.h> |
48 | #include <linux/pci-acpi.h> | 48 | #include <linux/pci-acpi.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/slab.h> | ||
50 | 51 | ||
51 | #include "../pci.h" | 52 | #include "../pci.h" |
52 | #include "acpiphp.h" | 53 | #include "acpiphp.h" |
53 | 54 | ||
54 | static LIST_HEAD(bridge_list); | 55 | static LIST_HEAD(bridge_list); |
55 | static LIST_HEAD(ioapic_list); | ||
56 | static DEFINE_SPINLOCK(ioapic_list_lock); | ||
57 | 56 | ||
58 | #define MY_NAME "acpiphp_glue" | 57 | #define MY_NAME "acpiphp_glue" |
59 | 58 | ||
@@ -266,7 +265,7 @@ static int detect_ejectable_slots(acpi_handle handle) | |||
266 | int found = acpi_pci_detect_ejectable(handle); | 265 | int found = acpi_pci_detect_ejectable(handle); |
267 | if (!found) { | 266 | if (!found) { |
268 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 267 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
269 | is_pci_dock_device, (void *)&found, NULL); | 268 | is_pci_dock_device, NULL, (void *)&found, NULL); |
270 | } | 269 | } |
271 | return found; | 270 | return found; |
272 | } | 271 | } |
@@ -281,7 +280,7 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
281 | 280 | ||
282 | /* register all slot objects under this bridge */ | 281 | /* register all slot objects under this bridge */ |
283 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | 282 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, |
284 | register_slot, bridge, NULL); | 283 | register_slot, NULL, bridge, NULL); |
285 | if (ACPI_FAILURE(status)) { | 284 | if (ACPI_FAILURE(status)) { |
286 | list_del(&bridge->list); | 285 | list_del(&bridge->list); |
287 | return; | 286 | return; |
@@ -311,17 +310,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
311 | /* find acpiphp_func from acpiphp_bridge */ | 310 | /* find acpiphp_func from acpiphp_bridge */ |
312 | static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) | 311 | static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) |
313 | { | 312 | { |
314 | struct list_head *node, *l; | ||
315 | struct acpiphp_bridge *bridge; | 313 | struct acpiphp_bridge *bridge; |
316 | struct acpiphp_slot *slot; | 314 | struct acpiphp_slot *slot; |
317 | struct acpiphp_func *func; | 315 | struct acpiphp_func *func; |
318 | 316 | ||
319 | list_for_each(node, &bridge_list) { | 317 | list_for_each_entry(bridge, &bridge_list, list) { |
320 | bridge = list_entry(node, struct acpiphp_bridge, list); | ||
321 | for (slot = bridge->slots; slot; slot = slot->next) { | 318 | for (slot = bridge->slots; slot; slot = slot->next) { |
322 | list_for_each(l, &slot->funcs) { | 319 | list_for_each_entry(func, &slot->funcs, sibling) { |
323 | func = list_entry(l, struct acpiphp_func, | ||
324 | sibling); | ||
325 | if (func->handle == handle) | 320 | if (func->handle == handle) |
326 | return func; | 321 | return func; |
327 | } | 322 | } |
@@ -447,7 +442,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
447 | 442 | ||
448 | /* search P2P bridges under this p2p bridge */ | 443 | /* search P2P bridges under this p2p bridge */ |
449 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 444 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
450 | find_p2p_bridge, NULL, NULL); | 445 | find_p2p_bridge, NULL, NULL, NULL); |
451 | if (ACPI_FAILURE(status)) | 446 | if (ACPI_FAILURE(status)) |
452 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 447 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
453 | 448 | ||
@@ -485,7 +480,7 @@ static int add_bridge(acpi_handle handle) | |||
485 | 480 | ||
486 | /* search P2P bridges under this host bridge */ | 481 | /* search P2P bridges under this host bridge */ |
487 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 482 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
488 | find_p2p_bridge, NULL, NULL); | 483 | find_p2p_bridge, NULL, NULL, NULL); |
489 | 484 | ||
490 | if (ACPI_FAILURE(status)) | 485 | if (ACPI_FAILURE(status)) |
491 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 486 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
@@ -495,21 +490,19 @@ static int add_bridge(acpi_handle handle) | |||
495 | 490 | ||
496 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | 491 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) |
497 | { | 492 | { |
498 | struct list_head *head; | 493 | struct acpiphp_bridge *bridge; |
499 | list_for_each(head, &bridge_list) { | 494 | |
500 | struct acpiphp_bridge *bridge = list_entry(head, | 495 | list_for_each_entry(bridge, &bridge_list, list) |
501 | struct acpiphp_bridge, list); | ||
502 | if (bridge->handle == handle) | 496 | if (bridge->handle == handle) |
503 | return bridge; | 497 | return bridge; |
504 | } | ||
505 | 498 | ||
506 | return NULL; | 499 | return NULL; |
507 | } | 500 | } |
508 | 501 | ||
509 | static void cleanup_bridge(struct acpiphp_bridge *bridge) | 502 | static void cleanup_bridge(struct acpiphp_bridge *bridge) |
510 | { | 503 | { |
511 | struct list_head *list, *tmp; | 504 | struct acpiphp_slot *slot, *next; |
512 | struct acpiphp_slot *slot; | 505 | struct acpiphp_func *func, *tmp; |
513 | acpi_status status; | 506 | acpi_status status; |
514 | acpi_handle handle = bridge->handle; | 507 | acpi_handle handle = bridge->handle; |
515 | 508 | ||
@@ -530,10 +523,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
530 | 523 | ||
531 | slot = bridge->slots; | 524 | slot = bridge->slots; |
532 | while (slot) { | 525 | while (slot) { |
533 | struct acpiphp_slot *next = slot->next; | 526 | next = slot->next; |
534 | list_for_each_safe (list, tmp, &slot->funcs) { | 527 | list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { |
535 | struct acpiphp_func *func; | ||
536 | func = list_entry(list, struct acpiphp_func, sibling); | ||
537 | if (is_dock_device(func->handle)) { | 528 | if (is_dock_device(func->handle)) { |
538 | unregister_hotplug_dock_device(func->handle); | 529 | unregister_hotplug_dock_device(func->handle); |
539 | unregister_dock_notifier(&func->nb); | 530 | unregister_dock_notifier(&func->nb); |
@@ -545,7 +536,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
545 | if (ACPI_FAILURE(status)) | 536 | if (ACPI_FAILURE(status)) |
546 | err("failed to remove notify handler\n"); | 537 | err("failed to remove notify handler\n"); |
547 | } | 538 | } |
548 | list_del(list); | 539 | list_del(&func->sibling); |
549 | kfree(func); | 540 | kfree(func); |
550 | } | 541 | } |
551 | acpiphp_unregister_hotplug_slot(slot); | 542 | acpiphp_unregister_hotplug_slot(slot); |
@@ -573,7 +564,7 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
573 | /* cleanup p2p bridges under this P2P bridge | 564 | /* cleanup p2p bridges under this P2P bridge |
574 | in a depth-first manner */ | 565 | in a depth-first manner */ |
575 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 566 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
576 | cleanup_p2p_bridge, NULL, NULL); | 567 | cleanup_p2p_bridge, NULL, NULL, NULL); |
577 | 568 | ||
578 | bridge = acpiphp_handle_to_bridge(handle); | 569 | bridge = acpiphp_handle_to_bridge(handle); |
579 | if (bridge) | 570 | if (bridge) |
@@ -589,7 +580,7 @@ static void remove_bridge(acpi_handle handle) | |||
589 | /* cleanup p2p bridges under this host bridge | 580 | /* cleanup p2p bridges under this host bridge |
590 | in a depth-first manner */ | 581 | in a depth-first manner */ |
591 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 582 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
592 | (u32)1, cleanup_p2p_bridge, NULL, NULL); | 583 | (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL); |
593 | 584 | ||
594 | /* | 585 | /* |
595 | * On root bridges with hotplug slots directly underneath (ie, | 586 | * On root bridges with hotplug slots directly underneath (ie, |
@@ -606,204 +597,17 @@ static void remove_bridge(acpi_handle handle) | |||
606 | handle_hotplug_event_bridge); | 597 | handle_hotplug_event_bridge); |
607 | } | 598 | } |
608 | 599 | ||
609 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) | ||
610 | { | ||
611 | struct pci_dev *dev; | ||
612 | |||
613 | dev = acpi_get_pci_dev(handle); | ||
614 | if (!dev) | ||
615 | return NULL; | ||
616 | |||
617 | if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) && | ||
618 | (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC)) | ||
619 | { | ||
620 | pci_dev_put(dev); | ||
621 | return NULL; | ||
622 | } | ||
623 | |||
624 | return dev; | ||
625 | } | ||
626 | |||
627 | static int get_gsi_base(acpi_handle handle, u32 *gsi_base) | ||
628 | { | ||
629 | acpi_status status; | ||
630 | int result = -1; | ||
631 | unsigned long long gsb; | ||
632 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
633 | union acpi_object *obj; | ||
634 | void *table; | ||
635 | |||
636 | status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); | ||
637 | if (ACPI_SUCCESS(status)) { | ||
638 | *gsi_base = (u32)gsb; | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer); | ||
643 | if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer) | ||
644 | return -1; | ||
645 | |||
646 | obj = buffer.pointer; | ||
647 | if (obj->type != ACPI_TYPE_BUFFER) | ||
648 | goto out; | ||
649 | |||
650 | table = obj->buffer.pointer; | ||
651 | switch (((struct acpi_subtable_header *)table)->type) { | ||
652 | case ACPI_MADT_TYPE_IO_SAPIC: | ||
653 | *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; | ||
654 | result = 0; | ||
655 | break; | ||
656 | case ACPI_MADT_TYPE_IO_APIC: | ||
657 | *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; | ||
658 | result = 0; | ||
659 | break; | ||
660 | default: | ||
661 | break; | ||
662 | } | ||
663 | out: | ||
664 | kfree(buffer.pointer); | ||
665 | return result; | ||
666 | } | ||
667 | |||
668 | static acpi_status | ||
669 | ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
670 | { | ||
671 | acpi_status status; | ||
672 | unsigned long long sta; | ||
673 | acpi_handle tmp; | ||
674 | struct pci_dev *pdev; | ||
675 | u32 gsi_base; | ||
676 | u64 phys_addr; | ||
677 | struct acpiphp_ioapic *ioapic; | ||
678 | |||
679 | /* Evaluate _STA if present */ | ||
680 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | ||
681 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) | ||
682 | return AE_CTRL_DEPTH; | ||
683 | |||
684 | /* Scan only PCI bus scope */ | ||
685 | status = acpi_get_handle(handle, "_HID", &tmp); | ||
686 | if (ACPI_SUCCESS(status)) | ||
687 | return AE_CTRL_DEPTH; | ||
688 | |||
689 | if (get_gsi_base(handle, &gsi_base)) | ||
690 | return AE_OK; | ||
691 | |||
692 | ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); | ||
693 | if (!ioapic) | ||
694 | return AE_NO_MEMORY; | ||
695 | |||
696 | pdev = get_apic_pci_info(handle); | ||
697 | if (!pdev) | ||
698 | goto exit_kfree; | ||
699 | |||
700 | if (pci_enable_device(pdev)) | ||
701 | goto exit_pci_dev_put; | ||
702 | |||
703 | pci_set_master(pdev); | ||
704 | |||
705 | if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) | ||
706 | goto exit_pci_disable_device; | ||
707 | |||
708 | phys_addr = pci_resource_start(pdev, 0); | ||
709 | if (acpi_register_ioapic(handle, phys_addr, gsi_base)) | ||
710 | goto exit_pci_release_region; | ||
711 | |||
712 | ioapic->gsi_base = gsi_base; | ||
713 | ioapic->dev = pdev; | ||
714 | spin_lock(&ioapic_list_lock); | ||
715 | list_add_tail(&ioapic->list, &ioapic_list); | ||
716 | spin_unlock(&ioapic_list_lock); | ||
717 | |||
718 | return AE_OK; | ||
719 | |||
720 | exit_pci_release_region: | ||
721 | pci_release_region(pdev, 0); | ||
722 | exit_pci_disable_device: | ||
723 | pci_disable_device(pdev); | ||
724 | exit_pci_dev_put: | ||
725 | pci_dev_put(pdev); | ||
726 | exit_kfree: | ||
727 | kfree(ioapic); | ||
728 | |||
729 | return AE_OK; | ||
730 | } | ||
731 | |||
732 | static acpi_status | ||
733 | ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
734 | { | ||
735 | acpi_status status; | ||
736 | unsigned long long sta; | ||
737 | acpi_handle tmp; | ||
738 | u32 gsi_base; | ||
739 | struct acpiphp_ioapic *pos, *n, *ioapic = NULL; | ||
740 | |||
741 | /* Evaluate _STA if present */ | ||
742 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | ||
743 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) | ||
744 | return AE_CTRL_DEPTH; | ||
745 | |||
746 | /* Scan only PCI bus scope */ | ||
747 | status = acpi_get_handle(handle, "_HID", &tmp); | ||
748 | if (ACPI_SUCCESS(status)) | ||
749 | return AE_CTRL_DEPTH; | ||
750 | |||
751 | if (get_gsi_base(handle, &gsi_base)) | ||
752 | return AE_OK; | ||
753 | |||
754 | acpi_unregister_ioapic(handle, gsi_base); | ||
755 | |||
756 | spin_lock(&ioapic_list_lock); | ||
757 | list_for_each_entry_safe(pos, n, &ioapic_list, list) { | ||
758 | if (pos->gsi_base != gsi_base) | ||
759 | continue; | ||
760 | ioapic = pos; | ||
761 | list_del(&ioapic->list); | ||
762 | break; | ||
763 | } | ||
764 | spin_unlock(&ioapic_list_lock); | ||
765 | |||
766 | if (!ioapic) | ||
767 | return AE_OK; | ||
768 | |||
769 | pci_release_region(ioapic->dev, 0); | ||
770 | pci_disable_device(ioapic->dev); | ||
771 | pci_dev_put(ioapic->dev); | ||
772 | kfree(ioapic); | ||
773 | |||
774 | return AE_OK; | ||
775 | } | ||
776 | |||
777 | static int acpiphp_configure_ioapics(acpi_handle handle) | ||
778 | { | ||
779 | ioapic_add(handle, 0, NULL, NULL); | ||
780 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
781 | ACPI_UINT32_MAX, ioapic_add, NULL, NULL); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | static int acpiphp_unconfigure_ioapics(acpi_handle handle) | ||
786 | { | ||
787 | ioapic_remove(handle, 0, NULL, NULL); | ||
788 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
789 | ACPI_UINT32_MAX, ioapic_remove, NULL, NULL); | ||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int power_on_slot(struct acpiphp_slot *slot) | 600 | static int power_on_slot(struct acpiphp_slot *slot) |
794 | { | 601 | { |
795 | acpi_status status; | 602 | acpi_status status; |
796 | struct acpiphp_func *func; | 603 | struct acpiphp_func *func; |
797 | struct list_head *l; | ||
798 | int retval = 0; | 604 | int retval = 0; |
799 | 605 | ||
800 | /* if already enabled, just skip */ | 606 | /* if already enabled, just skip */ |
801 | if (slot->flags & SLOT_POWEREDON) | 607 | if (slot->flags & SLOT_POWEREDON) |
802 | goto err_exit; | 608 | goto err_exit; |
803 | 609 | ||
804 | list_for_each (l, &slot->funcs) { | 610 | list_for_each_entry(func, &slot->funcs, sibling) { |
805 | func = list_entry(l, struct acpiphp_func, sibling); | ||
806 | |||
807 | if (func->flags & FUNC_HAS_PS0) { | 611 | if (func->flags & FUNC_HAS_PS0) { |
808 | dbg("%s: executing _PS0\n", __func__); | 612 | dbg("%s: executing _PS0\n", __func__); |
809 | status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); | 613 | status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); |
@@ -829,7 +633,6 @@ static int power_off_slot(struct acpiphp_slot *slot) | |||
829 | { | 633 | { |
830 | acpi_status status; | 634 | acpi_status status; |
831 | struct acpiphp_func *func; | 635 | struct acpiphp_func *func; |
832 | struct list_head *l; | ||
833 | 636 | ||
834 | int retval = 0; | 637 | int retval = 0; |
835 | 638 | ||
@@ -837,9 +640,7 @@ static int power_off_slot(struct acpiphp_slot *slot) | |||
837 | if ((slot->flags & SLOT_POWEREDON) == 0) | 640 | if ((slot->flags & SLOT_POWEREDON) == 0) |
838 | goto err_exit; | 641 | goto err_exit; |
839 | 642 | ||
840 | list_for_each (l, &slot->funcs) { | 643 | list_for_each_entry(func, &slot->funcs, sibling) { |
841 | func = list_entry(l, struct acpiphp_func, sibling); | ||
842 | |||
843 | if (func->flags & FUNC_HAS_PS3) { | 644 | if (func->flags & FUNC_HAS_PS3) { |
844 | status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); | 645 | status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); |
845 | if (ACPI_FAILURE(status)) { | 646 | if (ACPI_FAILURE(status)) { |
@@ -920,12 +721,6 @@ static int acpiphp_bus_add(struct acpiphp_func *func) | |||
920 | -ret_val); | 721 | -ret_val); |
921 | goto acpiphp_bus_add_out; | 722 | goto acpiphp_bus_add_out; |
922 | } | 723 | } |
923 | /* | ||
924 | * try to start anyway. We could have failed to add | ||
925 | * simply because this bus had previously been added | ||
926 | * on another add. Don't bother with the return value | ||
927 | * we just keep going. | ||
928 | */ | ||
929 | ret_val = acpi_bus_start(device); | 724 | ret_val = acpi_bus_start(device); |
930 | 725 | ||
931 | acpiphp_bus_add_out: | 726 | acpiphp_bus_add_out: |
@@ -955,6 +750,24 @@ static int acpiphp_bus_trim(acpi_handle handle) | |||
955 | return retval; | 750 | return retval; |
956 | } | 751 | } |
957 | 752 | ||
753 | static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) | ||
754 | { | ||
755 | struct acpiphp_func *func; | ||
756 | union acpi_object params[2]; | ||
757 | struct acpi_object_list arg_list; | ||
758 | |||
759 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
760 | arg_list.count = 2; | ||
761 | arg_list.pointer = params; | ||
762 | params[0].type = ACPI_TYPE_INTEGER; | ||
763 | params[0].integer.value = ACPI_ADR_SPACE_PCI_CONFIG; | ||
764 | params[1].type = ACPI_TYPE_INTEGER; | ||
765 | params[1].integer.value = 1; | ||
766 | /* _REG is optional, we don't care about if there is failure */ | ||
767 | acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL); | ||
768 | } | ||
769 | } | ||
770 | |||
958 | /** | 771 | /** |
959 | * enable_device - enable, configure a slot | 772 | * enable_device - enable, configure a slot |
960 | * @slot: slot to be enabled | 773 | * @slot: slot to be enabled |
@@ -966,7 +779,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
966 | { | 779 | { |
967 | struct pci_dev *dev; | 780 | struct pci_dev *dev; |
968 | struct pci_bus *bus = slot->bridge->pci_bus; | 781 | struct pci_bus *bus = slot->bridge->pci_bus; |
969 | struct list_head *l; | ||
970 | struct acpiphp_func *func; | 782 | struct acpiphp_func *func; |
971 | int retval = 0; | 783 | int retval = 0; |
972 | int num, max, pass; | 784 | int num, max, pass; |
@@ -1006,21 +818,17 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
1006 | } | 818 | } |
1007 | } | 819 | } |
1008 | 820 | ||
1009 | list_for_each (l, &slot->funcs) { | 821 | list_for_each_entry(func, &slot->funcs, sibling) |
1010 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1011 | acpiphp_bus_add(func); | 822 | acpiphp_bus_add(func); |
1012 | } | ||
1013 | 823 | ||
1014 | pci_bus_assign_resources(bus); | 824 | pci_bus_assign_resources(bus); |
1015 | acpiphp_sanitize_bus(bus); | 825 | acpiphp_sanitize_bus(bus); |
1016 | acpiphp_set_hpp_values(bus); | 826 | acpiphp_set_hpp_values(bus); |
1017 | list_for_each_entry(func, &slot->funcs, sibling) | 827 | acpiphp_set_acpi_region(slot); |
1018 | acpiphp_configure_ioapics(func->handle); | ||
1019 | pci_enable_bridges(bus); | 828 | pci_enable_bridges(bus); |
1020 | pci_bus_add_devices(bus); | 829 | pci_bus_add_devices(bus); |
1021 | 830 | ||
1022 | list_for_each (l, &slot->funcs) { | 831 | list_for_each_entry(func, &slot->funcs, sibling) { |
1023 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1024 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, | 832 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, |
1025 | func->function)); | 833 | func->function)); |
1026 | if (!dev) | 834 | if (!dev) |
@@ -1091,7 +899,6 @@ static int disable_device(struct acpiphp_slot *slot) | |||
1091 | } | 899 | } |
1092 | 900 | ||
1093 | list_for_each_entry(func, &slot->funcs, sibling) { | 901 | list_for_each_entry(func, &slot->funcs, sibling) { |
1094 | acpiphp_unconfigure_ioapics(func->handle); | ||
1095 | acpiphp_bus_trim(func->handle); | 902 | acpiphp_bus_trim(func->handle); |
1096 | } | 903 | } |
1097 | 904 | ||
@@ -1119,12 +926,9 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) | |||
1119 | acpi_status status; | 926 | acpi_status status; |
1120 | unsigned long long sta = 0; | 927 | unsigned long long sta = 0; |
1121 | u32 dvid; | 928 | u32 dvid; |
1122 | struct list_head *l; | ||
1123 | struct acpiphp_func *func; | 929 | struct acpiphp_func *func; |
1124 | 930 | ||
1125 | list_for_each (l, &slot->funcs) { | 931 | list_for_each_entry(func, &slot->funcs, sibling) { |
1126 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1127 | |||
1128 | if (func->flags & FUNC_HAS_STA) { | 932 | if (func->flags & FUNC_HAS_STA) { |
1129 | status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); | 933 | status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); |
1130 | if (ACPI_SUCCESS(status) && sta) | 934 | if (ACPI_SUCCESS(status) && sta) |
@@ -1152,13 +956,10 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) | |||
1152 | { | 956 | { |
1153 | acpi_status status; | 957 | acpi_status status; |
1154 | struct acpiphp_func *func; | 958 | struct acpiphp_func *func; |
1155 | struct list_head *l; | ||
1156 | struct acpi_object_list arg_list; | 959 | struct acpi_object_list arg_list; |
1157 | union acpi_object arg; | 960 | union acpi_object arg; |
1158 | 961 | ||
1159 | list_for_each (l, &slot->funcs) { | 962 | list_for_each_entry(func, &slot->funcs, sibling) { |
1160 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1161 | |||
1162 | /* We don't want to call _EJ0 on non-existing functions. */ | 963 | /* We don't want to call _EJ0 on non-existing functions. */ |
1163 | if ((func->flags & FUNC_HAS_EJ0)) { | 964 | if ((func->flags & FUNC_HAS_EJ0)) { |
1164 | /* _EJ0 method take one argument */ | 965 | /* _EJ0 method take one argument */ |
@@ -1275,7 +1076,6 @@ static int acpiphp_configure_bridge (acpi_handle handle) | |||
1275 | acpiphp_sanitize_bus(bus); | 1076 | acpiphp_sanitize_bus(bus); |
1276 | acpiphp_set_hpp_values(bus); | 1077 | acpiphp_set_hpp_values(bus); |
1277 | pci_enable_bridges(bus); | 1078 | pci_enable_bridges(bus); |
1278 | acpiphp_configure_ioapics(handle); | ||
1279 | return 0; | 1079 | return 0; |
1280 | } | 1080 | } |
1281 | 1081 | ||
@@ -1367,7 +1167,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1367 | bridge = acpiphp_handle_to_bridge(handle); | 1167 | bridge = acpiphp_handle_to_bridge(handle); |
1368 | if (type == ACPI_NOTIFY_BUS_CHECK) { | 1168 | if (type == ACPI_NOTIFY_BUS_CHECK) { |
1369 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, | 1169 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, |
1370 | count_sub_bridges, &num_sub_bridges, NULL); | 1170 | count_sub_bridges, NULL, &num_sub_bridges, NULL); |
1371 | } | 1171 | } |
1372 | 1172 | ||
1373 | if (!bridge && !num_sub_bridges) { | 1173 | if (!bridge && !num_sub_bridges) { |
@@ -1388,7 +1188,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1388 | } | 1188 | } |
1389 | if (num_sub_bridges) | 1189 | if (num_sub_bridges) |
1390 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 1190 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
1391 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL); | 1191 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); |
1392 | break; | 1192 | break; |
1393 | 1193 | ||
1394 | case ACPI_NOTIFY_DEVICE_CHECK: | 1194 | case ACPI_NOTIFY_DEVICE_CHECK: |
@@ -1512,7 +1312,7 @@ int __init acpiphp_glue_init(void) | |||
1512 | int num = 0; | 1312 | int num = 0; |
1513 | 1313 | ||
1514 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 1314 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1515 | ACPI_UINT32_MAX, find_root_bridges, &num, NULL); | 1315 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); |
1516 | 1316 | ||
1517 | if (num <= 0) | 1317 | if (num <= 0) |
1518 | return -1; | 1318 | return -1; |
@@ -1542,7 +1342,7 @@ int __init acpiphp_get_num_slots(void) | |||
1542 | struct acpiphp_bridge *bridge; | 1342 | struct acpiphp_bridge *bridge; |
1543 | int num_slots = 0; | 1343 | int num_slots = 0; |
1544 | 1344 | ||
1545 | list_for_each_entry (bridge, &bridge_list, list) { | 1345 | list_for_each_entry(bridge, &bridge_list, list) { |
1546 | dbg("Bus %04x:%02x has %d slot%s\n", | 1346 | dbg("Bus %04x:%02x has %d slot%s\n", |
1547 | pci_domain_nr(bridge->pci_bus), | 1347 | pci_domain_nr(bridge->pci_bus), |
1548 | bridge->pci_bus->number, bridge->nr_slots, | 1348 | bridge->pci_bus->number, bridge->nr_slots, |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index e7be66dbac21..6ecbfb27db9d 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
31 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
@@ -434,7 +435,7 @@ static int __init ibm_acpiphp_init(void) | |||
434 | dbg("%s\n", __func__); | 435 | dbg("%s\n", __func__); |
435 | 436 | ||
436 | if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 437 | if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
437 | ACPI_UINT32_MAX, ibm_find_acpi_device, | 438 | ACPI_UINT32_MAX, ibm_find_acpi_device, NULL, |
438 | &ibm_acpi_handle, NULL) != FOUND_APCI) { | 439 | &ibm_acpi_handle, NULL) != FOUND_APCI) { |
439 | err("%s: acpi_walk_namespace failed\n", __func__); | 440 | err("%s: acpi_walk_namespace failed\n", __func__); |
440 | retval = -ENODEV; | 441 | retval = -ENODEV; |
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index 148fb463b81c..fb3f84661bdc 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c | |||
@@ -162,6 +162,7 @@ static int __init cpcihp_generic_init(void) | |||
162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); | 162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); |
163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
164 | err("Invalid bridge device %s", bridge); | 164 | err("Invalid bridge device %s", bridge); |
165 | pci_dev_put(dev); | ||
165 | return -EINVAL; | 166 | return -EINVAL; |
166 | } | 167 | } |
167 | bus = dev->subordinate; | 168 | bus = dev->subordinate; |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 9c6a9fd26812..d8ffc7366801 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -310,8 +310,6 @@ struct controller { | |||
310 | u8 first_slot; | 310 | u8 first_slot; |
311 | u8 add_support; | 311 | u8 add_support; |
312 | u8 push_flag; | 312 | u8 push_flag; |
313 | enum pci_bus_speed speed; | ||
314 | enum pci_bus_speed speed_capability; | ||
315 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ | 313 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ |
316 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ | 314 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ |
317 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ | 315 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 075b4f4b6e0d..f184d1d2ecbe 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -583,30 +583,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
583 | return 0; | 583 | return 0; |
584 | } | 584 | } |
585 | 585 | ||
586 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
587 | { | ||
588 | struct slot *slot = hotplug_slot->private; | ||
589 | struct controller *ctrl = slot->ctrl; | ||
590 | |||
591 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
592 | |||
593 | *value = ctrl->speed_capability; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
599 | { | ||
600 | struct slot *slot = hotplug_slot->private; | ||
601 | struct controller *ctrl = slot->ctrl; | ||
602 | |||
603 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
604 | |||
605 | *value = ctrl->speed; | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | 586 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { |
611 | .set_attention_status = set_attention_status, | 587 | .set_attention_status = set_attention_status, |
612 | .enable_slot = process_SI, | 588 | .enable_slot = process_SI, |
@@ -616,8 +592,6 @@ static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | |||
616 | .get_attention_status = get_attention_status, | 592 | .get_attention_status = get_attention_status, |
617 | .get_latch_status = get_latch_status, | 593 | .get_latch_status = get_latch_status, |
618 | .get_adapter_status = get_adapter_status, | 594 | .get_adapter_status = get_adapter_status, |
619 | .get_max_bus_speed = get_max_bus_speed, | ||
620 | .get_cur_bus_speed = get_cur_bus_speed, | ||
621 | }; | 595 | }; |
622 | 596 | ||
623 | #define SLOT_NAME_SIZE 10 | 597 | #define SLOT_NAME_SIZE 10 |
@@ -629,6 +603,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
629 | struct slot *slot; | 603 | struct slot *slot; |
630 | struct hotplug_slot *hotplug_slot; | 604 | struct hotplug_slot *hotplug_slot; |
631 | struct hotplug_slot_info *hotplug_slot_info; | 605 | struct hotplug_slot_info *hotplug_slot_info; |
606 | struct pci_bus *bus = ctrl->pci_bus; | ||
632 | u8 number_of_slots; | 607 | u8 number_of_slots; |
633 | u8 slot_device; | 608 | u8 slot_device; |
634 | u8 slot_number; | 609 | u8 slot_number; |
@@ -694,7 +669,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
694 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | 669 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; |
695 | if (is_slot66mhz(slot)) | 670 | if (is_slot66mhz(slot)) |
696 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | 671 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; |
697 | if (ctrl->speed == PCI_SPEED_66MHz) | 672 | if (bus->cur_bus_speed == PCI_SPEED_66MHz) |
698 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | 673 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; |
699 | 674 | ||
700 | ctrl_slot = | 675 | ctrl_slot = |
@@ -844,6 +819,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
844 | u32 rc; | 819 | u32 rc; |
845 | struct controller *ctrl; | 820 | struct controller *ctrl; |
846 | struct pci_func *func; | 821 | struct pci_func *func; |
822 | struct pci_bus *bus; | ||
847 | int err; | 823 | int err; |
848 | 824 | ||
849 | err = pci_enable_device(pdev); | 825 | err = pci_enable_device(pdev); |
@@ -852,6 +828,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
852 | pci_name(pdev), err); | 828 | pci_name(pdev), err); |
853 | return err; | 829 | return err; |
854 | } | 830 | } |
831 | bus = pdev->subordinate; | ||
855 | 832 | ||
856 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC | 833 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC |
857 | * discovery | 834 | * discovery |
@@ -929,22 +906,22 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
929 | pci_read_config_byte(pdev, 0x41, &bus_cap); | 906 | pci_read_config_byte(pdev, 0x41, &bus_cap); |
930 | if (bus_cap & 0x80) { | 907 | if (bus_cap & 0x80) { |
931 | dbg("bus max supports 133MHz PCI-X\n"); | 908 | dbg("bus max supports 133MHz PCI-X\n"); |
932 | ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; | 909 | bus->max_bus_speed = PCI_SPEED_133MHz_PCIX; |
933 | break; | 910 | break; |
934 | } | 911 | } |
935 | if (bus_cap & 0x40) { | 912 | if (bus_cap & 0x40) { |
936 | dbg("bus max supports 100MHz PCI-X\n"); | 913 | dbg("bus max supports 100MHz PCI-X\n"); |
937 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 914 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
938 | break; | 915 | break; |
939 | } | 916 | } |
940 | if (bus_cap & 20) { | 917 | if (bus_cap & 20) { |
941 | dbg("bus max supports 66MHz PCI-X\n"); | 918 | dbg("bus max supports 66MHz PCI-X\n"); |
942 | ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; | 919 | bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; |
943 | break; | 920 | break; |
944 | } | 921 | } |
945 | if (bus_cap & 10) { | 922 | if (bus_cap & 10) { |
946 | dbg("bus max supports 66MHz PCI\n"); | 923 | dbg("bus max supports 66MHz PCI\n"); |
947 | ctrl->speed_capability = PCI_SPEED_66MHz; | 924 | bus->max_bus_speed = PCI_SPEED_66MHz; |
948 | break; | 925 | break; |
949 | } | 926 | } |
950 | 927 | ||
@@ -955,7 +932,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
955 | case PCI_SUB_HPC_ID: | 932 | case PCI_SUB_HPC_ID: |
956 | /* Original 6500/7000 implementation */ | 933 | /* Original 6500/7000 implementation */ |
957 | ctrl->slot_switch_type = 1; | 934 | ctrl->slot_switch_type = 1; |
958 | ctrl->speed_capability = PCI_SPEED_33MHz; | 935 | bus->max_bus_speed = PCI_SPEED_33MHz; |
959 | ctrl->push_button = 0; | 936 | ctrl->push_button = 0; |
960 | ctrl->pci_config_space = 1; | 937 | ctrl->pci_config_space = 1; |
961 | ctrl->defeature_PHP = 1; | 938 | ctrl->defeature_PHP = 1; |
@@ -966,7 +943,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
966 | /* First Pushbutton implementation */ | 943 | /* First Pushbutton implementation */ |
967 | ctrl->push_flag = 1; | 944 | ctrl->push_flag = 1; |
968 | ctrl->slot_switch_type = 1; | 945 | ctrl->slot_switch_type = 1; |
969 | ctrl->speed_capability = PCI_SPEED_33MHz; | 946 | bus->max_bus_speed = PCI_SPEED_33MHz; |
970 | ctrl->push_button = 1; | 947 | ctrl->push_button = 1; |
971 | ctrl->pci_config_space = 1; | 948 | ctrl->pci_config_space = 1; |
972 | ctrl->defeature_PHP = 1; | 949 | ctrl->defeature_PHP = 1; |
@@ -976,7 +953,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
976 | case PCI_SUB_HPC_ID_INTC: | 953 | case PCI_SUB_HPC_ID_INTC: |
977 | /* Third party (6500/7000) */ | 954 | /* Third party (6500/7000) */ |
978 | ctrl->slot_switch_type = 1; | 955 | ctrl->slot_switch_type = 1; |
979 | ctrl->speed_capability = PCI_SPEED_33MHz; | 956 | bus->max_bus_speed = PCI_SPEED_33MHz; |
980 | ctrl->push_button = 0; | 957 | ctrl->push_button = 0; |
981 | ctrl->pci_config_space = 1; | 958 | ctrl->pci_config_space = 1; |
982 | ctrl->defeature_PHP = 1; | 959 | ctrl->defeature_PHP = 1; |
@@ -987,7 +964,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
987 | /* First 66 Mhz implementation */ | 964 | /* First 66 Mhz implementation */ |
988 | ctrl->push_flag = 1; | 965 | ctrl->push_flag = 1; |
989 | ctrl->slot_switch_type = 1; | 966 | ctrl->slot_switch_type = 1; |
990 | ctrl->speed_capability = PCI_SPEED_66MHz; | 967 | bus->max_bus_speed = PCI_SPEED_66MHz; |
991 | ctrl->push_button = 1; | 968 | ctrl->push_button = 1; |
992 | ctrl->pci_config_space = 1; | 969 | ctrl->pci_config_space = 1; |
993 | ctrl->defeature_PHP = 1; | 970 | ctrl->defeature_PHP = 1; |
@@ -998,7 +975,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
998 | /* First PCI-X implementation, 100MHz */ | 975 | /* First PCI-X implementation, 100MHz */ |
999 | ctrl->push_flag = 1; | 976 | ctrl->push_flag = 1; |
1000 | ctrl->slot_switch_type = 1; | 977 | ctrl->slot_switch_type = 1; |
1001 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 978 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
1002 | ctrl->push_button = 1; | 979 | ctrl->push_button = 1; |
1003 | ctrl->pci_config_space = 1; | 980 | ctrl->pci_config_space = 1; |
1004 | ctrl->defeature_PHP = 1; | 981 | ctrl->defeature_PHP = 1; |
@@ -1015,9 +992,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1015 | case PCI_VENDOR_ID_INTEL: | 992 | case PCI_VENDOR_ID_INTEL: |
1016 | /* Check for speed capability (0=33, 1=66) */ | 993 | /* Check for speed capability (0=33, 1=66) */ |
1017 | if (subsystem_deviceid & 0x0001) | 994 | if (subsystem_deviceid & 0x0001) |
1018 | ctrl->speed_capability = PCI_SPEED_66MHz; | 995 | bus->max_bus_speed = PCI_SPEED_66MHz; |
1019 | else | 996 | else |
1020 | ctrl->speed_capability = PCI_SPEED_33MHz; | 997 | bus->max_bus_speed = PCI_SPEED_33MHz; |
1021 | 998 | ||
1022 | /* Check for push button */ | 999 | /* Check for push button */ |
1023 | if (subsystem_deviceid & 0x0002) | 1000 | if (subsystem_deviceid & 0x0002) |
@@ -1079,7 +1056,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1079 | pdev->bus->number); | 1056 | pdev->bus->number); |
1080 | 1057 | ||
1081 | dbg("Hotplug controller capabilities:\n"); | 1058 | dbg("Hotplug controller capabilities:\n"); |
1082 | dbg(" speed_capability %d\n", ctrl->speed_capability); | 1059 | dbg(" speed_capability %d\n", bus->max_bus_speed); |
1083 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? | 1060 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? |
1084 | "switch present" : "no switch"); | 1061 | "switch present" : "no switch"); |
1085 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? | 1062 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? |
@@ -1142,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1142 | } | 1119 | } |
1143 | 1120 | ||
1144 | /* Check for 66Mhz operation */ | 1121 | /* Check for 66Mhz operation */ |
1145 | ctrl->speed = get_controller_speed(ctrl); | 1122 | bus->cur_bus_speed = get_controller_speed(ctrl); |
1146 | 1123 | ||
1147 | 1124 | ||
1148 | /******************************************************** | 1125 | /******************************************************** |
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 0ff689afa757..e43908d9b5df 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -1130,12 +1130,13 @@ static int is_bridge(struct pci_func * func) | |||
1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) | 1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) |
1131 | { | 1131 | { |
1132 | struct slot *slot; | 1132 | struct slot *slot; |
1133 | struct pci_bus *bus = ctrl->pci_bus; | ||
1133 | u8 reg; | 1134 | u8 reg; |
1134 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); | 1135 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); |
1135 | u16 reg16; | 1136 | u16 reg16; |
1136 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); | 1137 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); |
1137 | 1138 | ||
1138 | if (ctrl->speed == adapter_speed) | 1139 | if (bus->cur_bus_speed == adapter_speed) |
1139 | return 0; | 1140 | return 0; |
1140 | 1141 | ||
1141 | /* We don't allow freq/mode changes if we find another adapter running | 1142 | /* We don't allow freq/mode changes if we find another adapter running |
@@ -1152,7 +1153,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1152 | * lower speed/mode, we allow the new adapter to function at | 1153 | * lower speed/mode, we allow the new adapter to function at |
1153 | * this rate if supported | 1154 | * this rate if supported |
1154 | */ | 1155 | */ |
1155 | if (ctrl->speed < adapter_speed) | 1156 | if (bus->cur_bus_speed < adapter_speed) |
1156 | return 0; | 1157 | return 0; |
1157 | 1158 | ||
1158 | return 1; | 1159 | return 1; |
@@ -1161,20 +1162,20 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1161 | /* If the controller doesn't support freq/mode changes and the | 1162 | /* If the controller doesn't support freq/mode changes and the |
1162 | * controller is running at a higher mode, we bail | 1163 | * controller is running at a higher mode, we bail |
1163 | */ | 1164 | */ |
1164 | if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) | 1165 | if ((bus->cur_bus_speed > adapter_speed) && (!ctrl->pcix_speed_capability)) |
1165 | return 1; | 1166 | return 1; |
1166 | 1167 | ||
1167 | /* But we allow the adapter to run at a lower rate if possible */ | 1168 | /* But we allow the adapter to run at a lower rate if possible */ |
1168 | if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) | 1169 | if ((bus->cur_bus_speed < adapter_speed) && (!ctrl->pcix_speed_capability)) |
1169 | return 0; | 1170 | return 0; |
1170 | 1171 | ||
1171 | /* We try to set the max speed supported by both the adapter and | 1172 | /* We try to set the max speed supported by both the adapter and |
1172 | * controller | 1173 | * controller |
1173 | */ | 1174 | */ |
1174 | if (ctrl->speed_capability < adapter_speed) { | 1175 | if (bus->max_bus_speed < adapter_speed) { |
1175 | if (ctrl->speed == ctrl->speed_capability) | 1176 | if (bus->cur_bus_speed == bus->max_bus_speed) |
1176 | return 0; | 1177 | return 0; |
1177 | adapter_speed = ctrl->speed_capability; | 1178 | adapter_speed = bus->max_bus_speed; |
1178 | } | 1179 | } |
1179 | 1180 | ||
1180 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); | 1181 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); |
@@ -1229,8 +1230,8 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1229 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); | 1230 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); |
1230 | 1231 | ||
1231 | /* Only if mode change...*/ | 1232 | /* Only if mode change...*/ |
1232 | if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || | 1233 | if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || |
1233 | ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) | 1234 | ((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) |
1234 | set_SOGO(ctrl); | 1235 | set_SOGO(ctrl); |
1235 | 1236 | ||
1236 | wait_for_ctrl_irq(ctrl); | 1237 | wait_for_ctrl_irq(ctrl); |
@@ -1243,7 +1244,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1243 | set_SOGO(ctrl); | 1244 | set_SOGO(ctrl); |
1244 | wait_for_ctrl_irq(ctrl); | 1245 | wait_for_ctrl_irq(ctrl); |
1245 | 1246 | ||
1246 | ctrl->speed = adapter_speed; | 1247 | bus->cur_bus_speed = adapter_speed; |
1247 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 1248 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
1248 | 1249 | ||
1249 | info("Successfully changed frequency/mode for adapter in slot %d\n", | 1250 | info("Successfully changed frequency/mode for adapter in slot %d\n", |
@@ -1269,6 +1270,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1269 | */ | 1270 | */ |
1270 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | 1271 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) |
1271 | { | 1272 | { |
1273 | struct pci_bus *bus = ctrl->pci_bus; | ||
1272 | u8 hp_slot; | 1274 | u8 hp_slot; |
1273 | u8 temp_byte; | 1275 | u8 temp_byte; |
1274 | u8 adapter_speed; | 1276 | u8 adapter_speed; |
@@ -1309,7 +1311,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1309 | wait_for_ctrl_irq (ctrl); | 1311 | wait_for_ctrl_irq (ctrl); |
1310 | 1312 | ||
1311 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1313 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
1312 | if (ctrl->speed != adapter_speed) | 1314 | if (bus->cur_bus_speed != adapter_speed) |
1313 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1315 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
1314 | rc = WRONG_BUS_FREQUENCY; | 1316 | rc = WRONG_BUS_FREQUENCY; |
1315 | 1317 | ||
@@ -1426,6 +1428,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1426 | u32 temp_register = 0xFFFFFFFF; | 1428 | u32 temp_register = 0xFFFFFFFF; |
1427 | u32 rc = 0; | 1429 | u32 rc = 0; |
1428 | struct pci_func *new_slot = NULL; | 1430 | struct pci_func *new_slot = NULL; |
1431 | struct pci_bus *bus = ctrl->pci_bus; | ||
1429 | struct slot *p_slot; | 1432 | struct slot *p_slot; |
1430 | struct resource_lists res_lists; | 1433 | struct resource_lists res_lists; |
1431 | 1434 | ||
@@ -1456,7 +1459,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1456 | wait_for_ctrl_irq (ctrl); | 1459 | wait_for_ctrl_irq (ctrl); |
1457 | 1460 | ||
1458 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1461 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
1459 | if (ctrl->speed != adapter_speed) | 1462 | if (bus->cur_bus_speed != adapter_speed) |
1460 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1463 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
1461 | rc = WRONG_BUS_FREQUENCY; | 1464 | rc = WRONG_BUS_FREQUENCY; |
1462 | 1465 | ||
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index e6089bdb6e5b..56215322930a 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/slab.h> | ||
31 | #include <linux/types.h> | 32 | #include <linux/types.h> |
32 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
33 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 6151389fd903..5317e4d7d96e 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/slab.h> | ||
22 | #include "../pci.h" | 23 | #include "../pci.h" |
23 | 24 | ||
24 | struct legacy_slot { | 25 | struct legacy_slot { |
@@ -73,7 +74,7 @@ static void legacy_release(struct kobject *kobj) | |||
73 | } | 74 | } |
74 | 75 | ||
75 | static struct kobj_type legacy_ktype = { | 76 | static struct kobj_type legacy_ktype = { |
76 | .sysfs_ops = &(struct sysfs_ops){ | 77 | .sysfs_ops = &(const struct sysfs_ops){ |
77 | .store = legacy_store, .show = legacy_show | 78 | .store = legacy_store, .show = legacy_show |
78 | }, | 79 | }, |
79 | .release = &legacy_release, | 80 | .release = &legacy_release, |
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 7485ffda950c..d934dd4fa873 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -395,89 +395,40 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) | |||
395 | return rc; | 395 | return rc; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 398 | static int get_max_bus_speed(struct slot *slot) |
399 | { | 399 | { |
400 | int rc = -ENODEV; | 400 | int rc; |
401 | struct slot *pslot; | ||
402 | u8 mode = 0; | 401 | u8 mode = 0; |
402 | enum pci_bus_speed speed; | ||
403 | struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; | ||
403 | 404 | ||
404 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 405 | debug("%s - Entry slot[%p]\n", __func__, slot); |
405 | hotplug_slot, value); | ||
406 | 406 | ||
407 | ibmphp_lock_operations(); | 407 | ibmphp_lock_operations(); |
408 | 408 | mode = slot->supported_bus_mode; | |
409 | if (hotplug_slot) { | 409 | speed = slot->supported_speed; |
410 | pslot = hotplug_slot->private; | ||
411 | if (pslot) { | ||
412 | rc = 0; | ||
413 | mode = pslot->supported_bus_mode; | ||
414 | *value = pslot->supported_speed; | ||
415 | switch (*value) { | ||
416 | case BUS_SPEED_33: | ||
417 | break; | ||
418 | case BUS_SPEED_66: | ||
419 | if (mode == BUS_MODE_PCIX) | ||
420 | *value += 0x01; | ||
421 | break; | ||
422 | case BUS_SPEED_100: | ||
423 | case BUS_SPEED_133: | ||
424 | *value = pslot->supported_speed + 0x01; | ||
425 | break; | ||
426 | default: | ||
427 | /* Note (will need to change): there would be soon 256, 512 also */ | ||
428 | rc = -ENODEV; | ||
429 | } | ||
430 | } | ||
431 | } | ||
432 | |||
433 | ibmphp_unlock_operations(); | 410 | ibmphp_unlock_operations(); |
434 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | ||
435 | return rc; | ||
436 | } | ||
437 | 411 | ||
438 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 412 | switch (speed) { |
439 | { | 413 | case BUS_SPEED_33: |
440 | int rc = -ENODEV; | 414 | break; |
441 | struct slot *pslot; | 415 | case BUS_SPEED_66: |
442 | u8 mode = 0; | 416 | if (mode == BUS_MODE_PCIX) |
443 | 417 | speed += 0x01; | |
444 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 418 | break; |
445 | hotplug_slot, value); | 419 | case BUS_SPEED_100: |
446 | 420 | case BUS_SPEED_133: | |
447 | ibmphp_lock_operations(); | 421 | speed += 0x01; |
448 | 422 | break; | |
449 | if (hotplug_slot) { | 423 | default: |
450 | pslot = hotplug_slot->private; | 424 | /* Note (will need to change): there would be soon 256, 512 also */ |
451 | if (pslot) { | 425 | rc = -ENODEV; |
452 | rc = get_cur_bus_info(&pslot); | ||
453 | if (!rc) { | ||
454 | mode = pslot->bus_on->current_bus_mode; | ||
455 | *value = pslot->bus_on->current_speed; | ||
456 | switch (*value) { | ||
457 | case BUS_SPEED_33: | ||
458 | break; | ||
459 | case BUS_SPEED_66: | ||
460 | if (mode == BUS_MODE_PCIX) | ||
461 | *value += 0x01; | ||
462 | else if (mode == BUS_MODE_PCI) | ||
463 | ; | ||
464 | else | ||
465 | *value = PCI_SPEED_UNKNOWN; | ||
466 | break; | ||
467 | case BUS_SPEED_100: | ||
468 | case BUS_SPEED_133: | ||
469 | *value += 0x01; | ||
470 | break; | ||
471 | default: | ||
472 | /* Note of change: there would also be 256, 512 soon */ | ||
473 | rc = -ENODEV; | ||
474 | } | ||
475 | } | ||
476 | } | ||
477 | } | 426 | } |
478 | 427 | ||
479 | ibmphp_unlock_operations(); | 428 | if (!rc) |
480 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | 429 | bus->max_bus_speed = speed; |
430 | |||
431 | debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); | ||
481 | return rc; | 432 | return rc; |
482 | } | 433 | } |
483 | 434 | ||
@@ -572,6 +523,7 @@ static int __init init_ops(void) | |||
572 | if (slot_cur->bus_on->current_speed == 0xFF) | 523 | if (slot_cur->bus_on->current_speed == 0xFF) |
573 | if (get_cur_bus_info(&slot_cur)) | 524 | if (get_cur_bus_info(&slot_cur)) |
574 | return -1; | 525 | return -1; |
526 | get_max_bus_speed(slot_cur); | ||
575 | 527 | ||
576 | if (slot_cur->ctrl->options == 0xFF) | 528 | if (slot_cur->ctrl->options == 0xFF) |
577 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) | 529 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) |
@@ -655,6 +607,7 @@ static int validate(struct slot *slot_cur, int opn) | |||
655 | int ibmphp_update_slot_info(struct slot *slot_cur) | 607 | int ibmphp_update_slot_info(struct slot *slot_cur) |
656 | { | 608 | { |
657 | struct hotplug_slot_info *info; | 609 | struct hotplug_slot_info *info; |
610 | struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus; | ||
658 | int rc; | 611 | int rc; |
659 | u8 bus_speed; | 612 | u8 bus_speed; |
660 | u8 mode; | 613 | u8 mode; |
@@ -700,8 +653,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) | |||
700 | bus_speed = PCI_SPEED_UNKNOWN; | 653 | bus_speed = PCI_SPEED_UNKNOWN; |
701 | } | 654 | } |
702 | 655 | ||
703 | info->cur_bus_speed = bus_speed; | 656 | bus->cur_bus_speed = bus_speed; |
704 | info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; | ||
705 | // To do: bus_names | 657 | // To do: bus_names |
706 | 658 | ||
707 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); | 659 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); |
@@ -1326,8 +1278,6 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { | |||
1326 | .get_attention_status = get_attention_status, | 1278 | .get_attention_status = get_attention_status, |
1327 | .get_latch_status = get_latch_status, | 1279 | .get_latch_status = get_latch_status, |
1328 | .get_adapter_status = get_adapter_present, | 1280 | .get_adapter_status = get_adapter_present, |
1329 | .get_max_bus_speed = get_max_bus_speed, | ||
1330 | .get_cur_bus_speed = get_cur_bus_speed, | ||
1331 | /* .get_max_adapter_speed = get_max_adapter_speed, | 1281 | /* .get_max_adapter_speed = get_max_adapter_speed, |
1332 | .get_bus_name_status = get_bus_name, | 1282 | .get_bus_name_status = get_bus_name, |
1333 | */ | 1283 | */ |
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index c1abac8ab5c3..5becbdee4027 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c | |||
@@ -245,7 +245,7 @@ static void __init print_ebda_hpc (void) | |||
245 | 245 | ||
246 | int __init ibmphp_access_ebda (void) | 246 | int __init ibmphp_access_ebda (void) |
247 | { | 247 | { |
248 | u8 format, num_ctlrs, rio_complete, hs_complete; | 248 | u8 format, num_ctlrs, rio_complete, hs_complete, ebda_sz; |
249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; | 249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; |
250 | int rc = 0; | 250 | int rc = 0; |
251 | 251 | ||
@@ -260,7 +260,16 @@ int __init ibmphp_access_ebda (void) | |||
260 | iounmap (io_mem); | 260 | iounmap (io_mem); |
261 | debug ("returned ebda segment: %x\n", ebda_seg); | 261 | debug ("returned ebda segment: %x\n", ebda_seg); |
262 | 262 | ||
263 | io_mem = ioremap(ebda_seg<<4, 1024); | 263 | io_mem = ioremap(ebda_seg<<4, 1); |
264 | if (!io_mem) | ||
265 | return -ENOMEM; | ||
266 | ebda_sz = readb(io_mem); | ||
267 | iounmap(io_mem); | ||
268 | debug("ebda size: %d(KiB)\n", ebda_sz); | ||
269 | if (ebda_sz == 0) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | io_mem = ioremap(ebda_seg<<4, (ebda_sz * 1024)); | ||
264 | if (!io_mem ) | 273 | if (!io_mem ) |
265 | return -ENOMEM; | 274 | return -ENOMEM; |
266 | next_offset = 0x180; | 275 | next_offset = 0x180; |
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 83f337c891a9..1aaf3f32d3cd 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
38 | #include <linux/semaphore.h> | ||
38 | #include <linux/kthread.h> | 39 | #include <linux/kthread.h> |
39 | #include "ibmphp.h" | 40 | #include "ibmphp.h" |
40 | 41 | ||
@@ -890,7 +891,7 @@ static int poll_hpc(void *data) | |||
890 | msleep(POLL_INTERVAL_SEC * 1000); | 891 | msleep(POLL_INTERVAL_SEC * 1000); |
891 | 892 | ||
892 | if (kthread_should_stop()) | 893 | if (kthread_should_stop()) |
893 | break; | 894 | goto out_sleep; |
894 | 895 | ||
895 | down (&semOperations); | 896 | down (&semOperations); |
896 | 897 | ||
@@ -904,6 +905,7 @@ static int poll_hpc(void *data) | |||
904 | /* give up the hardware semaphore */ | 905 | /* give up the hardware semaphore */ |
905 | up (&semOperations); | 906 | up (&semOperations); |
906 | /* sleep for a short time just for good measure */ | 907 | /* sleep for a short time just for good measure */ |
908 | out_sleep: | ||
907 | msleep(100); | 909 | msleep(100); |
908 | } | 910 | } |
909 | up (&sem_exit); | 911 | up (&sem_exit); |
diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index ec73294d1fa6..e2dc289f767c 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c | |||
@@ -40,7 +40,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno); | |||
40 | static int once_over (void); | 40 | static int once_over (void); |
41 | static int remove_ranges (struct bus_node *, struct bus_node *); | 41 | static int remove_ranges (struct bus_node *, struct bus_node *); |
42 | static int update_bridge_ranges (struct bus_node **); | 42 | static int update_bridge_ranges (struct bus_node **); |
43 | static int add_range (int type, struct range_node *, struct bus_node *); | 43 | static int add_bus_range (int type, struct range_node *, struct bus_node *); |
44 | static void fix_resources (struct bus_node *); | 44 | static void fix_resources (struct bus_node *); |
45 | static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); | 45 | static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); |
46 | 46 | ||
@@ -133,7 +133,7 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node | |||
133 | newrange->rangeno = 1; | 133 | newrange->rangeno = 1; |
134 | else { | 134 | else { |
135 | /* need to insert our range */ | 135 | /* need to insert our range */ |
136 | add_range (flag, newrange, newbus); | 136 | add_bus_range (flag, newrange, newbus); |
137 | debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end); | 137 | debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end); |
138 | } | 138 | } |
139 | 139 | ||
@@ -384,7 +384,7 @@ int __init ibmphp_rsrc_init (void) | |||
384 | * Input: type of the resource, range to add, current bus | 384 | * Input: type of the resource, range to add, current bus |
385 | * Output: 0 or -1, bus and range ptrs | 385 | * Output: 0 or -1, bus and range ptrs |
386 | ********************************************************************************/ | 386 | ********************************************************************************/ |
387 | static int add_range (int type, struct range_node *range, struct bus_node *bus_cur) | 387 | static int add_bus_range (int type, struct range_node *range, struct bus_node *bus_cur) |
388 | { | 388 | { |
389 | struct range_node *range_cur = NULL; | 389 | struct range_node *range_cur = NULL; |
390 | struct range_node *range_prev; | 390 | struct range_node *range_prev; |
@@ -455,7 +455,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c | |||
455 | 455 | ||
456 | /******************************************************************************* | 456 | /******************************************************************************* |
457 | * This routine goes through the list of resources of type 'type' and updates | 457 | * This routine goes through the list of resources of type 'type' and updates |
458 | * the range numbers that they correspond to. It was called from add_range fnc | 458 | * the range numbers that they correspond to. It was called from add_bus_range fnc |
459 | * | 459 | * |
460 | * Input: bus, type of the resource, the rangeno starting from which to update | 460 | * Input: bus, type of the resource, the rangeno starting from which to update |
461 | ******************************************************************************/ | 461 | ******************************************************************************/ |
@@ -1999,7 +1999,7 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
1999 | 1999 | ||
2000 | if (bus_sec->noIORanges > 0) { | 2000 | if (bus_sec->noIORanges > 0) { |
2001 | if (!range_exists_already (range, bus_sec, IO)) { | 2001 | if (!range_exists_already (range, bus_sec, IO)) { |
2002 | add_range (IO, range, bus_sec); | 2002 | add_bus_range (IO, range, bus_sec); |
2003 | ++bus_sec->noIORanges; | 2003 | ++bus_sec->noIORanges; |
2004 | } else { | 2004 | } else { |
2005 | kfree (range); | 2005 | kfree (range); |
@@ -2048,7 +2048,7 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2048 | 2048 | ||
2049 | if (bus_sec->noMemRanges > 0) { | 2049 | if (bus_sec->noMemRanges > 0) { |
2050 | if (!range_exists_already (range, bus_sec, MEM)) { | 2050 | if (!range_exists_already (range, bus_sec, MEM)) { |
2051 | add_range (MEM, range, bus_sec); | 2051 | add_bus_range (MEM, range, bus_sec); |
2052 | ++bus_sec->noMemRanges; | 2052 | ++bus_sec->noMemRanges; |
2053 | } else { | 2053 | } else { |
2054 | kfree (range); | 2054 | kfree (range); |
@@ -2102,7 +2102,7 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2102 | 2102 | ||
2103 | if (bus_sec->noPFMemRanges > 0) { | 2103 | if (bus_sec->noPFMemRanges > 0) { |
2104 | if (!range_exists_already (range, bus_sec, PFMEM)) { | 2104 | if (!range_exists_already (range, bus_sec, PFMEM)) { |
2105 | add_range (PFMEM, range, bus_sec); | 2105 | add_bus_range (PFMEM, range, bus_sec); |
2106 | ++bus_sec->noPFMemRanges; | 2106 | ++bus_sec->noPFMemRanges; |
2107 | } else { | 2107 | } else { |
2108 | kfree (range); | 2108 | kfree (range); |
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 0325d989bb46..6d2eea93298f 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/kobject.h> | 33 | #include <linux/kobject.h> |
34 | #include <linux/sysfs.h> | 34 | #include <linux/sysfs.h> |
35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
36 | #include <linux/slab.h> | ||
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
38 | #include <linux/mount.h> | 37 | #include <linux/mount.h> |
39 | #include <linux/namei.h> | 38 | #include <linux/namei.h> |
@@ -64,32 +63,6 @@ static int debug; | |||
64 | static LIST_HEAD(pci_hotplug_slot_list); | 63 | static LIST_HEAD(pci_hotplug_slot_list); |
65 | static DEFINE_MUTEX(pci_hp_mutex); | 64 | static DEFINE_MUTEX(pci_hp_mutex); |
66 | 65 | ||
67 | /* these strings match up with the values in pci_bus_speed */ | ||
68 | static char *pci_bus_speed_strings[] = { | ||
69 | "33 MHz PCI", /* 0x00 */ | ||
70 | "66 MHz PCI", /* 0x01 */ | ||
71 | "66 MHz PCIX", /* 0x02 */ | ||
72 | "100 MHz PCIX", /* 0x03 */ | ||
73 | "133 MHz PCIX", /* 0x04 */ | ||
74 | NULL, /* 0x05 */ | ||
75 | NULL, /* 0x06 */ | ||
76 | NULL, /* 0x07 */ | ||
77 | NULL, /* 0x08 */ | ||
78 | "66 MHz PCIX 266", /* 0x09 */ | ||
79 | "100 MHz PCIX 266", /* 0x0a */ | ||
80 | "133 MHz PCIX 266", /* 0x0b */ | ||
81 | NULL, /* 0x0c */ | ||
82 | NULL, /* 0x0d */ | ||
83 | NULL, /* 0x0e */ | ||
84 | NULL, /* 0x0f */ | ||
85 | NULL, /* 0x10 */ | ||
86 | "66 MHz PCIX 533", /* 0x11 */ | ||
87 | "100 MHz PCIX 533", /* 0x12 */ | ||
88 | "133 MHz PCIX 533", /* 0x13 */ | ||
89 | "2.5 GT/s PCI-E", /* 0x14 */ | ||
90 | "5.0 GT/s PCI-E", /* 0x15 */ | ||
91 | }; | ||
92 | |||
93 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 66 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
94 | extern int cpci_hotplug_init(int debug); | 67 | extern int cpci_hotplug_init(int debug); |
95 | extern void cpci_hotplug_exit(void); | 68 | extern void cpci_hotplug_exit(void); |
@@ -118,8 +91,6 @@ GET_STATUS(power_status, u8) | |||
118 | GET_STATUS(attention_status, u8) | 91 | GET_STATUS(attention_status, u8) |
119 | GET_STATUS(latch_status, u8) | 92 | GET_STATUS(latch_status, u8) |
120 | GET_STATUS(adapter_status, u8) | 93 | GET_STATUS(adapter_status, u8) |
121 | GET_STATUS(max_bus_speed, enum pci_bus_speed) | ||
122 | GET_STATUS(cur_bus_speed, enum pci_bus_speed) | ||
123 | 94 | ||
124 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) | 95 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) |
125 | { | 96 | { |
@@ -263,60 +234,6 @@ static struct pci_slot_attribute hotplug_slot_attr_presence = { | |||
263 | .show = presence_read_file, | 234 | .show = presence_read_file, |
264 | }; | 235 | }; |
265 | 236 | ||
266 | static char *unknown_speed = "Unknown bus speed"; | ||
267 | |||
268 | static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
269 | { | ||
270 | char *speed_string; | ||
271 | int retval; | ||
272 | enum pci_bus_speed value; | ||
273 | |||
274 | retval = get_max_bus_speed(slot->hotplug, &value); | ||
275 | if (retval) | ||
276 | goto exit; | ||
277 | |||
278 | if (value == PCI_SPEED_UNKNOWN) | ||
279 | speed_string = unknown_speed; | ||
280 | else | ||
281 | speed_string = pci_bus_speed_strings[value]; | ||
282 | |||
283 | retval = sprintf (buf, "%s\n", speed_string); | ||
284 | |||
285 | exit: | ||
286 | return retval; | ||
287 | } | ||
288 | |||
289 | static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = { | ||
290 | .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
291 | .show = max_bus_speed_read_file, | ||
292 | }; | ||
293 | |||
294 | static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
295 | { | ||
296 | char *speed_string; | ||
297 | int retval; | ||
298 | enum pci_bus_speed value; | ||
299 | |||
300 | retval = get_cur_bus_speed(slot->hotplug, &value); | ||
301 | if (retval) | ||
302 | goto exit; | ||
303 | |||
304 | if (value == PCI_SPEED_UNKNOWN) | ||
305 | speed_string = unknown_speed; | ||
306 | else | ||
307 | speed_string = pci_bus_speed_strings[value]; | ||
308 | |||
309 | retval = sprintf (buf, "%s\n", speed_string); | ||
310 | |||
311 | exit: | ||
312 | return retval; | ||
313 | } | ||
314 | |||
315 | static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = { | ||
316 | .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
317 | .show = cur_bus_speed_read_file, | ||
318 | }; | ||
319 | |||
320 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, | 237 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, |
321 | size_t count) | 238 | size_t count) |
322 | { | 239 | { |
@@ -391,26 +308,6 @@ static bool has_adapter_file(struct pci_slot *pci_slot) | |||
391 | return false; | 308 | return false; |
392 | } | 309 | } |
393 | 310 | ||
394 | static bool has_max_bus_speed_file(struct pci_slot *pci_slot) | ||
395 | { | ||
396 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
397 | if ((!slot) || (!slot->ops)) | ||
398 | return false; | ||
399 | if (slot->ops->get_max_bus_speed) | ||
400 | return true; | ||
401 | return false; | ||
402 | } | ||
403 | |||
404 | static bool has_cur_bus_speed_file(struct pci_slot *pci_slot) | ||
405 | { | ||
406 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
407 | if ((!slot) || (!slot->ops)) | ||
408 | return false; | ||
409 | if (slot->ops->get_cur_bus_speed) | ||
410 | return true; | ||
411 | return false; | ||
412 | } | ||
413 | |||
414 | static bool has_test_file(struct pci_slot *pci_slot) | 311 | static bool has_test_file(struct pci_slot *pci_slot) |
415 | { | 312 | { |
416 | struct hotplug_slot *slot = pci_slot->hotplug; | 313 | struct hotplug_slot *slot = pci_slot->hotplug; |
@@ -456,20 +353,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
456 | goto exit_adapter; | 353 | goto exit_adapter; |
457 | } | 354 | } |
458 | 355 | ||
459 | if (has_max_bus_speed_file(slot)) { | ||
460 | retval = sysfs_create_file(&slot->kobj, | ||
461 | &hotplug_slot_attr_max_bus_speed.attr); | ||
462 | if (retval) | ||
463 | goto exit_max_speed; | ||
464 | } | ||
465 | |||
466 | if (has_cur_bus_speed_file(slot)) { | ||
467 | retval = sysfs_create_file(&slot->kobj, | ||
468 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
469 | if (retval) | ||
470 | goto exit_cur_speed; | ||
471 | } | ||
472 | |||
473 | if (has_test_file(slot)) { | 356 | if (has_test_file(slot)) { |
474 | retval = sysfs_create_file(&slot->kobj, | 357 | retval = sysfs_create_file(&slot->kobj, |
475 | &hotplug_slot_attr_test.attr); | 358 | &hotplug_slot_attr_test.attr); |
@@ -480,14 +363,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
480 | goto exit; | 363 | goto exit; |
481 | 364 | ||
482 | exit_test: | 365 | exit_test: |
483 | if (has_cur_bus_speed_file(slot)) | ||
484 | sysfs_remove_file(&slot->kobj, | ||
485 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
486 | exit_cur_speed: | ||
487 | if (has_max_bus_speed_file(slot)) | ||
488 | sysfs_remove_file(&slot->kobj, | ||
489 | &hotplug_slot_attr_max_bus_speed.attr); | ||
490 | exit_max_speed: | ||
491 | if (has_adapter_file(slot)) | 366 | if (has_adapter_file(slot)) |
492 | sysfs_remove_file(&slot->kobj, | 367 | sysfs_remove_file(&slot->kobj, |
493 | &hotplug_slot_attr_presence.attr); | 368 | &hotplug_slot_attr_presence.attr); |
@@ -523,14 +398,6 @@ static void fs_remove_slot(struct pci_slot *slot) | |||
523 | sysfs_remove_file(&slot->kobj, | 398 | sysfs_remove_file(&slot->kobj, |
524 | &hotplug_slot_attr_presence.attr); | 399 | &hotplug_slot_attr_presence.attr); |
525 | 400 | ||
526 | if (has_max_bus_speed_file(slot)) | ||
527 | sysfs_remove_file(&slot->kobj, | ||
528 | &hotplug_slot_attr_max_bus_speed.attr); | ||
529 | |||
530 | if (has_cur_bus_speed_file(slot)) | ||
531 | sysfs_remove_file(&slot->kobj, | ||
532 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
533 | |||
534 | if (has_test_file(slot)) | 401 | if (has_test_file(slot)) |
535 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); | 402 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); |
536 | 403 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 3070f77eb56a..4ed76b47b6dc 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -91,7 +91,6 @@ struct controller { | |||
91 | struct slot *slot; | 91 | struct slot *slot; |
92 | wait_queue_head_t queue; /* sleep & wake process */ | 92 | wait_queue_head_t queue; /* sleep & wake process */ |
93 | u32 slot_cap; | 93 | u32 slot_cap; |
94 | u8 cap_base; | ||
95 | struct timer_list poll_timer; | 94 | struct timer_list poll_timer; |
96 | unsigned int cmd_busy:1; | 95 | unsigned int cmd_busy:1; |
97 | unsigned int no_cmd_complete:1; | 96 | unsigned int no_cmd_complete:1; |
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 37c8d3d0323e..1f4000a5a108 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/acpi.h> | 26 | #include <linux/acpi.h> |
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/pci_hotplug.h> | 28 | #include <linux/pci_hotplug.h> |
29 | #include <linux/slab.h> | ||
29 | #include "pciehp.h" | 30 | #include "pciehp.h" |
30 | 31 | ||
31 | #define PCIEHP_DETECT_PCIE (0) | 32 | #define PCIEHP_DETECT_PCIE (0) |
@@ -87,7 +88,8 @@ static int __init dummy_probe(struct pcie_device *dev) | |||
87 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ | 88 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ |
88 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) | 89 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) |
89 | return -ENODEV; | 90 | return -ENODEV; |
90 | if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) | 91 | pos = pci_pcie_cap(pdev); |
92 | if (!pos) | ||
91 | return -ENODEV; | 93 | return -ENODEV; |
92 | pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); | 94 | pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); |
93 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 95 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index bc234719b1df..3588ea61b0dd 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/types.h> | 34 | #include <linux/types.h> |
34 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
35 | #include "pciehp.h" | 36 | #include "pciehp.h" |
@@ -69,20 +70,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
69 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 70 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
70 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 71 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
71 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 72 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
72 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
73 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
74 | |||
75 | static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { | ||
76 | .set_attention_status = set_attention_status, | ||
77 | .enable_slot = enable_slot, | ||
78 | .disable_slot = disable_slot, | ||
79 | .get_power_status = get_power_status, | ||
80 | .get_attention_status = get_attention_status, | ||
81 | .get_latch_status = get_latch_status, | ||
82 | .get_adapter_status = get_adapter_status, | ||
83 | .get_max_bus_speed = get_max_bus_speed, | ||
84 | .get_cur_bus_speed = get_cur_bus_speed, | ||
85 | }; | ||
86 | 73 | ||
87 | /** | 74 | /** |
88 | * release_slot - free up the memory used by a slot | 75 | * release_slot - free up the memory used by a slot |
@@ -95,6 +82,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
95 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 82 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
96 | __func__, hotplug_slot_name(hotplug_slot)); | 83 | __func__, hotplug_slot_name(hotplug_slot)); |
97 | 84 | ||
85 | kfree(hotplug_slot->ops); | ||
98 | kfree(hotplug_slot->info); | 86 | kfree(hotplug_slot->info); |
99 | kfree(hotplug_slot); | 87 | kfree(hotplug_slot); |
100 | } | 88 | } |
@@ -104,6 +92,7 @@ static int init_slot(struct controller *ctrl) | |||
104 | struct slot *slot = ctrl->slot; | 92 | struct slot *slot = ctrl->slot; |
105 | struct hotplug_slot *hotplug = NULL; | 93 | struct hotplug_slot *hotplug = NULL; |
106 | struct hotplug_slot_info *info = NULL; | 94 | struct hotplug_slot_info *info = NULL; |
95 | struct hotplug_slot_ops *ops = NULL; | ||
107 | char name[SLOT_NAME_SIZE]; | 96 | char name[SLOT_NAME_SIZE]; |
108 | int retval = -ENOMEM; | 97 | int retval = -ENOMEM; |
109 | 98 | ||
@@ -115,11 +104,26 @@ static int init_slot(struct controller *ctrl) | |||
115 | if (!info) | 104 | if (!info) |
116 | goto out; | 105 | goto out; |
117 | 106 | ||
107 | /* Setup hotplug slot ops */ | ||
108 | ops = kzalloc(sizeof(*ops), GFP_KERNEL); | ||
109 | if (!ops) | ||
110 | goto out; | ||
111 | ops->enable_slot = enable_slot; | ||
112 | ops->disable_slot = disable_slot; | ||
113 | ops->get_power_status = get_power_status; | ||
114 | ops->get_adapter_status = get_adapter_status; | ||
115 | if (MRL_SENS(ctrl)) | ||
116 | ops->get_latch_status = get_latch_status; | ||
117 | if (ATTN_LED(ctrl)) { | ||
118 | ops->get_attention_status = get_attention_status; | ||
119 | ops->set_attention_status = set_attention_status; | ||
120 | } | ||
121 | |||
118 | /* register this slot with the hotplug pci core */ | 122 | /* register this slot with the hotplug pci core */ |
119 | hotplug->info = info; | 123 | hotplug->info = info; |
120 | hotplug->private = slot; | 124 | hotplug->private = slot; |
121 | hotplug->release = &release_slot; | 125 | hotplug->release = &release_slot; |
122 | hotplug->ops = &pciehp_hotplug_slot_ops; | 126 | hotplug->ops = ops; |
123 | slot->hotplug_slot = hotplug; | 127 | slot->hotplug_slot = hotplug; |
124 | snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl)); | 128 | snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl)); |
125 | 129 | ||
@@ -128,17 +132,12 @@ static int init_slot(struct controller *ctrl) | |||
128 | ctrl->pcie->port->subordinate->number, PSN(ctrl)); | 132 | ctrl->pcie->port->subordinate->number, PSN(ctrl)); |
129 | retval = pci_hp_register(hotplug, | 133 | retval = pci_hp_register(hotplug, |
130 | ctrl->pcie->port->subordinate, 0, name); | 134 | ctrl->pcie->port->subordinate, 0, name); |
131 | if (retval) { | 135 | if (retval) |
132 | ctrl_err(ctrl, | 136 | ctrl_err(ctrl, |
133 | "pci_hp_register failed with error %d\n", retval); | 137 | "pci_hp_register failed with error %d\n", retval); |
134 | goto out; | ||
135 | } | ||
136 | get_power_status(hotplug, &info->power_status); | ||
137 | get_attention_status(hotplug, &info->attention_status); | ||
138 | get_latch_status(hotplug, &info->latch_status); | ||
139 | get_adapter_status(hotplug, &info->adapter_status); | ||
140 | out: | 138 | out: |
141 | if (retval) { | 139 | if (retval) { |
140 | kfree(ops); | ||
142 | kfree(info); | 141 | kfree(info); |
143 | kfree(hotplug); | 142 | kfree(hotplug); |
144 | } | 143 | } |
@@ -160,12 +159,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) | |||
160 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 159 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
161 | __func__, slot_name(slot)); | 160 | __func__, slot_name(slot)); |
162 | 161 | ||
163 | hotplug_slot->info->attention_status = status; | 162 | return pciehp_set_attention_status(slot, status); |
164 | |||
165 | if (ATTN_LED(slot->ctrl)) | ||
166 | pciehp_set_attention_status(slot, status); | ||
167 | |||
168 | return 0; | ||
169 | } | 163 | } |
170 | 164 | ||
171 | 165 | ||
@@ -193,92 +187,41 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
193 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) | 187 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) |
194 | { | 188 | { |
195 | struct slot *slot = hotplug_slot->private; | 189 | struct slot *slot = hotplug_slot->private; |
196 | int retval; | ||
197 | 190 | ||
198 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 191 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
199 | __func__, slot_name(slot)); | 192 | __func__, slot_name(slot)); |
200 | 193 | ||
201 | retval = pciehp_get_power_status(slot, value); | 194 | return pciehp_get_power_status(slot, value); |
202 | if (retval < 0) | ||
203 | *value = hotplug_slot->info->power_status; | ||
204 | |||
205 | return 0; | ||
206 | } | 195 | } |
207 | 196 | ||
208 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) | 197 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) |
209 | { | 198 | { |
210 | struct slot *slot = hotplug_slot->private; | 199 | struct slot *slot = hotplug_slot->private; |
211 | int retval; | ||
212 | 200 | ||
213 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 201 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
214 | __func__, slot_name(slot)); | 202 | __func__, slot_name(slot)); |
215 | 203 | ||
216 | retval = pciehp_get_attention_status(slot, value); | 204 | return pciehp_get_attention_status(slot, value); |
217 | if (retval < 0) | ||
218 | *value = hotplug_slot->info->attention_status; | ||
219 | |||
220 | return 0; | ||
221 | } | 205 | } |
222 | 206 | ||
223 | static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) | 207 | static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) |
224 | { | 208 | { |
225 | struct slot *slot = hotplug_slot->private; | 209 | struct slot *slot = hotplug_slot->private; |
226 | int retval; | ||
227 | 210 | ||
228 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 211 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
229 | __func__, slot_name(slot)); | 212 | __func__, slot_name(slot)); |
230 | 213 | ||
231 | retval = pciehp_get_latch_status(slot, value); | 214 | return pciehp_get_latch_status(slot, value); |
232 | if (retval < 0) | ||
233 | *value = hotplug_slot->info->latch_status; | ||
234 | |||
235 | return 0; | ||
236 | } | 215 | } |
237 | 216 | ||
238 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | 217 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) |
239 | { | 218 | { |
240 | struct slot *slot = hotplug_slot->private; | 219 | struct slot *slot = hotplug_slot->private; |
241 | int retval; | ||
242 | 220 | ||
243 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 221 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
244 | __func__, slot_name(slot)); | 222 | __func__, slot_name(slot)); |
245 | 223 | ||
246 | retval = pciehp_get_adapter_status(slot, value); | 224 | return pciehp_get_adapter_status(slot, value); |
247 | if (retval < 0) | ||
248 | *value = hotplug_slot->info->adapter_status; | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
254 | enum pci_bus_speed *value) | ||
255 | { | ||
256 | struct slot *slot = hotplug_slot->private; | ||
257 | int retval; | ||
258 | |||
259 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
260 | __func__, slot_name(slot)); | ||
261 | |||
262 | retval = pciehp_get_max_link_speed(slot, value); | ||
263 | if (retval < 0) | ||
264 | *value = PCI_SPEED_UNKNOWN; | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
270 | { | ||
271 | struct slot *slot = hotplug_slot->private; | ||
272 | int retval; | ||
273 | |||
274 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
275 | __func__, slot_name(slot)); | ||
276 | |||
277 | retval = pciehp_get_cur_link_speed(slot, value); | ||
278 | if (retval < 0) | ||
279 | *value = PCI_SPEED_UNKNOWN; | ||
280 | |||
281 | return 0; | ||
282 | } | 225 | } |
283 | 226 | ||
284 | static int pciehp_probe(struct pcie_device *dev) | 227 | static int pciehp_probe(struct pcie_device *dev) |
@@ -286,14 +229,13 @@ static int pciehp_probe(struct pcie_device *dev) | |||
286 | int rc; | 229 | int rc; |
287 | struct controller *ctrl; | 230 | struct controller *ctrl; |
288 | struct slot *slot; | 231 | struct slot *slot; |
289 | u8 value; | 232 | u8 occupied, poweron; |
290 | struct pci_dev *pdev = dev->port; | ||
291 | 233 | ||
292 | if (pciehp_force) | 234 | if (pciehp_force) |
293 | dev_info(&dev->device, | 235 | dev_info(&dev->device, |
294 | "Bypassing BIOS check for pciehp use on %s\n", | 236 | "Bypassing BIOS check for pciehp use on %s\n", |
295 | pci_name(pdev)); | 237 | pci_name(dev->port)); |
296 | else if (pciehp_get_hp_hw_control_from_firmware(pdev)) | 238 | else if (pciehp_get_hp_hw_control_from_firmware(dev->port)) |
297 | goto err_out_none; | 239 | goto err_out_none; |
298 | 240 | ||
299 | ctrl = pcie_init(dev); | 241 | ctrl = pcie_init(dev); |
@@ -318,23 +260,18 @@ static int pciehp_probe(struct pcie_device *dev) | |||
318 | rc = pcie_init_notification(ctrl); | 260 | rc = pcie_init_notification(ctrl); |
319 | if (rc) { | 261 | if (rc) { |
320 | ctrl_err(ctrl, "Notification initialization failed\n"); | 262 | ctrl_err(ctrl, "Notification initialization failed\n"); |
321 | goto err_out_release_ctlr; | 263 | goto err_out_free_ctrl_slot; |
322 | } | 264 | } |
323 | 265 | ||
324 | /* Check if slot is occupied */ | 266 | /* Check if slot is occupied */ |
325 | slot = ctrl->slot; | 267 | slot = ctrl->slot; |
326 | pciehp_get_adapter_status(slot, &value); | 268 | pciehp_get_adapter_status(slot, &occupied); |
327 | if (value) { | 269 | pciehp_get_power_status(slot, &poweron); |
328 | if (pciehp_force) | 270 | if (occupied && pciehp_force) |
329 | pciehp_enable_slot(slot); | 271 | pciehp_enable_slot(slot); |
330 | } else { | 272 | /* If empty slot's power status is on, turn power off */ |
331 | /* Power off slot if not occupied */ | 273 | if (!occupied && poweron && POWER_CTRL(ctrl)) |
332 | if (POWER_CTRL(ctrl)) { | 274 | pciehp_power_off_slot(slot); |
333 | rc = pciehp_power_off_slot(slot); | ||
334 | if (rc) | ||
335 | goto err_out_free_ctrl_slot; | ||
336 | } | ||
337 | } | ||
338 | 275 | ||
339 | return 0; | 276 | return 0; |
340 | 277 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 84487d126e4d..8f58148be044 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
34 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
35 | #include "../pci.h" | 36 | #include "../pci.h" |
@@ -142,23 +143,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot) | |||
142 | 143 | ||
143 | /* power fault */ | 144 | /* power fault */ |
144 | ctrl_dbg(ctrl, "Power fault interrupt received\n"); | 145 | ctrl_dbg(ctrl, "Power fault interrupt received\n"); |
145 | 146 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); | |
146 | if (!pciehp_query_power_fault(p_slot)) { | 147 | event_type = INT_POWER_FAULT; |
147 | /* | 148 | ctrl_info(ctrl, "Power fault bit %x set\n", 0); |
148 | * power fault Cleared | ||
149 | */ | ||
150 | ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", | ||
151 | slot_name(p_slot)); | ||
152 | event_type = INT_POWER_FAULT_CLEAR; | ||
153 | } else { | ||
154 | /* | ||
155 | * power fault | ||
156 | */ | ||
157 | ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); | ||
158 | event_type = INT_POWER_FAULT; | ||
159 | ctrl_info(ctrl, "Power fault bit %x set\n", 0); | ||
160 | } | ||
161 | |||
162 | queue_interrupt_event(p_slot, event_type); | 149 | queue_interrupt_event(p_slot, event_type); |
163 | 150 | ||
164 | return 1; | 151 | return 1; |
@@ -224,13 +211,12 @@ static int board_added(struct slot *p_slot) | |||
224 | retval = pciehp_check_link_status(ctrl); | 211 | retval = pciehp_check_link_status(ctrl); |
225 | if (retval) { | 212 | if (retval) { |
226 | ctrl_err(ctrl, "Failed to check link status\n"); | 213 | ctrl_err(ctrl, "Failed to check link status\n"); |
227 | set_slot_off(ctrl, p_slot); | 214 | goto err_exit; |
228 | return retval; | ||
229 | } | 215 | } |
230 | 216 | ||
231 | /* Check for a power fault */ | 217 | /* Check for a power fault */ |
232 | if (pciehp_query_power_fault(p_slot)) { | 218 | if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { |
233 | ctrl_dbg(ctrl, "Power fault detected\n"); | 219 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); |
234 | retval = -EIO; | 220 | retval = -EIO; |
235 | goto err_exit; | 221 | goto err_exit; |
236 | } | 222 | } |
@@ -356,6 +342,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
356 | p_slot->state = POWERON_STATE; | 342 | p_slot->state = POWERON_STATE; |
357 | break; | 343 | break; |
358 | default: | 344 | default: |
345 | kfree(info); | ||
359 | goto out; | 346 | goto out; |
360 | } | 347 | } |
361 | queue_work(pciehp_wq, &info->work); | 348 | queue_work(pciehp_wq, &info->work); |
@@ -363,25 +350,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
363 | mutex_unlock(&p_slot->lock); | 350 | mutex_unlock(&p_slot->lock); |
364 | } | 351 | } |
365 | 352 | ||
366 | static int update_slot_info(struct slot *slot) | ||
367 | { | ||
368 | struct hotplug_slot_info *info; | ||
369 | int result; | ||
370 | |||
371 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
372 | if (!info) | ||
373 | return -ENOMEM; | ||
374 | |||
375 | pciehp_get_power_status(slot, &info->power_status); | ||
376 | pciehp_get_attention_status(slot, &info->attention_status); | ||
377 | pciehp_get_latch_status(slot, &info->latch_status); | ||
378 | pciehp_get_adapter_status(slot, &info->adapter_status); | ||
379 | |||
380 | result = pci_hp_change_slot_info(slot->hotplug_slot, info); | ||
381 | kfree (info); | ||
382 | return result; | ||
383 | } | ||
384 | |||
385 | /* | 353 | /* |
386 | * Note: This function must be called with slot->lock held | 354 | * Note: This function must be called with slot->lock held |
387 | */ | 355 | */ |
@@ -442,7 +410,6 @@ static void handle_button_press_event(struct slot *p_slot) | |||
442 | * to hot-add or hot-remove is undergoing | 410 | * to hot-add or hot-remove is undergoing |
443 | */ | 411 | */ |
444 | ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); | 412 | ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); |
445 | update_slot_info(p_slot); | ||
446 | break; | 413 | break; |
447 | default: | 414 | default: |
448 | ctrl_warn(ctrl, "Not a valid state\n"); | 415 | ctrl_warn(ctrl, "Not a valid state\n"); |
@@ -500,11 +467,9 @@ static void interrupt_event_handler(struct work_struct *work) | |||
500 | if (!HP_SUPR_RM(ctrl)) | 467 | if (!HP_SUPR_RM(ctrl)) |
501 | break; | 468 | break; |
502 | ctrl_dbg(ctrl, "Surprise Removal\n"); | 469 | ctrl_dbg(ctrl, "Surprise Removal\n"); |
503 | update_slot_info(p_slot); | ||
504 | handle_surprise_event(p_slot); | 470 | handle_surprise_event(p_slot); |
505 | break; | 471 | break; |
506 | default: | 472 | default: |
507 | update_slot_info(p_slot); | ||
508 | break; | 473 | break; |
509 | } | 474 | } |
510 | mutex_unlock(&p_slot->lock); | 475 | mutex_unlock(&p_slot->lock); |
@@ -547,9 +512,6 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
547 | if (rc) { | 512 | if (rc) { |
548 | pciehp_get_latch_status(p_slot, &getstatus); | 513 | pciehp_get_latch_status(p_slot, &getstatus); |
549 | } | 514 | } |
550 | |||
551 | update_slot_info(p_slot); | ||
552 | |||
553 | return rc; | 515 | return rc; |
554 | } | 516 | } |
555 | 517 | ||
@@ -590,10 +552,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
590 | } | 552 | } |
591 | } | 553 | } |
592 | 554 | ||
593 | ret = remove_board(p_slot); | 555 | return remove_board(p_slot); |
594 | update_slot_info(p_slot); | ||
595 | |||
596 | return ret; | ||
597 | } | 556 | } |
598 | 557 | ||
599 | int pciehp_sysfs_enable_slot(struct slot *p_slot) | 558 | int pciehp_sysfs_enable_slot(struct slot *p_slot) |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9ef4605c1ef6..0cd42047d89b 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/time.h> | 38 | #include <linux/time.h> |
39 | #include <linux/slab.h> | ||
39 | 40 | ||
40 | #include "../pci.h" | 41 | #include "../pci.h" |
41 | #include "pciehp.h" | 42 | #include "pciehp.h" |
@@ -45,25 +46,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); | |||
45 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) | 46 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) |
46 | { | 47 | { |
47 | struct pci_dev *dev = ctrl->pcie->port; | 48 | struct pci_dev *dev = ctrl->pcie->port; |
48 | return pci_read_config_word(dev, ctrl->cap_base + reg, value); | 49 | return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value); |
49 | } | 50 | } |
50 | 51 | ||
51 | static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) | 52 | static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) |
52 | { | 53 | { |
53 | struct pci_dev *dev = ctrl->pcie->port; | 54 | struct pci_dev *dev = ctrl->pcie->port; |
54 | return pci_read_config_dword(dev, ctrl->cap_base + reg, value); | 55 | return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value); |
55 | } | 56 | } |
56 | 57 | ||
57 | static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) | 58 | static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) |
58 | { | 59 | { |
59 | struct pci_dev *dev = ctrl->pcie->port; | 60 | struct pci_dev *dev = ctrl->pcie->port; |
60 | return pci_write_config_word(dev, ctrl->cap_base + reg, value); | 61 | return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value); |
61 | } | 62 | } |
62 | 63 | ||
63 | static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | 64 | static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) |
64 | { | 65 | { |
65 | struct pci_dev *dev = ctrl->pcie->port; | 66 | struct pci_dev *dev = ctrl->pcie->port; |
66 | return pci_write_config_dword(dev, ctrl->cap_base + reg, value); | 67 | return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value); |
67 | } | 68 | } |
68 | 69 | ||
69 | /* Power Control Command */ | 70 | /* Power Control Command */ |
@@ -318,8 +319,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) | |||
318 | return retval; | 319 | return retval; |
319 | } | 320 | } |
320 | 321 | ||
321 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", | 322 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, |
322 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); | 323 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); |
323 | 324 | ||
324 | atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; | 325 | atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; |
325 | 326 | ||
@@ -356,8 +357,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) | |||
356 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | 357 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); |
357 | return retval; | 358 | return retval; |
358 | } | 359 | } |
359 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", | 360 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, |
360 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); | 361 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); |
361 | 362 | ||
362 | pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; | 363 | pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; |
363 | 364 | ||
@@ -427,27 +428,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value) | |||
427 | struct controller *ctrl = slot->ctrl; | 428 | struct controller *ctrl = slot->ctrl; |
428 | u16 slot_cmd; | 429 | u16 slot_cmd; |
429 | u16 cmd_mask; | 430 | u16 cmd_mask; |
430 | int rc; | ||
431 | 431 | ||
432 | cmd_mask = PCI_EXP_SLTCTL_AIC; | 432 | cmd_mask = PCI_EXP_SLTCTL_AIC; |
433 | switch (value) { | 433 | switch (value) { |
434 | case 0 : /* turn off */ | 434 | case 0 : /* turn off */ |
435 | slot_cmd = 0x00C0; | 435 | slot_cmd = 0x00C0; |
436 | break; | 436 | break; |
437 | case 1: /* turn on */ | 437 | case 1: /* turn on */ |
438 | slot_cmd = 0x0040; | 438 | slot_cmd = 0x0040; |
439 | break; | 439 | break; |
440 | case 2: /* turn blink */ | 440 | case 2: /* turn blink */ |
441 | slot_cmd = 0x0080; | 441 | slot_cmd = 0x0080; |
442 | break; | 442 | break; |
443 | default: | 443 | default: |
444 | return -1; | 444 | return -EINVAL; |
445 | } | 445 | } |
446 | rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 446 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
447 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 447 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
448 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 448 | return pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
449 | |||
450 | return rc; | ||
451 | } | 449 | } |
452 | 450 | ||
453 | void pciehp_green_led_on(struct slot *slot) | 451 | void pciehp_green_led_on(struct slot *slot) |
@@ -459,8 +457,8 @@ void pciehp_green_led_on(struct slot *slot) | |||
459 | slot_cmd = 0x0100; | 457 | slot_cmd = 0x0100; |
460 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 458 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
461 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 459 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
462 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 460 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
463 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 461 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
464 | } | 462 | } |
465 | 463 | ||
466 | void pciehp_green_led_off(struct slot *slot) | 464 | void pciehp_green_led_off(struct slot *slot) |
@@ -472,8 +470,8 @@ void pciehp_green_led_off(struct slot *slot) | |||
472 | slot_cmd = 0x0300; | 470 | slot_cmd = 0x0300; |
473 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 471 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
474 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 472 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
475 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 473 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
476 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 474 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
477 | } | 475 | } |
478 | 476 | ||
479 | void pciehp_green_led_blink(struct slot *slot) | 477 | void pciehp_green_led_blink(struct slot *slot) |
@@ -485,8 +483,8 @@ void pciehp_green_led_blink(struct slot *slot) | |||
485 | slot_cmd = 0x0200; | 483 | slot_cmd = 0x0200; |
486 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 484 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
487 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 485 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
488 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 486 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
489 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 487 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
490 | } | 488 | } |
491 | 489 | ||
492 | int pciehp_power_on_slot(struct slot * slot) | 490 | int pciehp_power_on_slot(struct slot * slot) |
@@ -495,6 +493,7 @@ int pciehp_power_on_slot(struct slot * slot) | |||
495 | u16 slot_cmd; | 493 | u16 slot_cmd; |
496 | u16 cmd_mask; | 494 | u16 cmd_mask; |
497 | u16 slot_status; | 495 | u16 slot_status; |
496 | u16 lnk_status; | ||
498 | int retval = 0; | 497 | int retval = 0; |
499 | 498 | ||
500 | /* Clear sticky power-fault bit from previous power failures */ | 499 | /* Clear sticky power-fault bit from previous power failures */ |
@@ -514,58 +513,27 @@ int pciehp_power_on_slot(struct slot * slot) | |||
514 | return retval; | 513 | return retval; |
515 | } | 514 | } |
516 | } | 515 | } |
516 | ctrl->power_fault_detected = 0; | ||
517 | 517 | ||
518 | slot_cmd = POWER_ON; | 518 | slot_cmd = POWER_ON; |
519 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 519 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
520 | if (!pciehp_poll_mode) { | ||
521 | /* Enable power fault detection turned off at power off time */ | ||
522 | slot_cmd |= PCI_EXP_SLTCTL_PFDE; | ||
523 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; | ||
524 | } | ||
525 | |||
526 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 520 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
527 | if (retval) { | 521 | if (retval) { |
528 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); | 522 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); |
529 | return retval; | 523 | return retval; |
530 | } | 524 | } |
531 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 525 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
532 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 526 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
533 | |||
534 | ctrl->power_fault_detected = 0; | ||
535 | return retval; | ||
536 | } | ||
537 | |||
538 | static inline int pcie_mask_bad_dllp(struct controller *ctrl) | ||
539 | { | ||
540 | struct pci_dev *dev = ctrl->pcie->port; | ||
541 | int pos; | ||
542 | u32 reg; | ||
543 | |||
544 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
545 | if (!pos) | ||
546 | return 0; | ||
547 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); | ||
548 | if (reg & PCI_ERR_COR_BAD_DLLP) | ||
549 | return 0; | ||
550 | reg |= PCI_ERR_COR_BAD_DLLP; | ||
551 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); | ||
552 | return 1; | ||
553 | } | ||
554 | 527 | ||
555 | static inline void pcie_unmask_bad_dllp(struct controller *ctrl) | 528 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); |
556 | { | 529 | if (retval) { |
557 | struct pci_dev *dev = ctrl->pcie->port; | 530 | ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n", |
558 | u32 reg; | 531 | __func__); |
559 | int pos; | 532 | return retval; |
533 | } | ||
534 | pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); | ||
560 | 535 | ||
561 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 536 | return retval; |
562 | if (!pos) | ||
563 | return; | ||
564 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); | ||
565 | if (!(reg & PCI_ERR_COR_BAD_DLLP)) | ||
566 | return; | ||
567 | reg &= ~PCI_ERR_COR_BAD_DLLP; | ||
568 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); | ||
569 | } | 537 | } |
570 | 538 | ||
571 | int pciehp_power_off_slot(struct slot * slot) | 539 | int pciehp_power_off_slot(struct slot * slot) |
@@ -573,38 +541,18 @@ int pciehp_power_off_slot(struct slot * slot) | |||
573 | struct controller *ctrl = slot->ctrl; | 541 | struct controller *ctrl = slot->ctrl; |
574 | u16 slot_cmd; | 542 | u16 slot_cmd; |
575 | u16 cmd_mask; | 543 | u16 cmd_mask; |
576 | int retval = 0; | 544 | int retval; |
577 | int changed; | ||
578 | |||
579 | /* | ||
580 | * Set Bad DLLP Mask bit in Correctable Error Mask | ||
581 | * Register. This is the workaround against Bad DLLP error | ||
582 | * that sometimes happens during turning power off the slot | ||
583 | * which conforms to PCI Express 1.0a spec. | ||
584 | */ | ||
585 | changed = pcie_mask_bad_dllp(ctrl); | ||
586 | 545 | ||
587 | slot_cmd = POWER_OFF; | 546 | slot_cmd = POWER_OFF; |
588 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 547 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
589 | if (!pciehp_poll_mode) { | ||
590 | /* Disable power fault detection */ | ||
591 | slot_cmd &= ~PCI_EXP_SLTCTL_PFDE; | ||
592 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; | ||
593 | } | ||
594 | |||
595 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 548 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
596 | if (retval) { | 549 | if (retval) { |
597 | ctrl_err(ctrl, "Write command failed!\n"); | 550 | ctrl_err(ctrl, "Write command failed!\n"); |
598 | retval = -1; | 551 | return retval; |
599 | goto out; | ||
600 | } | 552 | } |
601 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 553 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
602 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 554 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
603 | out: | 555 | return 0; |
604 | if (changed) | ||
605 | pcie_unmask_bad_dllp(ctrl); | ||
606 | |||
607 | return retval; | ||
608 | } | 556 | } |
609 | 557 | ||
610 | static irqreturn_t pcie_isr(int irq, void *dev_id) | 558 | static irqreturn_t pcie_isr(int irq, void *dev_id) |
@@ -672,37 +620,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
672 | return IRQ_HANDLED; | 620 | return IRQ_HANDLED; |
673 | } | 621 | } |
674 | 622 | ||
675 | int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
676 | { | ||
677 | struct controller *ctrl = slot->ctrl; | ||
678 | enum pcie_link_speed lnk_speed; | ||
679 | u32 lnk_cap; | ||
680 | int retval = 0; | ||
681 | |||
682 | retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); | ||
683 | if (retval) { | ||
684 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | ||
685 | return retval; | ||
686 | } | ||
687 | |||
688 | switch (lnk_cap & 0x000F) { | ||
689 | case 1: | ||
690 | lnk_speed = PCIE_2_5GB; | ||
691 | break; | ||
692 | case 2: | ||
693 | lnk_speed = PCIE_5_0GB; | ||
694 | break; | ||
695 | default: | ||
696 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | *value = lnk_speed; | ||
701 | ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed); | ||
702 | |||
703 | return retval; | ||
704 | } | ||
705 | |||
706 | int pciehp_get_max_lnk_width(struct slot *slot, | 623 | int pciehp_get_max_lnk_width(struct slot *slot, |
707 | enum pcie_link_width *value) | 624 | enum pcie_link_width *value) |
708 | { | 625 | { |
@@ -753,38 +670,6 @@ int pciehp_get_max_lnk_width(struct slot *slot, | |||
753 | return retval; | 670 | return retval; |
754 | } | 671 | } |
755 | 672 | ||
756 | int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
757 | { | ||
758 | struct controller *ctrl = slot->ctrl; | ||
759 | enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; | ||
760 | int retval = 0; | ||
761 | u16 lnk_status; | ||
762 | |||
763 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | ||
764 | if (retval) { | ||
765 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | ||
766 | __func__); | ||
767 | return retval; | ||
768 | } | ||
769 | |||
770 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { | ||
771 | case 1: | ||
772 | lnk_speed = PCIE_2_5GB; | ||
773 | break; | ||
774 | case 2: | ||
775 | lnk_speed = PCIE_5_0GB; | ||
776 | break; | ||
777 | default: | ||
778 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
779 | break; | ||
780 | } | ||
781 | |||
782 | *value = lnk_speed; | ||
783 | ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed); | ||
784 | |||
785 | return retval; | ||
786 | } | ||
787 | |||
788 | int pciehp_get_cur_lnk_width(struct slot *slot, | 673 | int pciehp_get_cur_lnk_width(struct slot *slot, |
789 | enum pcie_link_width *value) | 674 | enum pcie_link_width *value) |
790 | { | 675 | { |
@@ -840,11 +725,19 @@ int pcie_enable_notification(struct controller *ctrl) | |||
840 | { | 725 | { |
841 | u16 cmd, mask; | 726 | u16 cmd, mask; |
842 | 727 | ||
728 | /* | ||
729 | * TBD: Power fault detected software notification support. | ||
730 | * | ||
731 | * Power fault detected software notification is not enabled | ||
732 | * now, because it caused power fault detected interrupt storm | ||
733 | * on some machines. On those machines, power fault detected | ||
734 | * bit in the slot status register was set again immediately | ||
735 | * when it is cleared in the interrupt service routine, and | ||
736 | * next power fault detected interrupt was notified again. | ||
737 | */ | ||
843 | cmd = PCI_EXP_SLTCTL_PDCE; | 738 | cmd = PCI_EXP_SLTCTL_PDCE; |
844 | if (ATTN_BUTTN(ctrl)) | 739 | if (ATTN_BUTTN(ctrl)) |
845 | cmd |= PCI_EXP_SLTCTL_ABPE; | 740 | cmd |= PCI_EXP_SLTCTL_ABPE; |
846 | if (POWER_CTRL(ctrl)) | ||
847 | cmd |= PCI_EXP_SLTCTL_PFDE; | ||
848 | if (MRL_SENS(ctrl)) | 741 | if (MRL_SENS(ctrl)) |
849 | cmd |= PCI_EXP_SLTCTL_MRLSCE; | 742 | cmd |= PCI_EXP_SLTCTL_MRLSCE; |
850 | if (!pciehp_poll_mode) | 743 | if (!pciehp_poll_mode) |
@@ -866,7 +759,8 @@ static void pcie_disable_notification(struct controller *ctrl) | |||
866 | u16 mask; | 759 | u16 mask; |
867 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | | 760 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
868 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | | 761 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
869 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); | 762 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | |
763 | PCI_EXP_SLTCTL_DLLSCE); | ||
870 | if (pcie_write_cmd(ctrl, 0, mask)) | 764 | if (pcie_write_cmd(ctrl, 0, mask)) |
871 | ctrl_warn(ctrl, "Cannot disable software notification\n"); | 765 | ctrl_warn(ctrl, "Cannot disable software notification\n"); |
872 | } | 766 | } |
@@ -934,13 +828,13 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
934 | pdev->subsystem_device); | 828 | pdev->subsystem_device); |
935 | ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n", | 829 | ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n", |
936 | pdev->subsystem_vendor); | 830 | pdev->subsystem_vendor); |
937 | ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base); | 831 | ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", |
832 | pci_pcie_cap(pdev)); | ||
938 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 833 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
939 | if (!pci_resource_len(pdev, i)) | 834 | if (!pci_resource_len(pdev, i)) |
940 | continue; | 835 | continue; |
941 | ctrl_info(ctrl, " PCI resource [%d] : 0x%llx@0x%llx\n", | 836 | ctrl_info(ctrl, " PCI resource [%d] : %pR\n", |
942 | i, (unsigned long long)pci_resource_len(pdev, i), | 837 | i, &pdev->resource[i]); |
943 | (unsigned long long)pci_resource_start(pdev, i)); | ||
944 | } | 838 | } |
945 | ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); | 839 | ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); |
946 | ctrl_info(ctrl, " Physical Slot Number : %d\n", PSN(ctrl)); | 840 | ctrl_info(ctrl, " Physical Slot Number : %d\n", PSN(ctrl)); |
@@ -978,8 +872,7 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
978 | goto abort; | 872 | goto abort; |
979 | } | 873 | } |
980 | ctrl->pcie = dev; | 874 | ctrl->pcie = dev; |
981 | ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 875 | if (!pci_pcie_cap(pdev)) { |
982 | if (!ctrl->cap_base) { | ||
983 | ctrl_err(ctrl, "Cannot find PCI Express capability\n"); | 876 | ctrl_err(ctrl, "Cannot find PCI Express capability\n"); |
984 | goto abort_ctrl; | 877 | goto abort_ctrl; |
985 | } | 878 | } |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 21733108adde..0a16444c14c9 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -53,17 +53,15 @@ static int __ref pciehp_add_bridge(struct pci_dev *dev) | |||
53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); | 53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); |
54 | if (!dev->subordinate) | 54 | if (!dev->subordinate) |
55 | return -1; | 55 | return -1; |
56 | pci_bus_size_bridges(dev->subordinate); | 56 | |
57 | pci_bus_assign_resources(parent); | ||
58 | pci_enable_bridges(parent); | ||
59 | pci_bus_add_devices(parent); | ||
60 | return 0; | 57 | return 0; |
61 | } | 58 | } |
62 | 59 | ||
63 | int pciehp_configure_device(struct slot *p_slot) | 60 | int pciehp_configure_device(struct slot *p_slot) |
64 | { | 61 | { |
65 | struct pci_dev *dev; | 62 | struct pci_dev *dev; |
66 | struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; | 63 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
64 | struct pci_bus *parent = bridge->subordinate; | ||
67 | int num, fn; | 65 | int num, fn; |
68 | struct controller *ctrl = p_slot->ctrl; | 66 | struct controller *ctrl = p_slot->ctrl; |
69 | 67 | ||
@@ -96,12 +94,25 @@ int pciehp_configure_device(struct slot *p_slot) | |||
96 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 94 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
97 | pciehp_add_bridge(dev); | 95 | pciehp_add_bridge(dev); |
98 | } | 96 | } |
97 | pci_dev_put(dev); | ||
98 | } | ||
99 | |||
100 | pci_assign_unassigned_bridge_resources(bridge); | ||
101 | |||
102 | for (fn = 0; fn < 8; fn++) { | ||
103 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | ||
104 | if (!dev) | ||
105 | continue; | ||
106 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
107 | pci_dev_put(dev); | ||
108 | continue; | ||
109 | } | ||
99 | pci_configure_slot(dev); | 110 | pci_configure_slot(dev); |
100 | pci_dev_put(dev); | 111 | pci_dev_put(dev); |
101 | } | 112 | } |
102 | 113 | ||
103 | pci_bus_assign_resources(parent); | ||
104 | pci_bus_add_devices(parent); | 114 | pci_bus_add_devices(parent); |
115 | |||
105 | return 0; | 116 | return 0; |
106 | } | 117 | } |
107 | 118 | ||
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index cc8ec3aa41a7..80b461c98557 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c | |||
@@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) | |||
43 | * Perhaps we *should* use default settings for PCIe, but | 43 | * Perhaps we *should* use default settings for PCIe, but |
44 | * pciehp didn't, so we won't either. | 44 | * pciehp didn't, so we won't either. |
45 | */ | 45 | */ |
46 | if (dev->is_pcie) | 46 | if (pci_is_pcie(dev)) |
47 | return; | 47 | return; |
48 | dev_info(&dev->dev, "using default PCI settings\n"); | 48 | dev_info(&dev->dev, "using default PCI settings\n"); |
49 | hpp = &pci_default_type0; | 49 | hpp = &pci_default_type0; |
@@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | |||
102 | return; | 102 | return; |
103 | 103 | ||
104 | /* Find PCI Express capability */ | 104 | /* Find PCI Express capability */ |
105 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 105 | pos = pci_pcie_cap(dev); |
106 | if (!pos) | 106 | if (!pos) |
107 | return; | 107 | return; |
108 | 108 | ||
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 4e3e0382c16e..083034710fa6 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/vmalloc.h> | ||
23 | 24 | ||
24 | #include <asm/pci-bridge.h> | 25 | #include <asm/pci-bridge.h> |
25 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
@@ -430,6 +431,8 @@ int dlpar_remove_slot(char *drc_name) | |||
430 | rc = dlpar_remove_pci_slot(drc_name, dn); | 431 | rc = dlpar_remove_pci_slot(drc_name, dn); |
431 | break; | 432 | break; |
432 | } | 433 | } |
434 | vm_unmap_aliases(); | ||
435 | |||
433 | printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); | 436 | printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); |
434 | exit: | 437 | exit: |
435 | mutex_unlock(&rpadlpar_mutex); | 438 | mutex_unlock(&rpadlpar_mutex); |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index c159223389ec..ef7411c660b9 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/pci_hotplug.h> | 29 | #include <linux/pci_hotplug.h> |
30 | #include <linux/slab.h> | ||
31 | #include <linux/smp.h> | 30 | #include <linux/smp.h> |
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/vmalloc.h> | ||
33 | #include <asm/eeh.h> /* for eeh_add_device() */ | 33 | #include <asm/eeh.h> /* for eeh_add_device() */ |
34 | #include <asm/rtas.h> /* rtas_call */ | 34 | #include <asm/rtas.h> /* rtas_call */ |
35 | #include <asm/pci-bridge.h> /* for pci_controller */ | 35 | #include <asm/pci-bridge.h> /* for pci_controller */ |
@@ -130,10 +130,9 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) | |||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 133 | static enum pci_bus_speed get_max_bus_speed(struct slot *slot) |
134 | { | 134 | { |
135 | struct slot *slot = (struct slot *)hotplug_slot->private; | 135 | enum pci_bus_speed speed; |
136 | |||
137 | switch (slot->type) { | 136 | switch (slot->type) { |
138 | case 1: | 137 | case 1: |
139 | case 2: | 138 | case 2: |
@@ -141,30 +140,30 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe | |||
141 | case 4: | 140 | case 4: |
142 | case 5: | 141 | case 5: |
143 | case 6: | 142 | case 6: |
144 | *value = PCI_SPEED_33MHz; /* speed for case 1-6 */ | 143 | speed = PCI_SPEED_33MHz; /* speed for case 1-6 */ |
145 | break; | 144 | break; |
146 | case 7: | 145 | case 7: |
147 | case 8: | 146 | case 8: |
148 | *value = PCI_SPEED_66MHz; | 147 | speed = PCI_SPEED_66MHz; |
149 | break; | 148 | break; |
150 | case 11: | 149 | case 11: |
151 | case 14: | 150 | case 14: |
152 | *value = PCI_SPEED_66MHz_PCIX; | 151 | speed = PCI_SPEED_66MHz_PCIX; |
153 | break; | 152 | break; |
154 | case 12: | 153 | case 12: |
155 | case 15: | 154 | case 15: |
156 | *value = PCI_SPEED_100MHz_PCIX; | 155 | speed = PCI_SPEED_100MHz_PCIX; |
157 | break; | 156 | break; |
158 | case 13: | 157 | case 13: |
159 | case 16: | 158 | case 16: |
160 | *value = PCI_SPEED_133MHz_PCIX; | 159 | speed = PCI_SPEED_133MHz_PCIX; |
161 | break; | 160 | break; |
162 | default: | 161 | default: |
163 | *value = PCI_SPEED_UNKNOWN; | 162 | speed = PCI_SPEED_UNKNOWN; |
164 | break; | 163 | break; |
165 | |||
166 | } | 164 | } |
167 | return 0; | 165 | |
166 | return speed; | ||
168 | } | 167 | } |
169 | 168 | ||
170 | static int get_children_props(struct device_node *dn, const int **drc_indexes, | 169 | static int get_children_props(struct device_node *dn, const int **drc_indexes, |
@@ -408,6 +407,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
408 | slot->state = NOT_VALID; | 407 | slot->state = NOT_VALID; |
409 | return -EINVAL; | 408 | return -EINVAL; |
410 | } | 409 | } |
410 | |||
411 | slot->bus->max_bus_speed = get_max_bus_speed(slot); | ||
411 | return 0; | 412 | return 0; |
412 | } | 413 | } |
413 | 414 | ||
@@ -418,6 +419,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
418 | return -EINVAL; | 419 | return -EINVAL; |
419 | 420 | ||
420 | pcibios_remove_pci_devices(slot->bus); | 421 | pcibios_remove_pci_devices(slot->bus); |
422 | vm_unmap_aliases(); | ||
423 | |||
421 | slot->state = NOT_CONFIGURED; | 424 | slot->state = NOT_CONFIGURED; |
422 | return 0; | 425 | return 0; |
423 | } | 426 | } |
@@ -429,7 +432,6 @@ struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { | |||
429 | .get_power_status = get_power_status, | 432 | .get_power_status = get_power_status, |
430 | .get_attention_status = get_attention_status, | 433 | .get_attention_status = get_attention_status, |
431 | .get_adapter_status = get_adapter_status, | 434 | .get_adapter_status = get_adapter_status, |
432 | .get_max_bus_speed = get_max_bus_speed, | ||
433 | }; | 435 | }; |
434 | 436 | ||
435 | module_init(rpaphp_init); | 437 | module_init(rpaphp_init); |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 8aebe1e9d3d6..72d507b6a2aa 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/pci_hotplug.h> | 16 | #include <linux/pci_hotplug.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
19 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
20 | 21 | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index bd588eb8e922..d2627e1c3ac1 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -121,7 +121,7 @@ struct controller { | |||
121 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 | 121 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 |
122 | #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 | 122 | #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 |
123 | 123 | ||
124 | /* AMD PCIX bridge registers */ | 124 | /* AMD PCI-X bridge registers */ |
125 | #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C | 125 | #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C |
126 | #define PCIX_MISCII_OFFSET 0x48 | 126 | #define PCIX_MISCII_OFFSET 0x48 |
127 | #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 | 127 | #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 |
@@ -333,8 +333,6 @@ struct hpc_ops { | |||
333 | int (*set_attention_status)(struct slot *slot, u8 status); | 333 | int (*set_attention_status)(struct slot *slot, u8 status); |
334 | int (*get_latch_status)(struct slot *slot, u8 *status); | 334 | int (*get_latch_status)(struct slot *slot, u8 *status); |
335 | int (*get_adapter_status)(struct slot *slot, u8 *status); | 335 | int (*get_adapter_status)(struct slot *slot, u8 *status); |
336 | int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
337 | int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
338 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); | 336 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); |
339 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); | 337 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); |
340 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); | 338 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 8a520a3d0f59..a7bd5048396e 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
35 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
36 | #include "shpchp.h" | 37 | #include "shpchp.h" |
@@ -65,8 +66,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 66 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 67 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 68 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
68 | 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 | 69 | ||
71 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | 70 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { |
72 | .set_attention_status = set_attention_status, | 71 | .set_attention_status = set_attention_status, |
@@ -76,8 +75,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | |||
76 | .get_attention_status = get_attention_status, | 75 | .get_attention_status = get_attention_status, |
77 | .get_latch_status = get_latch_status, | 76 | .get_latch_status = get_latch_status, |
78 | .get_adapter_status = get_adapter_status, | 77 | .get_adapter_status = get_adapter_status, |
79 | .get_max_bus_speed = get_max_bus_speed, | ||
80 | .get_cur_bus_speed = get_cur_bus_speed, | ||
81 | }; | 78 | }; |
82 | 79 | ||
83 | /** | 80 | /** |
@@ -279,37 +276,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
279 | return 0; | 276 | return 0; |
280 | } | 277 | } |
281 | 278 | ||
282 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
283 | enum pci_bus_speed *value) | ||
284 | { | ||
285 | struct slot *slot = get_slot(hotplug_slot); | ||
286 | int retval; | ||
287 | |||
288 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
289 | __func__, slot_name(slot)); | ||
290 | |||
291 | retval = slot->hpc_ops->get_max_bus_speed(slot, value); | ||
292 | if (retval < 0) | ||
293 | *value = PCI_SPEED_UNKNOWN; | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
299 | { | ||
300 | struct slot *slot = get_slot(hotplug_slot); | ||
301 | int retval; | ||
302 | |||
303 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
304 | __func__, slot_name(slot)); | ||
305 | |||
306 | retval = slot->hpc_ops->get_cur_bus_speed(slot, value); | ||
307 | if (retval < 0) | ||
308 | *value = PCI_SPEED_UNKNOWN; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int is_shpc_capable(struct pci_dev *dev) | 279 | static int is_shpc_capable(struct pci_dev *dev) |
314 | { | 280 | { |
315 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == | 281 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b8ab2796e66a..3387fbfb0c54 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
34 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
35 | #include "../pci.h" | 36 | #include "../pci.h" |
@@ -285,17 +286,8 @@ static int board_added(struct slot *p_slot) | |||
285 | return WRONG_BUS_FREQUENCY; | 286 | return WRONG_BUS_FREQUENCY; |
286 | } | 287 | } |
287 | 288 | ||
288 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); | 289 | bsp = ctrl->pci_dev->bus->cur_bus_speed; |
289 | if (rc) { | 290 | msp = ctrl->pci_dev->bus->max_bus_speed; |
290 | ctrl_err(ctrl, "Can't get bus operation speed\n"); | ||
291 | return WRONG_BUS_FREQUENCY; | ||
292 | } | ||
293 | |||
294 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); | ||
295 | if (rc) { | ||
296 | ctrl_err(ctrl, "Can't get max bus operation speed\n"); | ||
297 | msp = bsp; | ||
298 | } | ||
299 | 291 | ||
300 | /* Check if there are other slots or devices on the same bus */ | 292 | /* Check if there are other slots or devices on the same bus */ |
301 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) | 293 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) |
@@ -462,6 +454,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) | |||
462 | p_slot->state = POWERON_STATE; | 454 | p_slot->state = POWERON_STATE; |
463 | break; | 455 | break; |
464 | default: | 456 | default: |
457 | kfree(info); | ||
465 | goto out; | 458 | goto out; |
466 | } | 459 | } |
467 | queue_work(shpchp_wq, &info->work); | 460 | queue_work(shpchp_wq, &info->work); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 86dc39847769..5f5e8d2e3552 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -660,6 +660,75 @@ static int hpc_slot_disable(struct slot * slot) | |||
660 | return retval; | 660 | return retval; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int shpc_get_cur_bus_speed(struct controller *ctrl) | ||
664 | { | ||
665 | int retval = 0; | ||
666 | struct pci_bus *bus = ctrl->pci_dev->subordinate; | ||
667 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
668 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
669 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
670 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
671 | |||
672 | if ((pi == 1) && (speed_mode > 4)) { | ||
673 | retval = -ENODEV; | ||
674 | goto out; | ||
675 | } | ||
676 | |||
677 | switch (speed_mode) { | ||
678 | case 0x0: | ||
679 | bus_speed = PCI_SPEED_33MHz; | ||
680 | break; | ||
681 | case 0x1: | ||
682 | bus_speed = PCI_SPEED_66MHz; | ||
683 | break; | ||
684 | case 0x2: | ||
685 | bus_speed = PCI_SPEED_66MHz_PCIX; | ||
686 | break; | ||
687 | case 0x3: | ||
688 | bus_speed = PCI_SPEED_100MHz_PCIX; | ||
689 | break; | ||
690 | case 0x4: | ||
691 | bus_speed = PCI_SPEED_133MHz_PCIX; | ||
692 | break; | ||
693 | case 0x5: | ||
694 | bus_speed = PCI_SPEED_66MHz_PCIX_ECC; | ||
695 | break; | ||
696 | case 0x6: | ||
697 | bus_speed = PCI_SPEED_100MHz_PCIX_ECC; | ||
698 | break; | ||
699 | case 0x7: | ||
700 | bus_speed = PCI_SPEED_133MHz_PCIX_ECC; | ||
701 | break; | ||
702 | case 0x8: | ||
703 | bus_speed = PCI_SPEED_66MHz_PCIX_266; | ||
704 | break; | ||
705 | case 0x9: | ||
706 | bus_speed = PCI_SPEED_100MHz_PCIX_266; | ||
707 | break; | ||
708 | case 0xa: | ||
709 | bus_speed = PCI_SPEED_133MHz_PCIX_266; | ||
710 | break; | ||
711 | case 0xb: | ||
712 | bus_speed = PCI_SPEED_66MHz_PCIX_533; | ||
713 | break; | ||
714 | case 0xc: | ||
715 | bus_speed = PCI_SPEED_100MHz_PCIX_533; | ||
716 | break; | ||
717 | case 0xd: | ||
718 | bus_speed = PCI_SPEED_133MHz_PCIX_533; | ||
719 | break; | ||
720 | default: | ||
721 | retval = -ENODEV; | ||
722 | break; | ||
723 | } | ||
724 | |||
725 | out: | ||
726 | bus->cur_bus_speed = bus_speed; | ||
727 | dbg("Current bus speed = %d\n", bus_speed); | ||
728 | return retval; | ||
729 | } | ||
730 | |||
731 | |||
663 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | 732 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) |
664 | { | 733 | { |
665 | int retval; | 734 | int retval; |
@@ -720,6 +789,8 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
720 | retval = shpc_write_cmd(slot, 0, cmd); | 789 | retval = shpc_write_cmd(slot, 0, cmd); |
721 | if (retval) | 790 | if (retval) |
722 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); | 791 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); |
792 | else | ||
793 | shpc_get_cur_bus_speed(ctrl); | ||
723 | 794 | ||
724 | return retval; | 795 | return retval; |
725 | } | 796 | } |
@@ -803,10 +874,10 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
803 | return IRQ_HANDLED; | 874 | return IRQ_HANDLED; |
804 | } | 875 | } |
805 | 876 | ||
806 | static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | 877 | static int shpc_get_max_bus_speed(struct controller *ctrl) |
807 | { | 878 | { |
808 | int retval = 0; | 879 | int retval = 0; |
809 | struct controller *ctrl = slot->ctrl; | 880 | struct pci_bus *bus = ctrl->pci_dev->subordinate; |
810 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | 881 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; |
811 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | 882 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); |
812 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); | 883 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); |
@@ -842,79 +913,12 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
842 | retval = -ENODEV; | 913 | retval = -ENODEV; |
843 | } | 914 | } |
844 | 915 | ||
845 | *value = bus_speed; | 916 | bus->max_bus_speed = bus_speed; |
846 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); | 917 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); |
847 | 918 | ||
848 | return retval; | 919 | return retval; |
849 | } | 920 | } |
850 | 921 | ||
851 | static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | ||
852 | { | ||
853 | int retval = 0; | ||
854 | struct controller *ctrl = slot->ctrl; | ||
855 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
856 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
857 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
858 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
859 | |||
860 | if ((pi == 1) && (speed_mode > 4)) { | ||
861 | *value = PCI_SPEED_UNKNOWN; | ||
862 | return -ENODEV; | ||
863 | } | ||
864 | |||
865 | switch (speed_mode) { | ||
866 | case 0x0: | ||
867 | *value = PCI_SPEED_33MHz; | ||
868 | break; | ||
869 | case 0x1: | ||
870 | *value = PCI_SPEED_66MHz; | ||
871 | break; | ||
872 | case 0x2: | ||
873 | *value = PCI_SPEED_66MHz_PCIX; | ||
874 | break; | ||
875 | case 0x3: | ||
876 | *value = PCI_SPEED_100MHz_PCIX; | ||
877 | break; | ||
878 | case 0x4: | ||
879 | *value = PCI_SPEED_133MHz_PCIX; | ||
880 | break; | ||
881 | case 0x5: | ||
882 | *value = PCI_SPEED_66MHz_PCIX_ECC; | ||
883 | break; | ||
884 | case 0x6: | ||
885 | *value = PCI_SPEED_100MHz_PCIX_ECC; | ||
886 | break; | ||
887 | case 0x7: | ||
888 | *value = PCI_SPEED_133MHz_PCIX_ECC; | ||
889 | break; | ||
890 | case 0x8: | ||
891 | *value = PCI_SPEED_66MHz_PCIX_266; | ||
892 | break; | ||
893 | case 0x9: | ||
894 | *value = PCI_SPEED_100MHz_PCIX_266; | ||
895 | break; | ||
896 | case 0xa: | ||
897 | *value = PCI_SPEED_133MHz_PCIX_266; | ||
898 | break; | ||
899 | case 0xb: | ||
900 | *value = PCI_SPEED_66MHz_PCIX_533; | ||
901 | break; | ||
902 | case 0xc: | ||
903 | *value = PCI_SPEED_100MHz_PCIX_533; | ||
904 | break; | ||
905 | case 0xd: | ||
906 | *value = PCI_SPEED_133MHz_PCIX_533; | ||
907 | break; | ||
908 | default: | ||
909 | *value = PCI_SPEED_UNKNOWN; | ||
910 | retval = -ENODEV; | ||
911 | break; | ||
912 | } | ||
913 | |||
914 | ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed); | ||
915 | return retval; | ||
916 | } | ||
917 | |||
918 | static struct hpc_ops shpchp_hpc_ops = { | 922 | static struct hpc_ops shpchp_hpc_ops = { |
919 | .power_on_slot = hpc_power_on_slot, | 923 | .power_on_slot = hpc_power_on_slot, |
920 | .slot_enable = hpc_slot_enable, | 924 | .slot_enable = hpc_slot_enable, |
@@ -926,8 +930,6 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
926 | .get_latch_status = hpc_get_latch_status, | 930 | .get_latch_status = hpc_get_latch_status, |
927 | .get_adapter_status = hpc_get_adapter_status, | 931 | .get_adapter_status = hpc_get_adapter_status, |
928 | 932 | ||
929 | .get_max_bus_speed = hpc_get_max_bus_speed, | ||
930 | .get_cur_bus_speed = hpc_get_cur_bus_speed, | ||
931 | .get_adapter_speed = hpc_get_adapter_speed, | 933 | .get_adapter_speed = hpc_get_adapter_speed, |
932 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, | 934 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, |
933 | .get_prog_int = hpc_get_prog_int, | 935 | .get_prog_int = hpc_get_prog_int, |
@@ -1086,6 +1088,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
1086 | } | 1088 | } |
1087 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); | 1089 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); |
1088 | 1090 | ||
1091 | shpc_get_max_bus_speed(ctrl); | ||
1092 | shpc_get_cur_bus_speed(ctrl); | ||
1093 | |||
1089 | /* | 1094 | /* |
1090 | * If this is the first controller to be initialized, | 1095 | * If this is the first controller to be initialized, |
1091 | * initialize the shpchpd work queue | 1096 | * initialize the shpchpd work queue |
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 29fa9d26adae..071b7dc0094b 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c | |||
@@ -47,8 +47,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
47 | bus = pdev->subordinate; | 47 | bus = pdev->subordinate; |
48 | 48 | ||
49 | out += sprintf(buf, "Free resources: memory\n"); | 49 | out += sprintf(buf, "Free resources: memory\n"); |
50 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 50 | pci_bus_for_each_resource(bus, res, index) { |
51 | res = bus->resource[index]; | ||
52 | if (res && (res->flags & IORESOURCE_MEM) && | 51 | if (res && (res->flags & IORESOURCE_MEM) && |
53 | !(res->flags & IORESOURCE_PREFETCH)) { | 52 | !(res->flags & IORESOURCE_PREFETCH)) { |
54 | out += sprintf(out, "start = %8.8llx, " | 53 | out += sprintf(out, "start = %8.8llx, " |
@@ -58,8 +57,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
58 | } | 57 | } |
59 | } | 58 | } |
60 | out += sprintf(out, "Free resources: prefetchable memory\n"); | 59 | out += sprintf(out, "Free resources: prefetchable memory\n"); |
61 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 60 | pci_bus_for_each_resource(bus, res, index) { |
62 | res = bus->resource[index]; | ||
63 | if (res && (res->flags & IORESOURCE_MEM) && | 61 | if (res && (res->flags & IORESOURCE_MEM) && |
64 | (res->flags & IORESOURCE_PREFETCH)) { | 62 | (res->flags & IORESOURCE_PREFETCH)) { |
65 | out += sprintf(out, "start = %8.8llx, " | 63 | out += sprintf(out, "start = %8.8llx, " |
@@ -69,8 +67,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
69 | } | 67 | } |
70 | } | 68 | } |
71 | out += sprintf(out, "Free resources: IO\n"); | 69 | out += sprintf(out, "Free resources: IO\n"); |
72 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 70 | pci_bus_for_each_resource(bus, res, index) { |
73 | res = bus->resource[index]; | ||
74 | if (res && (res->flags & IORESOURCE_IO)) { | 71 | if (res && (res->flags & IORESOURCE_IO)) { |
75 | out += sprintf(out, "start = %8.8llx, " | 72 | out += sprintf(out, "start = %8.8llx, " |
76 | "length = %8.8llx\n", | 73 | "length = %8.8llx\n", |