Pablo Greco e6a3ae
From 72cc005ad139d9d5d4bf2cb7402cf730c6726fd3 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Date: Wed, 17 Apr 2019 13:57:37 +0100
Pablo Greco e6a3ae
Subject: [PATCH 20/24] s390x/pci: Fix hotplugging of PCI bridges
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Message-id: <20190417135741.25297-21-cohuck@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 85801
Pablo Greco e6a3ae
O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 20/24] s390x/pci: Fix hotplugging of PCI bridges
Pablo Greco e6a3ae
Bugzilla: 1699070
Pablo Greco e6a3ae
RH-Acked-by: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
When hotplugging a PCI bridge right now to the root port, we resolve
Pablo Greco e6a3ae
pci_get_bus(pdev)->parent_dev, which results in a SEGFAULT. Hotplugging
Pablo Greco e6a3ae
really only works right now when hotplugging to another bridge.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Instead, we have to properly check if we are already at the root.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Let's cleanup the code while at it a bit and factor out updating the
Pablo Greco e6a3ae
subordinate bus number into a separate function. The check for
Pablo Greco e6a3ae
"old_nr < nr" is right now not strictly necessary, but makes it more
Pablo Greco e6a3ae
obvious what is actually going on.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Most probably fixing up the topology is not our responsibility when
Pablo Greco e6a3ae
hotplugging. The guest has to sort this out. But let's keep it for now
Pablo Greco e6a3ae
and only fix current code to not crash.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Reviewed-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
Message-Id: <20190130155733.32742-3-david@redhat.com>
Pablo Greco e6a3ae
Reviewed-by: Collin Walling <walling@linux.ibm.com>
Pablo Greco e6a3ae
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit 150f462538a6f3b78efe785c911669375032b0d2)
Pablo Greco e6a3ae
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/s390x/s390-pci-bus.c | 28 +++++++++++++++++++---------
Pablo Greco e6a3ae
 1 file changed, 19 insertions(+), 9 deletions(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
Pablo Greco e6a3ae
index 309ad79..a0f7245 100644
Pablo Greco e6a3ae
--- a/hw/s390x/s390-pci-bus.c
Pablo Greco e6a3ae
+++ b/hw/s390x/s390-pci-bus.c
Pablo Greco e6a3ae
@@ -881,6 +881,21 @@ static void s390_pcihost_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+static void s390_pci_update_subordinate(PCIDevice *dev, uint32_t nr)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    uint32_t old_nr;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1);
Pablo Greco e6a3ae
+    while (!pci_bus_is_root(pci_get_bus(dev))) {
Pablo Greco e6a3ae
+        dev = pci_get_bus(dev)->parent_dev;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+        old_nr = pci_default_read_config(dev, PCI_SUBORDINATE_BUS, 1);
Pablo Greco e6a3ae
+        if (old_nr < nr) {
Pablo Greco e6a3ae
+            pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1);
Pablo Greco e6a3ae
+        }
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Pablo Greco e6a3ae
                               Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
@@ -889,26 +904,21 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Pablo Greco e6a3ae
     S390PCIBusDevice *pbdev = NULL;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
Pablo Greco e6a3ae
-        BusState *bus;
Pablo Greco e6a3ae
         PCIBridge *pb = PCI_BRIDGE(dev);
Pablo Greco e6a3ae
-        PCIDevice *pdev = PCI_DEVICE(dev);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+        pdev = PCI_DEVICE(dev);
Pablo Greco e6a3ae
         pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq);
Pablo Greco e6a3ae
         pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-        bus = BUS(&pb->sec_bus);
Pablo Greco e6a3ae
-        qbus_set_hotplug_handler(bus, DEVICE(s), errp);
Pablo Greco e6a3ae
+        qbus_set_hotplug_handler(BUS(&pb->sec_bus), DEVICE(s), errp);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
         if (dev->hotplugged) {
Pablo Greco e6a3ae
             pci_default_write_config(pdev, PCI_PRIMARY_BUS,
Pablo Greco e6a3ae
                                      pci_dev_bus_num(pdev), 1);
Pablo Greco e6a3ae
             s->bus_no += 1;
Pablo Greco e6a3ae
             pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1);
Pablo Greco e6a3ae
-            do {
Pablo Greco e6a3ae
-                pdev = pci_get_bus(pdev)->parent_dev;
Pablo Greco e6a3ae
-                pci_default_write_config(pdev, PCI_SUBORDINATE_BUS,
Pablo Greco e6a3ae
-                                         s->bus_no, 1);
Pablo Greco e6a3ae
-            } while (pci_get_bus(pdev) && pci_dev_bus_num(pdev));
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+            s390_pci_update_subordinate(pdev, s->bus_no);
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
Pablo Greco e6a3ae
         pdev = PCI_DEVICE(dev);
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae