From 7f1bdec5fa0a0cd258116f6ebb556362365a5598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 15 Feb 2017 01:04:12 +0400 Subject: [PATCH] nodedev: add drm capability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Michal Privoznik --- 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 ecdd1dbcb4..a368ffc07d 100644 --- a/docs/formatnode.html.in +++ b/docs/formatnode.html.in @@ -314,6 +314,16 @@ and media_label. +
drm
+
Describes a Direct Rendering Manager (DRM) device. + Sub-elements include: +
+
type
+
The type of DRM device. Could be + primary, control or + render.
+
+
diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 62e29b6cc1..0f90a73c8a 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -82,6 +82,7 @@ + @@ -540,6 +541,19 @@ + + + drm + + + + primary + control + render + + + + diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index a3cefcda8d..f996db1152 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, "%s\n", data->sg.path); break; + case VIR_NODE_DEV_CAP_DRM: + virBufferEscapeString(&buf, "%s\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: @@ -798,6 +807,35 @@ virNodeDevCapsDefParseULongLong(const char *xpath, return 0; } +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, @@ -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 f46e9841ae..be7e0e003a 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 4900e32227..df217f847b 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 d7658410a9..6a91e0722f 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 0000000000..161481624f --- /dev/null +++ b/tests/nodedevschemadata/drm_renderD129.xml @@ -0,0 +1,10 @@ + + drm_renderD129 + /sys/devices/pci0000:00/0000:00:02.0/drm/renderD129 + /dev/dri/renderD129 + /dev/dri/by-path/pci-0000:00:02.0-render + pci_0000_00_02_0 + + render + + diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index ec96943cb1..5e1ae170c3 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; } -- GitLab