X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fplatforms%2Fpseries%2Feeh_pseries.c;h=8752f79a6af828fb3333c12b84630b6912a576bc;hb=5375871d432ae9fc581014ac117b96aaee3cd0c7;hp=7c8434f902bc14b2802cdd30ec9c7b28e4c87c02;hpb=8d633291b4fc0539ecad31f972447104be6953ec;p=firefly-linux-kernel-4.4.55.git diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 7c8434f902bc..8752f79a6af8 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -144,11 +144,11 @@ static int pseries_eeh_init(void) static int pseries_eeh_set_option(struct device_node *dn, int option) { int ret = 0; - struct pci_dn *pdn; + struct eeh_dev *edev; const u32 *reg; int config_addr; - pdn = PCI_DN(dn); + edev = of_node_to_eeh_dev(dn); /* * When we're enabling or disabling EEH functioality on @@ -165,9 +165,9 @@ static int pseries_eeh_set_option(struct device_node *dn, int option) case EEH_OPT_THAW_MMIO: case EEH_OPT_THAW_DMA: - config_addr = pdn->eeh_config_addr; - if (pdn->eeh_pe_config_addr) - config_addr = pdn->eeh_pe_config_addr; + config_addr = edev->config_addr; + if (edev->pe_config_addr) + config_addr = edev->pe_config_addr; break; default: @@ -177,8 +177,8 @@ static int pseries_eeh_set_option(struct device_node *dn, int option) } ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, - config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), option); + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid), option); return ret; } @@ -198,11 +198,11 @@ static int pseries_eeh_set_option(struct device_node *dn, int option) */ static int pseries_eeh_get_pe_addr(struct device_node *dn) { - struct pci_dn *pdn; + struct eeh_dev *edev; int ret = 0; int rets[3]; - pdn = PCI_DN(dn); + edev = of_node_to_eeh_dev(dn); if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { /* @@ -211,15 +211,15 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn) * meaningless. */ ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets, - pdn->eeh_config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), 1); + edev->config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid), 1); if (ret || (rets[0] == 0)) return 0; /* Retrieve the associated PE config address */ ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets, - pdn->eeh_config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), 0); + edev->config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid), 0); if (ret) { pr_warning("%s: Failed to get PE address for %s\n", __func__, dn->full_name); @@ -231,8 +231,8 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn) if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets, - pdn->eeh_config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), 0); + edev->config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid), 0); if (ret) { pr_warning("%s: Failed to get PE address for %s\n", __func__, dn->full_name); @@ -260,28 +260,28 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn) */ static int pseries_eeh_get_state(struct device_node *dn, int *state) { - struct pci_dn *pdn; + struct eeh_dev *edev; int config_addr; int ret; int rets[4]; int result; /* Figure out PE config address if possible */ - pdn = PCI_DN(dn); - config_addr = pdn->eeh_config_addr; - if (pdn->eeh_pe_config_addr) - config_addr = pdn->eeh_pe_config_addr; + edev = of_node_to_eeh_dev(dn); + config_addr = edev->config_addr; + if (edev->pe_config_addr) + config_addr = edev->pe_config_addr; if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets, - config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid)); + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid)); } else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) { /* Fake PE unavailable info */ rets[2] = 0; ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets, - config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid)); + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid)); } else { return EEH_STATE_NOT_SUPPORT; } @@ -340,27 +340,27 @@ static int pseries_eeh_get_state(struct device_node *dn, int *state) */ static int pseries_eeh_reset(struct device_node *dn, int option) { - struct pci_dn *pdn; + struct eeh_dev *edev; 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; + edev = of_node_to_eeh_dev(dn); + config_addr = edev->config_addr; + if (edev->pe_config_addr) + config_addr = edev->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); + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->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); + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid), EEH_RESET_HOT); } return ret; @@ -437,22 +437,22 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait) */ static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len) { - struct pci_dn *pdn; + struct eeh_dev *edev; int config_addr; unsigned long flags; int ret; - pdn = PCI_DN(dn); + edev = of_node_to_eeh_dev(dn); spin_lock_irqsave(&slot_errbuf_lock, flags); memset(slot_errbuf, 0, eeh_error_buf_size); /* Figure out the PE address */ - config_addr = pdn->eeh_config_addr; - if (pdn->eeh_pe_config_addr) - config_addr = pdn->eeh_pe_config_addr; + config_addr = edev->config_addr; + if (edev->pe_config_addr) + config_addr = edev->pe_config_addr; ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr, - BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid), + BUID_HI(edev->phb->buid), BUID_LO(edev->phb->buid), virt_to_phys(drv_log), len, virt_to_phys(slot_errbuf), eeh_error_buf_size, severity); @@ -473,7 +473,70 @@ static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_l */ static int pseries_eeh_configure_bridge(struct device_node *dn) { - return 0; + struct eeh_dev *edev; + int config_addr; + int ret; + + /* Figure out the PE address */ + edev = of_node_to_eeh_dev(dn); + config_addr = edev->config_addr; + if (edev->pe_config_addr) + config_addr = edev->pe_config_addr; + + /* Use new configure-pe function, if supported */ + if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { + ret = rtas_call(ibm_configure_pe, 3, 1, NULL, + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid)); + } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { + ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, + config_addr, BUID_HI(edev->phb->buid), + BUID_LO(edev->phb->buid)); + } else { + return -EFAULT; + } + + if (ret) + pr_warning("%s: Unable to configure bridge %d for %s\n", + __func__, ret, dn->full_name); + + return ret; +} + +/** + * pseries_eeh_read_config - Read PCI config space + * @dn: device node + * @where: PCI address + * @size: size to read + * @val: return value + * + * Read config space from the speicifed device + */ +static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val) +{ + struct pci_dn *pdn; + + pdn = PCI_DN(dn); + + return rtas_read_config(pdn, where, size, val); +} + +/** + * pseries_eeh_write_config - Write PCI config space + * @dn: device node + * @where: PCI address + * @size: size to write + * @val: value to be written + * + * Write config space to the specified device + */ +static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val) +{ + struct pci_dn *pdn; + + pdn = PCI_DN(dn); + + return rtas_write_config(pdn, where, size, val); } static struct eeh_ops pseries_eeh_ops = { @@ -485,7 +548,9 @@ static struct eeh_ops pseries_eeh_ops = { .reset = pseries_eeh_reset, .wait_state = pseries_eeh_wait_state, .get_log = pseries_eeh_get_log, - .configure_bridge = pseries_eeh_configure_bridge + .configure_bridge = pseries_eeh_configure_bridge, + .read_config = pseries_eeh_read_config, + .write_config = pseries_eeh_write_config }; /**