Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / arch / powerpc / platforms / pseries / eeh_pseries.c
index 2039397..405baaf 100644 (file)
@@ -433,42 +433,34 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
                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;
-                       }
-                       break;
-               default:
+       if (!rets[1])
+               return EEH_STATE_NOT_SUPPORT;
+
+       switch(rets[0]) {
+       case 0:
+               result = EEH_STATE_MMIO_ACTIVE |
+                        EEH_STATE_DMA_ACTIVE;
+               break;
+       case 1:
+               result = EEH_STATE_RESET_ACTIVE |
+                        EEH_STATE_MMIO_ACTIVE  |
+                        EEH_STATE_DMA_ACTIVE;
+               break;
+       case 2:
+               result = 0;
+               break;
+       case 4:
+               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;
                }
-       } else {
+               break;
+       default:
                result = EEH_STATE_NOT_SUPPORT;
        }
 
@@ -519,7 +511,7 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option)
 /**
  * pseries_eeh_wait_state - Wait for PE state
  * @pe: EEH PE
- * @max_wait: maximal period in microsecond
+ * @max_wait: maximal period in millisecond
  *
  * Wait for the state of associated PE. It might take some time
  * to retrieve the PE's state.
@@ -623,29 +615,50 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
 {
        int config_addr;
        int ret;
+       /* Waiting 0.2s maximum before skipping configuration */
+       int max_wait = 200;
 
        /* Figure out the PE address */
        config_addr = pe->config_addr;
        if (pe->addr)
                config_addr = pe->addr;
 
-       /* Use new configure-pe function, if supported */
-       if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
-               ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
-                               config_addr, BUID_HI(pe->phb->buid),
-                               BUID_LO(pe->phb->buid));
-       } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
-               ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-                               config_addr, BUID_HI(pe->phb->buid),
-                               BUID_LO(pe->phb->buid));
-       } else {
-               return -EFAULT;
-       }
+       while (max_wait > 0) {
+               /* Use new configure-pe function, if supported */
+               if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+                       ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
+                                       config_addr, BUID_HI(pe->phb->buid),
+                                       BUID_LO(pe->phb->buid));
+               } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
+                       ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
+                                       config_addr, BUID_HI(pe->phb->buid),
+                                       BUID_LO(pe->phb->buid));
+               } else {
+                       return -EFAULT;
+               }
 
-       if (ret)
-               pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
-                       __func__, pe->phb->global_number, pe->addr, ret);
+               if (!ret)
+                       return ret;
+
+               /*
+                * If RTAS returns a delay value that's above 100ms, cut it
+                * down to 100ms in case firmware made a mistake.  For more
+                * on how these delay values work see rtas_busy_delay_time
+                */
+               if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+                   ret <= RTAS_EXTENDED_DELAY_MAX)
+                       ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+               max_wait -= rtas_busy_delay_time(ret);
+
+               if (max_wait < 0)
+                       break;
+
+               rtas_busy_delay(ret);
+       }
 
+       pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+               __func__, pe->phb->global_number, pe->addr, ret);
        return ret;
 }