| .. | .. |
|---|
| 8 | 8 | #define _I915_SCHEDULER_H_ |
|---|
| 9 | 9 | |
|---|
| 10 | 10 | #include <linux/bitops.h> |
|---|
| 11 | +#include <linux/list.h> |
|---|
| 12 | +#include <linux/kernel.h> |
|---|
| 11 | 13 | |
|---|
| 12 | | -#include <uapi/drm/i915_drm.h> |
|---|
| 14 | +#include "i915_scheduler_types.h" |
|---|
| 13 | 15 | |
|---|
| 14 | | -enum { |
|---|
| 15 | | - I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1, |
|---|
| 16 | | - I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY, |
|---|
| 17 | | - I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1, |
|---|
| 16 | +#define priolist_for_each_request(it, plist, idx) \ |
|---|
| 17 | + for (idx = 0; idx < ARRAY_SIZE((plist)->requests); idx++) \ |
|---|
| 18 | + list_for_each_entry(it, &(plist)->requests[idx], sched.link) |
|---|
| 18 | 19 | |
|---|
| 19 | | - I915_PRIORITY_INVALID = INT_MIN |
|---|
| 20 | | -}; |
|---|
| 20 | +#define priolist_for_each_request_consume(it, n, plist, idx) \ |
|---|
| 21 | + for (; \ |
|---|
| 22 | + (plist)->used ? (idx = __ffs((plist)->used)), 1 : 0; \ |
|---|
| 23 | + (plist)->used &= ~BIT(idx)) \ |
|---|
| 24 | + list_for_each_entry_safe(it, n, \ |
|---|
| 25 | + &(plist)->requests[idx], \ |
|---|
| 26 | + sched.link) |
|---|
| 21 | 27 | |
|---|
| 22 | | -struct i915_sched_attr { |
|---|
| 23 | | - /** |
|---|
| 24 | | - * @priority: execution and service priority |
|---|
| 25 | | - * |
|---|
| 26 | | - * All clients are equal, but some are more equal than others! |
|---|
| 27 | | - * |
|---|
| 28 | | - * Requests from a context with a greater (more positive) value of |
|---|
| 29 | | - * @priority will be executed before those with a lower @priority |
|---|
| 30 | | - * value, forming a simple QoS. |
|---|
| 31 | | - * |
|---|
| 32 | | - * The &drm_i915_private.kernel_context is assigned the lowest priority. |
|---|
| 33 | | - */ |
|---|
| 34 | | - int priority; |
|---|
| 35 | | -}; |
|---|
| 28 | +void i915_sched_node_init(struct i915_sched_node *node); |
|---|
| 29 | +void i915_sched_node_reinit(struct i915_sched_node *node); |
|---|
| 36 | 30 | |
|---|
| 37 | | -/* |
|---|
| 38 | | - * "People assume that time is a strict progression of cause to effect, but |
|---|
| 39 | | - * actually, from a nonlinear, non-subjective viewpoint, it's more like a big |
|---|
| 40 | | - * ball of wibbly-wobbly, timey-wimey ... stuff." -The Doctor, 2015 |
|---|
| 41 | | - * |
|---|
| 42 | | - * Requests exist in a complex web of interdependencies. Each request |
|---|
| 43 | | - * has to wait for some other request to complete before it is ready to be run |
|---|
| 44 | | - * (e.g. we have to wait until the pixels have been rendering into a texture |
|---|
| 45 | | - * before we can copy from it). We track the readiness of a request in terms |
|---|
| 46 | | - * of fences, but we also need to keep the dependency tree for the lifetime |
|---|
| 47 | | - * of the request (beyond the life of an individual fence). We use the tree |
|---|
| 48 | | - * at various points to reorder the requests whilst keeping the requests |
|---|
| 49 | | - * in order with respect to their various dependencies. |
|---|
| 50 | | - * |
|---|
| 51 | | - * There is no active component to the "scheduler". As we know the dependency |
|---|
| 52 | | - * DAG of each request, we are able to insert it into a sorted queue when it |
|---|
| 53 | | - * is ready, and are able to reorder its portion of the graph to accommodate |
|---|
| 54 | | - * dynamic priority changes. |
|---|
| 55 | | - */ |
|---|
| 56 | | -struct i915_sched_node { |
|---|
| 57 | | - struct list_head signalers_list; /* those before us, we depend upon */ |
|---|
| 58 | | - struct list_head waiters_list; /* those after us, they depend upon us */ |
|---|
| 59 | | - struct list_head link; |
|---|
| 60 | | - struct i915_sched_attr attr; |
|---|
| 61 | | -}; |
|---|
| 31 | +bool __i915_sched_node_add_dependency(struct i915_sched_node *node, |
|---|
| 32 | + struct i915_sched_node *signal, |
|---|
| 33 | + struct i915_dependency *dep, |
|---|
| 34 | + unsigned long flags); |
|---|
| 62 | 35 | |
|---|
| 63 | | -struct i915_dependency { |
|---|
| 64 | | - struct i915_sched_node *signaler; |
|---|
| 65 | | - struct list_head signal_link; |
|---|
| 66 | | - struct list_head wait_link; |
|---|
| 67 | | - struct list_head dfs_link; |
|---|
| 68 | | - unsigned long flags; |
|---|
| 69 | | -#define I915_DEPENDENCY_ALLOC BIT(0) |
|---|
| 70 | | -}; |
|---|
| 36 | +int i915_sched_node_add_dependency(struct i915_sched_node *node, |
|---|
| 37 | + struct i915_sched_node *signal, |
|---|
| 38 | + unsigned long flags); |
|---|
| 39 | + |
|---|
| 40 | +void i915_sched_node_fini(struct i915_sched_node *node); |
|---|
| 41 | + |
|---|
| 42 | +void i915_schedule(struct i915_request *request, |
|---|
| 43 | + const struct i915_sched_attr *attr); |
|---|
| 44 | + |
|---|
| 45 | +void i915_schedule_bump_priority(struct i915_request *rq, unsigned int bump); |
|---|
| 46 | + |
|---|
| 47 | +struct list_head * |
|---|
| 48 | +i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio); |
|---|
| 49 | + |
|---|
| 50 | +void __i915_priolist_free(struct i915_priolist *p); |
|---|
| 51 | +static inline void i915_priolist_free(struct i915_priolist *p) |
|---|
| 52 | +{ |
|---|
| 53 | + if (p->priority != I915_PRIORITY_NORMAL) |
|---|
| 54 | + __i915_priolist_free(p); |
|---|
| 55 | +} |
|---|
| 71 | 56 | |
|---|
| 72 | 57 | #endif /* _I915_SCHEDULER_H_ */ |
|---|