Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / arch / powerpc / kernel / eeh_driver.c
index 52c1e27..c314db8 100644 (file)
@@ -166,6 +166,16 @@ static void *eeh_dev_save_state(void *data, void *userdata)
        if (!edev)
                return NULL;
 
+       /*
+        * We cannot access the config space on some adapters.
+        * Otherwise, it will cause fenced PHB. We don't save
+        * the content in their config space and will restore
+        * from the initial config space saved when the EEH
+        * device is created.
+        */
+       if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
+               return NULL;
+
        pdev = eeh_dev_to_pci_dev(edev);
        if (!pdev)
                return NULL;
@@ -305,6 +315,19 @@ static void *eeh_dev_restore_state(void *data, void *userdata)
        if (!edev)
                return NULL;
 
+       /*
+        * The content in the config space isn't saved because
+        * the blocked config space on some adapters. We have
+        * to restore the initial saved config space when the
+        * EEH device is created.
+        */
+       if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) {
+               if (list_is_last(&edev->list, &edev->pe->edevs))
+                       eeh_pe_restore_bars(edev->pe);
+
+               return NULL;
+       }
+
        pdev = eeh_dev_to_pci_dev(edev);
        if (!pdev)
                return NULL;
@@ -462,7 +485,7 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
 static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
 {
        struct eeh_pe *pe = (struct eeh_pe *)data;
-       bool *clear_sw_state = flag;
+       bool clear_sw_state = *(bool *)flag;
        int i, rc = 1;
 
        for (i = 0; rc && i < 3; i++)
@@ -504,9 +527,6 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
        /* Save states */
        eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
-       /* Report error */
-       eeh_pe_dev_traverse(pe, eeh_report_error, &result);
-
        /* Issue reset */
        ret = eeh_reset_pe(pe);
        if (ret) {
@@ -592,8 +612,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 
        /* Clear frozen state */
        rc = eeh_clear_pe_frozen_state(pe, false);
-       if (rc)
+       if (rc) {
+               pci_unlock_rescan_remove();
                return rc;
+       }
 
        /* Give the system 5 seconds to finish running the user-space
         * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
@@ -889,6 +911,14 @@ static void eeh_handle_special_event(void)
                                /* Notify all devices to be down */
                                eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                                bus = eeh_pe_bus_get(phb_pe);
+                               if (!bus) {
+                                       pr_err("%s: Cannot find PCI bus for "
+                                              "PHB#%d-PE#%x\n",
+                                              __func__,
+                                              pe->phb->global_number,
+                                              pe->addr);
+                                       break;
+                               }
                                eeh_pe_dev_traverse(pe,
                                        eeh_report_failure, NULL);
                                pcibios_remove_pci_devices(bus);