summaryrefslogtreecommitdiffstats
path: root/core/pci.c
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2017-10-09 15:06:24 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-10-10 13:36:17 +1100
commit347e24521e87549f50ab049fc131567dd2d0ff92 (patch)
treee132f53dde47a76e79dac95b7b69ed1d05dede60 /core/pci.c
parentc375cfca55d70b079720b80153a8631a60504bcb (diff)
downloadtalos-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/pci.c')
-rw-r--r--core/pci.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/core/pci.c b/core/pci.c
index b6e7e824..0809521f 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -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);
}
}
OpenPOWER on IntegriCloud