mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
nodedev: add drm capability
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>
This commit is contained in:
parent
14a3e7ab5c
commit
7f1bdec5fa
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
10
tests/nodedevschemadata/drm_renderD129.xml
Normal file
10
tests/nodedevschemadata/drm_renderD129.xml
Normal file
@ -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>
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user