Commit 0d5ee520 authored by Gavin Shan's avatar Gavin Shan Committed by Michael Ellerman

powerpc/eeh: Freeze PE before PE reset

The patch adds one more option (EEH_OPT_FREEZE_PE) to set_option()
method to proactively freeze PE, which will be issued before resetting
pass-throughed PE to drop MMIO access during reset because it's
always contributing to recursive EEH error.
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 940376b3
......@@ -172,6 +172,7 @@ enum {
#define EEH_OPT_ENABLE 1 /* EEH enable */
#define EEH_OPT_THAW_MMIO 2 /* MMIO enable */
#define EEH_OPT_THAW_DMA 3 /* DMA enable */
#define EEH_OPT_FREEZE_PE 4 /* Freeze PE */
#define EEH_STATE_UNAVAILABLE (1 << 0) /* State unavailable */
#define EEH_STATE_NOT_SUPPORT (1 << 1) /* EEH not supported */
#define EEH_STATE_RESET_ACTIVE (1 << 2) /* Active reset */
......
......@@ -1382,6 +1382,13 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
break;
case EEH_RESET_HOT:
case EEH_RESET_FUNDAMENTAL:
/*
* Proactively freeze the PE to drop all MMIO access
* during reset, which should be banned as it's always
* cause recursive EEH error.
*/
eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
ret = eeh_ops->reset(pe, option);
break;
default:
......
......@@ -189,6 +189,7 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
{
struct pci_controller *hose = pe->phb;
struct pnv_phb *phb = hose->private_data;
bool freeze_pe = false;
int enable, ret = 0;
s64 rc;
......@@ -212,6 +213,10 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
case EEH_OPT_THAW_DMA:
enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA;
break;
case EEH_OPT_FREEZE_PE:
freeze_pe = true;
enable = OPAL_EEH_ACTION_SET_FREEZE_ALL;
break;
default:
pr_warn("%s: Invalid option %d\n",
__func__, option);
......@@ -219,17 +224,35 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
}
/* If PHB supports compound PE, to handle it */
if (phb->unfreeze_pe) {
ret = phb->unfreeze_pe(phb, pe->addr, enable);
if (freeze_pe) {
if (phb->freeze_pe) {
phb->freeze_pe(phb, pe->addr);
} else {
rc = opal_pci_eeh_freeze_set(phb->opal_id,
pe->addr,
enable);
if (rc != OPAL_SUCCESS) {
pr_warn("%s: Failure %lld freezing "
"PHB#%x-PE#%x\n",
__func__, rc,
phb->hose->global_number, pe->addr);
ret = -EIO;
}
}
} else {
rc = opal_pci_eeh_freeze_clear(phb->opal_id,
pe->addr,
enable);
if (rc != OPAL_SUCCESS) {
pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n",
__func__, rc, option, phb->hose->global_number,
pe->addr);
ret = -EIO;
if (phb->unfreeze_pe) {
ret = phb->unfreeze_pe(phb, pe->addr, enable);
} else {
rc = opal_pci_eeh_freeze_clear(phb->opal_id,
pe->addr,
enable);
if (rc != OPAL_SUCCESS) {
pr_warn("%s: Failure %lld enable %d "
"for PHB#%x-PE#%x\n",
__func__, rc, option,
phb->hose->global_number, pe->addr);
ret = -EIO;
}
}
}
......
......@@ -349,7 +349,9 @@ static int pseries_eeh_set_option(struct eeh_pe *pe, int option)
if (pe->addr)
config_addr = pe->addr;
break;
case EEH_OPT_FREEZE_PE:
/* Not support */
return 0;
default:
pr_err("%s: Invalid option %d\n",
__func__, option);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment