[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL v2 15/21] pci: Replace pci_find_domain() with more ge
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PULL v2 15/21] pci: Replace pci_find_domain() with more general pci_root_bus_path() |
Date: |
Tue, 25 Jun 2013 18:41:36 +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 bab992d..0d0609f 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,
@@ -2003,10 +2005,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;
@@ -2140,30 +2142,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 62ff323..2d102f5 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -693,11 +693,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 7376b9e..962b7a3 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -392,7 +392,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 v2 00/21] pci,kvm,misc enhancements, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 01/21] range: add Range structure, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 03/21] pc: pass PCI hole ranges to Guests, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 06/21] kvm: zero-initialize KVM_SET_GSI_ROUTING input, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 05/21] e1000: cleanup process_tx_desc, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 12/21] pci: Move pci_read_devaddr to pci-hotplug-old.c, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 10/21] pvpanic: fix fwcfg for big endian hosts, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 13/21] pci: Abolish pci_find_root_bus(), Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 14/21] pci: Use helper to find device's root bus in pci_find_domain(), Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 15/21] pci: Replace pci_find_domain() with more general pci_root_bus_path(),
Michael S. Tsirkin <=
- [Qemu-devel] [PULL v2 16/21] pci: Add root bus argument to pci_get_bus_devfn(), Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 18/21] pci: Simpler implementation of primary PCI bus, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 19/21] pci: Remove domain from PCIHostBus, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 11/21] pci: Cleanup configuration for pci-hotplug.c, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 20/21] pci: Fold host_buses list into PCIHostState functionality, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 17/21] pci: Add root bus parameter to pci_nic_init(), Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 02/21] pci: store PCI hole ranges in guestinfo structure, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 21/21] net: add support of mac-programming over macvtap in QEMU side, Michael S. Tsirkin, 2013/06/25
- [Qemu-devel] [PULL v2 09/21] pvpanic: initialization cleanup, Michael S. Tsirkin, 2013/06/25