mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
node_device: detecting mdev_types capability on CSS devices
Add detection of mdev_types capability to channel subsystem devices. Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com> Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com> Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
9c7ac83bd9
commit
0c841f9b70
@ -139,7 +139,7 @@
|
|||||||
|
|
||||||
<h3><a id="MDEVCap">MDEV capability</a></h3>
|
<h3><a id="MDEVCap">MDEV capability</a></h3>
|
||||||
<p>
|
<p>
|
||||||
A PCI device capable of creating mediated devices will include a nested
|
A device capable of creating mediated devices will include a nested
|
||||||
capability <code>mdev_types</code> which enumerates all supported mdev
|
capability <code>mdev_types</code> which enumerates all supported mdev
|
||||||
types on the physical device, along with the type attributes available
|
types on the physical device, along with the type attributes available
|
||||||
through sysfs. A detailed description of the XML format for the
|
through sysfs. A detailed description of the XML format for the
|
||||||
|
@ -405,6 +405,21 @@
|
|||||||
<dd>The subchannel-set identifier.</dd>
|
<dd>The subchannel-set identifier.</dd>
|
||||||
<dt><code>devno</code></dt>
|
<dt><code>devno</code></dt>
|
||||||
<dd>The device number.</dd>
|
<dd>The device number.</dd>
|
||||||
|
<dt><code>capability</code></dt>
|
||||||
|
<dd>
|
||||||
|
This optional element can occur multiple times. If it
|
||||||
|
exists, it has a mandatory <code>type</code> attribute
|
||||||
|
which will be set to:
|
||||||
|
<dl>
|
||||||
|
<dt><code><a id="MDEVTypesCapCSS">mdev_types</a></code></dt>
|
||||||
|
<dd>
|
||||||
|
<span class="since">Since 6.10.0</span>
|
||||||
|
This device is capable of creating mediated devices.
|
||||||
|
The sub-elements are summarized in
|
||||||
|
<a href="#MDevTypesCap">mdev_types capability</a>.
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>vdpa</code></dt>
|
<dt><code>vdpa</code></dt>
|
||||||
@ -423,10 +438,10 @@
|
|||||||
<h3><a id="MDEVTypesCap">mdev_types capability</a></h3>
|
<h3><a id="MDEVTypesCap">mdev_types capability</a></h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="#MDEVTypesCapPCI">PCI</a> devices can be capable of
|
<a href="#MDEVTypesCapPCI">PCI</a> and <a href="#MDEVTypesCapCSS">CSS</a>
|
||||||
creating mediated devices. If they indeed are capable,
|
devices can be capable of creating mediated devices.
|
||||||
then the parent <code>capability</code> element for
|
If they indeed are capable, then the parent <code>capability</code>
|
||||||
<code>mdev_types</code> type will contain a list of
|
element for <code>mdev_types</code> type will contain a list of
|
||||||
<code>type</code> elements, which list all mdev types supported
|
<code>type</code> elements, which list all mdev types supported
|
||||||
on the physical device. <span class="since">Since 3.4.0</span>
|
on the physical device. <span class="since">Since 3.4.0</span>
|
||||||
Each <code>type</code> element has a single <code>id</code>
|
Each <code>type</code> element has a single <code>id</code>
|
||||||
|
@ -654,6 +654,9 @@
|
|||||||
<element name="devno">
|
<element name="devno">
|
||||||
<ref name="ccwDevnoRange"/>
|
<ref name="ccwDevnoRange"/>
|
||||||
</element>
|
</element>
|
||||||
|
<optional>
|
||||||
|
<ref name="mdev_types"/>
|
||||||
|
</optional>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name="capvdpa">
|
<define name="capvdpa">
|
||||||
@ -702,6 +705,7 @@
|
|||||||
<element name="deviceAPI">
|
<element name="deviceAPI">
|
||||||
<choice>
|
<choice>
|
||||||
<value>vfio-pci</value>
|
<value>vfio-pci</value>
|
||||||
|
<value>vfio-ccw</value>
|
||||||
</choice>
|
</choice>
|
||||||
</element>
|
</element>
|
||||||
<element name="availableInstances">
|
<element name="availableInstances">
|
||||||
|
@ -552,6 +552,10 @@ virNodeDeviceCapCCWDefFormat(virBufferPtr buf,
|
|||||||
data->ccw_dev.ssid);
|
data->ccw_dev.ssid);
|
||||||
virBufferAsprintf(buf, "<devno>0x%04x</devno>\n",
|
virBufferAsprintf(buf, "<devno>0x%04x</devno>\n",
|
||||||
data->ccw_dev.devno);
|
data->ccw_dev.devno);
|
||||||
|
if (data->ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV)
|
||||||
|
virNodeDeviceCapMdevTypesFormat(buf,
|
||||||
|
data->ccw_dev.mdev_types,
|
||||||
|
data->ccw_dev.nmdev_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -843,6 +847,33 @@ virNodeDevCapMdevTypesParseXML(xmlXPathContextPtr ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
virNodeDevCapCCWPtr ccw_dev)
|
||||||
|
{
|
||||||
|
g_autofree char *type = virXMLPropString(node, "type");
|
||||||
|
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STREQ(type, "mdev_types")) {
|
||||||
|
if (virNodeDevCapMdevTypesParseXML(ctxt,
|
||||||
|
&ccw_dev->mdev_types,
|
||||||
|
&ccw_dev->nmdev_types) < 0)
|
||||||
|
return -1;
|
||||||
|
ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
|
virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
|
||||||
virNodeDeviceDefPtr def,
|
virNodeDeviceDefPtr def,
|
||||||
@ -850,6 +881,9 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
|
|||||||
virNodeDevCapCCWPtr ccw_dev)
|
virNodeDevCapCCWPtr ccw_dev)
|
||||||
{
|
{
|
||||||
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
||||||
|
g_autofree xmlNodePtr *nodes = NULL;
|
||||||
|
int n = 0;
|
||||||
|
size_t i = 0;
|
||||||
g_autofree char *cssid = NULL;
|
g_autofree char *cssid = NULL;
|
||||||
g_autofree char *ssid = NULL;
|
g_autofree char *ssid = NULL;
|
||||||
g_autofree char *devno = NULL;
|
g_autofree char *devno = NULL;
|
||||||
@ -895,6 +929,14 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (virNodeDevCSSCapabilityParseXML(ctxt, nodes[i], ccw_dev) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2253,12 +2295,16 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
|||||||
virMediatedDeviceAttrFree(data->mdev.attributes[i]);
|
virMediatedDeviceAttrFree(data->mdev.attributes[i]);
|
||||||
VIR_FREE(data->mdev.attributes);
|
VIR_FREE(data->mdev.attributes);
|
||||||
break;
|
break;
|
||||||
|
case VIR_NODE_DEV_CAP_CSS_DEV:
|
||||||
|
for (i = 0; i < data->ccw_dev.nmdev_types; i++)
|
||||||
|
virMediatedDeviceTypeFree(data->ccw_dev.mdev_types[i]);
|
||||||
|
VIR_FREE(data->ccw_dev.mdev_types);
|
||||||
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_DRM:
|
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_CCW_DEV:
|
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||||
case VIR_NODE_DEV_CAP_CSS_DEV:
|
|
||||||
case VIR_NODE_DEV_CAP_VDPA:
|
case VIR_NODE_DEV_CAP_VDPA:
|
||||||
case VIR_NODE_DEV_CAP_LAST:
|
case VIR_NODE_DEV_CAP_LAST:
|
||||||
/* This case is here to shutup the compiler */
|
/* This case is here to shutup the compiler */
|
||||||
@ -2297,6 +2343,11 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
|
|||||||
&cap->data.pci_dev) < 0)
|
&cap->data.pci_dev) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
case VIR_NODE_DEV_CAP_CSS_DEV:
|
||||||
|
if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path,
|
||||||
|
&cap->data.ccw_dev) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
/* 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.
|
||||||
@ -2313,7 +2364,6 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
|
|||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
case VIR_NODE_DEV_CAP_CCW_DEV:
|
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||||
case VIR_NODE_DEV_CAP_CSS_DEV:
|
|
||||||
case VIR_NODE_DEV_CAP_VDPA:
|
case VIR_NODE_DEV_CAP_VDPA:
|
||||||
case VIR_NODE_DEV_CAP_LAST:
|
case VIR_NODE_DEV_CAP_LAST:
|
||||||
break;
|
break;
|
||||||
@ -2388,6 +2438,15 @@ virNodeDeviceCapsListExport(virNodeDeviceDefPtr def,
|
|||||||
ncaps++;
|
ncaps++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (caps->data.type == VIR_NODE_DEV_CAP_CSS_DEV) {
|
||||||
|
flags = caps->data.ccw_dev.flags;
|
||||||
|
|
||||||
|
if (flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV) {
|
||||||
|
MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES);
|
||||||
|
ncaps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef MAYBE_ADD_CAP
|
#undef MAYBE_ADD_CAP
|
||||||
@ -2653,6 +2712,28 @@ virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* virNodeDeviceGetCSSDynamicCaps() get info that is stored in sysfs
|
||||||
|
* about devices related to this device, i.e. things that can change
|
||||||
|
* without this device itself changing. These must be refreshed
|
||||||
|
* anytime full XML of the device is requested, because they can
|
||||||
|
* change with no corresponding notification from the kernel/udev.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
|
||||||
|
virNodeDevCapCCWPtr ccw_dev)
|
||||||
|
{
|
||||||
|
ccw_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
|
||||||
|
if (virNodeDeviceGetMdevTypesCaps(sysfsPath,
|
||||||
|
&ccw_dev->mdev_types,
|
||||||
|
&ccw_dev->nmdev_types) < 0)
|
||||||
|
return -1;
|
||||||
|
if (ccw_dev->nmdev_types > 0)
|
||||||
|
ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -2675,4 +2756,11 @@ int virNodeDeviceGetSCSITargetCaps(const char *sysfsPath G_GNUC_UNUSED,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
|
||||||
|
virNodeDevCapCCWPtr ccw_dev G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
@ -102,6 +102,10 @@ typedef enum {
|
|||||||
VIR_NODE_DEV_CAP_FLAG_PCI_MDEV = (1 << 3),
|
VIR_NODE_DEV_CAP_FLAG_PCI_MDEV = (1 << 3),
|
||||||
} virNodeDevPCICapFlags;
|
} virNodeDevPCICapFlags;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VIR_NODE_DEV_CAP_FLAG_CSS_MDEV = (1 << 0),
|
||||||
|
} virNodeDevCCWCapFlags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
|
/* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
|
||||||
VIR_NODE_DEV_DRM_PRIMARY,
|
VIR_NODE_DEV_DRM_PRIMARY,
|
||||||
@ -274,6 +278,9 @@ struct _virNodeDevCapCCW {
|
|||||||
unsigned int cssid;
|
unsigned int cssid;
|
||||||
unsigned int ssid;
|
unsigned int ssid;
|
||||||
unsigned int devno;
|
unsigned int devno;
|
||||||
|
unsigned int flags; /* enum virNodeDevCCWCapFlags */
|
||||||
|
virMediatedDeviceTypePtr *mdev_types;
|
||||||
|
size_t nmdev_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _virNodeDevCapVDPA virNodeDevCapVDPA;
|
typedef struct _virNodeDevCapVDPA virNodeDevCapVDPA;
|
||||||
@ -391,6 +398,10 @@ int
|
|||||||
virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
|
virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
|
||||||
virNodeDevCapPCIDevPtr pci_dev);
|
virNodeDevCapPCIDevPtr pci_dev);
|
||||||
|
|
||||||
|
int
|
||||||
|
virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
|
||||||
|
virNodeDevCapCCWPtr ccw_dev);
|
||||||
|
|
||||||
int
|
int
|
||||||
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def);
|
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def);
|
||||||
|
|
||||||
|
@ -696,6 +696,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj,
|
|||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_NODE_DEV_CAP_CSS_DEV:
|
||||||
|
if (type == VIR_NODE_DEV_CAP_MDEV_TYPES &&
|
||||||
|
(cap->data.ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
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:
|
||||||
@ -710,7 +716,6 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj,
|
|||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
case VIR_NODE_DEV_CAP_CCW_DEV:
|
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||||
case VIR_NODE_DEV_CAP_CSS_DEV:
|
|
||||||
case VIR_NODE_DEV_CAP_VDPA:
|
case VIR_NODE_DEV_CAP_VDPA:
|
||||||
case VIR_NODE_DEV_CAP_LAST:
|
case VIR_NODE_DEV_CAP_LAST:
|
||||||
break;
|
break;
|
||||||
|
@ -824,6 +824,7 @@ virNodeDeviceDefFree;
|
|||||||
virNodeDeviceDefParseFile;
|
virNodeDeviceDefParseFile;
|
||||||
virNodeDeviceDefParseNode;
|
virNodeDeviceDefParseNode;
|
||||||
virNodeDeviceDefParseString;
|
virNodeDeviceDefParseString;
|
||||||
|
virNodeDeviceGetCSSDynamicCaps;
|
||||||
virNodeDeviceGetPCIDynamicCaps;
|
virNodeDeviceGetPCIDynamicCaps;
|
||||||
virNodeDeviceGetSCSIHostCaps;
|
virNodeDeviceGetSCSIHostCaps;
|
||||||
virNodeDeviceGetSCSITargetCaps;
|
virNodeDeviceGetSCSITargetCaps;
|
||||||
|
@ -1139,6 +1139,9 @@ udevProcessCSS(struct udev_device *device,
|
|||||||
if (udevGenerateDeviceName(device, def, NULL) != 0)
|
if (udevGenerateDeviceName(device, def, NULL) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path, &def->caps->data.ccw_dev) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml
Normal file
17
tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<device>
|
||||||
|
<name>css_0_0_fffe</name>
|
||||||
|
<path>/sys/devices/css0/0.0.fffe</path>
|
||||||
|
<parent>computer</parent>
|
||||||
|
<capability type='css'>
|
||||||
|
<cssid>0x0</cssid>
|
||||||
|
<ssid>0x0</ssid>
|
||||||
|
<devno>0xfffe</devno>
|
||||||
|
<capability type='mdev_types'>
|
||||||
|
<type id='vfio_ccw-io'>
|
||||||
|
<name>I/O subchannel (Non-QDIO)</name>
|
||||||
|
<deviceAPI>vfio-ccw</deviceAPI>
|
||||||
|
<availableInstances>1</availableInstances>
|
||||||
|
</type>
|
||||||
|
</capability>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -124,6 +124,7 @@ mymain(void)
|
|||||||
DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
|
DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
|
||||||
DO_TEST("ccw_0_0_ffff");
|
DO_TEST("ccw_0_0_ffff");
|
||||||
DO_TEST("css_0_0_ffff");
|
DO_TEST("css_0_0_ffff");
|
||||||
|
DO_TEST("css_0_0_fffe_mdev_types");
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user