|
@@ -2217,7 +2217,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group,
|
|
|
|
|
|
pnv_pci_link_table_and_group(phb->hose->node, num,
|
|
|
tbl, &pe->table_group);
|
|
|
- pnv_pci_phb3_tce_invalidate_pe(pe);
|
|
|
+ pnv_pci_ioda2_tce_invalidate_pe(pe);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -2355,7 +2355,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group,
|
|
|
if (ret)
|
|
|
pe_warn(pe, "Unmapping failed, ret = %ld\n", ret);
|
|
|
else
|
|
|
- pnv_pci_phb3_tce_invalidate_pe(pe);
|
|
|
+ pnv_pci_ioda2_tce_invalidate_pe(pe);
|
|
|
|
|
|
pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
|
|
|
|
|
@@ -3426,7 +3426,17 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pnv_ioda_free_pe(pe);
|
|
|
+ /*
|
|
|
+ * The PE for root bus can be removed because of hotplug in EEH
|
|
|
+ * recovery for fenced PHB error. We need to mark the PE dead so
|
|
|
+ * that it can be populated again in PCI hot add path. The PE
|
|
|
+ * shouldn't be destroyed as it's the global reserved resource.
|
|
|
+ */
|
|
|
+ if (phb->ioda.root_pe_populated &&
|
|
|
+ phb->ioda.root_pe_idx == pe->pe_number)
|
|
|
+ phb->ioda.root_pe_populated = false;
|
|
|
+ else
|
|
|
+ pnv_ioda_free_pe(pe);
|
|
|
}
|
|
|
|
|
|
static void pnv_pci_release_device(struct pci_dev *pdev)
|
|
@@ -3442,7 +3452,17 @@ static void pnv_pci_release_device(struct pci_dev *pdev)
|
|
|
if (!pdn || pdn->pe_number == IODA_INVALID_PE)
|
|
|
return;
|
|
|
|
|
|
+ /*
|
|
|
+ * PCI hotplug can happen as part of EEH error recovery. The @pdn
|
|
|
+ * isn't removed and added afterwards in this scenario. We should
|
|
|
+ * set the PE number in @pdn to an invalid one. Otherwise, the PE's
|
|
|
+ * device count is decreased on removing devices while failing to
|
|
|
+ * be increased on adding devices. It leads to unbalanced PE's device
|
|
|
+ * count and eventually make normal PCI hotplug path broken.
|
|
|
+ */
|
|
|
pe = &phb->ioda.pe_array[pdn->pe_number];
|
|
|
+ pdn->pe_number = IODA_INVALID_PE;
|
|
|
+
|
|
|
WARN_ON(--pe->device_count < 0);
|
|
|
if (pe->device_count == 0)
|
|
|
pnv_ioda_release_pe(pe);
|