diff options
author | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-10-09 15:06:24 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-10-10 13:36:17 +1100 |
commit | 347e24521e87549f50ab049fc131567dd2d0ff92 (patch) | |
tree | e132f53dde47a76e79dac95b7b69ed1d05dede60 /core | |
parent | c375cfca55d70b079720b80153a8631a60504bcb (diff) | |
download | talos-skiboot-347e24521e87549f50ab049fc131567dd2d0ff92.tar.gz talos-skiboot-347e24521e87549f50ab049fc131567dd2d0ff92.zip |
pci-iov: free memory across fast-reboot
pci_set_cap needs a callback to free data and we need to call
that when we're doing __pci_reset()
We also need to free pcrf entries.
In the future, __pci_reset() and pci_remove_bus() need to come
together to be one canonical place on how to free a PCI device
rather than the two we have now. This patch *purely* focuses
on the problem of not leaking memory across fast-reboot.
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/pci-iov.c | 9 | ||||
-rw-r--r-- | core/pci.c | 14 |
2 files changed, 19 insertions, 4 deletions
diff --git a/core/pci-iov.c b/core/pci-iov.c index 06fc4c6f..8fecebc1 100644 --- a/core/pci-iov.c +++ b/core/pci-iov.c @@ -189,6 +189,13 @@ static void pci_iov_init_VF(struct pci_device *pd, struct pci_device *vf) list_head_init(&vf->children); } +static void pci_free_iov_cap(void *data) +{ + struct pci_iov *iov = data; + free(iov->VFs); + free(iov); +} + void pci_init_iov_cap(struct phb *phb, struct pci_device *pd) { int64_t pos; @@ -254,5 +261,5 @@ void pci_init_iov_cap(struct phb *phb, struct pci_device *pd) iov->pos = pos; iov->enabled = false; pci_iov_update_parameters(iov); - pci_set_cap(pd, PCIECAP_ID_SRIOV, pos, iov, true); + pci_set_cap(pd, PCIECAP_ID_SRIOV, pos, iov, pci_free_iov_cap, true); } @@ -162,7 +162,7 @@ static void pci_init_pcie_cap(struct phb *phb, struct pci_device *pd) return; } - pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, NULL, false); + pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, NULL, NULL, false); /* * XXX We observe a problem on some PLX switches where one @@ -198,7 +198,7 @@ static void pci_init_aer_cap(struct phb *phb, struct pci_device *pd) pos = pci_find_ecap(phb, pd->bdfn, PCIECAP_ID_AER, NULL); if (pos > 0) - pci_set_cap(pd, PCIECAP_ID_AER, pos, NULL, true); + pci_set_cap(pd, PCIECAP_ID_AER, pos, NULL, NULL, true); } static void pci_init_pm_cap(struct phb *phb, struct pci_device *pd) @@ -207,7 +207,7 @@ static void pci_init_pm_cap(struct phb *phb, struct pci_device *pd) pos = pci_find_cap(phb, pd->bdfn, PCI_CFG_CAP_ID_PM); if (pos > 0) - pci_set_cap(pd, PCI_CFG_CAP_ID_PM, pos, NULL, false); + pci_set_cap(pd, PCI_CFG_CAP_ID_PM, pos, NULL, NULL, false); } void pci_init_capabilities(struct phb *phb, struct pci_device *pd) @@ -1651,11 +1651,19 @@ void pci_add_device_nodes(struct phb *phb, static void __pci_reset(struct list_head *list) { struct pci_device *pd; + struct pci_cfg_reg_filter *pcrf; + int i; while ((pd = list_pop(list, struct pci_device, link)) != NULL) { __pci_reset(&pd->children); dt_free(pd->dn); free(pd->slot); + while((pcrf = list_pop(&pd->pcrf, struct pci_cfg_reg_filter, link)) != NULL) { + free(pcrf); + } + for(i=0; i < 64; i++) + if (pd->cap[i].free_func) + pd->cap[i].free_func(pd->cap[i].data); free(pd); } } |