On Mon, Nov 20, 2017 at 03:57:49PM +0000, Tvrtko Ursulin wrote: > > On 20/11/2017 12:23, Lionel Landwerlin wrote: > > This enables userspace to discover the engines available on the GPU. > > Here is the layout on a Skylake GT4: > > > > /sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt > > ├── bcs > > It niggles me a bit that engine class names are directly under gt. If we end > up having to add something else under gt then it will be a little bit of an > enumeration trouble for userspace. > > So I wanted to suggest gt/engines/rcs if that makes sense to people? > > Regards, > > Tvrtko > Good suggestion. After adding anything else to gt/ will be more clearly. -- Cheers, Ewelina > > │ └── 0 > > │ ├── capabilities > > │ ├── class > > │ └── id > > ├── rcs > > │ └── 0 > > │ ├── capabilities > > │ ├── class > > │ └── id > > ├── vcs > > │ ├── 0 > > │ │ ├── capabilities > > │ │ │ └── hevc > > │ │ ├── class > > │ │ └── id > > │ └── 1 > > │ ├── capabilities > > │ ├── class > > │ └── id > > └── vecs > > └── 0 > > ├── capabilities > > ├── class > > └── id > > > > Further capabilities can be added later as attributes of each engine. > > > > v2: Add capabilities sub directory (Tvrtko) > > Move engines directory to drm/card/gt (Chris) > > > > Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@xxxxxxxxx> > > --- > > drivers/gpu/drm/i915/i915_drv.h | 5 + > > drivers/gpu/drm/i915/i915_reg.h | 1 + > > drivers/gpu/drm/i915/i915_sysfs.c | 160 ++++++++++++++++++++++++++++++++ > > drivers/gpu/drm/i915/intel_engine_cs.c | 12 +++ > > drivers/gpu/drm/i915/intel_ringbuffer.h | 4 + > > 5 files changed, 182 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > > index 78c49db4280a..db550322207c 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -2729,6 +2729,11 @@ struct drm_i915_private { > > } oa; > > } perf; > > + struct { > > + struct kobject kobj; > > + struct kobject classes_kobjs[MAX_ENGINE_CLASS]; > > + } gt_topology; > > + > > /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ > > struct { > > void (*resume)(struct drm_i915_private *); > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > > index 96c80fa0fcac..17aecd4fc6aa 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) > > #define VIDEO_ENHANCEMENT_CLASS 2 > > #define COPY_ENGINE_CLASS 3 > > #define OTHER_CLASS 4 > > +#define MAX_ENGINE_CLASS 5 > > /* PCI config space */ > > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c > > index 791759f632e1..fd04d0b93eaf 100644 > > --- a/drivers/gpu/drm/i915/i915_sysfs.c > > +++ b/drivers/gpu/drm/i915/i915_sysfs.c > > @@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {} > > static void i915_teardown_error_capture(struct device *kdev) {} > > #endif > > +static struct attribute engine_id_attr = { > > + .name = "id", > > + .mode = 0444, > > +}; > > + > > +static struct attribute engine_class_attr = { > > + .name = "class", > > + .mode = 0444, > > +}; > > + > > +static ssize_t > > +show_engine_attr(struct kobject *kobj, struct attribute *attr, char *buf) > > +{ > > + struct intel_engine_cs *engine = > > + container_of(kobj, struct intel_engine_cs, instance_kobj); > > + > > + if (attr == &engine_id_attr) > > + return sprintf(buf, "%hhu\n", engine->uabi_id); > > + if (attr == &engine_class_attr) > > + return sprintf(buf, "%hhu\n", engine->uabi_class); > > + return sprintf(buf, "\n"); > > +} > > + > > +static const struct sysfs_ops engine_ops = { > > + .show = show_engine_attr, > > +}; > > + > > +static struct kobj_type engine_type = { > > + .sysfs_ops = &engine_ops, > > +}; > > + > > +static struct attribute engine_capability_hevc_attr = { > > + .name = "hevc", > > + .mode = 0444, > > +}; > > + > > +static ssize_t > > +show_engine_capabilities_attr(struct kobject *kobj, struct attribute *attr, char *buf) > > +{ > > + struct intel_engine_cs *engine = > > + container_of(kobj, struct intel_engine_cs, capabilities_kobj); > > + > > + if (attr == &engine_capability_hevc_attr) > > + return sprintf(buf, "%i\n", INTEL_GEN(engine->i915) >= 8); > > + return sprintf(buf, "\n"); > > +} > > + > > +static const struct sysfs_ops engine_capabilities_ops = { > > + .show = show_engine_capabilities_attr, > > +}; > > + > > +static struct kobj_type engine_capabilities_type = { > > + .sysfs_ops = &engine_capabilities_ops, > > +}; > > + > > +static int i915_setup_engines_sysfs(struct drm_i915_private *dev_priv, > > + struct kobject *gt_kobj) > > +{ > > + struct intel_engine_cs *engine_for_class, *engine; > > + enum intel_engine_id id_for_class, id; > > + bool registred[MAX_ENGINE_CLASS] = { false, }; > > + int ret; > > + > > + for_each_engine(engine_for_class, dev_priv, id_for_class) { > > + struct kobject *engine_class_kobj = > > + &dev_priv->gt_topology.classes_kobjs[engine_for_class->class]; > > + > > + if (registred[engine_for_class->class]) > > + continue; > > + > > + registred[engine_for_class->class] = true; > > + > > + ret = kobject_init_and_add(engine_class_kobj, > > + gt_kobj->ktype, > > + gt_kobj, > > + intel_engine_get_class_name(engine_for_class)); > > + if (ret) > > + return ret; > > + > > + for_each_engine(engine, dev_priv, id) { > > + if (engine->class != engine_for_class->class) > > + continue; > > + > > + ret = kobject_init_and_add(&engine->instance_kobj, > > + &engine_type, > > + engine_class_kobj, > > + "%d", engine->instance); > > + if (ret) > > + return ret; > > + > > + ret = sysfs_create_file(&engine->instance_kobj, > > + &engine_id_attr); > > + if (ret) > > + return ret; > > + ret = sysfs_create_file(&engine->instance_kobj, > > + &engine_class_attr); > > + if (ret) > > + return ret; > > + > > + ret = kobject_init_and_add(&engine->capabilities_kobj, > > + &engine_capabilities_type, > > + &engine->instance_kobj, > > + "capabilities"); > > + if (ret) > > + return ret; > > + > > + if (engine->id == VCS) { > > + ret = sysfs_create_file(&engine->capabilities_kobj, > > + &engine_capability_hevc_attr); > > + if (ret) > > + return ret; > > + } > > + } > > + } > > + > > + return 0; > > +} > > + > > +static void i915_teardown_engines_sysfs(struct drm_i915_private *dev_priv) > > +{ > > + struct intel_engine_cs *engine; > > + enum intel_engine_id id; > > + > > + for_each_engine(engine, dev_priv, id) { > > + sysfs_remove_file(&engine->instance_kobj, &engine_id_attr); > > + sysfs_remove_file(&engine->instance_kobj, &engine_class_attr); > > + sysfs_remove_file(&engine->capabilities_kobj, > > + &engine_capability_hevc_attr); > > + } > > +} > > + > > +static int i915_setup_gt_sysfs(struct drm_i915_private *dev_priv, > > + struct device *kdev) > > +{ > > + int ret; > > + > > + ret = kobject_init_and_add(&dev_priv->gt_topology.kobj, > > + kdev->kobj.ktype, > > + &kdev->kobj, > > + "gt"); > > + if (ret) > > + return ret; > > + > > + return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.kobj); > > +} > > + > > +static void i915_teardown_gt_sysfs(struct drm_i915_private *dev_priv) > > +{ > > + i915_teardown_engines_sysfs(dev_priv); > > + > > + kobject_get(&dev_priv->gt_topology.kobj); > > + kobject_del(&dev_priv->gt_topology.kobj); > > +} > > + > > void i915_setup_sysfs(struct drm_i915_private *dev_priv) > > { > > struct device *kdev = dev_priv->drm.primary->kdev; > > @@ -605,6 +759,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) > > if (ret) > > DRM_ERROR("RPS sysfs setup failed\n"); > > + ret = i915_setup_gt_sysfs(dev_priv, kdev); > > + if (ret) > > + DRM_ERROR("GT sysfs setup failed\n"); > > + > > i915_setup_error_capture(kdev); > > } > > @@ -614,6 +772,8 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) > > i915_teardown_error_capture(kdev); > > + i915_teardown_gt_sysfs(dev_priv); > > + > > if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > > sysfs_remove_files(&kdev->kobj, vlv_attrs); > > else > > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c > > index 9897c7f78c51..9d82dfbb45db 100644 > > --- a/drivers/gpu/drm/i915/intel_engine_cs.c > > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c > > @@ -133,6 +133,18 @@ static const struct engine_info intel_engines[] = { > > }, > > }; > > +/** > > + * intel_engine_get_class_name() - return the name of the class for an engine > > + * @engine: engine > > + * > > + * Return: a string naming the class of the engine > > + */ > > +const char * > > +intel_engine_get_class_name(struct intel_engine_cs *engine) > > +{ > > + return intel_engine_classes[engine->class].name; > > +} > > + > > /** > > * ___intel_engine_context_size() - return the size of the context for an engine > > * @dev_priv: i915 device private > > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h > > index 5f96533e5341..eca6c87a1e06 100644 > > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > > @@ -290,6 +290,9 @@ struct intel_engine_cs { > > struct drm_i915_private *i915; > > char name[INTEL_ENGINE_CS_MAX_NAME]; > > + struct kobject instance_kobj; > > + struct kobject capabilities_kobj; > > + > > enum intel_engine_id id; > > unsigned int hw_id; > > unsigned int guc_id; > > @@ -924,6 +927,7 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset) > > return cs; > > } > > +const char *intel_engine_get_class_name(struct intel_engine_cs *engine); > > bool intel_engine_is_idle(struct intel_engine_cs *engine); > > bool intel_engines_are_idle(struct drm_i915_private *dev_priv); > > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx