From patchwork Wed Apr 29 19:20:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 466257 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E485B14030C for ; Thu, 30 Apr 2015 05:26:08 +1000 (AEST) Received: from localhost ([::1]:40730 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXcV-0001RT-3N for incoming@patchwork.ozlabs.org; Wed, 29 Apr 2015 15:26:07 -0400 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 Received: from d03dlp01.boulder.ibm.com (9.17.202.177) by e31.co.us.ibm.com (192.168.1.131) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 29 Apr 2015 13:21:06 -0600 Received: from b03cxnp07028.gho.boulder.ibm.com (b03cxnp07028.gho.boulder.ibm.com [9.17.130.15]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id 4AB121FF0039; Wed, 29 Apr 2015 13:12:16 -0600 (MDT) Received: from d03av03.boulder.ibm.com (d03av03.boulder.ibm.com [9.17.195.169]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t3TJJ67020971662; Wed, 29 Apr 2015 12:19:06 -0700 Received: from d03av03.boulder.ibm.com (localhost [127.0.0.1]) by d03av03.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t3TJL4WJ021558; Wed, 29 Apr 2015 13:21:05 -0600 Received: from localhost ([9.80.84.126]) by d03av03.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t3TJL3Wq021470; Wed, 29 Apr 2015 13:21:03 -0600 From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 29 Apr 2015 14:20:10 -0500 Message-Id: <1430335224-6716-2-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.9.1 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> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15042919-8236-0000-0000-00000B1D4954 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 32.97.110.149 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 Subject: [Qemu-devel] [RFC PATCH 01/15] pci: allow cleanup/unregistration of PCI buses X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: David Gibson --- 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);