]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
nodedev: add drm capability
authorMarc-André Lureau <marcandre.lureau@redhat.com>
Tue, 14 Feb 2017 21:04:12 +0000 (01:04 +0400)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 17 Feb 2017 14:47:58 +0000 (15:47 +0100)
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@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
docs/formatnode.html.in
docs/schemas/nodedev.rng
src/conf/node_device_conf.c
src/conf/node_device_conf.h
src/node_device/node_device_driver.c
src/node_device/node_device_udev.c
tests/nodedevschemadata/drm_renderD129.xml [new file with mode: 0644]
tests/nodedevxml2xmltest.c

index ecdd1dbcb482a23bec8a4b6dfed47e26f8e344e1..a368ffc07dadbd4d22b4fbf93c9147a3c52230b4 100644 (file)
                 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>
index 62e29b6cc1ab0884b2b69f8ddae5cc25d9fa8337..0f90a73c8ad8d14cd4246213639ba780526c44b9 100644 (file)
@@ -82,6 +82,7 @@
         <ref name="capscsitarget"/>
         <ref name="capscsi"/>
         <ref name="capstorage"/>
+        <ref name="capdrm"/>
       </choice>
     </element>
   </define>
     </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>
index a3cefcda8d8bd96e665052943b8d703db0c49e6c..f996db115221a7807d42c8aa491a2a600956e1d2 100644 (file)
@@ -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:
@@ -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:
index f46e9841aeeffc854a4cd6f53b4aa5fe729f4540..be7e0e003afbac50ce472e9120fcdfa99cee4b81 100644 (file)
@@ -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;
 
index 4900e322270d784999b7e85547ec04b9261e7600..df217f847b76882e259682ef9c75f9ef0b648d36 100644 (file)
@@ -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:
index d7658410a94937d64382d1d96c620259891f07cd..6a91e0722f87282637e93cf868ccf5db48f0abf5 100644 (file)
@@ -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 (file)
index 0000000..1614816
--- /dev/null
@@ -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>
index ec96943cb16c7a200cda5de579dbe2a0af51d365..5e1ae170c37839711302870d11cebf24d3045fba 100644 (file)
@@ -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;
 }