Skip to content

Commit

Permalink
pci-iov: free memory across fast-reboot
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
stewartsmith committed Oct 10, 2017
1 parent c375cfc commit 347e245
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 6 deletions.
9 changes: 8 additions & 1 deletion core/pci-iov.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
14 changes: 11 additions & 3 deletions core/pci.c
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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);
}
}
Expand Down
9 changes: 7 additions & 2 deletions include/pci.h
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand All @@ -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;
}
}

Expand Down

0 comments on commit 347e245

Please sign in to comment.