#include "standard-headers/linux/virtio_pci.h"
#include "hw/virtio/virtio.h"
+#include "migration/qemu-file-types.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
+#include "qemu/module.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "hw/loader.h"
pci_default_write_config(pci_dev, address, val, len);
+ if (proxy->flags & VIRTIO_PCI_FLAG_INIT_FLR) {
+ pcie_cap_flr_write_config(pci_dev, address, val, len);
+ }
+
if (range_covers_byte(address, len, PCI_COMMAND) &&
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
virtio_pci_stop_ioeventfd(proxy);
pcie_ats_init(pci_dev, 256);
}
+ if (proxy->flags & VIRTIO_PCI_FLAG_INIT_FLR) {
+ /* Set Function Level Reset capability bit */
+ pcie_cap_flr_init(pci_dev);
+ }
} else {
/*
* make future invocations of pci_is_express() return false
VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, true),
DEFINE_PROP_BIT("x-pcie-pm-init", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_INIT_PM_BIT, true),
+ DEFINE_PROP_BIT("x-pcie-flr-init", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_INIT_FLR_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
dc->props = virtio_pci_generic_properties;
}
-/* Used when the generic type and the base type is the same */
-static void virtio_pci_generic_base_class_init(ObjectClass *klass, void *data)
-{
- virtio_pci_base_class_init(klass, data);
- virtio_pci_generic_class_init(klass, NULL);
-}
-
static void virtio_pci_transitional_instance_init(Object *obj)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(obj);
void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
{
+ char *base_name = NULL;
TypeInfo base_type_info = {
.name = t->base_name,
.parent = t->parent ? t->parent : TYPE_VIRTIO_PCI,
.instance_size = t->instance_size,
.instance_init = t->instance_init,
.class_size = t->class_size,
- .class_init = virtio_pci_base_class_init,
- .class_data = (void *)t,
.abstract = true,
+ .interfaces = t->interfaces,
};
TypeInfo generic_type_info = {
.name = t->generic_name,
if (!base_type_info.name) {
/* No base type -> register a single generic device type */
- base_type_info.name = t->generic_name;
- base_type_info.class_init = virtio_pci_generic_base_class_init;
- base_type_info.interfaces = generic_type_info.interfaces;
- base_type_info.abstract = false;
- generic_type_info.name = NULL;
+ /* use intermediate %s-base-type to add generic device props */
+ base_name = g_strdup_printf("%s-base-type", t->generic_name);
+ base_type_info.name = base_name;
+ base_type_info.class_init = virtio_pci_generic_class_init;
+
+ generic_type_info.parent = base_name;
+ generic_type_info.class_init = virtio_pci_base_class_init;
+ generic_type_info.class_data = (void *)t;
+
assert(!t->non_transitional_name);
assert(!t->transitional_name);
+ } else {
+ base_type_info.class_init = virtio_pci_base_class_init;
+ base_type_info.class_data = (void *)t;
}
type_register(&base_type_info);
};
type_register(&transitional_type_info);
}
+ g_free(base_name);
}
/* virtio-pci-bus */