drivers/gpu/drm/i915/i915_scheduler.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/i915_scheduler.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/i915/i915_scheduler.c- Extension
.c- Size
- 13777 bytes
- Lines
- 512
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/mutex.hi915_drv.hi915_request.hi915_scheduler.h
Detected Declarations
struct sched_cachefunction node_to_requestfunction node_startedfunction node_signaledfunction assert_priolistsfunction i915_sched_lookup_priolistfunction __i915_priolist_freefunction lock_sched_enginefunction __i915_schedulefunction update_prioritiesfunction listfunction list_for_each_entryfunction requestfunction i915_schedulefunction i915_sched_node_initfunction i915_sched_node_reinitfunction i915_dependency_allocfunction i915_dependency_freefunction __i915_sched_node_add_dependencyfunction i915_sched_node_add_dependencyfunction i915_sched_node_finifunction uponfunction i915_request_show_with_schedulefunction default_destroyfunction default_disabledfunction i915_sched_engine_createfunction i915_scheduler_module_exitfunction i915_scheduler_module_init
Annotated Snippet
struct sched_cache {
struct list_head *priolist;
};
static struct i915_sched_engine *
lock_sched_engine(struct i915_sched_node *node,
struct i915_sched_engine *locked,
struct sched_cache *cache)
{
const struct i915_request *rq = node_to_request(node);
struct i915_sched_engine *sched_engine;
GEM_BUG_ON(!locked);
/*
* Virtual engines complicate acquiring the engine timeline lock,
* as their rq->engine pointer is not stable until under that
* engine lock. The simple ploy we use is to take the lock then
* check that the rq still belongs to the newly locked engine.
*/
while (locked != (sched_engine = READ_ONCE(rq->engine)->sched_engine)) {
spin_unlock(&locked->lock);
memset(cache, 0, sizeof(*cache));
spin_lock(&sched_engine->lock);
locked = sched_engine;
}
GEM_BUG_ON(locked != sched_engine);
return locked;
}
static void __i915_schedule(struct i915_sched_node *node,
const struct i915_sched_attr *attr)
{
const int prio = max(attr->priority, node->attr.priority);
struct i915_sched_engine *sched_engine;
struct i915_dependency *dep, *p;
struct i915_dependency stack;
struct sched_cache cache;
LIST_HEAD(dfs);
/* Needed in order to use the temporary link inside i915_dependency */
lockdep_assert_held(&schedule_lock);
GEM_BUG_ON(prio == I915_PRIORITY_INVALID);
if (node_signaled(node))
return;
stack.signaler = node;
list_add(&stack.dfs_link, &dfs);
/*
* Recursively bump all dependent priorities to match the new request.
*
* A naive approach would be to use recursion:
* static void update_priorities(struct i915_sched_node *node, prio) {
* list_for_each_entry(dep, &node->signalers_list, signal_link)
* update_priorities(dep->signal, prio)
* queue_request(node);
* }
* but that may have unlimited recursion depth and so runs a very
* real risk of overunning the kernel stack. Instead, we build
* a flat list of all dependencies starting with the current request.
* As we walk the list of dependencies, we add all of its dependencies
* to the end of the list (this may include an already visited
* request) and continue to walk onwards onto the new dependencies. The
* end result is a topological list of requests in reverse order, the
* last element in the list is the request we must execute first.
*/
list_for_each_entry(dep, &dfs, dfs_link) {
struct i915_sched_node *node = dep->signaler;
/* If we are already flying, we know we have no signalers */
if (node_started(node))
continue;
/*
* Within an engine, there can be no cycle, but we may
* refer to the same dependency chain multiple times
* (redundant dependencies are not eliminated) and across
* engines.
*/
list_for_each_entry(p, &node->signalers_list, signal_link) {
GEM_BUG_ON(p == dep); /* no cycles! */
if (node_signaled(p->signaler))
continue;
if (prio > READ_ONCE(p->signaler->attr.priority))
list_move_tail(&p->dfs_link, &dfs);
Annotation
- Immediate include surface: `linux/mutex.h`, `i915_drv.h`, `i915_request.h`, `i915_scheduler.h`.
- Detected declarations: `struct sched_cache`, `function node_to_request`, `function node_started`, `function node_signaled`, `function assert_priolists`, `function i915_sched_lookup_priolist`, `function __i915_priolist_free`, `function lock_sched_engine`, `function __i915_schedule`, `function update_priorities`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.