qom: add support for qom objects in modules.
build some devices (qxl, virtio-gpu, ccid, usb-redir) as modules. build braille chardev as module. v2: more verbose comment for "build: fix device module builds" patch. note: qemu doesn't rebuild objects on cflags changes (specifically -fPIC being added when code is switched from builtin to module). Workaround for resulting build errors: "make clean", rebuild. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCgAGBQJfBHu4AAoJEEy22O7T6HE4uh8P/0clQVfXb8jBsCnLw2dJuvdx rJzgZTn5BQElCmZYN43LElyCcD7DO2Exz6JtV554oK/tjH/QkOKAKzPzk+FzhKta 3zyGvlS79KMHoMoIf6xSIbSv3/jt2iP9TU9HpaHXIBQJTAtExAasEPtr3ewgAhDv wd5FC/slM7NNofQgyz5ycAKGddwOYFP/zAnTZPU2noCek2B86OgBX+BN5VIaxn/g Reuk4z0QBLWXGmb2j6RbmBKZ61V/qokpz9OjwZ1reRU+tTXOzhu8ROr+GDmNj3D8 m8mt1t8UUIH35Zo9Lc0+4P6aKCk5gQI4tYukut/8zXqnNdPhQxsnCFiR1U8kZter +189dhVXLZ+vp8IMe7piu/a4iU/5Jgz30VUOetrAM0CDjzuI0Bbp1wSjgiLyZ9EC CZLxIm2lZCHCr92G4UtmUR0dnacoee96bsAs/Rd9U3DWRLaDwuTNGYPfW1J5fEyn nqLscU/8H2H8tQhSjX8nTkxXh29/bA1pzb/auPKkajS+rblACWgYyj8035VyWIiB NTJZzvXXAxLNObLZSLteUQLOn5ugjmicH7Q8RJZmcQzudq0PDlJrF8vXJ2R6PZLF 4ecSgy1b1xA7xvXc4tAdtnlcVvVl/LU5EMWooQP26cKZzJOM0GnUUlBo+K6oEQTf 0lXrg6LAhH1sevdFzhNd =DVlH -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/modules-20200707-pull-request' into staging qom: add support for qom objects in modules. build some devices (qxl, virtio-gpu, ccid, usb-redir) as modules. build braille chardev as module. v2: more verbose comment for "build: fix device module builds" patch. note: qemu doesn't rebuild objects on cflags changes (specifically -fPIC being added when code is switched from builtin to module). Workaround for resulting build errors: "make clean", rebuild. # gpg: Signature made Tue 07 Jul 2020 14:42:16 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/modules-20200707-pull-request: chardev: enable modules, use for braille vga: build virtio-gpu as module vga: build virtio-gpu only once vga: build qxl as module usb: build usb-redir as module ccid: build smartcard as module build: fix device module builds qdev: device module support object: qom module support module: qom module support Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
aff2caf6b3
@ -59,6 +59,7 @@ common-obj-y += migration/
|
|||||||
common-obj-y += audio/
|
common-obj-y += audio/
|
||||||
common-obj-m += audio/
|
common-obj-m += audio/
|
||||||
common-obj-y += hw/
|
common-obj-y += hw/
|
||||||
|
common-obj-m += hw/
|
||||||
|
|
||||||
common-obj-y += replay/
|
common-obj-y += replay/
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ common-obj-$(CONFIG_TPM) += tpm.o
|
|||||||
|
|
||||||
common-obj-y += backends/
|
common-obj-y += backends/
|
||||||
common-obj-y += chardev/
|
common-obj-y += chardev/
|
||||||
|
common-obj-m += chardev/
|
||||||
|
|
||||||
common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
|
common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
|
||||||
qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS)
|
qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS)
|
||||||
|
@ -179,6 +179,20 @@ endif # CONFIG_SOFTMMU
|
|||||||
dummy := $(call unnest-vars,,obj-y)
|
dummy := $(call unnest-vars,,obj-y)
|
||||||
all-obj-y := $(obj-y)
|
all-obj-y := $(obj-y)
|
||||||
|
|
||||||
|
#
|
||||||
|
# common-obj-m has some crap here, probably as side effect from
|
||||||
|
# unnest-vars recursing into target directories to fill obj-y and not
|
||||||
|
# properly handling the -m case.
|
||||||
|
#
|
||||||
|
# Clear common-obj-m as workaround. Fixes suspious dependency errors
|
||||||
|
# when building devices as modules. A bit hackish, but should be ok
|
||||||
|
# as long as we do not have any target-specific modules.
|
||||||
|
#
|
||||||
|
# The meson-based build system currently in development doesn't need
|
||||||
|
# unnest-vars and will obsolete this workaround.
|
||||||
|
#
|
||||||
|
common-obj-m :=
|
||||||
|
|
||||||
include $(SRC_PATH)/Makefile.objs
|
include $(SRC_PATH)/Makefile.objs
|
||||||
dummy := $(call unnest-vars,.., \
|
dummy := $(call unnest-vars,.., \
|
||||||
authz-obj-y \
|
authz-obj-y \
|
||||||
|
@ -18,8 +18,11 @@ chardev-obj-$(CONFIG_WIN32) += char-win.o
|
|||||||
chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
|
chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
|
||||||
|
|
||||||
common-obj-y += msmouse.o wctablet.o testdev.o
|
common-obj-y += msmouse.o wctablet.o testdev.o
|
||||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
|
||||||
|
ifeq ($(CONFIG_BRLAPI),y)
|
||||||
|
common-obj-m += baum.o
|
||||||
baum.o-cflags := $(SDL_CFLAGS)
|
baum.o-cflags := $(SDL_CFLAGS)
|
||||||
baum.o-libs := $(BRLAPI_LIBS)
|
baum.o-libs := $(BRLAPI_LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
common-obj-$(CONFIG_SPICE) += spice.o
|
common-obj-$(CONFIG_SPICE) += spice.o
|
||||||
|
@ -527,7 +527,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
|
|||||||
const ChardevClass *cc;
|
const ChardevClass *cc;
|
||||||
char *typename = g_strdup_printf("chardev-%s", driver);
|
char *typename = g_strdup_printf("chardev-%s", driver);
|
||||||
|
|
||||||
oc = object_class_by_name(typename);
|
oc = module_object_class_by_name(typename);
|
||||||
g_free(typename);
|
g_free(typename);
|
||||||
|
|
||||||
if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
|
if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
|
||||||
|
@ -43,4 +43,6 @@ devices-dirs-y += smbios/
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
common-obj-y += $(devices-dirs-y)
|
common-obj-y += $(devices-dirs-y)
|
||||||
|
common-obj-m += display/
|
||||||
|
common-obj-m += usb/
|
||||||
obj-y += $(devices-dirs-y)
|
obj-y += $(devices-dirs-y)
|
||||||
|
@ -137,6 +137,9 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
|
|||||||
*/
|
*/
|
||||||
DeviceState *qdev_new(const char *name)
|
DeviceState *qdev_new(const char *name)
|
||||||
{
|
{
|
||||||
|
if (!object_class_by_name(name)) {
|
||||||
|
module_load_qom_one(name);
|
||||||
|
}
|
||||||
return DEVICE(object_new(name));
|
return DEVICE(object_new(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,10 +150,9 @@ DeviceState *qdev_new(const char *name)
|
|||||||
*/
|
*/
|
||||||
DeviceState *qdev_try_new(const char *name)
|
DeviceState *qdev_try_new(const char *name)
|
||||||
{
|
{
|
||||||
if (!object_class_by_name(name)) {
|
if (!module_object_class_by_name(name)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DEVICE(object_new(name));
|
return DEVICE(object_new(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,18 +44,24 @@ common-obj-$(CONFIG_ARTIST) += artist.o
|
|||||||
|
|
||||||
obj-$(CONFIG_VGA) += vga.o
|
obj-$(CONFIG_VGA) += vga.o
|
||||||
|
|
||||||
common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
|
ifeq ($(CONFIG_QXL),y)
|
||||||
|
common-obj-m += qxl.mo
|
||||||
|
qxl.mo-objs = qxl.o qxl-logger.o qxl-render.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_VIRTIO_GPU),y)
|
||||||
|
common-obj-m += virtio-gpu.mo
|
||||||
|
virtio-gpu-obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o
|
||||||
|
virtio-gpu-obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o
|
||||||
|
virtio-gpu-obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o
|
||||||
|
virtio-gpu-obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o
|
||||||
|
virtio-gpu-obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
|
||||||
|
virtio-gpu-obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o
|
||||||
|
virtio-gpu.mo-objs := $(virtio-gpu-obj-y)
|
||||||
|
virtio-gpu.mo-cflags := $(VIRGL_CFLAGS)
|
||||||
|
virtio-gpu.mo-libs := $(VIRGL_LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o
|
|
||||||
obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o
|
|
||||||
obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o
|
|
||||||
obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o
|
|
||||||
obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
|
|
||||||
obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o
|
|
||||||
virtio-gpu.o-cflags := $(VIRGL_CFLAGS)
|
|
||||||
virtio-gpu.o-libs += $(VIRGL_LIBS)
|
|
||||||
virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS)
|
|
||||||
virtio-gpu-3d.o-libs += $(VIRGL_LIBS)
|
|
||||||
common-obj-$(CONFIG_DPCD) += dpcd.o
|
common-obj-$(CONFIG_DPCD) += dpcd.o
|
||||||
common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dp.o
|
common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dp.o
|
||||||
|
|
||||||
|
@ -29,11 +29,13 @@ common-obj-$(CONFIG_USB_NETWORK) += dev-network.o
|
|||||||
|
|
||||||
ifeq ($(CONFIG_USB_SMARTCARD),y)
|
ifeq ($(CONFIG_USB_SMARTCARD),y)
|
||||||
common-obj-y += dev-smartcard-reader.o
|
common-obj-y += dev-smartcard-reader.o
|
||||||
common-obj-$(CONFIG_SMARTCARD) += smartcard.mo
|
ifeq ($(CONFIG_SMARTCARD),y)
|
||||||
|
common-obj-m += smartcard.mo
|
||||||
smartcard.mo-objs := ccid-card-passthru.o ccid-card-emulated.o
|
smartcard.mo-objs := ccid-card-passthru.o ccid-card-emulated.o
|
||||||
smartcard.mo-cflags := $(SMARTCARD_CFLAGS)
|
smartcard.mo-cflags := $(SMARTCARD_CFLAGS)
|
||||||
smartcard.mo-libs := $(SMARTCARD_LIBS)
|
smartcard.mo-libs := $(SMARTCARD_LIBS)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_POSIX),y)
|
ifeq ($(CONFIG_POSIX),y)
|
||||||
common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o
|
common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o
|
||||||
@ -41,9 +43,12 @@ endif
|
|||||||
|
|
||||||
# usb redirection
|
# usb redirection
|
||||||
ifeq ($(CONFIG_USB),y)
|
ifeq ($(CONFIG_USB),y)
|
||||||
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
ifeq ($(CONFIG_USB_REDIR),y)
|
||||||
redirect.o-cflags = $(USB_REDIR_CFLAGS)
|
common-obj-m += redirect.mo
|
||||||
redirect.o-libs = $(USB_REDIR_LIBS)
|
redirect.mo-objs = redirect.o quirks.o
|
||||||
|
redirect.mo-cflags = $(USB_REDIR_CFLAGS)
|
||||||
|
redirect.mo-libs = $(USB_REDIR_LIBS)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# usb pass-through
|
# usb pass-through
|
||||||
|
@ -70,5 +70,7 @@ void register_dso_module_init(void (*fn)(void), module_init_type type);
|
|||||||
|
|
||||||
void module_call_init(module_init_type type);
|
void module_call_init(module_init_type type);
|
||||||
bool module_load_one(const char *prefix, const char *lib_name);
|
bool module_load_one(const char *prefix, const char *lib_name);
|
||||||
|
void module_load_qom_one(const char *type);
|
||||||
|
void module_load_qom_all(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -994,6 +994,18 @@ bool object_class_is_abstract(ObjectClass *klass);
|
|||||||
*/
|
*/
|
||||||
ObjectClass *object_class_by_name(const char *typename);
|
ObjectClass *object_class_by_name(const char *typename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module_object_class_by_name:
|
||||||
|
* @typename: The QOM typename to obtain the class for.
|
||||||
|
*
|
||||||
|
* For objects which might be provided by a module. Behaves like
|
||||||
|
* object_class_by_name, but additionally tries to load the module
|
||||||
|
* needed in case the class is not available.
|
||||||
|
*
|
||||||
|
* Returns: The class for @typename or %NULL if not found.
|
||||||
|
*/
|
||||||
|
ObjectClass *module_object_class_by_name(const char *typename);
|
||||||
|
|
||||||
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
|
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
|
||||||
const char *implements_type, bool include_abstract,
|
const char *implements_type, bool include_abstract,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
@ -149,6 +149,7 @@ static void qdev_print_devinfos(bool show_no_user)
|
|||||||
int i;
|
int i;
|
||||||
bool cat_printed;
|
bool cat_printed;
|
||||||
|
|
||||||
|
module_load_qom_all();
|
||||||
list = object_class_get_list_sorted(TYPE_DEVICE, false);
|
list = object_class_get_list_sorted(TYPE_DEVICE, false);
|
||||||
|
|
||||||
for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) {
|
for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) {
|
||||||
@ -217,13 +218,13 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
|
|||||||
DeviceClass *dc;
|
DeviceClass *dc;
|
||||||
const char *original_name = *driver;
|
const char *original_name = *driver;
|
||||||
|
|
||||||
oc = object_class_by_name(*driver);
|
oc = module_object_class_by_name(*driver);
|
||||||
if (!oc) {
|
if (!oc) {
|
||||||
const char *typename = find_typename_by_alias(*driver);
|
const char *typename = find_typename_by_alias(*driver);
|
||||||
|
|
||||||
if (typename) {
|
if (typename) {
|
||||||
*driver = typename;
|
*driver = typename;
|
||||||
oc = object_class_by_name(*driver);
|
oc = module_object_class_by_name(*driver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
qom/object.c
14
qom/object.c
@ -985,6 +985,20 @@ ObjectClass *object_class_by_name(const char *typename)
|
|||||||
return type->class;
|
return type->class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjectClass *module_object_class_by_name(const char *typename)
|
||||||
|
{
|
||||||
|
ObjectClass *oc;
|
||||||
|
|
||||||
|
oc = object_class_by_name(typename);
|
||||||
|
#ifdef CONFIG_MODULES
|
||||||
|
if (!oc) {
|
||||||
|
module_load_qom_one(typename);
|
||||||
|
oc = object_class_by_name(typename);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return oc;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectClass *object_class_get_parent(ObjectClass *class)
|
ObjectClass *object_class_get_parent(ObjectClass *class)
|
||||||
{
|
{
|
||||||
TypeImpl *type = type_get_parent(class->type);
|
TypeImpl *type = type_get_parent(class->type);
|
||||||
|
@ -116,6 +116,7 @@ ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
|
|||||||
{
|
{
|
||||||
ObjectTypeInfoList *ret = NULL;
|
ObjectTypeInfoList *ret = NULL;
|
||||||
|
|
||||||
|
module_load_qom_all();
|
||||||
object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
|
object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -130,7 +131,7 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
|
|||||||
ObjectPropertyIterator iter;
|
ObjectPropertyIterator iter;
|
||||||
ObjectPropertyInfoList *prop_list = NULL;
|
ObjectPropertyInfoList *prop_list = NULL;
|
||||||
|
|
||||||
klass = object_class_by_name(typename);
|
klass = module_object_class_by_name(typename);
|
||||||
if (klass == NULL) {
|
if (klass == NULL) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||||
"Device '%s' not found", typename);
|
"Device '%s' not found", typename);
|
||||||
|
@ -1772,8 +1772,8 @@ static bool vga_interface_available(VGAInterfaceType t)
|
|||||||
|
|
||||||
assert(t < VGA_TYPE_MAX);
|
assert(t < VGA_TYPE_MAX);
|
||||||
return !ti->class_names[0] ||
|
return !ti->class_names[0] ||
|
||||||
object_class_by_name(ti->class_names[0]) ||
|
module_object_class_by_name(ti->class_names[0]) ||
|
||||||
object_class_by_name(ti->class_names[1]);
|
module_object_class_by_name(ti->class_names[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -245,3 +245,70 @@ bool module_load_one(const char *prefix, const char *lib_name)
|
|||||||
#endif
|
#endif
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Building devices and other qom objects modular is mostly useful in
|
||||||
|
* case they have dependencies to external shared libraries, so we can
|
||||||
|
* cut down the core qemu library dependencies. Which is the case for
|
||||||
|
* only a very few devices & objects.
|
||||||
|
*
|
||||||
|
* So with the expectation that this will be rather the exception than
|
||||||
|
* to rule and the list will not gain that many entries go with a
|
||||||
|
* simple manually maintained list for now.
|
||||||
|
*/
|
||||||
|
static struct {
|
||||||
|
const char *type;
|
||||||
|
const char *prefix;
|
||||||
|
const char *module;
|
||||||
|
} const qom_modules[] = {
|
||||||
|
{ "ccid-card-passthru", "hw-", "usb-smartcard" },
|
||||||
|
{ "ccid-card-emulated", "hw-", "usb-smartcard" },
|
||||||
|
{ "usb-redir", "hw-", "usb-redirect" },
|
||||||
|
{ "qxl-vga", "hw-", "display-qxl" },
|
||||||
|
{ "qxl", "hw-", "display-qxl" },
|
||||||
|
{ "virtio-gpu-device", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "virtio-gpu-pci", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "virtio-vga", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "vhost-user-gpu-device", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "vhost-user-gpu-pci", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "vhost-user-vga", "hw-", "display-virtio-gpu" },
|
||||||
|
{ "chardev-braille", "chardev-", "baum" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool module_loaded_qom_all;
|
||||||
|
|
||||||
|
void module_load_qom_one(const char *type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (module_loaded_qom_all) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ARRAY_SIZE(qom_modules); i++) {
|
||||||
|
if (strcmp(qom_modules[i].type, type) == 0) {
|
||||||
|
module_load_one(qom_modules[i].prefix,
|
||||||
|
qom_modules[i].module);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void module_load_qom_all(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (module_loaded_qom_all) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ARRAY_SIZE(qom_modules); i++) {
|
||||||
|
if (i > 0 && (strcmp(qom_modules[i - 1].module,
|
||||||
|
qom_modules[i].module) == 0 &&
|
||||||
|
strcmp(qom_modules[i - 1].prefix,
|
||||||
|
qom_modules[i].prefix) == 0)) {
|
||||||
|
/* one module implementing multiple types -> load only once */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
module_load_one(qom_modules[i].prefix, qom_modules[i].module);
|
||||||
|
}
|
||||||
|
module_loaded_qom_all = true;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user