diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
index e0a2c5032f6bcb58e50035750828156980463b44..924f73861b83d61e831d8065804e3cf1f12bf66d 100644
--- a/docs/schemas/nodedev.rng
+++ b/docs/schemas/nodedev.rng
@@ -83,6 +83,7 @@
+
@@ -580,6 +581,22 @@
+
+
+ mdev
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index 7eeeff793283e589536c3498ccfceed69be9334b..9cb63860f53b7ed42d57d0882fbee110fd1d979c 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -577,6 +577,10 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferEscapeString(&buf, "%s\n", virNodeDevDRMTypeToString(data->drm.type));
break;
case VIR_NODE_DEV_CAP_MDEV:
+ virBufferEscapeString(&buf, "\n", data->mdev.type);
+ virBufferAsprintf(&buf, "\n",
+ data->mdev.iommuGroupNumber);
+ break;
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS:
@@ -1647,6 +1651,39 @@ virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,
}
+static int
+virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
+ virNodeDeviceDefPtr def,
+ xmlNodePtr node,
+ virNodeDevCapMdevPtr mdev)
+{
+ xmlNodePtr orignode;
+ int ret = -1;
+
+ orignode = ctxt->node;
+ ctxt->node = node;
+
+ if (!(mdev->type = virXPathString("string(./type[1]/@id)", ctxt))) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("missing type id attribute for '%s'"), def->name);
+ goto out;
+ }
+
+ if (virNodeDevCapsDefParseULong("number(./iommuGroup[1]/@number)", ctxt,
+ &mdev->iommuGroupNumber, def,
+ _("missing iommuGroup number attribute for "
+ "'%s'"),
+ _("invalid iommuGroup number attribute for "
+ "'%s'")) < 0)
+ goto out;
+
+ ret = 0;
+ out:
+ ctxt->node = orignode;
+ return ret;
+}
+
+
static virNodeDevCapsDefPtr
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def,
@@ -1715,6 +1752,8 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
ret = virNodeDevCapDRMParseXML(ctxt, def, node, &caps->data.drm);
break;
case VIR_NODE_DEV_CAP_MDEV:
+ ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev);
+ break;
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS:
@@ -2038,6 +2077,8 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
VIR_FREE(data->sg.path);
break;
case VIR_NODE_DEV_CAP_MDEV:
+ VIR_FREE(data->mdev.type);
+ break;
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_DRM:
case VIR_NODE_DEV_CAP_FC_HOST:
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 18aaff8b52d47768b3188036d42a3296505f0d07..5743f9d3e2d04e3f008aa9e6fe31361898433dc9 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -143,6 +143,13 @@ struct _virNodeDevCapMdevType {
unsigned int available_instances;
};
+typedef struct _virNodeDevCapMdev virNodeDevCapMdev;
+typedef virNodeDevCapMdev *virNodeDevCapMdevPtr;
+struct _virNodeDevCapMdev {
+ char *type;
+ unsigned int iommuGroupNumber;
+};
+
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
typedef virNodeDevCapPCIDev *virNodeDevCapPCIDevPtr;
struct _virNodeDevCapPCIDev {
@@ -276,6 +283,7 @@ struct _virNodeDevCapData {
virNodeDevCapStorage storage;
virNodeDevCapSCSIGeneric sg;
virNodeDevCapDRM drm;
+ virNodeDevCapMdev mdev;
};
};
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 4c75dec2bccc522b41ba218c61974cf26676f4aa..8288be1cbae93fb2ac69b51056fccf2d1bd582bb 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1068,6 +1068,42 @@ udevProcessSCSIGeneric(struct udev_device *dev,
return 0;
}
+static int
+udevProcessMediatedDevice(struct udev_device *dev,
+ virNodeDeviceDefPtr def)
+{
+ int ret = -1;
+ const char *uuidstr = NULL;
+ int iommugrp = -1;
+ char *linkpath = NULL;
+ char *realpath = NULL;
+ virNodeDevCapMdevPtr data = &def->caps->data.mdev;
+
+ if (virAsprintf(&linkpath, "%s/mdev_type", udev_device_get_syspath(dev)) < 0)
+ goto cleanup;
+
+ if (virFileResolveLink(linkpath, &realpath) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(data->type, last_component(realpath)) < 0)
+ goto cleanup;
+
+ uuidstr = udev_device_get_sysname(dev);
+ if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(uuidstr)) < 0)
+ goto cleanup;
+
+ if (udevGenerateDeviceName(dev, def, NULL) != 0)
+ goto cleanup;
+
+ data->iommuGroupNumber = iommugrp;
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(linkpath);
+ VIR_FREE(realpath);
+ return ret;
+}
+
static int
udevGetDeviceNodes(struct udev_device *device,
virNodeDeviceDefPtr def)
@@ -1136,12 +1172,16 @@ udevGetDeviceType(struct udev_device *device,
if (udevHasDeviceProperty(device, "INTERFACE"))
*type = VIR_NODE_DEV_CAP_NET;
- /* SCSI generic device doesn't set DEVTYPE property */
+ /* Neither SCSI generic devices nor mediated devices set DEVTYPE
+ * property, therefore we need to rely on the SUBSYSTEM property */
if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
return -1;
if (STREQ_NULLABLE(subsystem, "scsi_generic"))
*type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
+ else if (STREQ_NULLABLE(subsystem, "mdev"))
+ *type = VIR_NODE_DEV_CAP_MDEV;
+
VIR_FREE(subsystem);
}
@@ -1181,6 +1221,7 @@ static int udevGetDeviceDetails(struct udev_device *device,
case VIR_NODE_DEV_CAP_DRM:
return udevProcessDRMDevice(device, def);
case VIR_NODE_DEV_CAP_MDEV:
+ return udevProcessMediatedDevice(device, def);
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_SYSTEM:
case VIR_NODE_DEV_CAP_FC_HOST:
diff --git a/tests/nodedevschemadata/mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml b/tests/nodedevschemadata/mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml
new file mode 100644
index 0000000000000000000000000000000000000000..470e5917ec8cb8e4888a03df0accba49e47d4b28
--- /dev/null
+++ b/tests/nodedevschemadata/mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml
@@ -0,0 +1,8 @@
+
+ mdev_3627463d_b7f0_4fea_b468_f1da537d301b
+ computer
+
+
+
+
+
diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
index e3a77646c11a4ce077511c624a89e9d65b924cfc..a2aad518d339d75532109c2c6963196c6a4f9b85 100644
--- a/tests/nodedevxml2xmltest.c
+++ b/tests/nodedevxml2xmltest.c
@@ -102,6 +102,7 @@ mymain(void)
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
DO_TEST("drm_renderD129");
DO_TEST("pci_0000_02_10_7_mdev_types");
+ DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}