summaryrefslogtreecommitdiffstats
path: root/core
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
parentc375cfca55d70b079720b80153a8631a60504bcb (diff)
downloadblackbird-skiboot-347e24521e87549f50ab049fc131567dd2d0ff92.tar.gz
blackbird-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.c9
-rw-r--r--core/pci.c14
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);
}
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