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; |
