From patchwork Wed Mar 7 00:14:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 145119 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 97B77B6F9D for ; Wed, 7 Mar 2012 11:15:08 +1100 (EST) Received: from localhost ([::1]:57772 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54X4-0006U3-CA for incoming@patchwork.ozlabs.org; Tue, 06 Mar 2012 19:15:06 -0500 Received: from eggs.gnu.org ([208.118.235.92]:43173) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54Wt-0006LL-QR for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S54Wr-0005Zi-Rv for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:55 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56967) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54Wr-0005ZT-Jq for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:53 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q270Eqhn031517 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 6 Mar 2012 19:14:52 -0500 Received: from bling.home ([10.3.113.14]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q270Ep5e001800; Tue, 6 Mar 2012 19:14:51 -0500 From: Alex Williamson To: qemu-devel@nongnu.org Date: Tue, 06 Mar 2012 17:14:51 -0700 Message-ID: <20120307001438.3079.32280.stgit@bling.home> In-Reply-To: <20120307000340.3079.87515.stgit@bling.home> References: <20120307000340.3079.87515.stgit@bling.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: alex.williamson@redhat.com, ddutile@redhat.com, gleb@redhat.com, mst@redhat.com Subject: [Qemu-devel] [PATCH 4/6] acpi_piix4: Track PCI hotplug status and allow non-ACPI remove path 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 When a guest probes a device, clear the "up" bit in the hotplug register. This allows us to enable a non-ACPI remove path for devices added, but never accessed by the guest. This is useful when a guest does not have ACPI PCI hotplug support to avoid losing devices to a guest. We also now individually track bits for "up" and "down" rather than clearing both on each PCI hotplug action. Signed-off-by: Alex Williamson --- hw/acpi_piix4.c | 58 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 46 insertions(+), 12 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 4d88e23..7e766e5 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -27,6 +27,7 @@ #include "sysemu.h" #include "range.h" #include "ioport.h" +#include "pci_host.h" //#define DEBUG @@ -75,6 +76,7 @@ typedef struct PIIX4PMState { qemu_irq smi_irq; int kvm_enabled; Notifier machine_ready; + Notifier device_probe; /* for pci hotplug */ ACPIGPE gpe; @@ -336,6 +338,16 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) } +static void piix4_pm_device_probe(Notifier *n, void *opaque) +{ + PIIX4PMState *s = container_of(n, PIIX4PMState, device_probe); + PCIDevice *pdev = opaque; + + if (pci_find_domain(pdev->bus) == 0 && pci_bus_num(pdev->bus) == 0) { + s->pci0_status.up &= ~(1U << PCI_SLOT(pdev->devfn)); + } +} + static PIIX4PMState *global_piix4_pm_state; /* cpu hotadd */ static int piix4_pm_initfn(PCIDevice *dev) @@ -383,6 +395,8 @@ static int piix4_pm_initfn(PCIDevice *dev) qemu_add_machine_init_done_notifier(&s->machine_ready); qemu_register_reset(piix4_reset, s); piix4_acpi_system_hot_add_init(dev->bus, s); + s->device_probe.notify = piix4_pm_device_probe; + pci_host_add_dev_probe_notifier(&s->device_probe); return 0; } @@ -502,6 +516,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val) PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) { qdev_free(qdev); + s->pci0_status.down &= ~(1U << slot); } } @@ -594,16 +609,41 @@ void qemu_system_cpu_hot_add(int cpu, int state) } #endif -static void enable_device(PIIX4PMState *s, int slot) +static int enable_device(PIIX4PMState *s, int slot) { + uint32_t mask = 1U << slot; + + if ((s->pci0_status.up | s->pci0_status.down) & mask) { + return -1; + } + s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_status.up |= (1 << slot); + s->pci0_status.up |= mask; + + pm_update_sci(s); + return 0; } -static void disable_device(PIIX4PMState *s, int slot) +static int disable_device(PIIX4PMState *s, int slot) { + uint32_t mask = 1U << slot; + + if (s->pci0_status.up & mask) { + s->pci0_status.up &= ~mask; + pciej_write(s, PCI_EJ_BASE, mask); + + /* Clear GPE PCI hotplug status if nothing left pending */ + if (!(s->pci0_status.up | s->pci0_status.down)) { + s->gpe.sts[0] &= ~PIIX4_PCI_HOTPLUG_STATUS; + } + return 0; + } + s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_status.down |= (1 << slot); + s->pci0_status.down |= mask; + + pm_update_sci(s); + return 0; } static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, @@ -620,15 +660,9 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, return 0; } - s->pci0_status.up = 0; - s->pci0_status.down = 0; if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, slot); + return enable_device(s, slot); } else { - disable_device(s, slot); + return disable_device(s, slot); } - - pm_update_sci(s); - - return 0; }