Commit 99d09dd3 authored by Igor Mammedov's avatar Igor Mammedov Committed by Michael S. Tsirkin
Browse files

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: default avatarIgor Mammedov <imammedo@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent a7b613cf
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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;
        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);
+2 −1
Original line number Diff line number Diff line
@@ -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);
+2 −1
Original line number Diff line number Diff line
@@ -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 *,