From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> Add a new 'drm' capability for Direct Rendering Manager (DRM) devices, providing device type information. Teach the udev backend to populate those devices. Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> --- docs/formatnode.html.in | 10 +++++++ docs/schemas/nodedev.rng | 14 ++++++++++ src/conf/node_device_conf.c | 44 +++++++++++++++++++++++++++++- src/conf/node_device_conf.h | 15 ++++++++++ src/node_device/node_device_driver.c | 1 + src/node_device/node_device_udev.c | 41 ++++++++++++++++++++++++++++ tests/nodedevschemadata/drm_renderD129.xml | 10 +++++++ tests/nodedevxml2xmltest.c | 1 + 8 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 tests/nodedevschemadata/drm_renderD129.xml diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in index ecdd1dbcb..a368ffc07 100644 --- a/docs/formatnode.html.in +++ b/docs/formatnode.html.in @@ -314,6 +314,16 @@ and <code>media_label</code>.</dd> </dl> </dd> + <dt><code>drm</code></dt> + <dd>Describes a Direct Rendering Manager (DRM) device. + Sub-elements include: + <dl> + <dt><code>type</code></dt> + <dd>The type of DRM device. Could be + <code>primary</code>, <code>control</code> or + <code>render</code>.</dd> + </dl> + </dd> </dl> </dd> </dl> diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 62e29b6cc..0f90a73c8 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -82,6 +82,7 @@ <ref name="capscsitarget"/> <ref name="capscsi"/> <ref name="capstorage"/> + <ref name="capdrm"/> </choice> </element> </define> @@ -540,6 +541,19 @@ </element> </define> + <define name='capdrm'> + <attribute name='type'> + <value>drm</value> + </attribute> + <element name='type'> + <choice> + <value>primary</value> + <value>control</value> + <value>render</value> + </choice> + </element> + </define> + <define name='address'> <element name='address'> <attribute name='domain'><ref name='hexuint'/></attribute> diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 0d1dafcd6..04b63cc93 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -56,12 +56,18 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST, "storage", "fc_host", "vports", - "scsi_generic") + "scsi_generic", + "drm") VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST, "80203", "80211") +VIR_ENUM_IMPL(virNodeDevDRM, VIR_NODE_DEV_DRM_LAST, + "primary", + "control", + "render") + static int virNodeDevCapsDefParseString(const char *xpath, xmlXPathContextPtr ctxt, @@ -698,6 +704,9 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def) virBufferEscapeString(&buf, "<char>%s</char>\n", data->sg.path); break; + case VIR_NODE_DEV_CAP_DRM: + virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type)); + break; case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_LAST: @@ -799,6 +808,35 @@ virNodeDevCapsDefParseULongLong(const char *xpath, } static int +virNodeDevCapDRMParseXML(xmlXPathContextPtr ctxt, + virNodeDeviceDefPtr def, + xmlNodePtr node, + virNodeDevCapDataPtr data) +{ + xmlNodePtr orignode; + int ret = -1; + char *type = NULL; + + orignode = ctxt->node; + ctxt->node = node; + + type = virXPathString("string(./type[1])", ctxt); + + if ((data->drm.type = virNodeDevDRMTypeFromString(type)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown drm type '%s' for '%s'"), type, def->name); + goto out; + } + + ret = 0; + +out: + VIR_FREE(type); + ctxt->node = orignode; + return ret; +} + +static int virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, xmlNodePtr node, @@ -1689,6 +1727,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, case VIR_NODE_DEV_CAP_STORAGE: ret = virNodeDevCapStorageParseXML(ctxt, def, node, &caps->data); break; + case VIR_NODE_DEV_CAP_DRM: + ret = virNodeDevCapDRMParseXML(ctxt, def, node, &caps->data); + break; case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_SCSI_GENERIC: @@ -2116,6 +2157,7 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) case VIR_NODE_DEV_CAP_SCSI_GENERIC: VIR_FREE(data->sg.path); break; + case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_LAST: diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index f46e9841a..be7e0e003 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -62,6 +62,7 @@ typedef enum { VIR_NODE_DEV_CAP_FC_HOST, /* FC Host Bus Adapter */ VIR_NODE_DEV_CAP_VPORTS, /* HBA which is capable of vports */ VIR_NODE_DEV_CAP_SCSI_GENERIC, /* SCSI generic device */ + VIR_NODE_DEV_CAP_DRM, /* DRM device */ VIR_NODE_DEV_CAP_LAST } virNodeDevCapType; @@ -93,6 +94,17 @@ typedef enum { VIR_NODE_DEV_CAP_FLAG_PCIE = (1 << 2), } virNodeDevPCICapFlags; +typedef enum { + /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */ + VIR_NODE_DEV_DRM_PRIMARY, + VIR_NODE_DEV_DRM_CONTROL, + VIR_NODE_DEV_DRM_RENDER, + + VIR_NODE_DEV_DRM_LAST +} virNodeDevDRMType; + +VIR_ENUM_DECL(virNodeDevDRM) + typedef struct _virNodeDevCapData { virNodeDevCapType type; union { @@ -192,6 +204,9 @@ typedef struct _virNodeDevCapData { struct { char *path; } sg; /* SCSI generic device */ + struct { + virNodeDevDRMType type; + } drm; }; } virNodeDevCapData, *virNodeDevCapDataPtr; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index 5238e231d..d04713f5e 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -72,6 +72,7 @@ static int update_caps(virNodeDeviceObjPtr dev) /* all types that (supposedly) don't require any updates * relative to what's in the cache. */ + case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_INTERFACE: diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index d7658410a..6a91e0722 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -410,6 +410,42 @@ static int udevProcessPCI(struct udev_device *device, return ret; } +static int drmGetMinorType(int minor) +{ + int type = minor >> 6; + + if (minor < 0) + return -1; + + switch (type) { + case VIR_NODE_DEV_DRM_PRIMARY: + case VIR_NODE_DEV_DRM_CONTROL: + case VIR_NODE_DEV_DRM_RENDER: + return type; + default: + return -1; + } +} + +static int udevProcessDRMDevice(struct udev_device *device, + virNodeDeviceDefPtr def) +{ + virNodeDevCapDataPtr data = &def->caps->data; + int minor; + + if (udevGenerateDeviceName(device, def, NULL) != 0) + return -1; + + if (udevGetIntProperty(device, "MINOR", &minor, 10) < 0) + return -1; + + if ((minor = drmGetMinorType(minor)) == -1) + return -1; + + data->drm.type = minor; + + return 0; +} static int udevProcessUSBDevice(struct udev_device *device, virNodeDeviceDefPtr def) @@ -971,6 +1007,8 @@ udevGetDeviceType(struct udev_device *device, *type = VIR_NODE_DEV_CAP_STORAGE; else if (STREQ(devtype, "wlan")) *type = VIR_NODE_DEV_CAP_NET; + else if (STREQ(devtype, "drm_minor")) + *type = VIR_NODE_DEV_CAP_DRM; } else { /* PCI devices don't set the DEVTYPE property. */ if (udevHasDeviceProperty(device, "PCI_CLASS")) @@ -1039,6 +1077,9 @@ static int udevGetDeviceDetails(struct udev_device *device, case VIR_NODE_DEV_CAP_SCSI_GENERIC: ret = udevProcessSCSIGeneric(device, def); break; + case VIR_NODE_DEV_CAP_DRM: + ret = udevProcessDRMDevice(device, def); + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown device type %d"), def->caps->data.type); diff --git a/tests/nodedevschemadata/drm_renderD129.xml b/tests/nodedevschemadata/drm_renderD129.xml new file mode 100644 index 000000000..161481624 --- /dev/null +++ b/tests/nodedevschemadata/drm_renderD129.xml @@ -0,0 +1,10 @@ +<device> + <name>drm_renderD129</name> + <path>/sys/devices/pci0000:00/0000:00:02.0/drm/renderD129</path> + <devnode type='dev'>/dev/dri/renderD129</devnode> + <devnode type='link'>/dev/dri/by-path/pci-0000:00:02.0-render</devnode> + <parent>pci_0000_00_02_0</parent> + <capability type='drm'> + <type>render</type> + </capability> +</device> diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index ec96943cb..5e1ae170c 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -100,6 +100,7 @@ mymain(void) DO_TEST("pci_0000_02_10_7_sriov_zero_vfs_max_count"); DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all"); DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type"); + DO_TEST("drm_renderD129"); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 2.11.0.295.gd7dffce1c.dirty -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list