summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Mammedov <imammedo@redhat.com>2014-02-03 11:44:59 +0100
committerMichael S. Tsirkin <mst@redhat.com>2014-02-05 16:55:49 +0200
commit99d09dd32820f5702031e3c08c81f8c209dc2220 (patch)
treefdc0505a6f922b9cf8a614ad552eadc05a1f2080
parenta7b613cf68b65d04ef2b1b601bb18f31e8ca0c11 (diff)
downloadqemu-99d09dd32820f5702031e3c08c81f8c209dc2220.tar.gz
pcihp: make pci_read() mmio calback compatible with legacy ACPI hotplug
due to recent change introduced by: "pcihp: reduce number of device check events" 'up' field is cleared right after it's read. This is incompatible with legacy BIOS ACPI code where PCNF ACPI method reads this field 32 times. To make pci_read mmio callback compatible with legacy 'up' behavior, pcihp code will need to know in which mode it runs add 'legacy_piix' field to AcpiPciHpState structure and alter register behavior accordingly. Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/acpi/pcihp.c7
-rw-r--r--hw/acpi/piix4.c3
-rw-r--r--include/hw/acpi/pcihp.h3
3 files changed, 9 insertions, 4 deletions
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 64c8cf28f1..974f01c114 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -215,7 +215,9 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
switch (addr) {
case PCI_UP_BASE:
val = s->acpi_pcihp_pci_status[bsel].up;
- s->acpi_pcihp_pci_status[bsel].up = 0;
+ if (!s->legacy_piix) {
+ s->acpi_pcihp_pci_status[bsel].up = 0;
+ }
ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val);
break;
case PCI_DOWN_BASE:
@@ -273,9 +275,10 @@ static const MemoryRegionOps acpi_pcihp_io_ops = {
};
void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
- MemoryRegion *address_space_io)
+ MemoryRegion *address_space_io, bool bridges_enabled)
{
s->root= root_bus;
+ s->legacy_piix = !bridges_enabled;
memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s,
"acpi-pci-hotplug",
PCI_HOTPLUG_SIZE);
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 5d55a3c222..2aedfe5998 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -695,7 +695,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
if (s->use_acpi_pci_hotplug) {
- acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent);
+ acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent,
+ s->use_acpi_pci_hotplug);
} else {
memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
"acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index aa297c2450..02d3ce33a1 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -46,10 +46,11 @@ typedef struct AcpiPciHpState {
uint32_t hotplug_select;
PCIBus *root;
MemoryRegion io;
+ bool legacy_piix;
} AcpiPciHpState;
void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root,
- MemoryRegion *address_space_io);
+ MemoryRegion *address_space_io, bool bridges_enabled);
/* Invoke on device hotplug */
int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *,