qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] pci: PCIBus clean up.


From: Isaku Yamahata
Subject: [Qemu-devel] [PATCH] pci: PCIBus clean up.
Date: Thu, 18 Jun 2009 19:57:15 +0900
User-agent: Mutt/1.5.6i

- use LIST_xxx macros for bus list.
- remove duplicated member in PCIDevice and PCIBus
  because qdev layer tracks bus<->device relation.
- introduce helper function to get PCIDevice/PCIBus

Signed-off-by: Isaku Yamahata <address@hidden>
---
Changes
- rebased not to depend on pci callback patch.
- don't eliminate PCIBridge. Keep it
---
 hw/pci-hotplug.c |    4 +-
 hw/pci.c         |  141 +++++++++++++++++++++++++++++++++++-------------------
 hw/pci.h         |    3 +-
 3 files changed, 96 insertions(+), 52 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 4d49c29..2d50b3b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -158,8 +158,8 @@ void pci_device_hot_add(Monitor *mon, const char *pci_addr, 
const char *type,
     if (dev) {
         qemu_system_device_hot_add(bus, 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, pci_bus_num(pci_get_parent_bus(dev)),
+                       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 0a738db..3ac73d2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -40,8 +40,8 @@ struct PCIBus {
     SetIRQFunc *low_set_irq;
     qemu_irq *irq_opaque;
     PCIDevice *devices[256];
-    PCIDevice *parent_dev;
-    PCIBus *next;
+    LIST_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.  */
     int nirq;
@@ -54,7 +54,27 @@ static void pci_set_irq(void *opaque, int irq_num, int 
level);
 target_phys_addr_t pci_mem_base;
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-static PCIBus *first_bus;
+static LIST_HEAD(, PCIBus) first_bus;
+
+static PCIBus *qbus_to_pcibus(struct BusState *qbus)
+{
+    return container_of(qbus, PCIBus, qbus);
+}
+
+static PCIDevice *qdev_to_pcidev(struct DeviceState *qdev)
+{
+    return container_of(qdev, PCIDevice, qdev);
+}
+
+PCIBus *pci_get_parent_bus(PCIDevice *dev)
+{
+    return qbus_to_pcibus(dev->qdev.parent_bus);
+}
+
+PCIDevice *pci_bus_to_dev(PCIBus *bus)
+{
+    return qdev_to_pcidev(bus->qbus.parent);
+}
 
 static void pcibus_save(QEMUFile *f, void *opaque)
 {
@@ -102,8 +122,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char 
*name,
     bus->irq_opaque = pic;
     bus->devfn_min = devfn_min;
     bus->nirq = nirq;
-    bus->next = first_bus;
-    first_bus = bus;
+
+    LIST_INSERT_HEAD(&first_bus, bus, next);
     register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
     return bus;
 }
@@ -111,11 +131,19 @@ PCIBus *pci_register_bus(DeviceState *parent, const char 
*name,
 static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn 
map_irq)
 {
     PCIBus *bus;
-    bus = qemu_mallocz(sizeof(PCIBus));
+    PCIBus *parent_bus;
+    int devfn_min = qdev_get_prop_int(&dev->qdev, "devfn_min", 0);
+    int nirq = qdev_get_prop_int(&dev->qdev, "nirq", 0);
+
+    bus = FROM_QBUS(PCIBus, qbus_create(BUS_TYPE_PCI,
+                                        sizeof(PCIBus) + (nirq * sizeof(int)),
+                                        &dev->qdev, "pci"));
     bus->map_irq = map_irq;
-    bus->parent_dev = dev;
-    bus->next = dev->bus->next;
-    dev->bus->next = bus;
+    bus->devfn_min = devfn_min;
+    bus->nirq = nirq;
+
+    parent_bus = pci_get_parent_bus(dev);
+    LIST_INSERT_AFTER(parent_bus, bus, next);
     return bus;
 }
 
@@ -252,7 +280,6 @@ static PCIDevice *do_pci_register_device(PCIDevice 
*pci_dev, PCIBus *bus,
         return NULL;
     found: ;
     }
-    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));
@@ -317,7 +344,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;
 }
@@ -571,6 +598,16 @@ void pci_default_write_config(PCIDevice *d,
     }
 }
 
+static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
+{
+    PCIBus *s = from;
+
+    while (s && s->bus_num != bus_num)
+        s = LIST_NEXT(s, next);
+
+    return s;
+}
+
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
 {
     PCIBus *s = opaque;
@@ -582,8 +619,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t 
val, int len)
            addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s = s->next;
+    s = pci_find_bus_from(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -605,8 +641,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s= s->next;
+    s = pci_find_bus_from(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -656,11 +691,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);
@@ -722,7 +757,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, d->devfn >> 3, d->devfn & 7);
+                   pci_get_parent_bus(d)->bus_num,
+                   d->devfn >> 3, d->devfn & 7);
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -764,12 +800,11 @@ static void pci_info_device(PCIDevice *d)
 
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
 {
-    PCIBus *bus = first_bus;
+    PCIBus *bus;
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    bus = pci_find_bus_from(LIST_FIRST(&first_bus), bus_num);
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
@@ -833,21 +868,31 @@ PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int 
devfn,
 
 typedef struct {
     PCIDevice dev;
-    PCIBus *bus;
 } PCIBridge;
 
+static PCIBridge *pcidev_to_pcibr(PCIDevice *d)
+{
+    return container_of(d, PCIBridge, dev);
+}
+
+static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
+{
+    /* assuming only one bus is registered */
+    return qbus_to_pcibus(LIST_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;
-
     if (address == 0x19 || (address == 0x18 && len > 1)) {
+        PCIBridge *bridge = pcidev_to_pcibr(d);
+        PCIBus *bus = pci_bridge_get_secbus(bridge);
         if (address == 0x19)
-            s->bus->bus_num = val & 0xff;
+            bus->bus_num = val & 0xff;
         else
-            s->bus->bus_num = (val >> 8) & 0xff;
+            bus->bus_num = (val >> 8) & 0xff;
 #if defined(DEBUG_PCI)
-        printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
+        printf ("pci-bridge: %s: Assigned bus %d\n", d->name, bus->bus_num);
 #endif
     }
     pci_default_write_config(d, address, val, len);
@@ -855,12 +900,7 @@ static void pci_bridge_write_config(PCIDevice *d,
 
 PCIBus *pci_find_bus(int bus_num)
 {
-    PCIBus *bus = first_bus;
-
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
-
-    return bus;
+    return pci_find_bus_from(LIST_FIRST(&first_bus), bus_num);
 }
 
 PCIDevice *pci_find_device(int bus_num, int slot, int function)
@@ -877,26 +917,29 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t 
vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name)
 {
     PCIBridge *s;
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
     s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
                                          devfn, NULL, pci_bridge_write_config);
-
-    pci_config_set_vendor_id(s->dev.config, vid);
-    pci_config_set_device_id(s->dev.config, did);
-
-    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
-    s->dev.config[0x05] = 0x00;
-    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    s->dev.config[0x07] = 0x00; // status = fast devsel
-    s->dev.config[0x08] = 0x00; // revision
-    s->dev.config[0x09] = 0x00; // programming i/f
-    pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
-    s->dev.config[0x0D] = 0x10; // latency_timer
-    s->dev.config[PCI_HEADER_TYPE] =
+    d = &s->dev;
+    pci_conf = d->config;
+    pci_config_set_vendor_id(pci_conf, vid);
+    pci_config_set_device_id(pci_conf, did);
+
+    pci_conf[0x04] = 0x06; // command = bus master, pci mem
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_conf[0x07] = 0x00; // status = fast devsel
+    pci_conf[0x08] = 0x00; // revision
+    pci_conf[0x09] = 0x00; // programming i/f
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
+    pci_conf[0x0D] = 0x10; // latency_timer
+    pci_conf[PCI_HEADER_TYPE] =
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
-    s->dev.config[0x1E] = 0xa0; // secondary status
+    pci_conf[0x1E] = 0xa0; // secondary status
 
-    s->bus = pci_register_secondary_bus(&s->dev, map_irq);
-    return s->bus;
+    return pci_register_secondary_bus(d, map_irq);
 }
 
 typedef struct {
diff --git a/hw/pci.h b/hw/pci.h
index fcca526..0c0e725 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -143,7 +143,6 @@ struct PCIDevice {
     uint8_t config[256];
 
     /* the following fields are read only */
-    PCIBus *bus;
     int devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
@@ -198,6 +197,8 @@ int pci_assign_devaddr(const char *addr, int *domp, int 
*busp, unsigned *slotp);
 void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name);
+PCIBus *pci_get_parent_bus(PCIDevice *dev);
+PCIDevice *pci_bus_to_dev(PCIBus *bus);
 
 static inline void
 pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
-- 
1.6.0.2



-- 
yamahata




reply via email to

[Prev in Thread] Current Thread [Next in Thread]