[PATCH 10/10] node_device: detecting mdev_types capability on CSS devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add detection of mdev_types capability to channel subsystem devices.

Signed-off-by: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxx>
Reviewed-by: Bjoern Walk <bwalk@xxxxxxxxxxxxx>
---
 docs/drvnodedev.html.in                       |  5 +-
 docs/formatnode.html.in                       | 39 ++++++++
 docs/schemas/nodedev.rng                      |  4 +
 src/conf/node_device_conf.c                   | 92 ++++++++++++++++++-
 src/conf/node_device_conf.h                   | 11 +++
 src/conf/virnodedeviceobj.c                   |  7 +-
 src/libvirt_private.syms                      |  1 +
 src/node_device/node_device_udev.c            |  3 +
 .../css_0_0_fffe_mdev_types.xml               | 17 ++++
 tests/nodedevxml2xmltest.c                    |  1 +
 10 files changed, 175 insertions(+), 5 deletions(-)
 create mode 100644 tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml

diff --git a/docs/drvnodedev.html.in b/docs/drvnodedev.html.in
index 0823c1888d..d5191d6d93 100644
--- a/docs/drvnodedev.html.in
+++ b/docs/drvnodedev.html.in
@@ -139,12 +139,13 @@
 
     <h3><a id="MDEVCap">MDEV capability</a></h3>
     <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
       types on the physical device, along with the type attributes available
       through sysfs. A detailed description of the XML format for the
       <code>mdev_types</code> capability can be found
-      <a href="formatnode.html#MDEVCap">here</a>.
+      <a href="formatnode.html#MDEVCap">here for PCI</a> or
+      <a href="formatnode.html#MDEVCapCSS">here for CSS</a>.
     </p>
     <p>
       The following example shows how we might represent an NVIDIA GPU device
diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in
index 594427468b..7f3c71941d 100644
--- a/docs/formatnode.html.in
+++ b/docs/formatnode.html.in
@@ -430,6 +430,45 @@
               <dd>The subchannel-set identifier.</dd>
               <dt><code>devno</code></dt>
               <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="MDEVCapCSS">mdev_types</a></code></dt>
+                  <dd>
+                    This device is capable of creating mediated devices, and
+                    the capability will contain a list of <code>type</code>
+                    elements, which list all mdev types supported on the
+                    physical device. <span class="since">Since 6.9.0</span>
+                    Each <code>type</code> element has a single <code>id</code>
+                    attribute that holds an official vendor-supplied identifier
+                    for the type. It supports the following sub-elements:
+                    <dl>
+                      <dt><code>name</code></dt>
+                      <dd>
+                        The <code>name</code> element holds a vendor-supplied
+                        code name for the given mediated device type. This is
+                        an optional element.
+                      </dd>
+                      <dt><code>deviceAPI</code></dt>
+                      <dd>
+                        The value of this element describes how an instance of
+                        the given type will be presented to the guest by the
+                        VFIO framework.
+                      </dd>
+                      <dt><code>availableInstances</code></dt>
+                      <dd>
+                        This element reports the current state of resource
+                        allocation. In other words, how many instances of the
+                        given type can still be successfully created on the
+                        physical device.
+                      </dd>
+                    </dl>
+                  </dd>
+                </dl>
+              </dd>
             </dl>
           </dd>
         </dl>
diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
index 9548412999..d3248e90a9 100644
--- a/docs/schemas/nodedev.rng
+++ b/docs/schemas/nodedev.rng
@@ -653,6 +653,9 @@
     <element name="devno">
       <ref name="ccwDevnoRange"/>
     </element>
+    <optional>
+      <ref name="mdev_types"/>
+    </optional>
   </define>
 
   <define name="address">
@@ -692,6 +695,7 @@
           <element name="deviceAPI">
             <choice>
               <value>vfio-pci</value>
+              <value>vfio-ccw</value>
             </choice>
           </element>
           <element name="availableInstances">
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index 39950565b5..75c033b0e1 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -544,6 +544,10 @@ virNodeDeviceCapCCWDefFormat(virBufferPtr buf,
                       data->ccw_dev.ssid);
     virBufferAsprintf(buf, "<devno>0x%04x</devno>\n",
                       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);
 }
 
 
@@ -832,6 +836,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
 virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
                          virNodeDeviceDefPtr def,
@@ -839,6 +870,9 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
                          virNodeDevCapCCWPtr ccw_dev)
 {
     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 *ssid = NULL;
     g_autofree char *devno = NULL;
@@ -884,6 +918,14 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
         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;
 }
 
@@ -2241,12 +2283,16 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
             virMediatedDeviceAttrFree(data->mdev.attributes[i]);
         VIR_FREE(data->mdev.attributes);
         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_DRM:
     case VIR_NODE_DEV_CAP_FC_HOST:
     case VIR_NODE_DEV_CAP_VPORTS:
     case VIR_NODE_DEV_CAP_CCW_DEV:
-    case VIR_NODE_DEV_CAP_CSS_DEV:
     case VIR_NODE_DEV_CAP_LAST:
         /* This case is here to shutup the compiler */
         break;
@@ -2284,6 +2330,11 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
                                                &cap->data.pci_dev) < 0)
                 return -1;
             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
              * relative to what's in the cache.
@@ -2300,7 +2351,6 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
         case VIR_NODE_DEV_CAP_MDEV_TYPES:
         case VIR_NODE_DEV_CAP_MDEV:
         case VIR_NODE_DEV_CAP_CCW_DEV:
-        case VIR_NODE_DEV_CAP_CSS_DEV:
         case VIR_NODE_DEV_CAP_LAST:
             break;
         }
@@ -2374,6 +2424,15 @@ virNodeDeviceCapsListExport(virNodeDeviceDefPtr def,
                 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
@@ -2639,6 +2698,28 @@ virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
     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
 
 int
@@ -2661,4 +2742,11 @@ int virNodeDeviceGetSCSITargetCaps(const char *sysfsPath G_GNUC_UNUSED,
     return -1;
 }
 
+int
+virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
+                               virNodeDevCapCCWPtr ccw_dev G_GNUC_UNUSED)
+{
+    return -1;
+}
+
 #endif /* __linux__ */
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 5484bc340f..c72b943ba3 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -101,6 +101,10 @@ typedef enum {
     VIR_NODE_DEV_CAP_FLAG_PCI_MDEV                  = (1 << 3),
 } virNodeDevPCICapFlags;
 
+typedef enum {
+    VIR_NODE_DEV_CAP_FLAG_CSS_MDEV                  = (1 << 0),
+} virNodeDevCCWCapFlags;
+
 typedef enum {
     /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
     VIR_NODE_DEV_DRM_PRIMARY,
@@ -273,6 +277,9 @@ struct _virNodeDevCapCCW {
     unsigned int cssid;
     unsigned int ssid;
     unsigned int devno;
+    unsigned int flags; /* enum virNodeDevCCWCapFlags */
+    virMediatedDeviceTypePtr *mdev_types;
+    size_t nmdev_types;
 };
 
 typedef struct _virNodeDevCapData virNodeDevCapData;
@@ -382,6 +389,10 @@ int
 virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
                                virNodeDevCapPCIDevPtr pci_dev);
 
+int
+virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
+                               virNodeDevCapCCWPtr ccw_dev);
+
 int
 virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def);
 
diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
index f240abf315..e5a1af8b3b 100644
--- a/src/conf/virnodedeviceobj.c
+++ b/src/conf/virnodedeviceobj.c
@@ -696,6 +696,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj,
                 return true;
             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_USB_DEV:
         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:
         case VIR_NODE_DEV_CAP_CCW_DEV:
-        case VIR_NODE_DEV_CAP_CSS_DEV:
         case VIR_NODE_DEV_CAP_LAST:
             break;
         }
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9029ea4fa2..d9c8df81a7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -823,6 +823,7 @@ virNodeDeviceDefFree;
 virNodeDeviceDefParseFile;
 virNodeDeviceDefParseNode;
 virNodeDeviceDefParseString;
+virNodeDeviceGetCSSDynamicCaps;
 virNodeDeviceGetPCIDynamicCaps;
 virNodeDeviceGetSCSIHostCaps;
 virNodeDeviceGetSCSITargetCaps;
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 29a7eaa07c..062c0fc52e 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1139,6 +1139,9 @@ udevProcessCSS(struct udev_device *device,
     if (udevGenerateDeviceName(device, def, NULL) != 0)
         return -1;
 
+    if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path, &def->caps->data.ccw_dev) < 0)
+        return -1;
+
     return 0;
 }
 
diff --git a/tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml b/tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml
new file mode 100644
index 0000000000..5058b6434e
--- /dev/null
+++ b/tests/nodedevschemadata/css_0_0_fffe_mdev_types.xml
@@ -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>
diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
index 3cb23b1df4..a009ecb343 100644
--- a/tests/nodedevxml2xmltest.c
+++ b/tests/nodedevxml2xmltest.c
@@ -124,6 +124,7 @@ mymain(void)
     DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
     DO_TEST("ccw_0_0_ffff");
     DO_TEST("css_0_0_ffff");
+    DO_TEST("css_0_0_fffe_mdev_types");
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.25.1




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux