powerpc/eeh: Clear frozen state for child PE
authorGavin Shan <gwshan@linux.vnet.ibm.com>
Sun, 4 May 2014 23:29:02 +0000 (09:29 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 11 Jun 2014 07:04:12 +0000 (17:04 +1000)
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.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/eeh_driver.c

index 7100a5b96e7059caf572609dec9d7f9393f0106f..8bb40e7cdeb6a65e13bc57647f0e2b2dfd0ad430 100644 (file)
@@ -447,8 +447,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++) {
@@ -461,13 +462,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;
 }
 
 /**