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

Erik Skultety eskultet at redhat.com
Wed Nov 11 09:39:36 UTC 2020


On Tue, Nov 10, 2020 at 07:09:06PM +0100, Boris Fiuczynski wrote:
> Add detection of mdev_types capability to channel subsystem devices.
> 
> Signed-off-by: Boris Fiuczynski <fiuczy at linux.ibm.com>
> Reviewed-by: Bjoern Walk <bwalk at linux.ibm.com>
> ---
>  docs/drvnodedev.html.in                       |  5 +-
>  docs/formatnode.html.in                       | 19 +++-
>  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, 153 insertions(+), 7 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>.

Both PCI and CSS mdev_types are just a pointer to the mdev_types XML element.
How about just fixing the href to MDEVTypesCap?

>      </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 bd3112c5a8..d9abba0efa 100644
> --- a/docs/formatnode.html.in
> +++ b/docs/formatnode.html.in
> @@ -405,6 +405,21 @@
>                <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>
> +                    <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>.

I think we should stay consistent and make this "MDEVTypesCap"...

> +                  </dd>
> +                </dl>
> +              </dd>
>              </dl>
>            </dd>
>            <dt><code>vdpa</code></dt>
> @@ -423,8 +438,8 @@
>      <h3><a id="MDevTypesCap">mdev_types capability</a></h3>
>  
>      <p>
> -      <a href="#MDEVCap">PCI</a> devices can be capable of
> -      creating mediated devices.
> +      <a href="#MDEVCap">PCI</a> and <a href="#MDEVCapCSS">CSS</a>

Here I'm wondering why we've closed the circle and point to a generic text
which will point us back here, shouldn't we point to the whole PCI/CSS
definitions instead?

These are just stylistic nitpicks, let me know your opinion whether you agree
with the proposed ideas and I'll do the changes and merge.

Erik

> +      devices can be capable of creating mediated devices.
>        If they are capable the attribute <code>type</code> of the
>        element <code>capability</code> is <code>mdev_types</code>.
>        This capability will contain a list of <code>type</code>
> diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
> index 231afa0218..b3e986659e 100644
> --- a/docs/schemas/nodedev.rng
> +++ b/docs/schemas/nodedev.rng
> @@ -654,6 +654,9 @@
>      <element name="devno">
>        <ref name="ccwDevnoRange"/>
>      </element>
> +    <optional>
> +      <ref name="mdev_types"/>
> +    </optional>
>    </define>
>  
>    <define name="capvdpa">
> @@ -702,6 +705,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 a57505a27e..4e2837c1cd 100644
> --- a/src/conf/node_device_conf.c
> +++ b/src/conf/node_device_conf.c
> @@ -552,6 +552,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);
>  }
>  
>  
> @@ -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
>  virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
>                           virNodeDeviceDefPtr def,
> @@ -850,6 +881,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;
> @@ -895,6 +929,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;
>  }
>  
> @@ -2253,12 +2295,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_VDPA:
>      case VIR_NODE_DEV_CAP_LAST:
>          /* This case is here to shutup the compiler */
> @@ -2297,6 +2343,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.
> @@ -2313,7 +2364,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_VDPA:
>          case VIR_NODE_DEV_CAP_LAST:
>              break;
> @@ -2388,6 +2438,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
> @@ -2653,6 +2712,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
> @@ -2675,4 +2756,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 3057c728a0..262524fc87 100644
> --- a/src/conf/node_device_conf.h
> +++ b/src/conf/node_device_conf.h
> @@ -102,6 +102,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,
> @@ -274,6 +278,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 _virNodeDevCapVDPA virNodeDevCapVDPA;
> @@ -391,6 +398,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 037a938e88..9e46d22a2f 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_VDPA:
>          case VIR_NODE_DEV_CAP_LAST:
>              break;
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index ddddc8f2d1..491bd5bd87 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -824,6 +824,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 b315894965..65f312d8f4 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.26.2
> 




More information about the libvir-list mailing list