Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2019 Intel Corporation
0004  */
0005 
0006 #include <linux/list.h>
0007 #include <linux/list_sort.h>
0008 #include <linux/llist.h>
0009 
0010 #include "i915_drv.h"
0011 #include "intel_engine.h"
0012 #include "intel_engine_user.h"
0013 #include "intel_gt.h"
0014 #include "uc/intel_guc_submission.h"
0015 
0016 struct intel_engine_cs *
0017 intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
0018 {
0019     struct rb_node *p = i915->uabi_engines.rb_node;
0020 
0021     while (p) {
0022         struct intel_engine_cs *it =
0023             rb_entry(p, typeof(*it), uabi_node);
0024 
0025         if (class < it->uabi_class)
0026             p = p->rb_left;
0027         else if (class > it->uabi_class ||
0028              instance > it->uabi_instance)
0029             p = p->rb_right;
0030         else if (instance < it->uabi_instance)
0031             p = p->rb_left;
0032         else
0033             return it;
0034     }
0035 
0036     return NULL;
0037 }
0038 
0039 void intel_engine_add_user(struct intel_engine_cs *engine)
0040 {
0041     llist_add((struct llist_node *)&engine->uabi_node,
0042           (struct llist_head *)&engine->i915->uabi_engines);
0043 }
0044 
0045 static const u8 uabi_classes[] = {
0046     [RENDER_CLASS] = I915_ENGINE_CLASS_RENDER,
0047     [COPY_ENGINE_CLASS] = I915_ENGINE_CLASS_COPY,
0048     [VIDEO_DECODE_CLASS] = I915_ENGINE_CLASS_VIDEO,
0049     [VIDEO_ENHANCEMENT_CLASS] = I915_ENGINE_CLASS_VIDEO_ENHANCE,
0050     [COMPUTE_CLASS] = I915_ENGINE_CLASS_COMPUTE,
0051 };
0052 
0053 static int engine_cmp(void *priv, const struct list_head *A,
0054               const struct list_head *B)
0055 {
0056     const struct intel_engine_cs *a =
0057         container_of((struct rb_node *)A, typeof(*a), uabi_node);
0058     const struct intel_engine_cs *b =
0059         container_of((struct rb_node *)B, typeof(*b), uabi_node);
0060 
0061     if (uabi_classes[a->class] < uabi_classes[b->class])
0062         return -1;
0063     if (uabi_classes[a->class] > uabi_classes[b->class])
0064         return 1;
0065 
0066     if (a->instance < b->instance)
0067         return -1;
0068     if (a->instance > b->instance)
0069         return 1;
0070 
0071     return 0;
0072 }
0073 
0074 static struct llist_node *get_engines(struct drm_i915_private *i915)
0075 {
0076     return llist_del_all((struct llist_head *)&i915->uabi_engines);
0077 }
0078 
0079 static void sort_engines(struct drm_i915_private *i915,
0080              struct list_head *engines)
0081 {
0082     struct llist_node *pos, *next;
0083 
0084     llist_for_each_safe(pos, next, get_engines(i915)) {
0085         struct intel_engine_cs *engine =
0086             container_of((struct rb_node *)pos, typeof(*engine),
0087                      uabi_node);
0088         list_add((struct list_head *)&engine->uabi_node, engines);
0089     }
0090     list_sort(NULL, engines, engine_cmp);
0091 }
0092 
0093 static void set_scheduler_caps(struct drm_i915_private *i915)
0094 {
0095     static const struct {
0096         u8 engine;
0097         u8 sched;
0098     } map[] = {
0099 #define MAP(x, y) { ilog2(I915_ENGINE_##x), ilog2(I915_SCHEDULER_CAP_##y) }
0100         MAP(HAS_PREEMPTION, PREEMPTION),
0101         MAP(HAS_SEMAPHORES, SEMAPHORES),
0102         MAP(SUPPORTS_STATS, ENGINE_BUSY_STATS),
0103 #undef MAP
0104     };
0105     struct intel_engine_cs *engine;
0106     u32 enabled, disabled;
0107 
0108     enabled = 0;
0109     disabled = 0;
0110     for_each_uabi_engine(engine, i915) { /* all engines must agree! */
0111         int i;
0112 
0113         if (engine->sched_engine->schedule)
0114             enabled |= (I915_SCHEDULER_CAP_ENABLED |
0115                     I915_SCHEDULER_CAP_PRIORITY);
0116         else
0117             disabled |= (I915_SCHEDULER_CAP_ENABLED |
0118                      I915_SCHEDULER_CAP_PRIORITY);
0119 
0120         if (intel_uc_uses_guc_submission(&to_gt(i915)->uc))
0121             enabled |= I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP;
0122 
0123         for (i = 0; i < ARRAY_SIZE(map); i++) {
0124             if (engine->flags & BIT(map[i].engine))
0125                 enabled |= BIT(map[i].sched);
0126             else
0127                 disabled |= BIT(map[i].sched);
0128         }
0129     }
0130 
0131     i915->caps.scheduler = enabled & ~disabled;
0132     if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_ENABLED))
0133         i915->caps.scheduler = 0;
0134 }
0135 
0136 const char *intel_engine_class_repr(u8 class)
0137 {
0138     static const char * const uabi_names[] = {
0139         [RENDER_CLASS] = "rcs",
0140         [COPY_ENGINE_CLASS] = "bcs",
0141         [VIDEO_DECODE_CLASS] = "vcs",
0142         [VIDEO_ENHANCEMENT_CLASS] = "vecs",
0143         [COMPUTE_CLASS] = "ccs",
0144     };
0145 
0146     if (class >= ARRAY_SIZE(uabi_names) || !uabi_names[class])
0147         return "xxx";
0148 
0149     return uabi_names[class];
0150 }
0151 
0152 struct legacy_ring {
0153     struct intel_gt *gt;
0154     u8 class;
0155     u8 instance;
0156 };
0157 
0158 static int legacy_ring_idx(const struct legacy_ring *ring)
0159 {
0160     static const struct {
0161         u8 base, max;
0162     } map[] = {
0163         [RENDER_CLASS] = { RCS0, 1 },
0164         [COPY_ENGINE_CLASS] = { BCS0, 1 },
0165         [VIDEO_DECODE_CLASS] = { VCS0, I915_MAX_VCS },
0166         [VIDEO_ENHANCEMENT_CLASS] = { VECS0, I915_MAX_VECS },
0167         [COMPUTE_CLASS] = { CCS0, I915_MAX_CCS },
0168     };
0169 
0170     if (GEM_DEBUG_WARN_ON(ring->class >= ARRAY_SIZE(map)))
0171         return INVALID_ENGINE;
0172 
0173     if (GEM_DEBUG_WARN_ON(ring->instance >= map[ring->class].max))
0174         return INVALID_ENGINE;
0175 
0176     return map[ring->class].base + ring->instance;
0177 }
0178 
0179 static void add_legacy_ring(struct legacy_ring *ring,
0180                 struct intel_engine_cs *engine)
0181 {
0182     if (engine->gt != ring->gt || engine->class != ring->class) {
0183         ring->gt = engine->gt;
0184         ring->class = engine->class;
0185         ring->instance = 0;
0186     }
0187 
0188     engine->legacy_idx = legacy_ring_idx(ring);
0189     if (engine->legacy_idx != INVALID_ENGINE)
0190         ring->instance++;
0191 }
0192 
0193 void intel_engines_driver_register(struct drm_i915_private *i915)
0194 {
0195     struct legacy_ring ring = {};
0196     struct list_head *it, *next;
0197     struct rb_node **p, *prev;
0198     LIST_HEAD(engines);
0199 
0200     sort_engines(i915, &engines);
0201 
0202     prev = NULL;
0203     p = &i915->uabi_engines.rb_node;
0204     list_for_each_safe(it, next, &engines) {
0205         struct intel_engine_cs *engine =
0206             container_of((struct rb_node *)it, typeof(*engine),
0207                      uabi_node);
0208         char old[sizeof(engine->name)];
0209 
0210         if (intel_gt_has_unrecoverable_error(engine->gt))
0211             continue; /* ignore incomplete engines */
0212 
0213         GEM_BUG_ON(engine->class >= ARRAY_SIZE(uabi_classes));
0214         engine->uabi_class = uabi_classes[engine->class];
0215 
0216         GEM_BUG_ON(engine->uabi_class >=
0217                ARRAY_SIZE(i915->engine_uabi_class_count));
0218         engine->uabi_instance =
0219             i915->engine_uabi_class_count[engine->uabi_class]++;
0220 
0221         /* Replace the internal name with the final user facing name */
0222         memcpy(old, engine->name, sizeof(engine->name));
0223         scnprintf(engine->name, sizeof(engine->name), "%s%u",
0224               intel_engine_class_repr(engine->class),
0225               engine->uabi_instance);
0226         DRM_DEBUG_DRIVER("renamed %s to %s\n", old, engine->name);
0227 
0228         rb_link_node(&engine->uabi_node, prev, p);
0229         rb_insert_color(&engine->uabi_node, &i915->uabi_engines);
0230 
0231         GEM_BUG_ON(intel_engine_lookup_user(i915,
0232                             engine->uabi_class,
0233                             engine->uabi_instance) != engine);
0234 
0235         /* Fix up the mapping to match default execbuf::user_map[] */
0236         add_legacy_ring(&ring, engine);
0237 
0238         prev = &engine->uabi_node;
0239         p = &prev->rb_right;
0240     }
0241 
0242     if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) &&
0243         IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
0244         struct intel_engine_cs *engine;
0245         unsigned int isolation;
0246         int class, inst;
0247         int errors = 0;
0248 
0249         for (class = 0; class < ARRAY_SIZE(i915->engine_uabi_class_count); class++) {
0250             for (inst = 0; inst < i915->engine_uabi_class_count[class]; inst++) {
0251                 engine = intel_engine_lookup_user(i915,
0252                                   class, inst);
0253                 if (!engine) {
0254                     pr_err("UABI engine not found for { class:%d, instance:%d }\n",
0255                            class, inst);
0256                     errors++;
0257                     continue;
0258                 }
0259 
0260                 if (engine->uabi_class != class ||
0261                     engine->uabi_instance != inst) {
0262                     pr_err("Wrong UABI engine:%s { class:%d, instance:%d } found for { class:%d, instance:%d }\n",
0263                            engine->name,
0264                            engine->uabi_class,
0265                            engine->uabi_instance,
0266                            class, inst);
0267                     errors++;
0268                     continue;
0269                 }
0270             }
0271         }
0272 
0273         /*
0274          * Make sure that classes with multiple engine instances all
0275          * share the same basic configuration.
0276          */
0277         isolation = intel_engines_has_context_isolation(i915);
0278         for_each_uabi_engine(engine, i915) {
0279             unsigned int bit = BIT(engine->uabi_class);
0280             unsigned int expected = engine->default_state ? bit : 0;
0281 
0282             if ((isolation & bit) != expected) {
0283                 pr_err("mismatching default context state for class %d on engine %s\n",
0284                        engine->uabi_class, engine->name);
0285                 errors++;
0286             }
0287         }
0288 
0289         if (drm_WARN(&i915->drm, errors,
0290                  "Invalid UABI engine mapping found"))
0291             i915->uabi_engines = RB_ROOT;
0292     }
0293 
0294     set_scheduler_caps(i915);
0295 }
0296 
0297 unsigned int intel_engines_has_context_isolation(struct drm_i915_private *i915)
0298 {
0299     struct intel_engine_cs *engine;
0300     unsigned int which;
0301 
0302     which = 0;
0303     for_each_uabi_engine(engine, i915)
0304         if (engine->default_state)
0305             which |= BIT(engine->uabi_class);
0306 
0307     return which;
0308 }