Patchwork [40/61] pci: use qdev to get parent bus with PCIBus.

login
register
mail settings
Submitter Isaku Yamahata
Date Sept. 30, 2009, 10:18 a.m.
Message ID <1254305917-14784-41-git-send-email-yamahata@valinux.co.jp>
Download mbox | patch
Permalink /patch/34594/
State Superseded
Headers show

Comments

Isaku Yamahata - Sept. 30, 2009, 10:18 a.m.
Now qdev tracks the relationship between bus and device, so
a member, bus, in PCIDevice/PCIBridge and parent_dev in PCIBus
are redundant.
This patch removes them and introduces some helper functions
which will be used later.

For non-qdevfied device, keep the bus member in PCIDevice.
It will be removed once all of PCIDevices are converted.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci-hotplug.c |    7 ++---
 hw/pci.c         |   69 +++++++++++++++++++++++++++++++++++++++++++-----------
 hw/pci.h         |    8 +++++-
 3 files changed, 65 insertions(+), 19 deletions(-)

Patch

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index f3dc421..1aa1241 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -181,11 +181,10 @@  void pci_device_hot_add(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "invalid type: %s\n", type);
 
     if (dev) {
-        qemu_system_device_hot_add(pci_bus_num(dev->bus),
-                                   PCI_SLOT(dev->devfn), 1);
+        int bus_num = pci_bus_num(pci_get_parent_bus(dev));
+        qemu_system_device_hot_add(bus_num, PCI_SLOT(dev->devfn), 1);
         monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
-                       0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
-                       PCI_FUNC(dev->devfn));
+                       0, bus_num, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
     } else
         monitor_printf(mon, "failed to add %s\n", opts);
 }
diff --git a/hw/pci.c b/hw/pci.c
index a8694f8..ec6c7d4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -44,7 +44,6 @@  struct PCIBus {
     uint32_t config_reg; /* XXX: suppress */
     void *irq_opaque;
     PCIDevice *devices[256];
-    PCIDevice *parent_dev;
     QLIST_ENTRY(PCIBus) next;
     /* The bus IRQ state is the logical OR of the connected devices.
        Keep a count of the number of devices with raised IRQs.  */
@@ -84,6 +83,37 @@  static const VMStateDescription vmstate_pcibus = {
     }
 };
 
+static PCIBus *qbus_to_pcibus(struct BusState *qbus)
+{
+    return DO_UPCAST(PCIBus, qbus, qbus);
+}
+
+PCIDevice *qdev_to_pcidev(struct DeviceState *qdev)
+{
+    return DO_UPCAST(PCIDevice, qdev, qdev);
+}
+
+PCIBus *pci_get_parent_bus(PCIDevice *dev)
+{
+    if (dev->qdev.info == NULL) {
+        /* for non-qdevfied device */
+        assert(dev->bus != NULL);
+        return dev->bus;
+    }
+
+    return qbus_to_pcibus(dev->qdev.parent_bus);
+}
+
+BusState *pci_bus_to_qbus(PCIBus *bus)
+{
+    return &bus->qbus;
+}
+
+PCIDevice *pci_bus_to_dev(PCIBus *bus)
+{
+    return qdev_to_pcidev(bus->qbus.parent);
+}
+
 static void pci_bus_reset(void *opaque)
 {
     PCIBus *bus = opaque;
@@ -127,7 +157,6 @@  static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
-    bus->parent_dev = dev;
     QLIST_INSERT_AFTER(dev->bus, bus, next);
     return bus;
 }
@@ -379,7 +408,6 @@  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     } else if (bus->devices[devfn]) {
         return NULL;
     }
-    pci_dev->bus = bus;
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
@@ -410,6 +438,8 @@  PCIDevice *pci_register_device(PCIBus *bus, const char *name,
     pci_dev = qemu_mallocz(instance_size);
     pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
                                      config_read, config_write);
+    /* XXX for non-qdevfied device */
+    pci_dev->bus = bus;
     return pci_dev;
 }
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
@@ -448,7 +478,7 @@  int pci_unregister_device(PCIDevice *pci_dev)
     pci_unregister_io_regions(pci_dev);
 
     qemu_free_irqs(pci_dev->irq);
-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_get_parent_bus(pci_dev)->devices[pci_dev->devfn] = NULL;
     qdev_free(&pci_dev->qdev);
     return 0;
 }
@@ -891,11 +921,11 @@  static void pci_set_irq(void *opaque, int irq_num, int level)
 
     pci_dev->irq_state[irq_num] = level;
     for (;;) {
-        bus = pci_dev->bus;
+        bus = pci_get_parent_bus(pci_dev);
         irq_num = bus->map_irq(pci_dev, irq_num);
         if (bus->set_irq)
             break;
-        pci_dev = bus->parent_dev;
+        pci_dev = pci_bus_to_dev(bus);
     }
     bus->irq_count[irq_num] += change;
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
@@ -963,7 +993,8 @@  static void pci_info_device(PCIDevice *d)
     const pci_class_desc *desc;
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
-                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+                   pci_get_parent_bus(d)->bus_num,
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -1118,16 +1149,27 @@  PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 
 typedef struct {
     PCIDevice dev;
-    PCIBus *bus;
 } PCIBridge;
 
+static PCIBridge *pci_dev_to_br(PCIDevice *d)
+{
+    return DO_UPCAST(PCIBridge, dev, d);
+}
+
+static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
+{
+    /* assuming only one bus is registered */
+    return qbus_to_pcibus(QLIST_FIRST(&bridge->dev.qdev.child_bus));
+}
+
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
-    PCIBridge *s = (PCIBridge *)d;
+    PCIBridge *bridge = pci_dev_to_br(d);
+    PCIBus *bus = pci_bridge_get_secbus(bridge);
 
     pci_default_write_config(d, address, val, len);
-    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    bus->bus_num = d->config[PCI_SECONDARY_BUS];
 }
 
 PCIBus *pci_find_bus(int bus_num)
@@ -1167,8 +1209,7 @@  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
     s->dev.config[0x1E] = 0xa0; // secondary status
 
-    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
-    return s->bus;
+    return pci_register_secondary_bus(&s->dev, map_irq, name);
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
@@ -1315,8 +1356,8 @@  static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
-                   indent, "", ctxt,
-                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
+                   indent, "", ctxt, pci_get_parent_bus(d)->bus_num,
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
diff --git a/hw/pci.h b/hw/pci.h
index 3327905..0aedbf5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -204,7 +204,9 @@  struct PCIDevice {
     uint8_t *used;
 
     /* the following fields are read only */
-    PCIBus *bus;
+    PCIBus *bus;     /* non qdevfied device only
+                      * Once all the device is qdevified, this will be removed.
+                      */
     uint32_t devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
@@ -291,6 +293,10 @@  int pci_bus_num(PCIBus *s);
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
 PCIBus *pci_find_bus(int bus_num);
 PCIDevice *pci_find_device(int bus_num, int slot, int function);
+PCIBus *pci_get_parent_bus(PCIDevice *dev);
+PCIDevice *qdev_to_pcidev(struct DeviceState *qdev);
+BusState *pci_bus_to_qbus(PCIBus *bus);
+PCIDevice *pci_bus_to_dev(PCIBus *bus);
 
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);