int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val) { unsigned long buid, addr; int ret; if (!pdn) return PCIBIOS_DEVICE_NOT_FOUND; if (!config_access_valid(pdn, where)) return PCIBIOS_BAD_REGISTER_NUMBER; addr = rtas_config_addr(pdn->busno, pdn->devfn, where); buid = pdn->phb->buid; if (buid) { ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, BUID_HI(buid), BUID_LO(buid), size, (ulong) val); } else { ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); } if (ret) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; }
/** * pseries_eeh_get_state - Retrieve PE state * @pe: EEH PE * @state: return value * * Retrieve the state of the specified PE. On RTAS compliant * pseries platform, there already has one dedicated RTAS function * for the purpose. It's notable that the associated PE config address * might be ready when calling the function. Therefore, endeavour to * use the PE config address if possible. Further more, there're 2 * RTAS calls for the purpose, we need to try the new one and back * to the old one if the new one couldn't work properly. */ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) { int config_addr; int ret; int rets[4]; int result; /* Figure out PE config address if possible */ config_addr = pe->config_addr; if (pe->addr) config_addr = pe->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(pe->phb->buid), BUID_LO(pe->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(pe->phb->buid), BUID_LO(pe->phb->buid)); } else { return EEH_STATE_NOT_SUPPORT; } if (ret) return ret; /* Parse the result out */ result = 0; if (rets[1]) { switch(rets[0]) { case 0: result &= ~EEH_STATE_RESET_ACTIVE; result |= EEH_STATE_MMIO_ACTIVE; result |= EEH_STATE_DMA_ACTIVE; break; case 1: result |= EEH_STATE_RESET_ACTIVE; result |= EEH_STATE_MMIO_ACTIVE; result |= EEH_STATE_DMA_ACTIVE; break; case 2: result &= ~EEH_STATE_RESET_ACTIVE; result &= ~EEH_STATE_MMIO_ACTIVE; result &= ~EEH_STATE_DMA_ACTIVE; break; case 4: result &= ~EEH_STATE_RESET_ACTIVE; result &= ~EEH_STATE_MMIO_ACTIVE; result &= ~EEH_STATE_DMA_ACTIVE; result |= EEH_STATE_MMIO_ENABLED; break; case 5: if (rets[2]) { if (state) *state = rets[2]; result = EEH_STATE_UNAVAILABLE; } else { result = EEH_STATE_NOT_SUPPORT; } default: result = EEH_STATE_NOT_SUPPORT; } } else { result = EEH_STATE_NOT_SUPPORT; } return result; }
/* Check for an eeh failure at the given token address. * The given value has been read and it should be 1's (0xff, 0xffff or * 0xffffffff). * * Probe to determine if an error actually occurred. If not return val. * Otherwise panic. */ unsigned long eeh_check_failure(void *token, unsigned long val) { unsigned long addr; struct pci_dev *dev; struct device_node *dn; unsigned long ret, rets[2]; /* IO BAR access could get us here...or if we manually force EEH * operation on even if the hardware won't support it. */ if (!eeh_implemented || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) return val; /* Finding the phys addr + pci device is quite expensive. * However, the RTAS call is MUCH slower.... :( */ addr = eeh_token_to_phys((unsigned long)token); dev = pci_find_dev_by_addr(addr); if (!dev) { printk("EEH: no pci dev found for addr=0x%lx\n", addr); return val; } dn = pci_device_to_OF_node(dev); if (!dn) { printk("EEH: no pci dn found for addr=0x%lx\n", addr); return val; } /* Access to IO BARs might get this far and still not want checking. */ if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || dn->eeh_mode & EEH_MODE_NOCHECK) return val; /* Now test for an EEH failure. This is VERY expensive. * Note that the eeh_config_addr may be a parent device * in the case of a device behind a bridge, or it may be * function zero of a multi-function device. * In any case they must share a common PHB. */ if (dn->eeh_config_addr) { ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets, dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); if (ret == 0 && rets[1] == 1 && rets[0] >= 2) { unsigned char slot_err_buf[RTAS_ERROR_LOG_MAX]; unsigned long slot_err_ret; memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX); slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"), 8, 1, dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid), NULL, 0, __pa(slot_err_buf), RTAS_ERROR_LOG_MAX, 2 /* Permanent Error */); if (slot_err_ret == 0) log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */); panic("EEH: MMIO failure (%ld) on device:\n %s %s\n", rets[0], dev->slot_name, dev->name); } } eeh_false_positives++; return val; /* good case */ }