[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