|
|
3e5111 |
From 909d3ff4c0e4ab7486c60dade9900462c896d3ba Mon Sep 17 00:00:00 2001
|
|
|
3e5111 |
Message-Id: <909d3ff4c0e4ab7486c60dade9900462c896d3ba@dist-git>
|
|
|
3e5111 |
From: Erik Skultety <eskultet@redhat.com>
|
|
|
3e5111 |
Date: Thu, 18 May 2017 14:02:53 +0200
|
|
|
3e5111 |
Subject: [PATCH] nodedev: Introduce the mdev capability to a PCI parent device
|
|
|
3e5111 |
|
|
|
3e5111 |
The parent device needs to report the generic stuff about the supported
|
|
|
3e5111 |
mediated devices types, like device API, available instances, type name,
|
|
|
3e5111 |
etc. Therefore this patch introduces a new nested capability element of
|
|
|
3e5111 |
type 'mdev_types' with the resulting XML of the following format:
|
|
|
3e5111 |
|
|
|
3e5111 |
<device>
|
|
|
3e5111 |
...
|
|
|
3e5111 |
<capability type='pci'>
|
|
|
3e5111 |
...
|
|
|
3e5111 |
<capability type='mdev_types'>
|
|
|
3e5111 |
<type id='vendor_supplied_id'>
|
|
|
3e5111 |
<name>optional_vendor_supplied_codename</name>
|
|
|
3e5111 |
<deviceAPI>vfio-pci</deviceAPI>
|
|
|
3e5111 |
<availableInstances>NUM</availableInstances>
|
|
|
3e5111 |
</type>
|
|
|
3e5111 |
...
|
|
|
3e5111 |
<type>
|
|
|
3e5111 |
...
|
|
|
3e5111 |
</type>
|
|
|
3e5111 |
</capability>
|
|
|
3e5111 |
</capability>
|
|
|
3e5111 |
...
|
|
|
3e5111 |
</device>
|
|
|
3e5111 |
|
|
|
3e5111 |
https://bugzilla.redhat.com/show_bug.cgi?id=1452072
|
|
|
3e5111 |
|
|
|
3e5111 |
Signed-off-by: Erik Skultety <eskultet@redhat.com>
|
|
|
3e5111 |
(cherry picked from commit 500cbc066a5362834462c4eefb260b7c96a8554f)
|
|
|
3e5111 |
Signed-off-by: Erik Skultety <eskultet@redhat.com>
|
|
|
3e5111 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
---
|
|
|
3e5111 |
docs/schemas/nodedev.rng | 26 +++++
|
|
|
3e5111 |
src/conf/node_device_conf.c | 101 +++++++++++++++++
|
|
|
3e5111 |
src/conf/node_device_conf.h | 15 +++
|
|
|
3e5111 |
src/conf/virnodedeviceobj.c | 20 +++-
|
|
|
3e5111 |
src/libvirt_private.syms | 1 +
|
|
|
3e5111 |
src/node_device/node_device_udev.c | 119 +++++++++++++++++++++
|
|
|
3e5111 |
.../pci_0000_02_10_7_mdev_types.xml | 32 ++++++
|
|
|
3e5111 |
tests/nodedevxml2xmltest.c | 1 +
|
|
|
3e5111 |
8 files changed, 313 insertions(+), 2 deletions(-)
|
|
|
3e5111 |
create mode 100644 tests/nodedevschemadata/pci_0000_02_10_7_mdev_types.xml
|
|
|
3e5111 |
|
|
|
3e5111 |
diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
|
|
|
3e5111 |
index 0f90a73c8..e0a2c5032 100644
|
|
|
3e5111 |
--- a/docs/schemas/nodedev.rng
|
|
|
3e5111 |
+++ b/docs/schemas/nodedev.rng
|
|
|
3e5111 |
@@ -205,6 +205,32 @@
|
|
|
3e5111 |
</optional>
|
|
|
3e5111 |
|
|
|
3e5111 |
<optional>
|
|
|
3e5111 |
+ <element name='capability'>
|
|
|
3e5111 |
+ <attribute name='type'>
|
|
|
3e5111 |
+ <value>mdev_types</value>
|
|
|
3e5111 |
+ </attribute>
|
|
|
3e5111 |
+ <oneOrMore>
|
|
|
3e5111 |
+ <element name='type'>
|
|
|
3e5111 |
+ <attribute name='id'>
|
|
|
3e5111 |
+ <data type='string'/>
|
|
|
3e5111 |
+ </attribute>
|
|
|
3e5111 |
+ <optional>
|
|
|
3e5111 |
+ <element name='name'><text/></element>
|
|
|
3e5111 |
+ </optional>
|
|
|
3e5111 |
+ <element name='deviceAPI'>
|
|
|
3e5111 |
+ <choice>
|
|
|
3e5111 |
+ <value>vfio-pci</value>
|
|
|
3e5111 |
+ </choice>
|
|
|
3e5111 |
+ </element>
|
|
|
3e5111 |
+ <element name='availableInstances'>
|
|
|
3e5111 |
+ <ref name='unsignedInt'/>
|
|
|
3e5111 |
+ </element>
|
|
|
3e5111 |
+ </element>
|
|
|
3e5111 |
+ </oneOrMore>
|
|
|
3e5111 |
+ </element>
|
|
|
3e5111 |
+ </optional>
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ <optional>
|
|
|
3e5111 |
<element name='iommuGroup'>
|
|
|
3e5111 |
<attribute name='number'>
|
|
|
3e5111 |
<ref name='unsignedInt'/>
|
|
|
3e5111 |
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
|
|
|
3e5111 |
index 90a087a37..de8ba8f9d 100644
|
|
|
3e5111 |
--- a/src/conf/node_device_conf.c
|
|
|
3e5111 |
+++ b/src/conf/node_device_conf.c
|
|
|
3e5111 |
@@ -89,6 +89,19 @@ virNodeDevCapsDefParseString(const char *xpath,
|
|
|
3e5111 |
|
|
|
3e5111 |
|
|
|
3e5111 |
void
|
|
|
3e5111 |
+virNodeDevCapMdevTypeFree(virNodeDevCapMdevTypePtr type)
|
|
|
3e5111 |
+{
|
|
|
3e5111 |
+ if (!type)
|
|
|
3e5111 |
+ return;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ VIR_FREE(type->id);
|
|
|
3e5111 |
+ VIR_FREE(type->name);
|
|
|
3e5111 |
+ VIR_FREE(type->device_api);
|
|
|
3e5111 |
+ VIR_FREE(type);
|
|
|
3e5111 |
+}
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+void
|
|
|
3e5111 |
virNodeDeviceDefFree(virNodeDeviceDefPtr def)
|
|
|
3e5111 |
{
|
|
|
3e5111 |
virNodeDevCapsDefPtr caps;
|
|
|
3e5111 |
@@ -265,6 +278,27 @@ virNodeDeviceCapPCIDefFormat(virBufferPtr buf,
|
|
|
3e5111 |
virBufferAsprintf(buf, "<capability type='%s'/>\n",
|
|
|
3e5111 |
virPCIHeaderTypeToString(data->pci_dev.hdrType));
|
|
|
3e5111 |
}
|
|
|
3e5111 |
+ if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) {
|
|
|
3e5111 |
+ virBufferAddLit(buf, "<capability type='mdev_types'>\n");
|
|
|
3e5111 |
+ virBufferAdjustIndent(buf, 2);
|
|
|
3e5111 |
+ for (i = 0; i < data->pci_dev.nmdev_types; i++) {
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr type = data->pci_dev.mdev_types[i];
|
|
|
3e5111 |
+ virBufferEscapeString(buf, "<type id='%s'>\n", type->id);
|
|
|
3e5111 |
+ virBufferAdjustIndent(buf, 2);
|
|
|
3e5111 |
+ if (type->name)
|
|
|
3e5111 |
+ virBufferEscapeString(buf, "<name>%s</name>\n",
|
|
|
3e5111 |
+ type->name);
|
|
|
3e5111 |
+ virBufferEscapeString(buf, "<deviceAPI>%s</deviceAPI>\n",
|
|
|
3e5111 |
+ type->device_api);
|
|
|
3e5111 |
+ virBufferAsprintf(buf,
|
|
|
3e5111 |
+ "<availableInstances>%u</availableInstances>\n",
|
|
|
3e5111 |
+ type->available_instances);
|
|
|
3e5111 |
+ virBufferAdjustIndent(buf, -2);
|
|
|
3e5111 |
+ virBufferAddLit(buf, "</type>\n");
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+ virBufferAdjustIndent(buf, -2);
|
|
|
3e5111 |
+ virBufferAddLit(buf, "</capability>\n");
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
if (data->pci_dev.nIommuGroupDevices) {
|
|
|
3e5111 |
virBufferAsprintf(buf, "<iommuGroup number='%d'>\n",
|
|
|
3e5111 |
data->pci_dev.iommuGroupNumber);
|
|
|
3e5111 |
@@ -1365,6 +1399,67 @@ virNodeDevPCICapSRIOVVirtualParseXML(xmlXPathContextPtr ctxt,
|
|
|
3e5111 |
|
|
|
3e5111 |
|
|
|
3e5111 |
static int
|
|
|
3e5111 |
+virNodeDevPCICapMdevTypesParseXML(xmlXPathContextPtr ctxt,
|
|
|
3e5111 |
+ virNodeDevCapPCIDevPtr pci_dev)
|
|
|
3e5111 |
+{
|
|
|
3e5111 |
+ int ret = -1;
|
|
|
3e5111 |
+ xmlNodePtr orignode = NULL;
|
|
|
3e5111 |
+ xmlNodePtr *nodes = NULL;
|
|
|
3e5111 |
+ int nmdev_types = -1;
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr type = NULL;
|
|
|
3e5111 |
+ size_t i;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if ((nmdev_types = virXPathNodeSet("./type", ctxt, &nodes)) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ orignode = ctxt->node;
|
|
|
3e5111 |
+ for (i = 0; i < nmdev_types; i++) {
|
|
|
3e5111 |
+ ctxt->node = nodes[i];
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (VIR_ALLOC(type) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (!(type->id = virXPathString("string(./@id[1])", ctxt))) {
|
|
|
3e5111 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
3e5111 |
+ _("missing 'id' attribute for mediated device's "
|
|
|
3e5111 |
+ "<type> element"));
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (!(type->device_api = virXPathString("string(./deviceAPI[1])", ctxt))) {
|
|
|
3e5111 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
3e5111 |
+ _("missing device API for mediated device type '%s'"),
|
|
|
3e5111 |
+ type->id);
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (virXPathUInt("number(./availableInstances)", ctxt,
|
|
|
3e5111 |
+ &type->available_instances) < 0) {
|
|
|
3e5111 |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
3e5111 |
+ _("missing number of available instances for "
|
|
|
3e5111 |
+ "mediated device type '%s'"),
|
|
|
3e5111 |
+ type->id);
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ type->name = virXPathString("string(./name)", ctxt);
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (VIR_APPEND_ELEMENT(pci_dev->mdev_types,
|
|
|
3e5111 |
+ pci_dev->nmdev_types, type) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
|
|
|
3e5111 |
+ ret = 0;
|
|
|
3e5111 |
+ cleanup:
|
|
|
3e5111 |
+ VIR_FREE(nodes);
|
|
|
3e5111 |
+ virNodeDevCapMdevTypeFree(type);
|
|
|
3e5111 |
+ ctxt->node = orignode;
|
|
|
3e5111 |
+ return ret;
|
|
|
3e5111 |
+}
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+static int
|
|
|
3e5111 |
virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,
|
|
|
3e5111 |
xmlNodePtr node,
|
|
|
3e5111 |
virNodeDevCapPCIDevPtr pci_dev)
|
|
|
3e5111 |
@@ -1386,6 +1481,9 @@ virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,
|
|
|
3e5111 |
} else if (STREQ(type, "virt_functions") &&
|
|
|
3e5111 |
virNodeDevPCICapSRIOVVirtualParseXML(ctxt, pci_dev) < 0) {
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
+ } else if (STREQ(type, "mdev_types") &&
|
|
|
3e5111 |
+ virNodeDevPCICapMdevTypesParseXML(ctxt, pci_dev) < 0) {
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
} else {
|
|
|
3e5111 |
int hdrType = virPCIHeaderTypeFromString(type);
|
|
|
3e5111 |
|
|
|
3e5111 |
@@ -1898,6 +1996,9 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
|
|
3e5111 |
VIR_FREE(data->pci_dev.iommuGroupDevices[i]);
|
|
|
3e5111 |
VIR_FREE(data->pci_dev.iommuGroupDevices);
|
|
|
3e5111 |
virPCIEDeviceInfoFree(data->pci_dev.pci_express);
|
|
|
3e5111 |
+ for (i = 0; i < data->pci_dev.nmdev_types; i++)
|
|
|
3e5111 |
+ virNodeDevCapMdevTypeFree(data->pci_dev.mdev_types[i]);
|
|
|
3e5111 |
+ VIR_FREE(data->pci_dev.mdev_types);
|
|
|
3e5111 |
break;
|
|
|
3e5111 |
case VIR_NODE_DEV_CAP_USB_DEV:
|
|
|
3e5111 |
VIR_FREE(data->usb_dev.product_name);
|
|
|
3e5111 |
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
|
|
|
3e5111 |
index e168f2e27..18aaff8b5 100644
|
|
|
3e5111 |
--- a/src/conf/node_device_conf.h
|
|
|
3e5111 |
+++ b/src/conf/node_device_conf.h
|
|
|
3e5111 |
@@ -95,6 +95,7 @@ typedef enum {
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION = (1 << 0),
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION = (1 << 1),
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_PCIE = (1 << 2),
|
|
|
3e5111 |
+ VIR_NODE_DEV_CAP_FLAG_PCI_MDEV = (1 << 3),
|
|
|
3e5111 |
} virNodeDevPCICapFlags;
|
|
|
3e5111 |
|
|
|
3e5111 |
typedef enum {
|
|
|
3e5111 |
@@ -133,6 +134,15 @@ struct _virNodeDevCapSystem {
|
|
|
3e5111 |
virNodeDevCapSystemFirmware firmware;
|
|
|
3e5111 |
};
|
|
|
3e5111 |
|
|
|
3e5111 |
+typedef struct _virNodeDevCapMdevType virNodeDevCapMdevType;
|
|
|
3e5111 |
+typedef virNodeDevCapMdevType *virNodeDevCapMdevTypePtr;
|
|
|
3e5111 |
+struct _virNodeDevCapMdevType {
|
|
|
3e5111 |
+ char *id;
|
|
|
3e5111 |
+ char *name;
|
|
|
3e5111 |
+ char *device_api;
|
|
|
3e5111 |
+ unsigned int available_instances;
|
|
|
3e5111 |
+};
|
|
|
3e5111 |
+
|
|
|
3e5111 |
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
|
|
|
3e5111 |
typedef virNodeDevCapPCIDev *virNodeDevCapPCIDevPtr;
|
|
|
3e5111 |
struct _virNodeDevCapPCIDev {
|
|
|
3e5111 |
@@ -156,6 +166,8 @@ struct _virNodeDevCapPCIDev {
|
|
|
3e5111 |
int numa_node;
|
|
|
3e5111 |
virPCIEDeviceInfoPtr pci_express;
|
|
|
3e5111 |
int hdrType; /* enum virPCIHeaderType or -1 */
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr *mdev_types;
|
|
|
3e5111 |
+ size_t nmdev_types;
|
|
|
3e5111 |
};
|
|
|
3e5111 |
|
|
|
3e5111 |
typedef struct _virNodeDevCapUSBDev virNodeDevCapUSBDev;
|
|
|
3e5111 |
@@ -340,6 +352,9 @@ virNodeDeviceDefFree(virNodeDeviceDefPtr def);
|
|
|
3e5111 |
void
|
|
|
3e5111 |
virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps);
|
|
|
3e5111 |
|
|
|
3e5111 |
+void
|
|
|
3e5111 |
+virNodeDevCapMdevTypeFree(virNodeDevCapMdevTypePtr type);
|
|
|
3e5111 |
+
|
|
|
3e5111 |
# define VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP \
|
|
|
3e5111 |
(VIR_CONNECT_LIST_NODE_DEVICES_CAP_SYSTEM | \
|
|
|
3e5111 |
VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV | \
|
|
|
3e5111 |
diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
|
|
|
3e5111 |
index 21d5d3f75..ac25fb598 100644
|
|
|
3e5111 |
--- a/src/conf/virnodedeviceobj.c
|
|
|
3e5111 |
+++ b/src/conf/virnodedeviceobj.c
|
|
|
3e5111 |
@@ -42,11 +42,13 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *dev,
|
|
|
3e5111 |
virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_FC_HOST);
|
|
|
3e5111 |
const char *vports_cap =
|
|
|
3e5111 |
virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS);
|
|
|
3e5111 |
+ const char *mdev_types =
|
|
|
3e5111 |
+ virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_MDEV_TYPES);
|
|
|
3e5111 |
|
|
|
3e5111 |
while (caps) {
|
|
|
3e5111 |
- if (STREQ(cap, virNodeDevCapTypeToString(caps->data.type)))
|
|
|
3e5111 |
+ if (STREQ(cap, virNodeDevCapTypeToString(caps->data.type))) {
|
|
|
3e5111 |
return 1;
|
|
|
3e5111 |
- else if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST)
|
|
|
3e5111 |
+ } else if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
|
|
|
3e5111 |
if ((STREQ(cap, fc_host_cap) &&
|
|
|
3e5111 |
(caps->data.scsi_host.flags &
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) ||
|
|
|
3e5111 |
@@ -54,6 +56,13 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *dev,
|
|
|
3e5111 |
(caps->data.scsi_host.flags &
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)))
|
|
|
3e5111 |
return 1;
|
|
|
3e5111 |
+ } else if (caps->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
|
|
|
3e5111 |
+ if ((STREQ(cap, mdev_types)) &&
|
|
|
3e5111 |
+ (caps->data.pci_dev.flags &
|
|
|
3e5111 |
+ VIR_NODE_DEV_CAP_FLAG_PCI_MDEV))
|
|
|
3e5111 |
+ return 1;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
caps = caps->next;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
return 0;
|
|
|
3e5111 |
@@ -468,6 +477,13 @@ virNodeDeviceCapMatch(virNodeDeviceObjPtr devobj,
|
|
|
3e5111 |
VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS))
|
|
|
3e5111 |
return true;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (cap->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
|
|
|
3e5111 |
+ if (type == VIR_NODE_DEV_CAP_MDEV_TYPES &&
|
|
|
3e5111 |
+ (cap->data.pci_dev.flags &
|
|
|
3e5111 |
+ VIR_NODE_DEV_CAP_FLAG_PCI_MDEV))
|
|
|
3e5111 |
+ return true;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
return false;
|
|
|
3e5111 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
3e5111 |
index 7e1a06db3..343966cd0 100644
|
|
|
3e5111 |
--- a/src/libvirt_private.syms
|
|
|
3e5111 |
+++ b/src/libvirt_private.syms
|
|
|
3e5111 |
@@ -692,6 +692,7 @@ virNetDevIPRouteParseXML;
|
|
|
3e5111 |
|
|
|
3e5111 |
|
|
|
3e5111 |
# conf/node_device_conf.h
|
|
|
3e5111 |
+virNodeDevCapMdevTypeFree;
|
|
|
3e5111 |
virNodeDevCapsDefFree;
|
|
|
3e5111 |
virNodeDevCapTypeFromString;
|
|
|
3e5111 |
virNodeDevCapTypeToString;
|
|
|
3e5111 |
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
|
|
|
3e5111 |
index d4489e2a5..b89099c82 100644
|
|
|
3e5111 |
--- a/src/node_device/node_device_udev.c
|
|
|
3e5111 |
+++ b/src/node_device/node_device_udev.c
|
|
|
3e5111 |
@@ -314,6 +314,119 @@ static int udevTranslatePCIIds(unsigned int vendor,
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
|
|
|
3e5111 |
+static int
|
|
|
3e5111 |
+udevFillMdevType(struct udev_device *device,
|
|
|
3e5111 |
+ const char *dir,
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr type)
|
|
|
3e5111 |
+{
|
|
|
3e5111 |
+ int ret = -1;
|
|
|
3e5111 |
+ char *attrpath = NULL;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+#define MDEV_GET_SYSFS_ATTR(attr_name, cb, ...) \
|
|
|
3e5111 |
+ do { \
|
|
|
3e5111 |
+ if (virAsprintf(&attrpath, "%s/%s", dir, #attr_name) < 0) \
|
|
|
3e5111 |
+ goto cleanup; \
|
|
|
3e5111 |
+ \
|
|
|
3e5111 |
+ if (cb(device, attrpath, __VA_ARGS__) < 0) \
|
|
|
3e5111 |
+ goto cleanup; \
|
|
|
3e5111 |
+ \
|
|
|
3e5111 |
+ VIR_FREE(attrpath); \
|
|
|
3e5111 |
+ } while (0) \
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (VIR_STRDUP(type->id, last_component(dir)) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ /* query udev for the attributes under subdirectories using the relative
|
|
|
3e5111 |
+ * path stored in @dir, i.e. 'mdev_supported_types/<type_id>'
|
|
|
3e5111 |
+ */
|
|
|
3e5111 |
+ MDEV_GET_SYSFS_ATTR(name, udevGetStringSysfsAttr, &type->name);
|
|
|
3e5111 |
+ MDEV_GET_SYSFS_ATTR(device_api, udevGetStringSysfsAttr, &type->device_api);
|
|
|
3e5111 |
+ MDEV_GET_SYSFS_ATTR(available_instances, udevGetUintSysfsAttr,
|
|
|
3e5111 |
+ &type->available_instances, 10);
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+#undef MDEV_GET_SYSFS_ATTR
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ ret = 0;
|
|
|
3e5111 |
+ cleanup:
|
|
|
3e5111 |
+ VIR_FREE(attrpath);
|
|
|
3e5111 |
+ return ret;
|
|
|
3e5111 |
+}
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+static int
|
|
|
3e5111 |
+udevPCIGetMdevTypesCap(struct udev_device *device,
|
|
|
3e5111 |
+ virNodeDevCapPCIDevPtr pcidata)
|
|
|
3e5111 |
+{
|
|
|
3e5111 |
+ int ret = -1;
|
|
|
3e5111 |
+ int dirret = -1;
|
|
|
3e5111 |
+ DIR *dir = NULL;
|
|
|
3e5111 |
+ struct dirent *entry;
|
|
|
3e5111 |
+ char *path = NULL;
|
|
|
3e5111 |
+ char *tmppath = NULL;
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr type = NULL;
|
|
|
3e5111 |
+ virNodeDevCapMdevTypePtr *types = NULL;
|
|
|
3e5111 |
+ size_t ntypes = 0;
|
|
|
3e5111 |
+ size_t i;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (virAsprintf(&path, "%s/mdev_supported_types",
|
|
|
3e5111 |
+ udev_device_get_syspath(device)) < 0)
|
|
|
3e5111 |
+ return -1;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if ((dirret = virDirOpenIfExists(&dir, path)) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (dirret == 0) {
|
|
|
3e5111 |
+ ret = 0;
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (VIR_ALLOC(types) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ /* UDEV doesn't report attributes under subdirectories by default but is
|
|
|
3e5111 |
+ * able to query them if the path to the attribute is relative to the
|
|
|
3e5111 |
+ * device's base path, e.g. /sys/devices/../0000:00:01.0/ is the device's
|
|
|
3e5111 |
+ * base path as udev reports it, but we're interested in attributes under
|
|
|
3e5111 |
+ * /sys/devices/../0000:00:01.0/mdev_supported_types/<type>/. So, we need to
|
|
|
3e5111 |
+ * scan the subdirectories ourselves.
|
|
|
3e5111 |
+ */
|
|
|
3e5111 |
+ while ((dirret = virDirRead(dir, &entry, path)) > 0) {
|
|
|
3e5111 |
+ if (VIR_ALLOC(type) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ /* construct the relative mdev type path bit for udev */
|
|
|
3e5111 |
+ if (virAsprintf(&tmppath, "mdev_supported_types/%s", entry->d_name) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (udevFillMdevType(device, tmppath, type) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (VIR_APPEND_ELEMENT(types, ntypes, type) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ VIR_FREE(tmppath);
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (dirret < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ VIR_STEAL_PTR(pcidata->mdev_types, types);
|
|
|
3e5111 |
+ pcidata->nmdev_types = ntypes;
|
|
|
3e5111 |
+ pcidata->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
|
|
|
3e5111 |
+ ntypes = 0;
|
|
|
3e5111 |
+ ret = 0;
|
|
|
3e5111 |
+ cleanup:
|
|
|
3e5111 |
+ virNodeDevCapMdevTypeFree(type);
|
|
|
3e5111 |
+ for (i = 0; i < ntypes; i++)
|
|
|
3e5111 |
+ virNodeDevCapMdevTypeFree(types[i]);
|
|
|
3e5111 |
+ VIR_FREE(types);
|
|
|
3e5111 |
+ VIR_FREE(path);
|
|
|
3e5111 |
+ VIR_FREE(tmppath);
|
|
|
3e5111 |
+ VIR_DIR_CLOSE(dir);
|
|
|
3e5111 |
+ return ret;
|
|
|
3e5111 |
+}
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+
|
|
|
3e5111 |
static int udevProcessPCI(struct udev_device *device,
|
|
|
3e5111 |
virNodeDeviceDefPtr def)
|
|
|
3e5111 |
{
|
|
|
3e5111 |
@@ -404,6 +517,12 @@ static int udevProcessPCI(struct udev_device *device,
|
|
|
3e5111 |
}
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
+ /* check whether the device is mediated devices framework capable, if so,
|
|
|
3e5111 |
+ * process it
|
|
|
3e5111 |
+ */
|
|
|
3e5111 |
+ if (udevPCIGetMdevTypesCap(device, pci_dev) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
ret = 0;
|
|
|
3e5111 |
|
|
|
3e5111 |
cleanup:
|
|
|
3e5111 |
diff --git a/tests/nodedevschemadata/pci_0000_02_10_7_mdev_types.xml b/tests/nodedevschemadata/pci_0000_02_10_7_mdev_types.xml
|
|
|
3e5111 |
new file mode 100644
|
|
|
3e5111 |
index 000000000..a2d57569a
|
|
|
3e5111 |
--- /dev/null
|
|
|
3e5111 |
+++ b/tests/nodedevschemadata/pci_0000_02_10_7_mdev_types.xml
|
|
|
3e5111 |
@@ -0,0 +1,32 @@
|
|
|
3e5111 |
+<device>
|
|
|
3e5111 |
+ <name>pci_0000_02_10_7</name>
|
|
|
3e5111 |
+ <parent>pci_0000_00_04_0</parent>
|
|
|
3e5111 |
+ <capability type='pci'>
|
|
|
3e5111 |
+ <domain>0</domain>
|
|
|
3e5111 |
+ <bus>2</bus>
|
|
|
3e5111 |
+ <slot>16</slot>
|
|
|
3e5111 |
+ <function>7</function>
|
|
|
3e5111 |
+ <product id='0x10ca'>82576 Virtual Function</product>
|
|
|
3e5111 |
+ <vendor id='0x8086'>Intel Corporation</vendor>
|
|
|
3e5111 |
+ <capability type='mdev_types'>
|
|
|
3e5111 |
+ <type id='foo1'>
|
|
|
3e5111 |
+ <name>bar1</name>
|
|
|
3e5111 |
+ <deviceAPI>vfio-pci</deviceAPI>
|
|
|
3e5111 |
+ <availableInstances>1</availableInstances>
|
|
|
3e5111 |
+ </type>
|
|
|
3e5111 |
+ <type id='foo2'>
|
|
|
3e5111 |
+ <name>bar2</name>
|
|
|
3e5111 |
+ <deviceAPI>vfio-pci</deviceAPI>
|
|
|
3e5111 |
+ <availableInstances>2</availableInstances>
|
|
|
3e5111 |
+ </type>
|
|
|
3e5111 |
+ </capability>
|
|
|
3e5111 |
+ <iommuGroup number='31'>
|
|
|
3e5111 |
+ <address domain='0x0000' bus='0x02' slot='0x10' function='0x7'/>
|
|
|
3e5111 |
+ </iommuGroup>
|
|
|
3e5111 |
+ <numa node='0'/>
|
|
|
3e5111 |
+ <pci-express>
|
|
|
3e5111 |
+ <link validity='cap' port='0' speed='2.5' width='4'/>
|
|
|
3e5111 |
+ <link validity='sta' width='0'/>
|
|
|
3e5111 |
+ </pci-express>
|
|
|
3e5111 |
+ </capability>
|
|
|
3e5111 |
+</device>
|
|
|
3e5111 |
diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
|
|
|
3e5111 |
index 5e1ae170c..eb5c50b86 100644
|
|
|
3e5111 |
--- a/tests/nodedevxml2xmltest.c
|
|
|
3e5111 |
+++ b/tests/nodedevxml2xmltest.c
|
|
|
3e5111 |
@@ -101,6 +101,7 @@ mymain(void)
|
|
|
3e5111 |
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all");
|
|
|
3e5111 |
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
|
|
|
3e5111 |
DO_TEST("drm_renderD129");
|
|
|
3e5111 |
+ DO_TEST("pci_0000_02_10_7_mdev_types");
|
|
|
3e5111 |
|
|
|
3e5111 |
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
--
|
|
|
3e5111 |
2.13.0
|
|
|
3e5111 |
|