Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * SPDX-License-Identifier: MIT
0003  *
0004  * Copyright © 2018 Intel Corporation
0005  */
0006 
0007 #include <linux/mutex.h>
0008 
0009 #include "i915_drv.h"
0010 #include "i915_request.h"
0011 #include "i915_scheduler.h"
0012 
0013 static struct kmem_cache *slab_dependencies;
0014 static struct kmem_cache *slab_priorities;
0015 
0016 static DEFINE_SPINLOCK(schedule_lock);
0017 
0018 static const struct i915_request *
0019 node_to_request(const struct i915_sched_node *node)
0020 {
0021     return container_of(node, const struct i915_request, sched);
0022 }
0023 
0024 static inline bool node_started(const struct i915_sched_node *node)
0025 {
0026     return i915_request_started(node_to_request(node));
0027 }
0028 
0029 static inline bool node_signaled(const struct i915_sched_node *node)
0030 {
0031     return i915_request_completed(node_to_request(node));
0032 }
0033 
0034 static inline struct i915_priolist *to_priolist(struct rb_node *rb)
0035 {
0036     return rb_entry(rb, struct i915_priolist, node);
0037 }
0038 
0039 static void assert_priolists(struct i915_sched_engine * const sched_engine)
0040 {
0041     struct rb_node *rb;
0042     long last_prio;
0043 
0044     if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
0045         return;
0046 
0047     GEM_BUG_ON(rb_first_cached(&sched_engine->queue) !=
0048            rb_first(&sched_engine->queue.rb_root));
0049 
0050     last_prio = INT_MAX;
0051     for (rb = rb_first_cached(&sched_engine->queue); rb; rb = rb_next(rb)) {
0052         const struct i915_priolist *p = to_priolist(rb);
0053 
0054         GEM_BUG_ON(p->priority > last_prio);
0055         last_prio = p->priority;
0056     }
0057 }
0058 
0059 struct list_head *
0060 i915_sched_lookup_priolist(struct i915_sched_engine *sched_engine, int prio)
0061 {
0062     struct i915_priolist *p;
0063     struct rb_node **parent, *rb;
0064     bool first = true;
0065 
0066     lockdep_assert_held(&sched_engine->lock);
0067     assert_priolists(sched_engine);
0068 
0069     if (unlikely(sched_engine->no_priolist))
0070         prio = I915_PRIORITY_NORMAL;
0071 
0072 find_priolist:
0073     /* most positive priority is scheduled first, equal priorities fifo */
0074     rb = NULL;
0075     parent = &sched_engine->queue.rb_root.rb_node;
0076     while (*parent) {
0077         rb = *parent;
0078         p = to_priolist(rb);
0079         if (prio > p->priority) {
0080             parent = &rb->rb_left;
0081         } else if (prio < p->priority) {
0082             parent = &rb->rb_right;
0083             first = false;
0084         } else {
0085             return &p->requests;
0086         }
0087     }
0088 
0089     if (prio == I915_PRIORITY_NORMAL) {
0090         p = &sched_engine->default_priolist;
0091     } else {
0092         p = kmem_cache_alloc(slab_priorities, GFP_ATOMIC);
0093         /* Convert an allocation failure to a priority bump */
0094         if (unlikely(!p)) {
0095             prio = I915_PRIORITY_NORMAL; /* recurses just once */
0096 
0097             /* To maintain ordering with all rendering, after an
0098              * allocation failure we have to disable all scheduling.
0099              * Requests will then be executed in fifo, and schedule
0100              * will ensure that dependencies are emitted in fifo.
0101              * There will be still some reordering with existing
0102              * requests, so if userspace lied about their
0103              * dependencies that reordering may be visible.
0104              */
0105             sched_engine->no_priolist = true;
0106             goto find_priolist;
0107         }
0108     }
0109 
0110     p->priority = prio;
0111     INIT_LIST_HEAD(&p->requests);
0112 
0113     rb_link_node(&p->node, rb, parent);
0114     rb_insert_color_cached(&p->node, &sched_engine->queue, first);
0115 
0116     return &p->requests;
0117 }
0118 
0119 void __i915_priolist_free(struct i915_priolist *p)
0120 {
0121     kmem_cache_free(slab_priorities, p);
0122 }
0123 
0124 struct sched_cache {
0125     struct list_head *priolist;
0126 };
0127 
0128 static struct i915_sched_engine *
0129 lock_sched_engine(struct i915_sched_node *node,
0130           struct i915_sched_engine *locked,
0131           struct sched_cache *cache)
0132 {
0133     const struct i915_request *rq = node_to_request(node);
0134     struct i915_sched_engine *sched_engine;
0135 
0136     GEM_BUG_ON(!locked);
0137 
0138     /*
0139      * Virtual engines complicate acquiring the engine timeline lock,
0140      * as their rq->engine pointer is not stable until under that
0141      * engine lock. The simple ploy we use is to take the lock then
0142      * check that the rq still belongs to the newly locked engine.
0143      */
0144     while (locked != (sched_engine = READ_ONCE(rq->engine)->sched_engine)) {
0145         spin_unlock(&locked->lock);
0146         memset(cache, 0, sizeof(*cache));
0147         spin_lock(&sched_engine->lock);
0148         locked = sched_engine;
0149     }
0150 
0151     GEM_BUG_ON(locked != sched_engine);
0152     return locked;
0153 }
0154 
0155 static void __i915_schedule(struct i915_sched_node *node,
0156                 const struct i915_sched_attr *attr)
0157 {
0158     const int prio = max(attr->priority, node->attr.priority);
0159     struct i915_sched_engine *sched_engine;
0160     struct i915_dependency *dep, *p;
0161     struct i915_dependency stack;
0162     struct sched_cache cache;
0163     LIST_HEAD(dfs);
0164 
0165     /* Needed in order to use the temporary link inside i915_dependency */
0166     lockdep_assert_held(&schedule_lock);
0167     GEM_BUG_ON(prio == I915_PRIORITY_INVALID);
0168 
0169     if (node_signaled(node))
0170         return;
0171 
0172     stack.signaler = node;
0173     list_add(&stack.dfs_link, &dfs);
0174 
0175     /*
0176      * Recursively bump all dependent priorities to match the new request.
0177      *
0178      * A naive approach would be to use recursion:
0179      * static void update_priorities(struct i915_sched_node *node, prio) {
0180      *  list_for_each_entry(dep, &node->signalers_list, signal_link)
0181      *      update_priorities(dep->signal, prio)
0182      *  queue_request(node);
0183      * }
0184      * but that may have unlimited recursion depth and so runs a very
0185      * real risk of overunning the kernel stack. Instead, we build
0186      * a flat list of all dependencies starting with the current request.
0187      * As we walk the list of dependencies, we add all of its dependencies
0188      * to the end of the list (this may include an already visited
0189      * request) and continue to walk onwards onto the new dependencies. The
0190      * end result is a topological list of requests in reverse order, the
0191      * last element in the list is the request we must execute first.
0192      */
0193     list_for_each_entry(dep, &dfs, dfs_link) {
0194         struct i915_sched_node *node = dep->signaler;
0195 
0196         /* If we are already flying, we know we have no signalers */
0197         if (node_started(node))
0198             continue;
0199 
0200         /*
0201          * Within an engine, there can be no cycle, but we may
0202          * refer to the same dependency chain multiple times
0203          * (redundant dependencies are not eliminated) and across
0204          * engines.
0205          */
0206         list_for_each_entry(p, &node->signalers_list, signal_link) {
0207             GEM_BUG_ON(p == dep); /* no cycles! */
0208 
0209             if (node_signaled(p->signaler))
0210                 continue;
0211 
0212             if (prio > READ_ONCE(p->signaler->attr.priority))
0213                 list_move_tail(&p->dfs_link, &dfs);
0214         }
0215     }
0216 
0217     /*
0218      * If we didn't need to bump any existing priorities, and we haven't
0219      * yet submitted this request (i.e. there is no potential race with
0220      * execlists_submit_request()), we can set our own priority and skip
0221      * acquiring the engine locks.
0222      */
0223     if (node->attr.priority == I915_PRIORITY_INVALID) {
0224         GEM_BUG_ON(!list_empty(&node->link));
0225         node->attr = *attr;
0226 
0227         if (stack.dfs_link.next == stack.dfs_link.prev)
0228             return;
0229 
0230         __list_del_entry(&stack.dfs_link);
0231     }
0232 
0233     memset(&cache, 0, sizeof(cache));
0234     sched_engine = node_to_request(node)->engine->sched_engine;
0235     spin_lock(&sched_engine->lock);
0236 
0237     /* Fifo and depth-first replacement ensure our deps execute before us */
0238     sched_engine = lock_sched_engine(node, sched_engine, &cache);
0239     list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
0240         struct i915_request *from = container_of(dep->signaler,
0241                              struct i915_request,
0242                              sched);
0243         INIT_LIST_HEAD(&dep->dfs_link);
0244 
0245         node = dep->signaler;
0246         sched_engine = lock_sched_engine(node, sched_engine, &cache);
0247         lockdep_assert_held(&sched_engine->lock);
0248 
0249         /* Recheck after acquiring the engine->timeline.lock */
0250         if (prio <= node->attr.priority || node_signaled(node))
0251             continue;
0252 
0253         GEM_BUG_ON(node_to_request(node)->engine->sched_engine !=
0254                sched_engine);
0255 
0256         /* Must be called before changing the nodes priority */
0257         if (sched_engine->bump_inflight_request_prio)
0258             sched_engine->bump_inflight_request_prio(from, prio);
0259 
0260         WRITE_ONCE(node->attr.priority, prio);
0261 
0262         /*
0263          * Once the request is ready, it will be placed into the
0264          * priority lists and then onto the HW runlist. Before the
0265          * request is ready, it does not contribute to our preemption
0266          * decisions and we can safely ignore it, as it will, and
0267          * any preemption required, be dealt with upon submission.
0268          * See engine->submit_request()
0269          */
0270         if (list_empty(&node->link))
0271             continue;
0272 
0273         if (i915_request_in_priority_queue(node_to_request(node))) {
0274             if (!cache.priolist)
0275                 cache.priolist =
0276                     i915_sched_lookup_priolist(sched_engine,
0277                                    prio);
0278             list_move_tail(&node->link, cache.priolist);
0279         }
0280 
0281         /* Defer (tasklet) submission until after all of our updates. */
0282         if (sched_engine->kick_backend)
0283             sched_engine->kick_backend(node_to_request(node), prio);
0284     }
0285 
0286     spin_unlock(&sched_engine->lock);
0287 }
0288 
0289 void i915_schedule(struct i915_request *rq, const struct i915_sched_attr *attr)
0290 {
0291     spin_lock_irq(&schedule_lock);
0292     __i915_schedule(&rq->sched, attr);
0293     spin_unlock_irq(&schedule_lock);
0294 }
0295 
0296 void i915_sched_node_init(struct i915_sched_node *node)
0297 {
0298     INIT_LIST_HEAD(&node->signalers_list);
0299     INIT_LIST_HEAD(&node->waiters_list);
0300     INIT_LIST_HEAD(&node->link);
0301 
0302     i915_sched_node_reinit(node);
0303 }
0304 
0305 void i915_sched_node_reinit(struct i915_sched_node *node)
0306 {
0307     node->attr.priority = I915_PRIORITY_INVALID;
0308     node->semaphores = 0;
0309     node->flags = 0;
0310 
0311     GEM_BUG_ON(!list_empty(&node->signalers_list));
0312     GEM_BUG_ON(!list_empty(&node->waiters_list));
0313     GEM_BUG_ON(!list_empty(&node->link));
0314 }
0315 
0316 static struct i915_dependency *
0317 i915_dependency_alloc(void)
0318 {
0319     return kmem_cache_alloc(slab_dependencies, GFP_KERNEL);
0320 }
0321 
0322 static void
0323 i915_dependency_free(struct i915_dependency *dep)
0324 {
0325     kmem_cache_free(slab_dependencies, dep);
0326 }
0327 
0328 bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
0329                       struct i915_sched_node *signal,
0330                       struct i915_dependency *dep,
0331                       unsigned long flags)
0332 {
0333     bool ret = false;
0334 
0335     spin_lock_irq(&schedule_lock);
0336 
0337     if (!node_signaled(signal)) {
0338         INIT_LIST_HEAD(&dep->dfs_link);
0339         dep->signaler = signal;
0340         dep->waiter = node;
0341         dep->flags = flags;
0342 
0343         /* All set, now publish. Beware the lockless walkers. */
0344         list_add_rcu(&dep->signal_link, &node->signalers_list);
0345         list_add_rcu(&dep->wait_link, &signal->waiters_list);
0346 
0347         /* Propagate the chains */
0348         node->flags |= signal->flags;
0349         ret = true;
0350     }
0351 
0352     spin_unlock_irq(&schedule_lock);
0353 
0354     return ret;
0355 }
0356 
0357 int i915_sched_node_add_dependency(struct i915_sched_node *node,
0358                    struct i915_sched_node *signal,
0359                    unsigned long flags)
0360 {
0361     struct i915_dependency *dep;
0362 
0363     dep = i915_dependency_alloc();
0364     if (!dep)
0365         return -ENOMEM;
0366 
0367     if (!__i915_sched_node_add_dependency(node, signal, dep,
0368                           flags | I915_DEPENDENCY_ALLOC))
0369         i915_dependency_free(dep);
0370 
0371     return 0;
0372 }
0373 
0374 void i915_sched_node_fini(struct i915_sched_node *node)
0375 {
0376     struct i915_dependency *dep, *tmp;
0377 
0378     spin_lock_irq(&schedule_lock);
0379 
0380     /*
0381      * Everyone we depended upon (the fences we wait to be signaled)
0382      * should retire before us and remove themselves from our list.
0383      * However, retirement is run independently on each timeline and
0384      * so we may be called out-of-order.
0385      */
0386     list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) {
0387         GEM_BUG_ON(!list_empty(&dep->dfs_link));
0388 
0389         list_del_rcu(&dep->wait_link);
0390         if (dep->flags & I915_DEPENDENCY_ALLOC)
0391             i915_dependency_free(dep);
0392     }
0393     INIT_LIST_HEAD(&node->signalers_list);
0394 
0395     /* Remove ourselves from everyone who depends upon us */
0396     list_for_each_entry_safe(dep, tmp, &node->waiters_list, wait_link) {
0397         GEM_BUG_ON(dep->signaler != node);
0398         GEM_BUG_ON(!list_empty(&dep->dfs_link));
0399 
0400         list_del_rcu(&dep->signal_link);
0401         if (dep->flags & I915_DEPENDENCY_ALLOC)
0402             i915_dependency_free(dep);
0403     }
0404     INIT_LIST_HEAD(&node->waiters_list);
0405 
0406     spin_unlock_irq(&schedule_lock);
0407 }
0408 
0409 void i915_request_show_with_schedule(struct drm_printer *m,
0410                      const struct i915_request *rq,
0411                      const char *prefix,
0412                      int indent)
0413 {
0414     struct i915_dependency *dep;
0415 
0416     i915_request_show(m, rq, prefix, indent);
0417     if (i915_request_completed(rq))
0418         return;
0419 
0420     rcu_read_lock();
0421     for_each_signaler(dep, rq) {
0422         const struct i915_request *signaler =
0423             node_to_request(dep->signaler);
0424 
0425         /* Dependencies along the same timeline are expected. */
0426         if (signaler->timeline == rq->timeline)
0427             continue;
0428 
0429         if (__i915_request_is_complete(signaler))
0430             continue;
0431 
0432         i915_request_show(m, signaler, prefix, indent + 2);
0433     }
0434     rcu_read_unlock();
0435 }
0436 
0437 static void default_destroy(struct kref *kref)
0438 {
0439     struct i915_sched_engine *sched_engine =
0440         container_of(kref, typeof(*sched_engine), ref);
0441 
0442     tasklet_kill(&sched_engine->tasklet); /* flush the callback */
0443     kfree(sched_engine);
0444 }
0445 
0446 static bool default_disabled(struct i915_sched_engine *sched_engine)
0447 {
0448     return false;
0449 }
0450 
0451 struct i915_sched_engine *
0452 i915_sched_engine_create(unsigned int subclass)
0453 {
0454     struct i915_sched_engine *sched_engine;
0455 
0456     sched_engine = kzalloc(sizeof(*sched_engine), GFP_KERNEL);
0457     if (!sched_engine)
0458         return NULL;
0459 
0460     kref_init(&sched_engine->ref);
0461 
0462     sched_engine->queue = RB_ROOT_CACHED;
0463     sched_engine->queue_priority_hint = INT_MIN;
0464     sched_engine->destroy = default_destroy;
0465     sched_engine->disabled = default_disabled;
0466 
0467     INIT_LIST_HEAD(&sched_engine->requests);
0468     INIT_LIST_HEAD(&sched_engine->hold);
0469 
0470     spin_lock_init(&sched_engine->lock);
0471     lockdep_set_subclass(&sched_engine->lock, subclass);
0472 
0473     /*
0474      * Due to an interesting quirk in lockdep's internal debug tracking,
0475      * after setting a subclass we must ensure the lock is used. Otherwise,
0476      * nr_unused_locks is incremented once too often.
0477      */
0478 #ifdef CONFIG_DEBUG_LOCK_ALLOC
0479     local_irq_disable();
0480     lock_map_acquire(&sched_engine->lock.dep_map);
0481     lock_map_release(&sched_engine->lock.dep_map);
0482     local_irq_enable();
0483 #endif
0484 
0485     return sched_engine;
0486 }
0487 
0488 void i915_scheduler_module_exit(void)
0489 {
0490     kmem_cache_destroy(slab_dependencies);
0491     kmem_cache_destroy(slab_priorities);
0492 }
0493 
0494 int __init i915_scheduler_module_init(void)
0495 {
0496     slab_dependencies = KMEM_CACHE(i915_dependency,
0497                           SLAB_HWCACHE_ALIGN |
0498                           SLAB_TYPESAFE_BY_RCU);
0499     if (!slab_dependencies)
0500         return -ENOMEM;
0501 
0502     slab_priorities = KMEM_CACHE(i915_priolist, 0);
0503     if (!slab_priorities)
0504         goto err_priorities;
0505 
0506     return 0;
0507 
0508 err_priorities:
0509     kmem_cache_destroy(slab_priorities);
0510     return -ENOMEM;
0511 }