aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/eeh.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh.c')
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c82
1 files changed, 69 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 89649173d3a3..46b55cf563e3 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -93,6 +93,7 @@ static int ibm_slot_error_detail;
93static int ibm_get_config_addr_info; 93static int ibm_get_config_addr_info;
94static int ibm_get_config_addr_info2; 94static int ibm_get_config_addr_info2;
95static int ibm_configure_bridge; 95static int ibm_configure_bridge;
96static int ibm_configure_pe;
96 97
97int eeh_subsystem_enabled; 98int eeh_subsystem_enabled;
98EXPORT_SYMBOL(eeh_subsystem_enabled); 99EXPORT_SYMBOL(eeh_subsystem_enabled);
@@ -261,6 +262,8 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
261 pci_regs_buf[0] = 0; 262 pci_regs_buf[0] = 0;
262 263
263 rtas_pci_enable(pdn, EEH_THAW_MMIO); 264 rtas_pci_enable(pdn, EEH_THAW_MMIO);
265 rtas_configure_bridge(pdn);
266 eeh_restore_bars(pdn);
264 loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); 267 loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
265 268
266 rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); 269 rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen);
@@ -448,6 +451,39 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
448 raw_spin_unlock_irqrestore(&confirm_error_lock, flags); 451 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
449} 452}
450 453
454void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
455{
456 struct device_node *dn;
457
458 for_each_child_of_node(parent, dn) {
459 if (PCI_DN(dn)) {
460
461 struct pci_dev *dev = PCI_DN(dn)->pcidev;
462
463 if (dev && dev->driver)
464 *freset |= dev->needs_freset;
465
466 __eeh_set_pe_freset(dn, freset);
467 }
468 }
469}
470
471void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
472{
473 struct pci_dev *dev;
474 dn = find_device_pe(dn);
475
476 /* Back up one, since config addrs might be shared */
477 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
478 dn = dn->parent;
479
480 dev = PCI_DN(dn)->pcidev;
481 if (dev)
482 *freset |= dev->needs_freset;
483
484 __eeh_set_pe_freset(dn, freset);
485}
486
451/** 487/**
452 * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze 488 * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze
453 * @dn device node 489 * @dn device node
@@ -692,15 +728,24 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
692 if (pdn->eeh_pe_config_addr) 728 if (pdn->eeh_pe_config_addr)
693 config_addr = pdn->eeh_pe_config_addr; 729 config_addr = pdn->eeh_pe_config_addr;
694 730
695 rc = rtas_call(ibm_set_slot_reset,4,1, NULL, 731 rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
696 config_addr, 732 config_addr,
697 BUID_HI(pdn->phb->buid), 733 BUID_HI(pdn->phb->buid),
698 BUID_LO(pdn->phb->buid), 734 BUID_LO(pdn->phb->buid),
699 state); 735 state);
700 if (rc) 736
701 printk (KERN_WARNING "EEH: Unable to reset the failed slot," 737 /* Fundamental-reset not supported on this PE, try hot-reset */
702 " (%d) #RST=%d dn=%s\n", 738 if (rc == -8 && state == 3) {
703 rc, state, pdn->node->full_name); 739 rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
740 config_addr,
741 BUID_HI(pdn->phb->buid),
742 BUID_LO(pdn->phb->buid), 1);
743 if (rc)
744 printk(KERN_WARNING
745 "EEH: Unable to reset the failed slot,"
746 " #RST=%d dn=%s\n",
747 rc, pdn->node->full_name);
748 }
704} 749}
705 750
706/** 751/**
@@ -736,18 +781,21 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
736/** 781/**
737 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second 782 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
738 * @pdn: pci device node to be reset. 783 * @pdn: pci device node to be reset.
739 *
740 * Return 0 if success, else a non-zero value.
741 */ 784 */
742 785
743static void __rtas_set_slot_reset(struct pci_dn *pdn) 786static void __rtas_set_slot_reset(struct pci_dn *pdn)
744{ 787{
745 struct pci_dev *dev = pdn->pcidev; 788 unsigned int freset = 0;
746 789
747 /* Determine type of EEH reset required by device, 790 /* Determine type of EEH reset required for
748 * default hot reset or fundamental reset 791 * Partitionable Endpoint, a hot-reset (1)
749 */ 792 * or a fundamental reset (3).
750 if (dev && dev->needs_freset) 793 * A fundamental reset required by any device under
794 * Partitionable Endpoint trumps hot-reset.
795 */
796 eeh_set_pe_freset(pdn->node, &freset);
797
798 if (freset)
751 rtas_pci_slot_reset(pdn, 3); 799 rtas_pci_slot_reset(pdn, 3);
752 else 800 else
753 rtas_pci_slot_reset(pdn, 1); 801 rtas_pci_slot_reset(pdn, 1);
@@ -895,13 +943,20 @@ rtas_configure_bridge(struct pci_dn *pdn)
895{ 943{
896 int config_addr; 944 int config_addr;
897 int rc; 945 int rc;
946 int token;
898 947
899 /* Use PE configuration address, if present */ 948 /* Use PE configuration address, if present */
900 config_addr = pdn->eeh_config_addr; 949 config_addr = pdn->eeh_config_addr;
901 if (pdn->eeh_pe_config_addr) 950 if (pdn->eeh_pe_config_addr)
902 config_addr = pdn->eeh_pe_config_addr; 951 config_addr = pdn->eeh_pe_config_addr;
903 952
904 rc = rtas_call(ibm_configure_bridge,3,1, NULL, 953 /* Use new configure-pe function, if supported */
954 if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE)
955 token = ibm_configure_pe;
956 else
957 token = ibm_configure_bridge;
958
959 rc = rtas_call(token, 3, 1, NULL,
905 config_addr, 960 config_addr,
906 BUID_HI(pdn->phb->buid), 961 BUID_HI(pdn->phb->buid),
907 BUID_LO(pdn->phb->buid)); 962 BUID_LO(pdn->phb->buid));
@@ -1077,6 +1132,7 @@ void __init eeh_init(void)
1077 ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); 1132 ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
1078 ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); 1133 ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
1079 ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); 1134 ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
1135 ibm_configure_pe = rtas_token("ibm,configure-pe");
1080 1136
1081 if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) 1137 if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
1082 return; 1138 return;