pci: split shpc_cleanup and shpc_free

object_unparent should not be called until the parent device is going to be
destroyed.  Only remove the capability and do memory_region_del_subregion
at unrealize time.  Freeing the data structures is left in shpc_free, to
be called from the instance_finalize callback.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2015-02-12 21:39:20 +01:00
parent 3a8f2a9ce5
commit 5cd5e70159
3 changed files with 21 additions and 5 deletions

View file

@ -97,6 +97,11 @@ static void pci_bridge_dev_exitfn(PCIDevice *dev)
pci_bridge_exitfn(dev); pci_bridge_exitfn(dev);
} }
static void pci_bridge_dev_instance_finalize(Object *obj)
{
shpc_free(PCI_DEVICE(obj));
}
static void pci_bridge_dev_write_config(PCIDevice *d, static void pci_bridge_dev_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len) uint32_t address, uint32_t val, int len)
{ {
@ -158,6 +163,7 @@ static const TypeInfo pci_bridge_dev_info = {
.parent = TYPE_PCI_BRIDGE, .parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridgeDev), .instance_size = sizeof(PCIBridgeDev),
.class_init = pci_bridge_dev_class_init, .class_init = pci_bridge_dev_class_init,
.instance_finalize = pci_bridge_dev_instance_finalize,
.interfaces = (InterfaceInfo[]) { .interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER }, { TYPE_HOTPLUG_HANDLER },
{ } { }

View file

@ -663,13 +663,22 @@ void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
SHPCDevice *shpc = d->shpc; SHPCDevice *shpc = d->shpc;
d->cap_present &= ~QEMU_PCI_CAP_SHPC; d->cap_present &= ~QEMU_PCI_CAP_SHPC;
memory_region_del_subregion(bar, &shpc->mmio); memory_region_del_subregion(bar, &shpc->mmio);
object_unparent(OBJECT(&shpc->mmio));
/* TODO: cleanup config space changes? */ /* TODO: cleanup config space changes? */
}
void shpc_free(PCIDevice *d)
{
SHPCDevice *shpc = d->shpc;
if (!shpc) {
return;
}
object_unparent(OBJECT(&shpc->mmio));
g_free(shpc->config); g_free(shpc->config);
g_free(shpc->cmask); g_free(shpc->cmask);
g_free(shpc->wmask); g_free(shpc->wmask);
g_free(shpc->w1cmask); g_free(shpc->w1cmask);
g_free(shpc); g_free(shpc);
d->shpc = NULL;
} }
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)

View file

@ -41,6 +41,7 @@ void shpc_reset(PCIDevice *d);
int shpc_bar_size(PCIDevice *dev); int shpc_bar_size(PCIDevice *dev);
int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off); int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off);
void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar); void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
void shpc_free(PCIDevice *dev);
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);