diff options
author | Igor Mammedov <imammedo@redhat.com> | 2023-03-02 17:15:16 +0100 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2023-03-07 12:38:59 -0500 |
commit | 11215a349e39353f272256a72ed0fd4affe5fc78 (patch) | |
tree | 3748f3d2883d67a09d506123a35a6ccbd90c40a1 /hw/i386 | |
parent | 0c3bf7c4314f1512dcc6070994eeba3c6f526f41 (diff) | |
download | qemu-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.c | 22 |
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; } |