diff options
-rw-r--r-- | core/pci-iov.c | 9 | ||||
-rw-r--r-- | core/pci.c | 14 | ||||
-rw-r--r-- | include/pci.h | 9 |
3 files changed, 26 insertions, 6 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); } } diff --git a/include/pci.h b/include/pci.h index d75c8d14..c085b6b8 100644 --- a/include/pci.h +++ b/include/pci.h @@ -30,6 +30,7 @@ typedef int64_t (*pci_cfg_reg_func)(void *dev, struct pci_cfg_reg_filter *pcrf, uint32_t offset, uint32_t len, uint32_t *data, bool write); +typedef void (*pci_cap_free_data_func)(void *data); struct pci_cfg_reg_filter { uint32_t flags; #define PCI_REG_FLAG_READ 0x1 @@ -81,6 +82,7 @@ struct pci_device { struct { uint32_t pos; void *data; + pci_cap_free_data_func free_func; } cap[64]; uint32_t mps; /* Max payload size capability */ @@ -96,17 +98,20 @@ struct pci_device { struct list_node link; }; -static inline void pci_set_cap(struct pci_device *pd, int id, - int pos, void *data, bool ext) +static inline void pci_set_cap(struct pci_device *pd, int id, int pos, + void *data, pci_cap_free_data_func free_func, + bool ext) { if (!ext) { pd->cap_list |= (0x1ul << id); pd->cap[id].pos = pos; pd->cap[id].data = data; + pd->cap[id].free_func = free_func; } else { pd->cap_list |= (0x1ul << (id + 32)); pd->cap[id + 32].pos = pos; pd->cap[id + 32].data = data; + pd->cap[id + 32].free_func = free_func; } } |