@@ -138,6 +138,7 @@ struct eeh_dev {
struct pci_controller *phb; /* Associated PHB */
struct pci_dn *pdn; /* Associated PCI device node */
struct pci_dev *pdev; /* Associated PCI device */
+ struct pci_dev *physfn; /* Associated PF PORT */
struct pci_bus *bus; /* PCI bus for partial hotplug */
};
@@ -1135,6 +1135,10 @@ void eeh_add_device_late(struct pci_dev *dev)
}
edev->pdev = dev;
+#ifdef CONFIG_PCI_IOV
+ if (dev->is_virtfn)
+ edev->physfn = dev->physfn;
+#endif
dev->dev.archdata.edev = edev;
if (eeh_has_flag(EEH_PROBE_MODE_DEV))
@@ -180,6 +180,7 @@ static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
{
#ifdef CONFIG_PCI_IOV
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
struct pci_dn *parent, *pdn;
int i;
@@ -206,6 +207,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
__func__, i);
return NULL;
}
+ eeh_dev_init(pdn, hose);
}
#endif /* CONFIG_PCI_IOV */
@@ -254,10 +256,17 @@ void remove_dev_pci_data(struct pci_dev *pdev)
for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
list_for_each_entry_safe(pdn, tmp,
&parent->child_list, list) {
+ struct eeh_dev *edev;
if (pdn->busno != pci_iov_virtfn_bus(pdev, i) ||
pdn->devfn != pci_iov_virtfn_devfn(pdev, i))
continue;
+ edev = pdn_to_eeh_dev(pdn);
+ if (edev) {
+ pdn->edev = NULL;
+ kfree(edev);
+ }
+
if (!list_empty(&pdn->list))
list_del(&pdn->list);