diff options
Diffstat (limited to 'arch/ppc64/kernel/eeh.c')
-rw-r--r-- | arch/ppc64/kernel/eeh.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index 4c857a6516fc..ba93fd731222 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c | |||
@@ -254,6 +254,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
254 | static void __pci_addr_cache_insert_device(struct pci_dev *dev) | 254 | static void __pci_addr_cache_insert_device(struct pci_dev *dev) |
255 | { | 255 | { |
256 | struct device_node *dn; | 256 | struct device_node *dn; |
257 | struct pci_dn *pdn; | ||
257 | int i; | 258 | int i; |
258 | int inserted = 0; | 259 | int inserted = 0; |
259 | 260 | ||
@@ -265,8 +266,9 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
265 | } | 266 | } |
266 | 267 | ||
267 | /* Skip any devices for which EEH is not enabled. */ | 268 | /* Skip any devices for which EEH is not enabled. */ |
268 | if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || | 269 | pdn = dn->data; |
269 | dn->eeh_mode & EEH_MODE_NOCHECK) { | 270 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
271 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | ||
270 | #ifdef DEBUG | 272 | #ifdef DEBUG |
271 | printk(KERN_INFO "PCI: skip building address cache for=%s\n", | 273 | printk(KERN_INFO "PCI: skip building address cache for=%s\n", |
272 | pci_name(dev)); | 274 | pci_name(dev)); |
@@ -415,6 +417,7 @@ int eeh_unregister_notifier(struct notifier_block *nb) | |||
415 | static int read_slot_reset_state(struct device_node *dn, int rets[]) | 417 | static int read_slot_reset_state(struct device_node *dn, int rets[]) |
416 | { | 418 | { |
417 | int token, outputs; | 419 | int token, outputs; |
420 | struct pci_dn *pdn = dn->data; | ||
418 | 421 | ||
419 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { | 422 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { |
420 | token = ibm_read_slot_reset_state2; | 423 | token = ibm_read_slot_reset_state2; |
@@ -424,8 +427,8 @@ static int read_slot_reset_state(struct device_node *dn, int rets[]) | |||
424 | outputs = 3; | 427 | outputs = 3; |
425 | } | 428 | } |
426 | 429 | ||
427 | return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr, | 430 | return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr, |
428 | BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); | 431 | BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); |
429 | } | 432 | } |
430 | 433 | ||
431 | /** | 434 | /** |
@@ -534,6 +537,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
534 | unsigned long flags; | 537 | unsigned long flags; |
535 | int rc, reset_state; | 538 | int rc, reset_state; |
536 | struct eeh_event *event; | 539 | struct eeh_event *event; |
540 | struct pci_dn *pdn; | ||
537 | 541 | ||
538 | __get_cpu_var(total_mmio_ffs)++; | 542 | __get_cpu_var(total_mmio_ffs)++; |
539 | 543 | ||
@@ -542,14 +546,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
542 | 546 | ||
543 | if (!dn) | 547 | if (!dn) |
544 | return 0; | 548 | return 0; |
549 | pdn = dn->data; | ||
545 | 550 | ||
546 | /* Access to IO BARs might get this far and still not want checking. */ | 551 | /* Access to IO BARs might get this far and still not want checking. */ |
547 | if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || | 552 | if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
548 | dn->eeh_mode & EEH_MODE_NOCHECK) { | 553 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
549 | return 0; | 554 | return 0; |
550 | } | 555 | } |
551 | 556 | ||
552 | if (!dn->eeh_config_addr) { | 557 | if (!pdn->eeh_config_addr) { |
553 | return 0; | 558 | return 0; |
554 | } | 559 | } |
555 | 560 | ||
@@ -557,7 +562,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
557 | * If we already have a pending isolation event for this | 562 | * If we already have a pending isolation event for this |
558 | * slot, we know it's bad already, we don't need to check... | 563 | * slot, we know it's bad already, we don't need to check... |
559 | */ | 564 | */ |
560 | if (dn->eeh_mode & EEH_MODE_ISOLATED) { | 565 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { |
561 | atomic_inc(&eeh_fail_count); | 566 | atomic_inc(&eeh_fail_count); |
562 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { | 567 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { |
563 | /* re-read the slot reset state */ | 568 | /* re-read the slot reset state */ |
@@ -582,7 +587,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
582 | } | 587 | } |
583 | 588 | ||
584 | /* prevent repeated reports of this failure */ | 589 | /* prevent repeated reports of this failure */ |
585 | dn->eeh_mode |= EEH_MODE_ISOLATED; | 590 | pdn->eeh_mode |= EEH_MODE_ISOLATED; |
586 | 591 | ||
587 | reset_state = rets[0]; | 592 | reset_state = rets[0]; |
588 | 593 | ||
@@ -590,9 +595,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
590 | memset(slot_errbuf, 0, eeh_error_buf_size); | 595 | memset(slot_errbuf, 0, eeh_error_buf_size); |
591 | 596 | ||
592 | rc = rtas_call(ibm_slot_error_detail, | 597 | rc = rtas_call(ibm_slot_error_detail, |
593 | 8, 1, NULL, dn->eeh_config_addr, | 598 | 8, 1, NULL, pdn->eeh_config_addr, |
594 | BUID_HI(dn->phb->buid), | 599 | BUID_HI(pdn->phb->buid), |
595 | BUID_LO(dn->phb->buid), NULL, 0, | 600 | BUID_LO(pdn->phb->buid), NULL, 0, |
596 | virt_to_phys(slot_errbuf), | 601 | virt_to_phys(slot_errbuf), |
597 | eeh_error_buf_size, | 602 | eeh_error_buf_size, |
598 | 1 /* Temporary Error */); | 603 | 1 /* Temporary Error */); |
@@ -679,8 +684,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
679 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); | 684 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); |
680 | u32 *regs; | 685 | u32 *regs; |
681 | int enable; | 686 | int enable; |
687 | struct pci_dn *pdn = dn->data; | ||
682 | 688 | ||
683 | dn->eeh_mode = 0; | 689 | pdn->eeh_mode = 0; |
684 | 690 | ||
685 | if (status && strcmp(status, "ok") != 0) | 691 | if (status && strcmp(status, "ok") != 0) |
686 | return NULL; /* ignore devices with bad status */ | 692 | return NULL; /* ignore devices with bad status */ |
@@ -691,7 +697,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
691 | 697 | ||
692 | /* There is nothing to check on PCI to ISA bridges */ | 698 | /* There is nothing to check on PCI to ISA bridges */ |
693 | if (dn->type && !strcmp(dn->type, "isa")) { | 699 | if (dn->type && !strcmp(dn->type, "isa")) { |
694 | dn->eeh_mode |= EEH_MODE_NOCHECK; | 700 | pdn->eeh_mode |= EEH_MODE_NOCHECK; |
695 | return NULL; | 701 | return NULL; |
696 | } | 702 | } |
697 | 703 | ||
@@ -708,7 +714,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
708 | enable = 0; | 714 | enable = 0; |
709 | 715 | ||
710 | if (!enable) | 716 | if (!enable) |
711 | dn->eeh_mode |= EEH_MODE_NOCHECK; | 717 | pdn->eeh_mode |= EEH_MODE_NOCHECK; |
712 | 718 | ||
713 | /* Ok... see if this device supports EEH. Some do, some don't, | 719 | /* Ok... see if this device supports EEH. Some do, some don't, |
714 | * and the only way to find out is to check each and every one. */ | 720 | * and the only way to find out is to check each and every one. */ |
@@ -721,8 +727,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
721 | EEH_ENABLE); | 727 | EEH_ENABLE); |
722 | if (ret == 0) { | 728 | if (ret == 0) { |
723 | eeh_subsystem_enabled = 1; | 729 | eeh_subsystem_enabled = 1; |
724 | dn->eeh_mode |= EEH_MODE_SUPPORTED; | 730 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
725 | dn->eeh_config_addr = regs[0]; | 731 | pdn->eeh_config_addr = regs[0]; |
726 | #ifdef DEBUG | 732 | #ifdef DEBUG |
727 | printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); | 733 | printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); |
728 | #endif | 734 | #endif |
@@ -730,10 +736,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
730 | 736 | ||
731 | /* This device doesn't support EEH, but it may have an | 737 | /* This device doesn't support EEH, but it may have an |
732 | * EEH parent, in which case we mark it as supported. */ | 738 | * EEH parent, in which case we mark it as supported. */ |
733 | if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) { | 739 | if (dn->parent && dn->parent->data |
740 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | ||
734 | /* Parent supports EEH. */ | 741 | /* Parent supports EEH. */ |
735 | dn->eeh_mode |= EEH_MODE_SUPPORTED; | 742 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
736 | dn->eeh_config_addr = dn->parent->eeh_config_addr; | 743 | pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr; |
737 | return NULL; | 744 | return NULL; |
738 | } | 745 | } |
739 | } | 746 | } |
@@ -790,11 +797,13 @@ void __init eeh_init(void) | |||
790 | for (phb = of_find_node_by_name(NULL, "pci"); phb; | 797 | for (phb = of_find_node_by_name(NULL, "pci"); phb; |
791 | phb = of_find_node_by_name(phb, "pci")) { | 798 | phb = of_find_node_by_name(phb, "pci")) { |
792 | unsigned long buid; | 799 | unsigned long buid; |
800 | struct pci_dn *pci; | ||
793 | 801 | ||
794 | buid = get_phb_buid(phb); | 802 | buid = get_phb_buid(phb); |
795 | if (buid == 0) | 803 | if (buid == 0 || phb->data == NULL) |
796 | continue; | 804 | continue; |
797 | 805 | ||
806 | pci = phb->data; | ||
798 | info.buid_lo = BUID_LO(buid); | 807 | info.buid_lo = BUID_LO(buid); |
799 | info.buid_hi = BUID_HI(buid); | 808 | info.buid_hi = BUID_HI(buid); |
800 | traverse_pci_devices(phb, early_enable_eeh, &info); | 809 | traverse_pci_devices(phb, early_enable_eeh, &info); |
@@ -823,9 +832,9 @@ void eeh_add_device_early(struct device_node *dn) | |||
823 | struct pci_controller *phb; | 832 | struct pci_controller *phb; |
824 | struct eeh_early_enable_info info; | 833 | struct eeh_early_enable_info info; |
825 | 834 | ||
826 | if (!dn) | 835 | if (!dn || !dn->data) |
827 | return; | 836 | return; |
828 | phb = dn->phb; | 837 | phb = PCI_DN(dn)->phb; |
829 | if (NULL == phb || 0 == phb->buid) { | 838 | if (NULL == phb || 0 == phb->buid) { |
830 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); | 839 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); |
831 | return; | 840 | return; |