drm/i915/gt: Expose engine properties via sysfs
Preliminary stub to add engines underneath /sys/class/drm/cardN/, so that we can expose properties on each engine to the sysadmin. To start with we have basic analogues of the i915_query ioctl so that we can pretty print engine discovery from the shell, and flesh out the directory structure. Later we will add writeable sysadmin properties such as per-engine timeout controls. An example tree of the engine properties on Braswell: /sys/class/drm/card0 └── engine ├── bcs0 │ ├── capabilities │ ├── class │ ├── instance │ ├── known_capabilities │ └── name ├── rcs0 │ ├── capabilities │ ├── class │ ├── instance │ ├── known_capabilities │ └── name ├── vcs0 │ ├── capabilities │ ├── class │ ├── instance │ ├── known_capabilities │ └── name └── vecs0 ├── capabilities ├── class ├── instance ├── known_capabilities └── name v2: Include stringified capabilities v3: Include all known capabilities for futureproofing. v4: Combine the two caps loops into one v5: Hide underneath Kconfig.unstable for wider discussion Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Tested-by: Steve Carbonari <steven.carbonari@intel.com> Reviewed-by: Steve Carbonari <steven.carbonari@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200228131716.3243616-1-chris@chris-wilson.co.uk
This commit is contained in:
parent
efbf928824
commit
4ec76dbeb6
@ -109,7 +109,8 @@ gt-y += \
|
||||
gt/intel_rps.o \
|
||||
gt/intel_sseu.o \
|
||||
gt/intel_timeline.o \
|
||||
gt/intel_workarounds.o
|
||||
gt/intel_workarounds.o \
|
||||
gt/sysfs_engines.o
|
||||
# autogenerated null render state
|
||||
gt-y += \
|
||||
gt/gen6_renderstate.o \
|
||||
|
205
drivers/gpu/drm/i915/gt/sysfs_engines.c
Normal file
205
drivers/gpu/drm/i915/gt/sysfs_engines.c
Normal file
@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_engine.h"
|
||||
#include "sysfs_engines.h"
|
||||
|
||||
struct kobj_engine {
|
||||
struct kobject base;
|
||||
struct intel_engine_cs *engine;
|
||||
};
|
||||
|
||||
static struct intel_engine_cs *kobj_to_engine(struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct kobj_engine, base)->engine;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", kobj_to_engine(kobj)->name);
|
||||
}
|
||||
|
||||
static struct kobj_attribute name_attr =
|
||||
__ATTR(name, 0444, name_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
class_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", kobj_to_engine(kobj)->uabi_class);
|
||||
}
|
||||
|
||||
static struct kobj_attribute class_attr =
|
||||
__ATTR(class, 0444, class_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
inst_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", kobj_to_engine(kobj)->uabi_instance);
|
||||
}
|
||||
|
||||
static struct kobj_attribute inst_attr =
|
||||
__ATTR(instance, 0444, inst_show, NULL);
|
||||
|
||||
static const char * const vcs_caps[] = {
|
||||
[ilog2(I915_VIDEO_CLASS_CAPABILITY_HEVC)] = "hevc",
|
||||
[ilog2(I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC)] = "sfc",
|
||||
};
|
||||
|
||||
static const char * const vecs_caps[] = {
|
||||
[ilog2(I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC)] = "sfc",
|
||||
};
|
||||
|
||||
static ssize_t repr_trim(char *buf, ssize_t len)
|
||||
{
|
||||
/* Trim off the trailing space and replace with a newline */
|
||||
if (len > PAGE_SIZE)
|
||||
len = PAGE_SIZE;
|
||||
if (len > 0)
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
__caps_show(struct intel_engine_cs *engine,
|
||||
u32 caps, char *buf, bool show_unknown)
|
||||
{
|
||||
const char * const *repr;
|
||||
int count, n;
|
||||
ssize_t len;
|
||||
|
||||
BUILD_BUG_ON(!typecheck(typeof(caps), engine->uabi_capabilities));
|
||||
|
||||
switch (engine->class) {
|
||||
case VIDEO_DECODE_CLASS:
|
||||
repr = vcs_caps;
|
||||
count = ARRAY_SIZE(vcs_caps);
|
||||
break;
|
||||
|
||||
case VIDEO_ENHANCEMENT_CLASS:
|
||||
repr = vecs_caps;
|
||||
count = ARRAY_SIZE(vecs_caps);
|
||||
break;
|
||||
|
||||
default:
|
||||
repr = NULL;
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
GEM_BUG_ON(count > BITS_PER_TYPE(typeof(caps)));
|
||||
|
||||
len = 0;
|
||||
for_each_set_bit(n,
|
||||
(unsigned long *)&caps,
|
||||
show_unknown ? BITS_PER_TYPE(typeof(caps)) : count) {
|
||||
if (n >= count || !repr[n]) {
|
||||
if (GEM_WARN_ON(show_unknown))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
"[%x] ", n);
|
||||
} else {
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
"%s ", repr[n]);
|
||||
}
|
||||
if (GEM_WARN_ON(len >= PAGE_SIZE))
|
||||
break;
|
||||
}
|
||||
return repr_trim(buf, len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
caps_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct intel_engine_cs *engine = kobj_to_engine(kobj);
|
||||
|
||||
return __caps_show(engine, engine->uabi_capabilities, buf, true);
|
||||
}
|
||||
|
||||
static struct kobj_attribute caps_attr =
|
||||
__ATTR(capabilities, 0444, caps_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
all_caps_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return __caps_show(kobj_to_engine(kobj), -1, buf, false);
|
||||
}
|
||||
|
||||
static struct kobj_attribute all_caps_attr =
|
||||
__ATTR(known_capabilities, 0444, all_caps_show, NULL);
|
||||
|
||||
static void kobj_engine_release(struct kobject *kobj)
|
||||
{
|
||||
kfree(kobj);
|
||||
}
|
||||
|
||||
static struct kobj_type kobj_engine_type = {
|
||||
.release = kobj_engine_release,
|
||||
.sysfs_ops = &kobj_sysfs_ops
|
||||
};
|
||||
|
||||
static struct kobject *
|
||||
kobj_engine(struct kobject *dir, struct intel_engine_cs *engine)
|
||||
{
|
||||
struct kobj_engine *ke;
|
||||
|
||||
ke = kzalloc(sizeof(*ke), GFP_KERNEL);
|
||||
if (!ke)
|
||||
return NULL;
|
||||
|
||||
kobject_init(&ke->base, &kobj_engine_type);
|
||||
ke->engine = engine;
|
||||
|
||||
if (kobject_add(&ke->base, dir, "%s", engine->name)) {
|
||||
kobject_put(&ke->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* xfer ownership to sysfs tree */
|
||||
return &ke->base;
|
||||
}
|
||||
|
||||
void intel_engines_add_sysfs(struct drm_i915_private *i915)
|
||||
{
|
||||
static const struct attribute *files[] = {
|
||||
&name_attr.attr,
|
||||
&class_attr.attr,
|
||||
&inst_attr.attr,
|
||||
&caps_attr.attr,
|
||||
&all_caps_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct device *kdev = i915->drm.primary->kdev;
|
||||
struct intel_engine_cs *engine;
|
||||
struct kobject *dir;
|
||||
|
||||
dir = kobject_create_and_add("engine", &kdev->kobj);
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
for_each_uabi_engine(engine, i915) {
|
||||
struct kobject *kobj;
|
||||
|
||||
kobj = kobj_engine(dir, engine);
|
||||
if (!kobj)
|
||||
goto err_engine;
|
||||
|
||||
if (sysfs_create_files(kobj, files))
|
||||
goto err_object;
|
||||
|
||||
if (0) {
|
||||
err_object:
|
||||
kobject_put(kobj);
|
||||
err_engine:
|
||||
dev_err(kdev, "Failed to add sysfs engine '%s'\n",
|
||||
engine->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
13
drivers/gpu/drm/i915/gt/sysfs_engines.h
Normal file
13
drivers/gpu/drm/i915/gt/sysfs_engines.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef INTEL_ENGINE_SYSFS_H
|
||||
#define INTEL_ENGINE_SYSFS_H
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
void intel_engines_add_sysfs(struct drm_i915_private *i915);
|
||||
|
||||
#endif /* INTEL_ENGINE_SYSFS_H */
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "gt/intel_rc6.h"
|
||||
#include "gt/intel_rps.h"
|
||||
#include "gt/sysfs_engines.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_sysfs.h"
|
||||
@ -606,6 +607,8 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
|
||||
drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
|
||||
|
||||
i915_setup_error_capture(kdev);
|
||||
|
||||
intel_engines_add_sysfs(dev_priv);
|
||||
}
|
||||
|
||||
void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
|
||||
|
Loading…
Reference in New Issue
Block a user