提交 7f1bdec5 编写于 作者: M Marc-André Lureau 提交者: Michal Privoznik

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: NMarc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 14a3e7ab
...@@ -314,6 +314,16 @@ ...@@ -314,6 +314,16 @@
and <code>media_label</code>.</dd> and <code>media_label</code>.</dd>
</dl> </dl>
</dd> </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> </dl>
</dd> </dd>
</dl> </dl>
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
<ref name="capscsitarget"/> <ref name="capscsitarget"/>
<ref name="capscsi"/> <ref name="capscsi"/>
<ref name="capstorage"/> <ref name="capstorage"/>
<ref name="capdrm"/>
</choice> </choice>
</element> </element>
</define> </define>
...@@ -540,6 +541,19 @@ ...@@ -540,6 +541,19 @@
</element> </element>
</define> </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'> <define name='address'>
<element name='address'> <element name='address'>
<attribute name='domain'><ref name='hexuint'/></attribute> <attribute name='domain'><ref name='hexuint'/></attribute>
......
...@@ -56,12 +56,18 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST, ...@@ -56,12 +56,18 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST,
"storage", "storage",
"fc_host", "fc_host",
"vports", "vports",
"scsi_generic") "scsi_generic",
"drm")
VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST, VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST,
"80203", "80203",
"80211") "80211")
VIR_ENUM_IMPL(virNodeDevDRM, VIR_NODE_DEV_DRM_LAST,
"primary",
"control",
"render")
static int static int
virNodeDevCapsDefParseString(const char *xpath, virNodeDevCapsDefParseString(const char *xpath,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
...@@ -698,6 +704,9 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def) ...@@ -698,6 +704,9 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferEscapeString(&buf, "<char>%s</char>\n", virBufferEscapeString(&buf, "<char>%s</char>\n",
data->sg.path); data->sg.path);
break; 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_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
...@@ -798,6 +807,35 @@ virNodeDevCapsDefParseULongLong(const char *xpath, ...@@ -798,6 +807,35 @@ virNodeDevCapsDefParseULongLong(const char *xpath,
return 0; 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 static int
virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def, virNodeDeviceDefPtr def,
...@@ -1689,6 +1727,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, ...@@ -1689,6 +1727,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
case VIR_NODE_DEV_CAP_STORAGE: case VIR_NODE_DEV_CAP_STORAGE:
ret = virNodeDevCapStorageParseXML(ctxt, def, node, &caps->data); ret = virNodeDevCapStorageParseXML(ctxt, def, node, &caps->data);
break; 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_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_SCSI_GENERIC:
...@@ -2116,6 +2157,7 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) ...@@ -2116,6 +2157,7 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_SCSI_GENERIC:
VIR_FREE(data->sg.path); VIR_FREE(data->sg.path);
break; break;
case VIR_NODE_DEV_CAP_DRM:
case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
......
...@@ -62,6 +62,7 @@ typedef enum { ...@@ -62,6 +62,7 @@ typedef enum {
VIR_NODE_DEV_CAP_FC_HOST, /* FC Host Bus Adapter */ 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_VPORTS, /* HBA which is capable of vports */
VIR_NODE_DEV_CAP_SCSI_GENERIC, /* SCSI generic device */ VIR_NODE_DEV_CAP_SCSI_GENERIC, /* SCSI generic device */
VIR_NODE_DEV_CAP_DRM, /* DRM device */
VIR_NODE_DEV_CAP_LAST VIR_NODE_DEV_CAP_LAST
} virNodeDevCapType; } virNodeDevCapType;
...@@ -93,6 +94,17 @@ typedef enum { ...@@ -93,6 +94,17 @@ typedef enum {
VIR_NODE_DEV_CAP_FLAG_PCIE = (1 << 2), VIR_NODE_DEV_CAP_FLAG_PCIE = (1 << 2),
} virNodeDevPCICapFlags; } 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 { typedef struct _virNodeDevCapData {
virNodeDevCapType type; virNodeDevCapType type;
union { union {
...@@ -192,6 +204,9 @@ typedef struct _virNodeDevCapData { ...@@ -192,6 +204,9 @@ typedef struct _virNodeDevCapData {
struct { struct {
char *path; char *path;
} sg; /* SCSI generic device */ } sg; /* SCSI generic device */
struct {
virNodeDevDRMType type;
} drm;
}; };
} virNodeDevCapData, *virNodeDevCapDataPtr; } virNodeDevCapData, *virNodeDevCapDataPtr;
......
...@@ -72,6 +72,7 @@ static int update_caps(virNodeDeviceObjPtr dev) ...@@ -72,6 +72,7 @@ static int update_caps(virNodeDeviceObjPtr dev)
/* all types that (supposedly) don't require any updates /* all types that (supposedly) don't require any updates
* relative to what's in the cache. * relative to what's in the cache.
*/ */
case VIR_NODE_DEV_CAP_DRM:
case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_SYSTEM:
case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_DEV:
case VIR_NODE_DEV_CAP_USB_INTERFACE: case VIR_NODE_DEV_CAP_USB_INTERFACE:
......
...@@ -410,6 +410,42 @@ static int udevProcessPCI(struct udev_device *device, ...@@ -410,6 +410,42 @@ static int udevProcessPCI(struct udev_device *device,
return ret; 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, static int udevProcessUSBDevice(struct udev_device *device,
virNodeDeviceDefPtr def) virNodeDeviceDefPtr def)
...@@ -971,6 +1007,8 @@ udevGetDeviceType(struct udev_device *device, ...@@ -971,6 +1007,8 @@ udevGetDeviceType(struct udev_device *device,
*type = VIR_NODE_DEV_CAP_STORAGE; *type = VIR_NODE_DEV_CAP_STORAGE;
else if (STREQ(devtype, "wlan")) else if (STREQ(devtype, "wlan"))
*type = VIR_NODE_DEV_CAP_NET; *type = VIR_NODE_DEV_CAP_NET;
else if (STREQ(devtype, "drm_minor"))
*type = VIR_NODE_DEV_CAP_DRM;
} else { } else {
/* PCI devices don't set the DEVTYPE property. */ /* PCI devices don't set the DEVTYPE property. */
if (udevHasDeviceProperty(device, "PCI_CLASS")) if (udevHasDeviceProperty(device, "PCI_CLASS"))
...@@ -1039,6 +1077,9 @@ static int udevGetDeviceDetails(struct udev_device *device, ...@@ -1039,6 +1077,9 @@ static int udevGetDeviceDetails(struct udev_device *device,
case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_SCSI_GENERIC:
ret = udevProcessSCSIGeneric(device, def); ret = udevProcessSCSIGeneric(device, def);
break; break;
case VIR_NODE_DEV_CAP_DRM:
ret = udevProcessDRMDevice(device, def);
break;
default: default:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown device type %d"), def->caps->data.type); _("Unknown device type %d"), def->caps->data.type);
......
<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) ...@@ -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_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");
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type"); DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
DO_TEST("drm_renderD129");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册