xref: /qemu/hw/pci-bridge/pci_bridge_dev.c (revision e3d08143)
1c0907c9eSPaolo Bonzini /*
2c0907c9eSPaolo Bonzini  * Standard PCI Bridge Device
3c0907c9eSPaolo Bonzini  *
4c0907c9eSPaolo Bonzini  * Copyright (c) 2011 Red Hat Inc. Author: Michael S. Tsirkin <mst@redhat.com>
5c0907c9eSPaolo Bonzini  *
6c0907c9eSPaolo Bonzini  * http://www.pcisig.com/specifications/conventional/pci_to_pci_bridge_architecture/
7c0907c9eSPaolo Bonzini  *
8c0907c9eSPaolo Bonzini  * This program is free software; you can redistribute it and/or modify
9c0907c9eSPaolo Bonzini  * it under the terms of the GNU General Public License as published by
10c0907c9eSPaolo Bonzini  * the Free Software Foundation; either version 2 of the License, or
11c0907c9eSPaolo Bonzini  * (at your option) any later version.
12c0907c9eSPaolo Bonzini  *
13c0907c9eSPaolo Bonzini  * This program is distributed in the hope that it will be useful,
14c0907c9eSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15c0907c9eSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16c0907c9eSPaolo Bonzini  * GNU General Public License for more details.
17c0907c9eSPaolo Bonzini  *
18c0907c9eSPaolo Bonzini  * You should have received a copy of the GNU General Public License along
19c0907c9eSPaolo Bonzini  * with this program; if not, see <http://www.gnu.org/licenses/>.
20c0907c9eSPaolo Bonzini  */
21c0907c9eSPaolo Bonzini 
2297d5408fSPeter Maydell #include "qemu/osdep.h"
23da34e65cSMarkus Armbruster #include "qapi/error.h"
240b8fa32fSMarkus Armbruster #include "qemu/module.h"
25c0907c9eSPaolo Bonzini #include "hw/pci/pci_bridge.h"
26c0907c9eSPaolo Bonzini #include "hw/pci/pci_ids.h"
27c0907c9eSPaolo Bonzini #include "hw/pci/msi.h"
28c0907c9eSPaolo Bonzini #include "hw/pci/shpc.h"
29c0907c9eSPaolo Bonzini #include "hw/pci/slotid_cap.h"
30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
31c0907c9eSPaolo Bonzini #include "exec/memory.h"
32c0907c9eSPaolo Bonzini #include "hw/pci/pci_bus.h"
335d268704SIgor Mammedov #include "hw/hotplug.h"
34db1015e9SEduardo Habkost #include "qom/object.h"
35c0907c9eSPaolo Bonzini 
3657524e14SAndreas Färber #define TYPE_PCI_BRIDGE_DEV      "pci-bridge"
37eb6c6a60SGerd Hoffmann #define TYPE_PCI_BRIDGE_SEAT_DEV "pci-bridge-seat"
388063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(PCIBridgeDev, PCI_BRIDGE_DEV)
3957524e14SAndreas Färber 
40c0907c9eSPaolo Bonzini struct PCIBridgeDev {
4157524e14SAndreas Färber     /*< private >*/
4257524e14SAndreas Färber     PCIBridge parent_obj;
4357524e14SAndreas Färber     /*< public >*/
4457524e14SAndreas Färber 
45c0907c9eSPaolo Bonzini     MemoryRegion bar;
46c0907c9eSPaolo Bonzini     uint8_t chassis_nr;
4769b205bbSCao jin #define PCI_BRIDGE_DEV_F_SHPC_REQ 0
48c0907c9eSPaolo Bonzini     uint32_t flags;
4969b205bbSCao jin 
5069b205bbSCao jin     OnOffAuto msi;
516755e618SJing Liu 
526755e618SJing Liu     /* additional resources to reserve */
536755e618SJing Liu     PCIResReserve res_reserve;
54c0907c9eSPaolo Bonzini };
55c0907c9eSPaolo Bonzini 
pci_bridge_dev_realize(PCIDevice * dev,Error ** errp)56344475e7SMao Zhongyi static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp)
57c0907c9eSPaolo Bonzini {
58f055e96bSAndreas Färber     PCIBridge *br = PCI_BRIDGE(dev);
5957524e14SAndreas Färber     PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
60c0907c9eSPaolo Bonzini     int err;
611108b2f8SCao jin     Error *local_err = NULL;
62c0907c9eSPaolo Bonzini 
639cfaa007SCao jin     pci_bridge_initfn(dev, TYPE_PCI_BUS);
649cfaa007SCao jin 
654e5c9bfeSLaszlo Ersek     if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
66c008ac0cSMarcel Apfelbaum         dev->config[PCI_INTERRUPT_PIN] = 0x1;
674e5c9bfeSLaszlo Ersek         memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
684e5c9bfeSLaszlo Ersek                            shpc_bar_size(dev));
69344475e7SMao Zhongyi         err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0, errp);
70c0907c9eSPaolo Bonzini         if (err) {
71c0907c9eSPaolo Bonzini             goto shpc_error;
72c0907c9eSPaolo Bonzini         }
734e5c9bfeSLaszlo Ersek     } else {
744e5c9bfeSLaszlo Ersek         /* MSI is not applicable without SHPC */
7569b205bbSCao jin         bridge_dev->msi = ON_OFF_AUTO_OFF;
764e5c9bfeSLaszlo Ersek     }
7752ea63deSCao jin 
78344475e7SMao Zhongyi     err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0, errp);
79c0907c9eSPaolo Bonzini     if (err) {
80c0907c9eSPaolo Bonzini         goto slotid_error;
81c0907c9eSPaolo Bonzini     }
8252ea63deSCao jin 
831108b2f8SCao jin     if (bridge_dev->msi != ON_OFF_AUTO_OFF) {
841108b2f8SCao jin         /* it means SHPC exists, because MSI is needed by SHPC */
851108b2f8SCao jin 
861108b2f8SCao jin         err = msi_init(dev, 0, 1, true, true, &local_err);
871108b2f8SCao jin         /* Any error other than -ENOTSUP(board's MSI support is broken)
881108b2f8SCao jin          * is a programming error */
891108b2f8SCao jin         assert(!err || err == -ENOTSUP);
901108b2f8SCao jin         if (err && bridge_dev->msi == ON_OFF_AUTO_ON) {
911108b2f8SCao jin             /* Can't satisfy user's explicit msi=on request, fail */
921108b2f8SCao jin             error_append_hint(&local_err, "You have to use msi=auto (default) "
931108b2f8SCao jin                     "or msi=off with this machine type.\n");
94344475e7SMao Zhongyi             error_propagate(errp, local_err);
95c0907c9eSPaolo Bonzini             goto msi_error;
96c0907c9eSPaolo Bonzini         }
971108b2f8SCao jin         assert(!local_err || bridge_dev->msi == ON_OFF_AUTO_AUTO);
981108b2f8SCao jin         /* With msi=auto, we fall back to MSI off silently */
991108b2f8SCao jin         error_free(local_err);
100c0907c9eSPaolo Bonzini     }
10152ea63deSCao jin 
1026755e618SJing Liu     err = pci_bridge_qemu_reserve_cap_init(dev, 0,
1036755e618SJing Liu                                          bridge_dev->res_reserve, errp);
1046755e618SJing Liu     if (err) {
1056755e618SJing Liu         goto cap_error;
1066755e618SJing Liu     }
1076755e618SJing Liu 
1084e5c9bfeSLaszlo Ersek     if (shpc_present(dev)) {
109c0907c9eSPaolo Bonzini         /* TODO: spec recommends using 64 bit prefetcheable BAR.
110c0907c9eSPaolo Bonzini          * Check whether that works well. */
111c0907c9eSPaolo Bonzini         pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
112c0907c9eSPaolo Bonzini                          PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
1134e5c9bfeSLaszlo Ersek     }
114344475e7SMao Zhongyi     return;
11552ea63deSCao jin 
1166755e618SJing Liu cap_error:
1176755e618SJing Liu     msi_uninit(dev);
118c0907c9eSPaolo Bonzini msi_error:
119c0907c9eSPaolo Bonzini     slotid_cap_cleanup(dev);
120c0907c9eSPaolo Bonzini slotid_error:
1214e5c9bfeSLaszlo Ersek     if (shpc_present(dev)) {
122c0907c9eSPaolo Bonzini         shpc_cleanup(dev, &bridge_dev->bar);
1234e5c9bfeSLaszlo Ersek     }
124c0907c9eSPaolo Bonzini shpc_error:
125c0907c9eSPaolo Bonzini     pci_bridge_exitfn(dev);
126c0907c9eSPaolo Bonzini }
127c0907c9eSPaolo Bonzini 
pci_bridge_dev_exitfn(PCIDevice * dev)128c0907c9eSPaolo Bonzini static void pci_bridge_dev_exitfn(PCIDevice *dev)
129c0907c9eSPaolo Bonzini {
13057524e14SAndreas Färber     PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
1316755e618SJing Liu 
1326755e618SJing Liu     pci_del_capability(dev, PCI_CAP_ID_VNDR, sizeof(PCIBridgeQemuCap));
133c0907c9eSPaolo Bonzini     if (msi_present(dev)) {
134c0907c9eSPaolo Bonzini         msi_uninit(dev);
135c0907c9eSPaolo Bonzini     }
136c0907c9eSPaolo Bonzini     slotid_cap_cleanup(dev);
1374e5c9bfeSLaszlo Ersek     if (shpc_present(dev)) {
138c0907c9eSPaolo Bonzini         shpc_cleanup(dev, &bridge_dev->bar);
1394e5c9bfeSLaszlo Ersek     }
140c0907c9eSPaolo Bonzini     pci_bridge_exitfn(dev);
141c0907c9eSPaolo Bonzini }
142c0907c9eSPaolo Bonzini 
pci_bridge_dev_instance_finalize(Object * obj)1435cd5e701SPaolo Bonzini static void pci_bridge_dev_instance_finalize(Object *obj)
1445cd5e701SPaolo Bonzini {
1454e5c9bfeSLaszlo Ersek     /* this function is idempotent and handles (PCIDevice.shpc == NULL) */
1465cd5e701SPaolo Bonzini     shpc_free(PCI_DEVICE(obj));
1475cd5e701SPaolo Bonzini }
1485cd5e701SPaolo Bonzini 
pci_bridge_dev_write_config(PCIDevice * d,uint32_t address,uint32_t val,int len)149c0907c9eSPaolo Bonzini static void pci_bridge_dev_write_config(PCIDevice *d,
150c0907c9eSPaolo Bonzini                                         uint32_t address, uint32_t val, int len)
151c0907c9eSPaolo Bonzini {
152c0907c9eSPaolo Bonzini     pci_bridge_write_config(d, address, val, len);
153c0907c9eSPaolo Bonzini     if (msi_present(d)) {
154c0907c9eSPaolo Bonzini         msi_write_config(d, address, val, len);
155c0907c9eSPaolo Bonzini     }
1564e5c9bfeSLaszlo Ersek     if (shpc_present(d)) {
157c0907c9eSPaolo Bonzini         shpc_cap_write_config(d, address, val, len);
158c0907c9eSPaolo Bonzini     }
1594e5c9bfeSLaszlo Ersek }
160c0907c9eSPaolo Bonzini 
qdev_pci_bridge_dev_reset(DeviceState * qdev)161c0907c9eSPaolo Bonzini static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
162c0907c9eSPaolo Bonzini {
16357524e14SAndreas Färber     PCIDevice *dev = PCI_DEVICE(qdev);
164c0907c9eSPaolo Bonzini 
165c0907c9eSPaolo Bonzini     pci_bridge_reset(qdev);
1664e5c9bfeSLaszlo Ersek     if (shpc_present(dev)) {
167c0907c9eSPaolo Bonzini         shpc_reset(dev);
168c0907c9eSPaolo Bonzini     }
1694e5c9bfeSLaszlo Ersek }
170c0907c9eSPaolo Bonzini 
171c0907c9eSPaolo Bonzini static Property pci_bridge_dev_properties[] = {
172c0907c9eSPaolo Bonzini                     /* Note: 0 is not a legal chassis number. */
1733cf0ecb3SLaszlo Ersek     DEFINE_PROP_UINT8(PCI_BRIDGE_DEV_PROP_CHASSIS_NR, PCIBridgeDev, chassis_nr,
1743cf0ecb3SLaszlo Ersek                       0),
17569b205bbSCao jin     DEFINE_PROP_ON_OFF_AUTO(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, msi,
17669b205bbSCao jin                             ON_OFF_AUTO_AUTO),
1774e5c9bfeSLaszlo Ersek     DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags,
1782fa35662SMarcel Apfelbaum                     PCI_BRIDGE_DEV_F_SHPC_REQ, true),
1796755e618SJing Liu     DEFINE_PROP_UINT32("bus-reserve", PCIBridgeDev,
1806755e618SJing Liu                        res_reserve.bus, -1),
1816755e618SJing Liu     DEFINE_PROP_SIZE("io-reserve", PCIBridgeDev,
1826755e618SJing Liu                      res_reserve.io, -1),
1836755e618SJing Liu     DEFINE_PROP_SIZE("mem-reserve", PCIBridgeDev,
1846755e618SJing Liu                      res_reserve.mem_non_pref, -1),
1856755e618SJing Liu     DEFINE_PROP_SIZE("pref32-reserve", PCIBridgeDev,
1866755e618SJing Liu                      res_reserve.mem_pref_32, -1),
1876755e618SJing Liu     DEFINE_PROP_SIZE("pref64-reserve", PCIBridgeDev,
1886755e618SJing Liu                      res_reserve.mem_pref_64, -1),
189c0907c9eSPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
190c0907c9eSPaolo Bonzini };
191c0907c9eSPaolo Bonzini 
pci_device_shpc_present(void * opaque,int version_id)1924e5c9bfeSLaszlo Ersek static bool pci_device_shpc_present(void *opaque, int version_id)
1934e5c9bfeSLaszlo Ersek {
1944e5c9bfeSLaszlo Ersek     PCIDevice *dev = opaque;
1954e5c9bfeSLaszlo Ersek 
1964e5c9bfeSLaszlo Ersek     return shpc_present(dev);
1974e5c9bfeSLaszlo Ersek }
1984e5c9bfeSLaszlo Ersek 
199c0907c9eSPaolo Bonzini static const VMStateDescription pci_bridge_dev_vmstate = {
200c0907c9eSPaolo Bonzini     .name = "pci_bridge",
2019d6b9db1SPeter Xu     .priority = MIG_PRI_PCI_BUS,
202f026c578SRichard Henderson     .fields = (const VMStateField[]) {
20357524e14SAndreas Färber         VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
2044e5c9bfeSLaszlo Ersek         SHPC_VMSTATE(shpc, PCIDevice, pci_device_shpc_present),
205c0907c9eSPaolo Bonzini         VMSTATE_END_OF_LIST()
206c0907c9eSPaolo Bonzini     }
207c0907c9eSPaolo Bonzini };
208c0907c9eSPaolo Bonzini 
pci_bridge_dev_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)20962b76563SDavid Hildenbrand void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
21062b76563SDavid Hildenbrand                             Error **errp)
2114e5c9bfeSLaszlo Ersek {
2124e5c9bfeSLaszlo Ersek     PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
2134e5c9bfeSLaszlo Ersek 
2144e5c9bfeSLaszlo Ersek     if (!shpc_present(pci_hotplug_dev)) {
2154e5c9bfeSLaszlo Ersek         error_setg(errp, "standard hotplug controller has been disabled for "
21662b76563SDavid Hildenbrand                    "this %s", object_get_typename(OBJECT(hotplug_dev)));
2174e5c9bfeSLaszlo Ersek         return;
2184e5c9bfeSLaszlo Ersek     }
219851fedfbSDavid Hildenbrand     shpc_device_plug_cb(hotplug_dev, dev, errp);
2204e5c9bfeSLaszlo Ersek }
2214e5c9bfeSLaszlo Ersek 
pci_bridge_dev_unplug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)2228f560cdcSDavid Hildenbrand void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
2238f560cdcSDavid Hildenbrand                               Error **errp)
2248f560cdcSDavid Hildenbrand {
2258f560cdcSDavid Hildenbrand     PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
2268f560cdcSDavid Hildenbrand 
2278f560cdcSDavid Hildenbrand     g_assert(shpc_present(pci_hotplug_dev));
2288f560cdcSDavid Hildenbrand     shpc_device_unplug_cb(hotplug_dev, dev, errp);
2298f560cdcSDavid Hildenbrand }
2308f560cdcSDavid Hildenbrand 
pci_bridge_dev_unplug_request_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)23162b76563SDavid Hildenbrand void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
232851fedfbSDavid Hildenbrand                                       DeviceState *dev, Error **errp)
2334e5c9bfeSLaszlo Ersek {
2344e5c9bfeSLaszlo Ersek     PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
2354e5c9bfeSLaszlo Ersek 
2364e5c9bfeSLaszlo Ersek     if (!shpc_present(pci_hotplug_dev)) {
2374e5c9bfeSLaszlo Ersek         error_setg(errp, "standard hotplug controller has been disabled for "
23862b76563SDavid Hildenbrand                    "this %s", object_get_typename(OBJECT(hotplug_dev)));
2394e5c9bfeSLaszlo Ersek         return;
2404e5c9bfeSLaszlo Ersek     }
241851fedfbSDavid Hildenbrand     shpc_device_unplug_request_cb(hotplug_dev, dev, errp);
2424e5c9bfeSLaszlo Ersek }
2434e5c9bfeSLaszlo Ersek 
pci_bridge_dev_class_init(ObjectClass * klass,void * data)244c0907c9eSPaolo Bonzini static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
245c0907c9eSPaolo Bonzini {
246c0907c9eSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
247c0907c9eSPaolo Bonzini     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2485d268704SIgor Mammedov     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
2495d268704SIgor Mammedov 
250344475e7SMao Zhongyi     k->realize = pci_bridge_dev_realize;
251c0907c9eSPaolo Bonzini     k->exit = pci_bridge_dev_exitfn;
252c0907c9eSPaolo Bonzini     k->config_write = pci_bridge_dev_write_config;
253c0907c9eSPaolo Bonzini     k->vendor_id = PCI_VENDOR_ID_REDHAT;
254c0907c9eSPaolo Bonzini     k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE;
255c0907c9eSPaolo Bonzini     k->class_id = PCI_CLASS_BRIDGE_PCI;
256c0907c9eSPaolo Bonzini     dc->desc = "Standard PCI Bridge";
257*e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, qdev_pci_bridge_dev_reset);
2584f67d30bSMarc-André Lureau     device_class_set_props(dc, pci_bridge_dev_properties);
259c0907c9eSPaolo Bonzini     dc->vmsd = &pci_bridge_dev_vmstate;
260125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
261851fedfbSDavid Hildenbrand     hc->plug = pci_bridge_dev_plug_cb;
2628f560cdcSDavid Hildenbrand     hc->unplug = pci_bridge_dev_unplug_cb;
263851fedfbSDavid Hildenbrand     hc->unplug_request = pci_bridge_dev_unplug_request_cb;
264c0907c9eSPaolo Bonzini }
265c0907c9eSPaolo Bonzini 
266c0907c9eSPaolo Bonzini static const TypeInfo pci_bridge_dev_info = {
26757524e14SAndreas Färber     .name              = TYPE_PCI_BRIDGE_DEV,
268f055e96bSAndreas Färber     .parent            = TYPE_PCI_BRIDGE,
269c0907c9eSPaolo Bonzini     .instance_size     = sizeof(PCIBridgeDev),
270c0907c9eSPaolo Bonzini     .class_init        = pci_bridge_dev_class_init,
2715cd5e701SPaolo Bonzini     .instance_finalize = pci_bridge_dev_instance_finalize,
2725d268704SIgor Mammedov     .interfaces = (InterfaceInfo[]) {
2735d268704SIgor Mammedov         { TYPE_HOTPLUG_HANDLER },
274fd3b02c8SEduardo Habkost         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
2755d268704SIgor Mammedov         { }
2765d268704SIgor Mammedov     }
277c0907c9eSPaolo Bonzini };
278c0907c9eSPaolo Bonzini 
279eb6c6a60SGerd Hoffmann /*
280eb6c6a60SGerd Hoffmann  * Multiseat bridge.  Same as the standard pci bridge, only with a
281eb6c6a60SGerd Hoffmann  * different pci id, so we can match it easily in the guest for
282eb6c6a60SGerd Hoffmann  * automagic multiseat configuration.  See docs/multiseat.txt for more.
283eb6c6a60SGerd Hoffmann  */
pci_bridge_dev_seat_class_init(ObjectClass * klass,void * data)284eb6c6a60SGerd Hoffmann static void pci_bridge_dev_seat_class_init(ObjectClass *klass, void *data)
285eb6c6a60SGerd Hoffmann {
286eb6c6a60SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
287eb6c6a60SGerd Hoffmann     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
288eb6c6a60SGerd Hoffmann 
289eb6c6a60SGerd Hoffmann     k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT;
290eb6c6a60SGerd Hoffmann     dc->desc = "Standard PCI Bridge (multiseat)";
291eb6c6a60SGerd Hoffmann }
292eb6c6a60SGerd Hoffmann 
293eb6c6a60SGerd Hoffmann static const TypeInfo pci_bridge_dev_seat_info = {
294eb6c6a60SGerd Hoffmann     .name              = TYPE_PCI_BRIDGE_SEAT_DEV,
295eb6c6a60SGerd Hoffmann     .parent            = TYPE_PCI_BRIDGE_DEV,
296eb6c6a60SGerd Hoffmann     .instance_size     = sizeof(PCIBridgeDev),
297eb6c6a60SGerd Hoffmann     .class_init        = pci_bridge_dev_seat_class_init,
298eb6c6a60SGerd Hoffmann };
299eb6c6a60SGerd Hoffmann 
pci_bridge_dev_register(void)300c0907c9eSPaolo Bonzini static void pci_bridge_dev_register(void)
301c0907c9eSPaolo Bonzini {
302c0907c9eSPaolo Bonzini     type_register_static(&pci_bridge_dev_info);
303eb6c6a60SGerd Hoffmann     type_register_static(&pci_bridge_dev_seat_info);
304c0907c9eSPaolo Bonzini }
305c0907c9eSPaolo Bonzini 
306c0907c9eSPaolo Bonzini type_init(pci_bridge_dev_register);
307