Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+223 -1
+2 -1
drivers/gpu/drm/i915/Makefile
··· 109 109 gt/intel_rps.o \ 110 110 gt/intel_sseu.o \ 111 111 gt/intel_timeline.o \ 112 - gt/intel_workarounds.o 112 + gt/intel_workarounds.o \ 113 + gt/sysfs_engines.o 113 114 # autogenerated null render state 114 115 gt-y += \ 115 116 gt/gen6_renderstate.o \
+205
drivers/gpu/drm/i915/gt/sysfs_engines.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2019 Intel Corporation 4 + */ 5 + 6 + #include <linux/kobject.h> 7 + #include <linux/sysfs.h> 8 + 9 + #include "i915_drv.h" 10 + #include "intel_engine.h" 11 + #include "sysfs_engines.h" 12 + 13 + struct kobj_engine { 14 + struct kobject base; 15 + struct intel_engine_cs *engine; 16 + }; 17 + 18 + static struct intel_engine_cs *kobj_to_engine(struct kobject *kobj) 19 + { 20 + return container_of(kobj, struct kobj_engine, base)->engine; 21 + } 22 + 23 + static ssize_t 24 + name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 25 + { 26 + return sprintf(buf, "%s\n", kobj_to_engine(kobj)->name); 27 + } 28 + 29 + static struct kobj_attribute name_attr = 30 + __ATTR(name, 0444, name_show, NULL); 31 + 32 + static ssize_t 33 + class_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 34 + { 35 + return sprintf(buf, "%d\n", kobj_to_engine(kobj)->uabi_class); 36 + } 37 + 38 + static struct kobj_attribute class_attr = 39 + __ATTR(class, 0444, class_show, NULL); 40 + 41 + static ssize_t 42 + inst_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 43 + { 44 + return sprintf(buf, "%d\n", kobj_to_engine(kobj)->uabi_instance); 45 + } 46 + 47 + static struct kobj_attribute inst_attr = 48 + __ATTR(instance, 0444, inst_show, NULL); 49 + 50 + static const char * const vcs_caps[] = { 51 + [ilog2(I915_VIDEO_CLASS_CAPABILITY_HEVC)] = "hevc", 52 + [ilog2(I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC)] = "sfc", 53 + }; 54 + 55 + static const char * const vecs_caps[] = { 56 + [ilog2(I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC)] = "sfc", 57 + }; 58 + 59 + static ssize_t repr_trim(char *buf, ssize_t len) 60 + { 61 + /* Trim off the trailing space and replace with a newline */ 62 + if (len > PAGE_SIZE) 63 + len = PAGE_SIZE; 64 + if (len > 0) 65 + buf[len - 1] = '\n'; 66 + 67 + return len; 68 + } 69 + 70 + static ssize_t 71 + __caps_show(struct intel_engine_cs *engine, 72 + u32 caps, char *buf, bool show_unknown) 73 + { 74 + const char * const *repr; 75 + int count, n; 76 + ssize_t len; 77 + 78 + BUILD_BUG_ON(!typecheck(typeof(caps), engine->uabi_capabilities)); 79 + 80 + switch (engine->class) { 81 + case VIDEO_DECODE_CLASS: 82 + repr = vcs_caps; 83 + count = ARRAY_SIZE(vcs_caps); 84 + break; 85 + 86 + case VIDEO_ENHANCEMENT_CLASS: 87 + repr = vecs_caps; 88 + count = ARRAY_SIZE(vecs_caps); 89 + break; 90 + 91 + default: 92 + repr = NULL; 93 + count = 0; 94 + break; 95 + } 96 + GEM_BUG_ON(count > BITS_PER_TYPE(typeof(caps))); 97 + 98 + len = 0; 99 + for_each_set_bit(n, 100 + (unsigned long *)&caps, 101 + show_unknown ? BITS_PER_TYPE(typeof(caps)) : count) { 102 + if (n >= count || !repr[n]) { 103 + if (GEM_WARN_ON(show_unknown)) 104 + len += snprintf(buf + len, PAGE_SIZE - len, 105 + "[%x] ", n); 106 + } else { 107 + len += snprintf(buf + len, PAGE_SIZE - len, 108 + "%s ", repr[n]); 109 + } 110 + if (GEM_WARN_ON(len >= PAGE_SIZE)) 111 + break; 112 + } 113 + return repr_trim(buf, len); 114 + } 115 + 116 + static ssize_t 117 + caps_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 118 + { 119 + struct intel_engine_cs *engine = kobj_to_engine(kobj); 120 + 121 + return __caps_show(engine, engine->uabi_capabilities, buf, true); 122 + } 123 + 124 + static struct kobj_attribute caps_attr = 125 + __ATTR(capabilities, 0444, caps_show, NULL); 126 + 127 + static ssize_t 128 + all_caps_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 129 + { 130 + return __caps_show(kobj_to_engine(kobj), -1, buf, false); 131 + } 132 + 133 + static struct kobj_attribute all_caps_attr = 134 + __ATTR(known_capabilities, 0444, all_caps_show, NULL); 135 + 136 + static void kobj_engine_release(struct kobject *kobj) 137 + { 138 + kfree(kobj); 139 + } 140 + 141 + static struct kobj_type kobj_engine_type = { 142 + .release = kobj_engine_release, 143 + .sysfs_ops = &kobj_sysfs_ops 144 + }; 145 + 146 + static struct kobject * 147 + kobj_engine(struct kobject *dir, struct intel_engine_cs *engine) 148 + { 149 + struct kobj_engine *ke; 150 + 151 + ke = kzalloc(sizeof(*ke), GFP_KERNEL); 152 + if (!ke) 153 + return NULL; 154 + 155 + kobject_init(&ke->base, &kobj_engine_type); 156 + ke->engine = engine; 157 + 158 + if (kobject_add(&ke->base, dir, "%s", engine->name)) { 159 + kobject_put(&ke->base); 160 + return NULL; 161 + } 162 + 163 + /* xfer ownership to sysfs tree */ 164 + return &ke->base; 165 + } 166 + 167 + void intel_engines_add_sysfs(struct drm_i915_private *i915) 168 + { 169 + static const struct attribute *files[] = { 170 + &name_attr.attr, 171 + &class_attr.attr, 172 + &inst_attr.attr, 173 + &caps_attr.attr, 174 + &all_caps_attr.attr, 175 + NULL 176 + }; 177 + 178 + struct device *kdev = i915->drm.primary->kdev; 179 + struct intel_engine_cs *engine; 180 + struct kobject *dir; 181 + 182 + dir = kobject_create_and_add("engine", &kdev->kobj); 183 + if (!dir) 184 + return; 185 + 186 + for_each_uabi_engine(engine, i915) { 187 + struct kobject *kobj; 188 + 189 + kobj = kobj_engine(dir, engine); 190 + if (!kobj) 191 + goto err_engine; 192 + 193 + if (sysfs_create_files(kobj, files)) 194 + goto err_object; 195 + 196 + if (0) { 197 + err_object: 198 + kobject_put(kobj); 199 + err_engine: 200 + dev_err(kdev, "Failed to add sysfs engine '%s'\n", 201 + engine->name); 202 + break; 203 + } 204 + } 205 + }
+13
drivers/gpu/drm/i915/gt/sysfs_engines.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2019 Intel Corporation 4 + */ 5 + 6 + #ifndef INTEL_ENGINE_SYSFS_H 7 + #define INTEL_ENGINE_SYSFS_H 8 + 9 + struct drm_i915_private; 10 + 11 + void intel_engines_add_sysfs(struct drm_i915_private *i915); 12 + 13 + #endif /* INTEL_ENGINE_SYSFS_H */
+3
drivers/gpu/drm/i915/i915_sysfs.c
··· 32 32 33 33 #include "gt/intel_rc6.h" 34 34 #include "gt/intel_rps.h" 35 + #include "gt/sysfs_engines.h" 35 36 36 37 #include "i915_drv.h" 37 38 #include "i915_sysfs.h" ··· 607 606 drm_err(&dev_priv->drm, "RPS sysfs setup failed\n"); 608 607 609 608 i915_setup_error_capture(kdev); 609 + 610 + intel_engines_add_sysfs(dev_priv); 610 611 } 611 612 612 613 void i915_teardown_sysfs(struct drm_i915_private *dev_priv)