summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/scheduler/sched_internal.h
blob: 13ecb771d7a24d51fbb424c1fb0386eea686fce1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* SPDX-License-Identifier: MIT */

#ifndef _DRM_GPU_SCHEDULER_INTERNAL_H_
#define _DRM_GPU_SCHEDULER_INTERNAL_H_

#include <linux/ktime.h>
#include <linux/kref.h>
#include <linux/spinlock.h>

/**
 * struct drm_sched_entity_stats - execution stats for an entity.
 * @kref: reference count for the object.
 * @lock: lock guarding the @runtime updates.
 * @runtime: time entity spent on the GPU.
 * @prev_runtime: previous @runtime used to get the runtime delta.
 * @vruntime: virtual runtime as accumulated by the fair algorithm.
 * @avg_job_us: average job duration.
 *
 * Because jobs and entities have decoupled lifetimes, ie. we cannot access the
 * entity once the job has been de-queued, and we do need know how much GPU time
 * each entity has spent, we need to track this in a separate object which is
 * reference counted by both entities and jobs.
 */
struct drm_sched_entity_stats {
	struct kref	kref;
	spinlock_t	lock; /* Protects the below fields. */
	ktime_t		runtime;
	ktime_t		prev_runtime;
	ktime_t		vruntime;

	struct ewma_drm_sched_avgtime   avg_job_us;
};

bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
			 struct drm_sched_entity *entity);
void drm_sched_wakeup(struct drm_gpu_scheduler *sched);

void drm_sched_rq_init(struct drm_sched_rq *rq);

struct drm_gpu_scheduler *
drm_sched_rq_add_entity(struct drm_sched_entity *entity);
void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
				struct drm_sched_entity *entity);
void drm_sched_rq_pop_entity(struct drm_sched_entity *entity);

struct drm_sched_entity *
drm_sched_select_entity(struct drm_gpu_scheduler *sched);

void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);

struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *s_entity,
					      void *owner, u64 drm_client_id);
void drm_sched_fence_init(struct drm_sched_fence *fence,
			  struct drm_sched_entity *entity);
void drm_sched_fence_free(struct drm_sched_fence *fence);

void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
			       struct dma_fence *parent);
void drm_sched_fence_finished(struct drm_sched_fence *fence, int result);

/**
 * drm_sched_entity_queue_pop - Low level helper for popping queued jobs
 *
 * @entity: scheduler entity
 *
 * Low level helper for popping queued jobs.
 *
 * Returns: The job dequeued or NULL.
 */
static inline struct drm_sched_job *
drm_sched_entity_queue_pop(struct drm_sched_entity *entity)
{
	struct spsc_node *node;

	node = spsc_queue_pop(&entity->job_queue);
	if (!node)
		return NULL;

	return container_of(node, struct drm_sched_job, queue_node);
}

/**
 * drm_sched_entity_queue_peek - Low level helper for peeking at the job queue
 *
 * @entity: scheduler entity
 *
 * Low level helper for peeking at the job queue
 *
 * Returns: The job at the head of the queue or NULL.
 */
static inline struct drm_sched_job *
drm_sched_entity_queue_peek(struct drm_sched_entity *entity)
{
	struct spsc_node *node;

	node = spsc_queue_peek(&entity->job_queue);
	if (!node)
		return NULL;

	return container_of(node, struct drm_sched_job, queue_node);
}

/* Return true if entity could provide a job. */
static inline bool
drm_sched_entity_is_ready(struct drm_sched_entity *entity)
{
	if (!spsc_queue_count(&entity->job_queue))
		return false;

	if (READ_ONCE(entity->dependency))
		return false;

	return true;
}

void drm_sched_entity_stats_release(struct kref *kref);

/**
 * drm_sched_entity_stats_get - Obtain a reference count on &struct drm_sched_entity_stats object
 * @stats: struct drm_sched_entity_stats pointer
 *
 * Return: struct drm_sched_entity_stats pointer
 */
static inline struct drm_sched_entity_stats *
drm_sched_entity_stats_get(struct drm_sched_entity_stats *stats)
{
	kref_get(&stats->kref);

	return stats;
}

/**
 * drm_sched_entity_stats_put - Release a reference count on &struct drm_sched_entity_stats object
 * @stats: struct drm_sched_entity_stats pointer
 */
static inline void
drm_sched_entity_stats_put(struct drm_sched_entity_stats *stats)
{
	kref_put(&stats->kref, drm_sched_entity_stats_release);
}

ktime_t drm_sched_entity_stats_job_add_gpu_time(struct drm_sched_job *job);

#endif