diff options
Diffstat (limited to 'arch/ppc64/kernel/eeh.c')
-rw-r--r-- | arch/ppc64/kernel/eeh.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index af5272fedadf..ba93fd731222 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c | |||
@@ -202,10 +202,9 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache) | |||
202 | while (n) { | 202 | while (n) { |
203 | struct pci_io_addr_range *piar; | 203 | struct pci_io_addr_range *piar; |
204 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); | 204 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); |
205 | printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s %s\n", | 205 | printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n", |
206 | (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt, | 206 | (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt, |
207 | piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev), | 207 | piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev)); |
208 | pci_pretty_name(piar->pcidev)); | ||
209 | cnt++; | 208 | cnt++; |
210 | n = rb_next(n); | 209 | n = rb_next(n); |
211 | } | 210 | } |
@@ -255,22 +254,24 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
255 | static void __pci_addr_cache_insert_device(struct pci_dev *dev) | 254 | static void __pci_addr_cache_insert_device(struct pci_dev *dev) |
256 | { | 255 | { |
257 | struct device_node *dn; | 256 | struct device_node *dn; |
257 | struct pci_dn *pdn; | ||
258 | int i; | 258 | int i; |
259 | int inserted = 0; | 259 | int inserted = 0; |
260 | 260 | ||
261 | dn = pci_device_to_OF_node(dev); | 261 | dn = pci_device_to_OF_node(dev); |
262 | if (!dn) { | 262 | if (!dn) { |
263 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s %s\n", | 263 | printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", |
264 | pci_name(dev), pci_pretty_name(dev)); | 264 | pci_name(dev)); |
265 | return; | 265 | return; |
266 | } | 266 | } |
267 | 267 | ||
268 | /* Skip any devices for which EEH is not enabled. */ | 268 | /* Skip any devices for which EEH is not enabled. */ |
269 | if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || | 269 | pdn = dn->data; |
270 | dn->eeh_mode & EEH_MODE_NOCHECK) { | 270 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
271 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | ||
271 | #ifdef DEBUG | 272 | #ifdef DEBUG |
272 | printk(KERN_INFO "PCI: skip building address cache for=%s %s\n", | 273 | printk(KERN_INFO "PCI: skip building address cache for=%s\n", |
273 | pci_name(dev), pci_pretty_name(dev)); | 274 | pci_name(dev)); |
274 | #endif | 275 | #endif |
275 | return; | 276 | return; |
276 | } | 277 | } |
@@ -416,6 +417,7 @@ int eeh_unregister_notifier(struct notifier_block *nb) | |||
416 | 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[]) |
417 | { | 418 | { |
418 | int token, outputs; | 419 | int token, outputs; |
420 | struct pci_dn *pdn = dn->data; | ||
419 | 421 | ||
420 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { | 422 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { |
421 | token = ibm_read_slot_reset_state2; | 423 | token = ibm_read_slot_reset_state2; |
@@ -425,8 +427,8 @@ static int read_slot_reset_state(struct device_node *dn, int rets[]) | |||
425 | outputs = 3; | 427 | outputs = 3; |
426 | } | 428 | } |
427 | 429 | ||
428 | return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr, | 430 | return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr, |
429 | BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); | 431 | BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); |
430 | } | 432 | } |
431 | 433 | ||
432 | /** | 434 | /** |
@@ -447,12 +449,12 @@ static void eeh_panic(struct pci_dev *dev, int reset_state) | |||
447 | * in light of potential corruption, we can use it here. | 449 | * in light of potential corruption, we can use it here. |
448 | */ | 450 | */ |
449 | if (panic_on_oops) | 451 | if (panic_on_oops) |
450 | panic("EEH: MMIO failure (%d) on device:%s %s\n", reset_state, | 452 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, |
451 | pci_name(dev), pci_pretty_name(dev)); | 453 | pci_name(dev)); |
452 | else { | 454 | else { |
453 | __get_cpu_var(ignored_failures)++; | 455 | __get_cpu_var(ignored_failures)++; |
454 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s %s\n", | 456 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", |
455 | reset_state, pci_name(dev), pci_pretty_name(dev)); | 457 | reset_state, pci_name(dev)); |
456 | } | 458 | } |
457 | } | 459 | } |
458 | 460 | ||
@@ -482,8 +484,8 @@ static void eeh_event_handler(void *dummy) | |||
482 | break; | 484 | break; |
483 | 485 | ||
484 | printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device " | 486 | printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device " |
485 | "%s %s\n", event->reset_state, | 487 | "%s\n", event->reset_state, |
486 | pci_name(event->dev), pci_pretty_name(event->dev)); | 488 | pci_name(event->dev)); |
487 | 489 | ||
488 | atomic_set(&eeh_fail_count, 0); | 490 | atomic_set(&eeh_fail_count, 0); |
489 | notifier_call_chain (&eeh_notifier_chain, | 491 | notifier_call_chain (&eeh_notifier_chain, |
@@ -535,6 +537,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
535 | unsigned long flags; | 537 | unsigned long flags; |
536 | int rc, reset_state; | 538 | int rc, reset_state; |
537 | struct eeh_event *event; | 539 | struct eeh_event *event; |
540 | struct pci_dn *pdn; | ||
538 | 541 | ||
539 | __get_cpu_var(total_mmio_ffs)++; | 542 | __get_cpu_var(total_mmio_ffs)++; |
540 | 543 | ||
@@ -543,14 +546,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
543 | 546 | ||
544 | if (!dn) | 547 | if (!dn) |
545 | return 0; | 548 | return 0; |
549 | pdn = dn->data; | ||
546 | 550 | ||
547 | /* 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. */ |
548 | if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || | 552 | if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || |
549 | dn->eeh_mode & EEH_MODE_NOCHECK) { | 553 | pdn->eeh_mode & EEH_MODE_NOCHECK) { |
550 | return 0; | 554 | return 0; |
551 | } | 555 | } |
552 | 556 | ||
553 | if (!dn->eeh_config_addr) { | 557 | if (!pdn->eeh_config_addr) { |
554 | return 0; | 558 | return 0; |
555 | } | 559 | } |
556 | 560 | ||
@@ -558,7 +562,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
558 | * If we already have a pending isolation event for this | 562 | * If we already have a pending isolation event for this |
559 | * 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... |
560 | */ | 564 | */ |
561 | if (dn->eeh_mode & EEH_MODE_ISOLATED) { | 565 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { |
562 | atomic_inc(&eeh_fail_count); | 566 | atomic_inc(&eeh_fail_count); |
563 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { | 567 | if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { |
564 | /* re-read the slot reset state */ | 568 | /* re-read the slot reset state */ |
@@ -583,7 +587,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
583 | } | 587 | } |
584 | 588 | ||
585 | /* prevent repeated reports of this failure */ | 589 | /* prevent repeated reports of this failure */ |
586 | dn->eeh_mode |= EEH_MODE_ISOLATED; | 590 | pdn->eeh_mode |= EEH_MODE_ISOLATED; |
587 | 591 | ||
588 | reset_state = rets[0]; | 592 | reset_state = rets[0]; |
589 | 593 | ||
@@ -591,9 +595,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
591 | memset(slot_errbuf, 0, eeh_error_buf_size); | 595 | memset(slot_errbuf, 0, eeh_error_buf_size); |
592 | 596 | ||
593 | rc = rtas_call(ibm_slot_error_detail, | 597 | rc = rtas_call(ibm_slot_error_detail, |
594 | 8, 1, NULL, dn->eeh_config_addr, | 598 | 8, 1, NULL, pdn->eeh_config_addr, |
595 | BUID_HI(dn->phb->buid), | 599 | BUID_HI(pdn->phb->buid), |
596 | BUID_LO(dn->phb->buid), NULL, 0, | 600 | BUID_LO(pdn->phb->buid), NULL, 0, |
597 | virt_to_phys(slot_errbuf), | 601 | virt_to_phys(slot_errbuf), |
598 | eeh_error_buf_size, | 602 | eeh_error_buf_size, |
599 | 1 /* Temporary Error */); | 603 | 1 /* Temporary Error */); |
@@ -680,8 +684,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
680 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); | 684 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); |
681 | u32 *regs; | 685 | u32 *regs; |
682 | int enable; | 686 | int enable; |
687 | struct pci_dn *pdn = dn->data; | ||
683 | 688 | ||
684 | dn->eeh_mode = 0; | 689 | pdn->eeh_mode = 0; |
685 | 690 | ||
686 | if (status && strcmp(status, "ok") != 0) | 691 | if (status && strcmp(status, "ok") != 0) |
687 | return NULL; /* ignore devices with bad status */ | 692 | return NULL; /* ignore devices with bad status */ |
@@ -692,7 +697,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
692 | 697 | ||
693 | /* There is nothing to check on PCI to ISA bridges */ | 698 | /* There is nothing to check on PCI to ISA bridges */ |
694 | if (dn->type && !strcmp(dn->type, "isa")) { | 699 | if (dn->type && !strcmp(dn->type, "isa")) { |
695 | dn->eeh_mode |= EEH_MODE_NOCHECK; | 700 | pdn->eeh_mode |= EEH_MODE_NOCHECK; |
696 | return NULL; | 701 | return NULL; |
697 | } | 702 | } |
698 | 703 | ||
@@ -709,7 +714,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
709 | enable = 0; | 714 | enable = 0; |
710 | 715 | ||
711 | if (!enable) | 716 | if (!enable) |
712 | dn->eeh_mode |= EEH_MODE_NOCHECK; | 717 | pdn->eeh_mode |= EEH_MODE_NOCHECK; |
713 | 718 | ||
714 | /* 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, |
715 | * 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. */ |
@@ -722,8 +727,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
722 | EEH_ENABLE); | 727 | EEH_ENABLE); |
723 | if (ret == 0) { | 728 | if (ret == 0) { |
724 | eeh_subsystem_enabled = 1; | 729 | eeh_subsystem_enabled = 1; |
725 | dn->eeh_mode |= EEH_MODE_SUPPORTED; | 730 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
726 | dn->eeh_config_addr = regs[0]; | 731 | pdn->eeh_config_addr = regs[0]; |
727 | #ifdef DEBUG | 732 | #ifdef DEBUG |
728 | printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); | 733 | printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); |
729 | #endif | 734 | #endif |
@@ -731,10 +736,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
731 | 736 | ||
732 | /* This device doesn't support EEH, but it may have an | 737 | /* This device doesn't support EEH, but it may have an |
733 | * EEH parent, in which case we mark it as supported. */ | 738 | * EEH parent, in which case we mark it as supported. */ |
734 | 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)) { | ||
735 | /* Parent supports EEH. */ | 741 | /* Parent supports EEH. */ |
736 | dn->eeh_mode |= EEH_MODE_SUPPORTED; | 742 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; |
737 | dn->eeh_config_addr = dn->parent->eeh_config_addr; | 743 | pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr; |
738 | return NULL; | 744 | return NULL; |
739 | } | 745 | } |
740 | } | 746 | } |
@@ -791,11 +797,13 @@ void __init eeh_init(void) | |||
791 | for (phb = of_find_node_by_name(NULL, "pci"); phb; | 797 | for (phb = of_find_node_by_name(NULL, "pci"); phb; |
792 | phb = of_find_node_by_name(phb, "pci")) { | 798 | phb = of_find_node_by_name(phb, "pci")) { |
793 | unsigned long buid; | 799 | unsigned long buid; |
800 | struct pci_dn *pci; | ||
794 | 801 | ||
795 | buid = get_phb_buid(phb); | 802 | buid = get_phb_buid(phb); |
796 | if (buid == 0) | 803 | if (buid == 0 || phb->data == NULL) |
797 | continue; | 804 | continue; |
798 | 805 | ||
806 | pci = phb->data; | ||
799 | info.buid_lo = BUID_LO(buid); | 807 | info.buid_lo = BUID_LO(buid); |
800 | info.buid_hi = BUID_HI(buid); | 808 | info.buid_hi = BUID_HI(buid); |
801 | traverse_pci_devices(phb, early_enable_eeh, &info); | 809 | traverse_pci_devices(phb, early_enable_eeh, &info); |
@@ -824,9 +832,9 @@ void eeh_add_device_early(struct device_node *dn) | |||
824 | struct pci_controller *phb; | 832 | struct pci_controller *phb; |
825 | struct eeh_early_enable_info info; | 833 | struct eeh_early_enable_info info; |
826 | 834 | ||
827 | if (!dn) | 835 | if (!dn || !dn->data) |
828 | return; | 836 | return; |
829 | phb = dn->phb; | 837 | phb = PCI_DN(dn)->phb; |
830 | if (NULL == phb || 0 == phb->buid) { | 838 | if (NULL == phb || 0 == phb->buid) { |
831 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); | 839 | printk(KERN_WARNING "EEH: Expected buid but found none\n"); |
832 | return; | 840 | return; |
@@ -851,8 +859,7 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
851 | return; | 859 | return; |
852 | 860 | ||
853 | #ifdef DEBUG | 861 | #ifdef DEBUG |
854 | printk(KERN_DEBUG "EEH: adding device %s %s\n", pci_name(dev), | 862 | printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); |
855 | pci_pretty_name(dev)); | ||
856 | #endif | 863 | #endif |
857 | 864 | ||
858 | pci_addr_cache_insert_device (dev); | 865 | pci_addr_cache_insert_device (dev); |
@@ -873,8 +880,7 @@ void eeh_remove_device(struct pci_dev *dev) | |||
873 | 880 | ||
874 | /* Unregister the device with the EEH/PCI address search system */ | 881 | /* Unregister the device with the EEH/PCI address search system */ |
875 | #ifdef DEBUG | 882 | #ifdef DEBUG |
876 | printk(KERN_DEBUG "EEH: remove device %s %s\n", pci_name(dev), | 883 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
877 | pci_pretty_name(dev)); | ||
878 | #endif | 884 | #endif |
879 | pci_addr_cache_remove_device(dev); | 885 | pci_addr_cache_remove_device(dev); |
880 | } | 886 | } |