[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL v4 13/18] pci: Replace pci_find_domain() with more ge
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PULL v4 13/18] pci: Replace pci_find_domain() with more general pci_root_bus_path() |
Date: |
Sun, 7 Jul 2013 23:20:16 +0300 |
From: David Gibson <address@hidden>
pci_find_domain() is used in a number of places where we want an id for a
whole PCI domain (i.e. the subtree under a PCI root bus). The trouble is
that many platforms may support multiple independent host bridges with no
hardware supplied notion of domain number.
This patch, therefore, replaces calls to pci_find_domain() with calls to
a new pci_root_bus_path() returning a string. The new call is implemented
in terms of a new callback in the host bridge class, so it can be defined
in some way that's well defined for the platform. When no callback is
available we fall back on the qbus name.
Most current uses of pci_find_domain() are for error or informational
messages, so the change in identifiers should be harmless. The exception
is pci_get_dev_path(), whose results form part of migration streams. To
maintain compatibility with old migration streams, the PIIX PCI host is
altered to always supply "0000" for this path, which matches the old domain
number (since the code didn't actually support domains other than 0).
For the pseries (spapr) PCI bridge we use a different platform-unique
identifier (pseries machines can routinely have dozens of PCI host
bridges). Theoretically that breaks migration streams, but given that we
don't yet have migration support for pseries, it doesn't matter.
Any other machines that have working migration support including PCI
devices will need to be updated to maintain migration stream compatibility.
Signed-off-by: David Gibson <address@hidden>
Signed-off-by: Michael S. Tsirkin <address@hidden>
---
hw/pci-host/piix.c | 9 +++++++++
hw/pci-host/q35.c | 9 +++++++++
hw/pci/pci-hotplug-old.c | 4 ++--
hw/pci/pci.c | 38 ++++++++++++++++++++------------------
hw/pci/pci_host.c | 1 +
hw/pci/pcie_aer.c | 8 ++++----
hw/ppc/spapr_pci.c | 10 ++++++++++
include/hw/pci/pci.h | 2 +-
include/hw/pci/pci_host.h | 10 ++++++++++
9 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9e68c3..c36e725 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -629,11 +629,20 @@ static const TypeInfo i440fx_info = {
.class_init = i440fx_class_init,
};
+static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+ /* For backwards compat with old device paths */
+ return "0000";
+}
+
static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
+ hc->root_bus_path = i440fx_pcihost_root_bus_path;
k->init = i440fx_pcihost_initfn;
dc->fw_name = "pci";
dc->no_user = 1;
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 3a5cff9..13148ed 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -63,6 +63,13 @@ static int q35_host_init(SysBusDevice *dev)
return 0;
}
+static const char *q35_host_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+ /* For backwards compat with old device paths */
+ return "0000";
+}
+
static Property mch_props[] = {
DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
@@ -73,7 +80,9 @@ static void q35_host_class_init(ObjectClass *klass, void
*data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
+ hc->root_bus_path = q35_host_root_bus_path;
k->init = q35_host_init;
dc->props = mch_props;
dc->fw_name = "pci";
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index 37e0720..e251810 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -275,8 +275,8 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
}
if (dev) {
- monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
- pci_find_domain(dev),
+ monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n",
+ pci_root_bus_path(dev),
pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn));
} else
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 69a6995..350b872 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -25,6 +25,7 @@
#include "hw/pci/pci.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
#include "monitor/monitor.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
@@ -270,19 +271,20 @@ PCIBus *pci_device_root_bus(const PCIDevice *d)
return bus;
}
-int pci_find_domain(const PCIDevice *dev)
+const char *pci_root_bus_path(PCIDevice *dev)
{
- const PCIBus *rootbus = pci_device_root_bus(dev);
- struct PCIHostBus *host;
+ PCIBus *rootbus = pci_device_root_bus(dev);
+ PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent);
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge);
- QLIST_FOREACH(host, &host_buses, next) {
- if (host->bus == rootbus) {
- return host->domain;
- }
+ assert(!rootbus->parent_dev);
+ assert(host_bridge->bus == rootbus);
+
+ if (hc->root_bus_path) {
+ return (*hc->root_bus_path)(host_bridge, rootbus);
}
- abort(); /* should not be reached */
- return -1;
+ return rootbus->qbus.name;
}
static void pci_bus_init(PCIBus *bus, DeviceState *parent,
@@ -2000,10 +2002,10 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
for (i = offset; i < offset + size; i++) {
overlapping_cap = pci_find_capability_at_offset(pdev, i);
if (overlapping_cap) {
- fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
+ fprintf(stderr, "ERROR: %s:%02x:%02x.%x "
"Attempt to add PCI capability %x at offset "
"%x overlaps existing capability %x at offset %x\n",
- pci_find_domain(pdev), pci_bus_num(pdev->bus),
+ pci_root_bus_path(pdev), pci_bus_num(pdev->bus),
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
cap_id, offset, overlapping_cap, i);
return -EINVAL;
@@ -2137,30 +2139,30 @@ static char *pcibus_get_dev_path(DeviceState *dev)
* domain:Bus:Slot.Func for systems without nested PCI bridges.
* Slot.Function list specifies the slot and function numbers for all
* devices on the path from root to the specific device. */
- char domain[] = "DDDD:00";
+ const char *root_bus_path;
+ int root_bus_len;
char slot[] = ":SS.F";
- int domain_len = sizeof domain - 1 /* For '\0' */;
int slot_len = sizeof slot - 1 /* For '\0' */;
int path_len;
char *path, *p;
int s;
+ root_bus_path = pci_root_bus_path(d);
+ root_bus_len = strlen(root_bus_path);
+
/* Calculate # of slots on path between device and root. */;
slot_depth = 0;
for (t = d; t; t = t->bus->parent_dev) {
++slot_depth;
}
- path_len = domain_len + slot_len * slot_depth;
+ path_len = root_bus_len + slot_len * slot_depth;
/* Allocate memory, fill in the terminating null byte. */
path = g_malloc(path_len + 1 /* For '\0' */);
path[path_len] = '\0';
- /* First field is the domain. */
- s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d));
- assert(s == domain_len);
- memcpy(path, domain, domain_len);
+ memcpy(path, root_bus_path, root_bus_len);
/* Fill in slot numbers. We walk up from device to root, so need to print
* them in the reverse order, last to first. */
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 12254b1..7dd9b25 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -169,6 +169,7 @@ static const TypeInfo pci_host_type_info = {
.name = TYPE_PCI_HOST_BRIDGE,
.parent = TYPE_SYS_BUS_DEVICE,
.abstract = true,
+ .class_size = sizeof(PCIHostBridgeClass),
.instance_size = sizeof(PCIHostState),
};
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 06f77ac..ca762ab 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -817,9 +817,9 @@ void pcie_aer_inject_error_print(Monitor *mon, const
QObject *data)
qdict = qobject_to_qdict(data);
devfn = (int)qdict_get_int(qdict, "devfn");
- monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
+ monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
qdict_get_str(qdict, "id"),
- (int) qdict_get_int(qdict, "domain"),
+ qdict_get_str(qdict, "root_bus"),
(int) qdict_get_int(qdict, "bus"),
PCI_SLOT(devfn), PCI_FUNC(devfn));
}
@@ -1020,9 +1020,9 @@ int do_pcie_aer_inject_error(Monitor *mon,
ret = pcie_aer_inject_error(dev, &err);
*ret_data = qobject_from_jsonf("{'id': %s, "
- "'domain': %d, 'bus': %d, 'devfn': %d, "
+ "'root_bus': %s, 'bus': %d, 'devfn': %d, "
"'ret': %d}",
- id, pci_find_domain(dev),
+ id, pci_root_bus_path(dev),
pci_bus_num(dev->bus), dev->devfn,
ret);
assert(*ret_data);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c8c12c8..f7be24c 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -696,11 +696,21 @@ static Property spapr_phb_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge);
+
+ return sphb->dtbusname;
+}
+
static void spapr_phb_class_init(ObjectClass *klass, void *data)
{
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ hc->root_bus_path = spapr_phb_root_bus_path;
sdc->init = spapr_phb_init;
dc->props = spapr_phb_properties;
dc->reset = spapr_phb_reset;
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index f2bf1ed..e0597b7 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -391,7 +391,7 @@ void pci_for_each_device(PCIBus *bus, int bus_num,
void *opaque);
PCIBus *pci_find_primary_bus(void);
PCIBus *pci_device_root_bus(const PCIDevice *d);
-int pci_find_domain(const PCIDevice *dev);
+const char *pci_root_bus_path(PCIDevice *dev);
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
int pci_qdev_find_device(const char *id, PCIDevice **pdev);
PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index 236cd0f..44052f2 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -33,6 +33,10 @@
#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
#define PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
+#define PCI_HOST_BRIDGE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE)
+#define PCI_HOST_BRIDGE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE)
struct PCIHostState {
SysBusDevice busdev;
@@ -44,6 +48,12 @@ struct PCIHostState {
PCIBus *bus;
};
+typedef struct PCIHostBridgeClass {
+ SysBusDeviceClass parent_class;
+
+ const char *(*root_bus_path)(PCIHostState *, PCIBus *);
+} PCIHostBridgeClass;
+
/* common internal helpers for PCI/PCIe hosts, cut off overflows */
void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len);
--
MST
- [Qemu-devel] [PULL v4 01/18] range: add Range structure, (continued)
- [Qemu-devel] [PULL v4 01/18] range: add Range structure, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 03/18] pc: pass PCI hole ranges to Guests, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 04/18] pc_piix: cleanup init compat handling, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 05/18] e1000: cleanup process_tx_desc, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 06/18] MAINTAINERS: s/Marcelo/Paolo/, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 08/18] pvpanic: fix fwcfg for big endian hosts, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 07/18] pvpanic: initialization cleanup, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 10/18] pci: Move pci_read_devaddr to pci-hotplug-old.c, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 09/18] pci: Cleanup configuration for pci-hotplug.c, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 12/18] pci: Use helper to find device's root bus in pci_find_domain(), Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 13/18] pci: Replace pci_find_domain() with more general pci_root_bus_path(),
Michael S. Tsirkin <=
- [Qemu-devel] [PULL v4 11/18] pci: Abolish pci_find_root_bus(), Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 14/18] pci: Add root bus argument to pci_get_bus_devfn(), Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 16/18] pci: Simpler implementation of primary PCI bus, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 17/18] pci: Remove domain from PCIHostBus, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 18/18] pci: Fold host_buses list into PCIHostState functionality, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 02/18] pci: store PCI hole ranges in guestinfo structure, Michael S. Tsirkin, 2013/07/07
- [Qemu-devel] [PULL v4 15/18] pci: Add root bus parameter to pci_nic_init(), Michael S. Tsirkin, 2013/07/07
- Re: [Qemu-devel] [PULL v4 00/18] pci,misc enhancements, Stefano Stabellini, 2013/07/10