On Mon, Jun 29, 2015 at 05:24:53PM +0800, Hong Bo Li wrote:
This patch introduce a new facility(and bus)
to hold devices representing information actually
provided by s390 firmware and I/O configuration.
usage example:
-device s390-pcihost
-device vfio-pci,host=0000:00:00.0,id=vpci1
-device zpci,fid=2,uid=5,pci_id=vpci1,id=zpci1
The first line will create a s390 pci host bridge
and init the root bus. The second line will create
a standard vfio pci device, and attach it to the
root bus. These are similiar to the standard process
to define a pci device on other platform.
The third line will create a s390 pci device to
store s390 specific information, and references
the corresponding vfio pci device via device id.
We create a s390 pci facility bus to hold all the
zpci devices.
Signed-off-by: Hong Bo Li <address@hidden>
It's mostly up to s390 maintainers, but I'd like to note
one thing below
---
hw/s390x/s390-pci-bus.c | 314 +++++++++++++++++++++++++++++++++------------
hw/s390x/s390-pci-bus.h | 48 ++++++-
hw/s390x/s390-pci-inst.c | 4 +-
hw/s390x/s390-virtio-ccw.c | 5 +-
4 files changed, 283 insertions(+), 88 deletions(-)
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 560b66a..d5e7b2e 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -32,8 +32,8 @@ int chsc_sei_nt2_get_event(void *res)
PciCcdfErr *eccdf;
int rc = 1;
SeiContainer *sei_cont;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return rc;
@@ -72,8 +72,8 @@ int chsc_sei_nt2_get_event(void *res)
int chsc_sei_nt2_have_event(void)
{
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return 0;
@@ -82,20 +82,32 @@ int chsc_sei_nt2_have_event(void)
return !QTAILQ_EMPTY(&s->pending_sei);
}
+void s390_pci_device_enable(S390PCIBusDevice *zpci)
+{
+ zpci->fh = zpci->fh | 1 << ENABLE_BIT_OFFSET;
+}
+
+void s390_pci_device_disable(S390PCIBusDevice *zpci)
+{
+ zpci->fh = zpci->fh & ~(1 << ENABLE_BIT_OFFSET);
+ if (zpci->is_unplugged)
+ object_unparent(OBJECT(zpci));
+}
+
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
{
S390PCIBusDevice *pbdev;
- int i;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ BusChild *kid;
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
- if ((pbdev->fh != 0) && (pbdev->fid == fid)) {
+ QTAILQ_FOREACH(kid, &s->fbus->qbus.children, sibling) {
+ pbdev = (S390PCIBusDevice *)kid->child;
+ if (pbdev->fid == fid) {
return pbdev;
}
}
@@ -126,39 +138,24 @@ void s390_pci_sclp_configure(int configure, SCCB *sccb)
return;
}
-static uint32_t s390_pci_get_pfid(PCIDevice *pdev)
-{
- return PCI_SLOT(pdev->devfn);
-}
-
-static uint32_t s390_pci_get_pfh(PCIDevice *pdev)
-{
- return PCI_SLOT(pdev->devfn) | FH_VIRT;
-}
-
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
{
S390PCIBusDevice *pbdev;
- int i;
- int j = 0;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ BusChild *kid;
+ int i = 0;
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
-
- if (pbdev->fh == 0) {
- continue;
- }
-
- if (j == idx) {
+ QTAILQ_FOREACH(kid, &s->fbus->qbus.children, sibling) {
+ pbdev = (S390PCIBusDevice *)kid->child;
+ if (i == idx) {
return pbdev;
}
- j++;
+ i++;
}
return NULL;
This relies on the order of children on the qbus, that's wrong I think.
Generally I'm not sure why do you convert all slot lookups to child
lookups: more code to achieve the same effect?