mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
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:
parent
3a8f2a9ce5
commit
5cd5e70159
3 changed files with 21 additions and 5 deletions
|
@ -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 },
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue