[Intel-gfx] [PATCH v5 07/11] drm/i915: advertise available metrics via sysfs

Matthew Auld matthew.william.auld at gmail.com
Fri Oct 7 17:20:41 UTC 2016


On 14 September 2016 at 15:19, Robert Bragg <robert at sixbynine.org> wrote:
> Each metric set is given a sysfs entry like:
>
> /sys/class/drm/card0/metrics/<guid>/id
>
> This allows userspace to enumerate the specific sets that are available
> for the current system. The 'id' file contains an unsigned integer that
> can be used to open the associated metric set via
> DRM_IOCTL_I915_PERF_OPEN. The <guid> is a globally unique ID for a
> specific OA unit register configuration that can be reliably used by
> userspace as a key to lookup corresponding counter meta data and
> normalization equations.
>
> The guid registry is currently maintained as part of gputop along with
> the XML metric set descriptions and code generation scripts, ref:
>
>  https://github.com/rib/gputop
>  > gputop-data/guids.xml
>  > scripts/update-guids.py
>  > gputop-data/oa-*.xml
>  > scripts/i915-perf-kernelgen.py
>
>  $ make -C gputop-data -f Makefile.xml SYSFS=1 WHITELIST=RenderBasic
>
> Signed-off-by: Robert Bragg <robert at sixbynine.org>
> ---
>  drivers/gpu/drm/i915/i915_drv.c    |  5 ++++
>  drivers/gpu/drm/i915/i915_drv.h    |  4 +++
>  drivers/gpu/drm/i915/i915_oa_hsw.c | 51 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_oa_hsw.h |  4 +++
>  drivers/gpu/drm/i915/i915_perf.c   | 52 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 116 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 14f22fc..8965df2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1125,6 +1125,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
>         if (drm_dev_register(dev, 0) == 0) {
>                 i915_debugfs_register(dev_priv);
>                 i915_setup_sysfs(dev_priv);
> +
> +               /* Depends on sysfs having been initialized */
> +               i915_perf_register(dev_priv);
>         } else
>                 DRM_ERROR("Failed to register driver for userspace access!\n");
>
> @@ -1161,6 +1164,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
>         acpi_video_unregister();
>         intel_opregion_unregister(dev_priv);
>
> +       i915_perf_unregister(dev_priv);
> +
>         i915_teardown_sysfs(dev_priv);
>         i915_debugfs_unregister(dev_priv);
>         drm_dev_unregister(&dev_priv->drm);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 551f078..f5ddf70 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2141,6 +2141,8 @@ struct drm_i915_private {
>         struct {
>                 bool initialized;
>
> +               struct kobject *metrics_kobj;
> +
>                 struct mutex lock;
>                 struct list_head streams;
>
> @@ -3711,6 +3713,8 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
>  /* i915_perf.c */
>  extern void i915_perf_init(struct drm_i915_private *dev_priv);
>  extern void i915_perf_fini(struct drm_i915_private *dev_priv);
> +extern void i915_perf_register(struct drm_i915_private *dev_priv);
> +extern void i915_perf_unregister(struct drm_i915_private *dev_priv);
>
>  /* i915_suspend.c */
>  extern int i915_save_state(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_oa_hsw.c b/drivers/gpu/drm/i915/i915_oa_hsw.c
> index eb5ceca..656334d 100644
> --- a/drivers/gpu/drm/i915/i915_oa_hsw.c
> +++ b/drivers/gpu/drm/i915/i915_oa_hsw.c
> @@ -24,6 +24,8 @@
>   *
>   */
>
> +#include <linux/sysfs.h>
> +
>  #include "i915_drv.h"
>
>  enum metric_set_id {
> @@ -141,3 +143,52 @@ int i915_oa_select_metric_set_hsw(struct drm_i915_private *dev_priv)
>                 return -ENODEV;
>         }
>  }
> +
> +static ssize_t
> +show_render_basic_id(struct device *kdev, struct device_attribute *attr, char *buf)
> +{
> +       return sprintf(buf, "%d\n", METRIC_SET_ID_RENDER_BASIC);
> +}
> +
> +static struct device_attribute dev_attr_render_basic_id = {
> +       .attr = { .name = "id", .mode = S_IRUGO },
> +       .show = show_render_basic_id,
> +       .store = NULL,
> +};
> +
> +static struct attribute *attrs_render_basic[] = {
> +       &dev_attr_render_basic_id.attr,
> +       NULL,
> +};
> +
> +static struct attribute_group group_render_basic = {
> +       .name = "403d8832-1a27-4aa6-a64e-f5389ce7b212",
> +       .attrs =  attrs_render_basic,
> +};
> +
> +int
> +i915_perf_register_sysfs_hsw(struct drm_i915_private *dev_priv)
> +{
> +       int mux_len;
> +       int ret = 0;
> +
> +       if (get_render_basic_mux_config(dev_priv, &mux_len)) {
> +               ret = sysfs_create_group(dev_priv->perf.metrics_kobj, &group_render_basic);
> +               if (ret)
> +                       goto error_render_basic;
> +       }
> +
> +       return 0;
> +
> +error_render_basic:
> +       return ret;
> +}
> +
> +void
> +i915_perf_unregister_sysfs_hsw(struct drm_i915_private *dev_priv)
> +{
> +       int mux_len;
> +
> +       if (get_render_basic_mux_config(dev_priv, &mux_len))
> +               sysfs_remove_group(dev_priv->perf.metrics_kobj, &group_render_basic);
> +}
> diff --git a/drivers/gpu/drm/i915/i915_oa_hsw.h b/drivers/gpu/drm/i915/i915_oa_hsw.h
> index b618a1f..429a229 100644
> --- a/drivers/gpu/drm/i915/i915_oa_hsw.h
> +++ b/drivers/gpu/drm/i915/i915_oa_hsw.h
> @@ -31,4 +31,8 @@ extern int i915_oa_n_builtin_metric_sets_hsw;
>
>  extern int i915_oa_select_metric_set_hsw(struct drm_i915_private *dev_priv);
>
> +extern int i915_perf_register_sysfs_hsw(struct drm_i915_private *dev_priv);
> +
> +extern void i915_perf_unregister_sysfs_hsw(struct drm_i915_private *dev_priv);
> +
>  #endif
> diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
> index 5305982..e890c38 100644
> --- a/drivers/gpu/drm/i915/i915_perf.c
> +++ b/drivers/gpu/drm/i915/i915_perf.c
> @@ -743,6 +743,15 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>         int format_size;
>         int ret;
>
> +       /* If the sysfs metrics/ directory wasn't registered for some
> +        * reason then don't let userspace try their luck with config
> +        * IDs
> +        */
> +       if (!dev_priv->perf.metrics_kobj) {
> +               DRM_ERROR("OA metrics weren't advertised via sysfs\n");
> +               return -EINVAL;
> +       }
> +
>         if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
>                 DRM_ERROR("Only OA report sampling supported\n");
>                 return -EINVAL;
> @@ -1365,6 +1374,49 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
>         return ret;
>  }
>
> +void i915_perf_register(struct drm_i915_private *dev_priv)
> +{
> +       if (!IS_HASWELL(dev_priv))
> +               return;
> +
> +       if (!dev_priv->perf.initialized)
> +               return;
> +
> +       /* To be sure we're synchronized with an attempted
> +        * i915_perf_open_ioctl(); considering that we register after
> +        * being exposed to userspace.
> +        */
> +       mutex_lock(&dev_priv->perf.lock);
> +
> +       dev_priv->perf.metrics_kobj =
> +               kobject_create_and_add("metrics",
> +                                      &dev_priv->drm.primary->kdev->kobj);
> +       if (!dev_priv->perf.metrics_kobj)
> +               goto exit;
> +
> +       if (i915_perf_register_sysfs_hsw(dev_priv)) {
> +               kobject_put(dev_priv->perf.metrics_kobj);
> +               dev_priv->perf.metrics_kobj = NULL;
> +       }
> +
> +exit:
> +       mutex_unlock(&dev_priv->perf.lock);
> +}
> +
> +void i915_perf_unregister(struct drm_i915_private *dev_priv)
> +{
> +       if (!IS_HASWELL(dev_priv))
> +               return;
Probably no need for this check.

Reviewed-by: Matthew Auld <matthew.auld at intel.com>


More information about the dri-devel mailing list