diff options
-rw-r--r-- | arch/powerpc/include/asm/eeh.h | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 63 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 25 |
3 files changed, 33 insertions, 58 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 1d3c9e5..894ea6c 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -49,6 +49,9 @@ struct device_node; #define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ #define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ #define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ +#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ +#define EEH_RESET_HOT 1 /* Hot reset */ +#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ struct eeh_ops { char *name; diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index b5b03d4..4f329f5 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -87,7 +87,6 @@ #define PCI_BUS_RESET_WAIT_MSEC (60*1000) /* RTAS tokens */ -static int ibm_set_slot_reset; static int ibm_slot_error_detail; static int ibm_configure_bridge; static int ibm_configure_pe; @@ -607,54 +606,6 @@ int eeh_pci_enable(struct pci_dn *pdn, int function) } /** - * eeh_slot_reset - Raises/Lowers the pci #RST line - * @pdn: pci device node - * @state: 1/0 to raise/lower the #RST - * - * Clear the EEH-frozen condition on a slot. This routine - * asserts the PCI #RST line if the 'state' argument is '1', - * and drops the #RST line if 'state is '0'. This routine is - * safe to call in an interrupt context. - */ -static void eeh_slot_reset(struct pci_dn *pdn, int state) -{ - int config_addr; - int rc; - - BUG_ON(pdn==NULL); - - if (!pdn->phb) { - printk(KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", - pdn->node->full_name); - return; - } - - /* Use PE configuration address, if present */ - config_addr = pdn->eeh_config_addr; - if (pdn->eeh_pe_config_addr) - config_addr = pdn->eeh_pe_config_addr; - - rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL, - config_addr, - BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), - state); - - /* Fundamental-reset not supported on this PE, try hot-reset */ - if (rc == -8 && state == 3) { - rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL, - config_addr, - BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), 1); - if (rc) - printk(KERN_WARNING - "EEH: Unable to reset the failed slot," - " #RST=%d dn=%s\n", - rc, pdn->node->full_name); - } -} - -/** * pcibios_set_pcie_slot_reset - Set PCI-E reset state * @dev: pci device struct * @state: reset state to enter @@ -665,17 +616,16 @@ static void eeh_slot_reset(struct pci_dn *pdn, int state) int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) { struct device_node *dn = pci_device_to_OF_node(dev); - struct pci_dn *pdn = PCI_DN(dn); switch (state) { case pcie_deassert_reset: - eeh_slot_reset(pdn, 0); + eeh_ops->reset(dn, EEH_RESET_DEACTIVATE); break; case pcie_hot_reset: - eeh_slot_reset(pdn, 1); + eeh_ops->reset(dn, EEH_RESET_HOT); break; case pcie_warm_reset: - eeh_slot_reset(pdn, 3); + eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL); break; default: return -EINVAL; @@ -754,9 +704,9 @@ static void eeh_reset_pe_once(struct pci_dn *pdn) eeh_set_pe_freset(pdn->node, &freset); if (freset) - eeh_slot_reset(pdn, 3); + eeh_ops->reset(pdn->node, EEH_RESET_FUNDAMENTAL); else - eeh_slot_reset(pdn, 1); + eeh_ops->reset(pdn->node, EEH_RESET_HOT); /* The PCI bus requires that the reset be held high for at least * a 100 milliseconds. We wait a bit longer 'just in case'. @@ -770,7 +720,7 @@ static void eeh_reset_pe_once(struct pci_dn *pdn) */ eeh_clear_slot(pdn->node, EEH_MODE_ISOLATED); - eeh_slot_reset(pdn, 0); + eeh_ops->reset(pdn->node, EEH_RESET_DEACTIVATE); /* After a PCI slot has been reset, the PCI Express spec requires * a 1.5 second idle time for the bus to stabilize, before starting @@ -1127,7 +1077,6 @@ void __init eeh_init(void) if (np == NULL) return; - ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); ibm_configure_bridge = rtas_token("ibm,configure-bridge"); ibm_configure_pe = rtas_token("ibm,configure-pe"); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 7b60131..6643e06 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -318,7 +318,30 @@ static int pseries_eeh_get_state(struct device_node *dn, int *state) */ static int pseries_eeh_reset(struct device_node *dn, int option) { - return 0; + struct pci_dn *pdn; + int config_addr; + int ret; + + /* Figure out PE address */ + pdn = PCI_DN(dn); + config_addr = pdn->eeh_config_addr; + if (pdn->eeh_pe_config_addr) + config_addr = pdn->eeh_pe_config_addr; + + /* Reset PE through RTAS call */ + ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, + config_addr, BUID_HI(pdn->phb->buid), + BUID_LO(pdn->phb->buid), option); + + /* If fundamental-reset not supported, try hot-reset */ + if (option == EEH_RESET_FUNDAMENTAL && + ret == -8) { + ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, + config_addr, BUID_HI(pdn->phb->buid), + BUID_LO(pdn->phb->buid), EEH_RESET_HOT); + } + + return ret; } /** |