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