From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38961) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXXj-0001N9-P3 for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YnXXg-0006Bn-IQ for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:11 -0400 Received: from e31.co.us.ibm.com ([32.97.110.149]:52288) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXXg-0006Bc-Be for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:08 -0400 Received: from /spool/local by e31.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 29 Apr 2015 13:21:07 -0600 From: Michael Roth Date: Wed, 29 Apr 2015 14:20:10 -0500 Message-Id: <1430335224-6716-2-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1430335224-6716-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1430335224-6716-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC PATCH 01/15] pci: allow cleanup/unregistration of PCI buses List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: "Michael S. Tsirkin" , aik@ozlabs.ru, Paolo Bonzini , qemu-ppc@nongnu.org, bharata@linux.vnet.ibm.com, nfont@linux.vnet.ibm.com, david@gibson.dropbear.id.au This adds cleanup counterparts to pci_register_bus(), pci_bus_new(), and pci_bus_irqs(). These cleanup routines are needed in the case of hotpluggable PCIHostBridge implementations. Currently we can rely on the object_unparent()'ing of the PCIHostState recursively unparenting and cleaning up it's child buses, but we need explicit calls to also: 1) remove the PCIHostState from pci_host_bridges global list. otherwise, we risk accessing freed memory when we access the list later 2) clean up memory allocated in pci_bus_irqs() Both are handled outside the context of any particular bus or host bridge's init/realize functions, making it difficult to avoid the need for explicit cleanup functions without remodeling how PCIHostBridges are created. So keep it simple and just add them for now. Cc: Michael S. Tsirkin Cc: Paolo Bonzini Signed-off-by: Michael Roth --- hw/pci/pci.c | 33 +++++++++++++++++++++++++++++++++ include/hw/pci/pci.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index a88c8f3..201ad49 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -258,6 +258,13 @@ static void pci_host_bus_register(PCIBus *bus, DeviceState *parent) QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next); } +static void pci_host_bus_unregister(DeviceState *parent) +{ + PCIHostState *host_bridge = PCI_HOST_BRIDGE(parent); + + QLIST_REMOVE(host_bridge, next); +} + PCIBus *pci_find_primary_bus(void) { PCIBus *primary_bus = NULL; @@ -318,6 +325,11 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent, pci_host_bus_register(bus, parent); } +static void pci_bus_uninit(PCIBus *bus) +{ + pci_host_bus_unregister(BUS(bus)->parent); +} + bool pci_bus_is_express(PCIBus *bus) { return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); @@ -352,6 +364,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, return bus; } +void pci_bus_cleanup(PCIBus *bus) +{ + pci_bus_uninit(bus); + object_unparent(OBJECT(bus)); +} + void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq) { @@ -362,6 +380,15 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); } +void pci_bus_irqs_cleanup(PCIBus *bus) +{ + bus->set_irq = NULL; + bus->map_irq = NULL; + bus->irq_opaque = NULL; + bus->nirq = 0; + g_free(bus->irq_count); +} + PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, @@ -377,6 +404,12 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, return bus; } +void pci_unregister_bus(PCIBus *bus) +{ + pci_bus_irqs_cleanup(bus); + pci_bus_cleanup(bus); +} + int pci_bus_num(PCIBus *s) { if (pci_bus_is_root(s)) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 1a4e0be..eb4a292 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -353,8 +353,10 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, const char *typename); +void pci_bus_cleanup(PCIBus *bus); void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); +void pci_bus_irqs_cleanup(PCIBus *bus); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); @@ -364,6 +366,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, int nirq, const char *typename); +void pci_unregister_bus(PCIBus *bus); void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn); PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new); -- 1.9.1