mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 15:34:48 +08:00
powerpc/eeh: I/O chip EEH state retrieval
The patch adds I/O chip backend to retrieve the state for the indicated PE. While the PE state is temperarily unavailable, the upper layer (powernv platform) should return default delay (1 second). Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
eb0059836b
commit
8c41a7f3f7
@ -116,10 +116,107 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ioda_eeh_get_state - Retrieve the state of PE
|
||||
* @pe: EEH PE
|
||||
*
|
||||
* The PE's state should be retrieved from the PEEV, PEST
|
||||
* IODA tables. Since the OPAL has exported the function
|
||||
* to do it, it'd better to use that.
|
||||
*/
|
||||
static int ioda_eeh_get_state(struct eeh_pe *pe)
|
||||
{
|
||||
s64 ret = 0;
|
||||
u8 fstate;
|
||||
u16 pcierr;
|
||||
u32 pe_no;
|
||||
int result;
|
||||
struct pci_controller *hose = pe->phb;
|
||||
struct pnv_phb *phb = hose->private_data;
|
||||
|
||||
/*
|
||||
* Sanity check on PE address. The PHB PE address should
|
||||
* be zero.
|
||||
*/
|
||||
if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
|
||||
pr_err("%s: PE address %x out of range [0, %x] "
|
||||
"on PHB#%x\n",
|
||||
__func__, pe->addr, phb->ioda.total_pe,
|
||||
hose->global_number);
|
||||
return EEH_STATE_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* Retrieve PE status through OPAL */
|
||||
pe_no = pe->addr;
|
||||
ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no,
|
||||
&fstate, &pcierr, NULL);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to get EEH status on "
|
||||
"PHB#%x-PE#%x\n, err=%lld\n",
|
||||
__func__, hose->global_number, pe_no, ret);
|
||||
return EEH_STATE_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* Check PHB status */
|
||||
if (pe->type & EEH_PE_PHB) {
|
||||
result = 0;
|
||||
result &= ~EEH_STATE_RESET_ACTIVE;
|
||||
|
||||
if (pcierr != OPAL_EEH_PHB_ERROR) {
|
||||
result |= EEH_STATE_MMIO_ACTIVE;
|
||||
result |= EEH_STATE_DMA_ACTIVE;
|
||||
result |= EEH_STATE_MMIO_ENABLED;
|
||||
result |= EEH_STATE_DMA_ENABLED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse result out */
|
||||
result = 0;
|
||||
switch (fstate) {
|
||||
case OPAL_EEH_STOPPED_NOT_FROZEN:
|
||||
result &= ~EEH_STATE_RESET_ACTIVE;
|
||||
result |= EEH_STATE_MMIO_ACTIVE;
|
||||
result |= EEH_STATE_DMA_ACTIVE;
|
||||
result |= EEH_STATE_MMIO_ENABLED;
|
||||
result |= EEH_STATE_DMA_ENABLED;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_MMIO_FREEZE:
|
||||
result &= ~EEH_STATE_RESET_ACTIVE;
|
||||
result |= EEH_STATE_DMA_ACTIVE;
|
||||
result |= EEH_STATE_DMA_ENABLED;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_DMA_FREEZE:
|
||||
result &= ~EEH_STATE_RESET_ACTIVE;
|
||||
result |= EEH_STATE_MMIO_ACTIVE;
|
||||
result |= EEH_STATE_MMIO_ENABLED;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE:
|
||||
result &= ~EEH_STATE_RESET_ACTIVE;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_RESET:
|
||||
result |= EEH_STATE_RESET_ACTIVE;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_TEMP_UNAVAIL:
|
||||
result |= EEH_STATE_UNAVAILABLE;
|
||||
break;
|
||||
case OPAL_EEH_STOPPED_PERM_UNAVAIL:
|
||||
result |= EEH_STATE_NOT_SUPPORT;
|
||||
break;
|
||||
default:
|
||||
pr_warning("%s: Unexpected EEH status 0x%x "
|
||||
"on PHB#%x-PE#%x\n",
|
||||
__func__, fstate, hose->global_number, pe_no);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct pnv_eeh_ops ioda_eeh_ops = {
|
||||
.post_init = ioda_eeh_post_init,
|
||||
.set_option = ioda_eeh_set_option,
|
||||
.get_state = NULL,
|
||||
.get_state = ioda_eeh_get_state,
|
||||
.reset = NULL,
|
||||
.get_log = NULL,
|
||||
.configure_bridge = NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user