[Skiboot] [PATCH v2 3/4] core/pci: Release IOV capability on removing device
Gavin Shan
gwshan at linux.vnet.ibm.com
Mon Jun 19 16:46:48 AEST 2017
This introduces helper function pci_release_dev(), release the
specified PCI device, to be shared in fast-reboot and PCI hot
remove path. From there, pci_release_capabilities() and
pci_release_iov_cap() is called to free memory allocated for
IOV capability and VFs.
Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
core/pci-iov.c | 14 ++++++++++++++
core/pci.c | 52 +++++++++++++++++++++++++++++++++-------------------
include/pci-iov.h | 2 +-
3 files changed, 48 insertions(+), 20 deletions(-)
diff --git a/core/pci-iov.c b/core/pci-iov.c
index 627f300..9866b22 100644
--- a/core/pci-iov.c
+++ b/core/pci-iov.c
@@ -256,3 +256,17 @@ void pci_init_iov_cap(struct phb *phb, struct pci_device *pd)
pci_iov_update_parameters(iov);
pci_set_cap(pd, PCIECAP_ID_SRIOV, pos, true);
}
+
+void pci_release_iov_cap(struct pci_device *pd)
+{
+ if (!pd->iov)
+ return;
+
+ if (pd->iov->VFs) {
+ free(pd->iov->VFs);
+ pd->iov->VFs = NULL;
+ }
+
+ free(pd->iov);
+ pd->iov = NULL;
+}
diff --git a/core/pci.c b/core/pci.c
index 1aa906a..684c054 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -218,6 +218,11 @@ void pci_init_capabilities(struct phb *phb, struct pci_device *pd)
pci_init_pm_cap(phb, pd);
}
+static void pci_release_capabilities(struct pci_device *pd)
+{
+ pci_release_iov_cap(pd);
+}
+
static struct pci_device *pci_scan_one(struct phb *phb, struct pci_device *parent,
uint16_t bdfn)
{
@@ -673,6 +678,26 @@ static void pci_cleanup_bridge(struct phb *phb, struct pci_device *pd)
pci_cfg_write16(phb, pd->bdfn, PCI_CFG_CMD, cmd);
}
+static void pci_release_dev(struct phb *phb, struct pci_device *pd)
+{
+ if (phb->ops->device_remove)
+ phb->ops->device_remove(phb, pd);
+
+ pci_release_capabilities(pd);
+ if (pd->dn) {
+ dt_free(pd->dn);
+ pd->dn = NULL;
+ }
+
+ if (pd->slot) {
+ free(pd->slot);
+ pd->slot = NULL;
+ }
+
+ list_del(&pd->link);
+ free(pd);
+}
+
/* Remove all subordinate PCI devices leading from the indicated
* PCI bus. It's used to remove all PCI devices behind one PCI
* slot at unplugging time
@@ -684,18 +709,7 @@ void pci_remove_bus(struct phb *phb, struct list_head *list)
list_for_each_safe(list, pd, tmp, link) {
pci_remove_bus(phb, &pd->children);
- if (phb->ops->device_remove)
- phb->ops->device_remove(phb, pd);
-
- /* Release device node and PCI slot */
- if (pd->dn)
- dt_free(pd->dn);
- if (pd->slot)
- free(pd->slot);
-
- /* Remove from parent list and release itself */
- list_del(&pd->link);
- free(pd);
+ pci_release_dev(phb, pd);
}
}
@@ -1631,14 +1645,14 @@ void pci_add_device_nodes(struct phb *phb,
}
}
-static void __pci_reset(struct list_head *list)
+static void __pci_reset(struct phb *phb, struct list_head *list)
{
- struct pci_device *pd;
+ struct pci_device *pd, *tmp;
- while ((pd = list_pop(list, struct pci_device, link)) != NULL) {
- __pci_reset(&pd->children);
- dt_free(pd->dn);
- free(pd);
+ list_for_each_safe(list, pd, tmp, link) {
+ __pci_reset(phb, &pd->children);
+
+ pci_release_dev(phb, pd);
}
}
@@ -1657,7 +1671,7 @@ void pci_reset(void)
struct phb *phb = phbs[i];
if (!phb)
continue;
- __pci_reset(&phb->devices);
+ __pci_reset(phb, &phb->devices);
slot = phb->slot;
if (!slot || !slot->ops.creset) {
diff --git a/include/pci-iov.h b/include/pci-iov.h
index 787b2cd..18da320 100644
--- a/include/pci-iov.h
+++ b/include/pci-iov.h
@@ -33,5 +33,5 @@ struct pci_iov {
};
extern void pci_init_iov_cap(struct phb *phb, struct pci_device *pd);
-
+extern void pci_release_iov_cap(struct pci_device *pd);
#endif
--
2.7.4
More information about the Skiboot
mailing list