aboutsummaryrefslogtreecommitdiff
path: root/hw/i386
diff options
context:
space:
mode:
authorIgor Mammedov <imammedo@redhat.com>2023-03-02 17:15:16 +0100
committerMichael S. Tsirkin <mst@redhat.com>2023-03-07 12:38:59 -0500
commit11215a349e39353f272256a72ed0fd4affe5fc78 (patch)
tree3748f3d2883d67a09d506123a35a6ccbd90c40a1 /hw/i386
parent0c3bf7c4314f1512dcc6070994eeba3c6f526f41 (diff)
downloadqemu-11215a349e39353f272256a72ed0fd4affe5fc78.zip
qemu-11215a349e39353f272256a72ed0fd4affe5fc78.tar.gz
qemu-11215a349e39353f272256a72ed0fd4affe5fc78.tar.bz2
x86: pcihp: fix missing PCNT callchain when intermediate root-port has 'hotplug=off' set
Beside BSEL numbers change (due to 2 extra root-ports in q35/miltibridge test), following change is expected: Scope (\_SB.PCI0) { ... + Scope (S50) + { + Scope (S00) + { + Method (PCNT, 0, NotSerialized) + { + BNUM = Zero + DVNT (PCIU, One) + DVNT (PCID, 0x03) + } + } + + Method (PCNT, 0, NotSerialized) + { + ^S00.PCNT + } + } ... Method (PCNT, 0, NotSerialized) { + ^S50.PCNT () ^S13.PCNT () ^S12.PCNT () ^S11.PCNT () I practice [1] hasn't broke anything since on hardware side we unset hotplug_handler on such intermediate port => hotplug behind it has not been properly wired and as result not worked. 1) Fixes: ddab4d3fae4e8 ("pcihp: compose PCNT callchain right before its user _GPE._E01") Signed-off-by: Igor Mammedov <imammedo@redhat.com> Message-Id: <20230302161543.286002-8-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/acpi-build.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b19fb42..c691104 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -517,16 +517,24 @@ static bool build_append_notfication_callback(Aml *parent_scope,
PCIBus *sec;
QObject *bsel;
int nr_notifiers = 0;
+ GQueue *pcnt_bus_list = g_queue_new();
QLIST_FOREACH(sec, &bus->child, sibling) {
Aml *br_scope = aml_scope("S%.02X", sec->parent_dev->devfn);
- if (pci_bus_is_root(sec) ||
- !object_property_find(OBJECT(sec), ACPI_PCIHP_PROP_BSEL)) {
+ if (pci_bus_is_root(sec)) {
continue;
}
nr_notifiers = nr_notifiers +
build_append_notfication_callback(br_scope, sec);
- aml_append(parent_scope, br_scope);
+ /*
+ * add new child scope to parent
+ * and keep track of bus that have PCNT,
+ * bus list is used later to call children PCNTs from this level PCNT
+ */
+ if (nr_notifiers) {
+ g_queue_push_tail(pcnt_bus_list, sec);
+ aml_append(parent_scope, br_scope);
+ }
}
/*
@@ -550,17 +558,13 @@ static bool build_append_notfication_callback(Aml *parent_scope,
}
/* Notify about child bus events in any case */
- QLIST_FOREACH(sec, &bus->child, sibling) {
- if (pci_bus_is_root(sec) ||
- !object_property_find(OBJECT(sec), ACPI_PCIHP_PROP_BSEL)) {
- continue;
- }
-
+ while ((sec = g_queue_pop_head(pcnt_bus_list))) {
aml_append(method, aml_name("^S%.02X.PCNT", sec->parent_dev->devfn));
}
aml_append(parent_scope, method);
qobject_unref(bsel);
+ g_queue_free(pcnt_bus_list);
return !!nr_notifiers;
}