aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-05-01 19:49:46 +1000
committerEli Qiao <taget@linux.vnet.ibm.com>2014-05-04 10:55:21 +0800
commitf28eb4181a14995cd719e30552af2e16eed03972 (patch)
tree4a03995151c3c784fc454d66c39c779a9c3e7196
parent9bb3f57ada773ee8c9188f3d3710a13535b936f1 (diff)
downloadpowerkvm-f28eb4181a14995cd719e30552af2e16eed03972.tar.gz
powerpc/eeh: Clear frozen state for child PE
Since commit cb523e09 ("powerpc/eeh: Avoid I/O access during PE reset"), the PE is kept as frozen state on hardware level until the PE reset is done completely. After that, we explicitly clear the frozen state of the affected PE. However, there might have frozen child PEs of the affected PE and we also need clear their frozen state as well. Otherwise, the recovery is going to fail. It's responsing to bug#109562. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
-rw-r--r--arch/powerpc/kernel/eeh_driver.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 5f375073cf7f3..948477910d3e7 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -425,8 +425,9 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
* PE reset (for 3 times), we try to clear the frozen state
* for 3 times as well.
*/
-static int eeh_clear_pe_frozen_state(struct eeh_pe *pe)
+static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
{
+ struct eeh_pe *pe = (struct eeh_pe *)data;
int i, rc;
for (i = 0; i < 3; i++) {
@@ -439,13 +440,24 @@ static int eeh_clear_pe_frozen_state(struct eeh_pe *pe)
}
/* The PE has been isolated, clear it */
- if (rc)
+ if (rc) {
pr_warn("%s: Can't clear frozen PHB#%x-PE#%x (%d)\n",
__func__, pe->phb->global_number, pe->addr, rc);
- else
+ return (void *)pe;
+ }
+
+ return NULL;
+}
+
+static int eeh_clear_pe_frozen_state(struct eeh_pe *pe)
+{
+ void *rc;
+
+ rc = eeh_pe_traverse(pe, __eeh_clear_pe_frozen_state, NULL);
+ if (!rc)
eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
- return rc;
+ return rc ? -EIO : 0;
}
/**