aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.h')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h135
1 files changed, 105 insertions, 30 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index b33c876fed20..12cb7ed90014 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -62,18 +62,6 @@ struct intel_hw_status_page {
62 (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \ 62 (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
63 GEN8_SEMAPHORE_OFFSET(from, (__ring)->id)) 63 GEN8_SEMAPHORE_OFFSET(from, (__ring)->id))
64 64
65#define GEN8_RING_SEMAPHORE_INIT(e) do { \
66 if (!dev_priv->semaphore_obj) { \
67 break; \
68 } \
69 (e)->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET((e), RCS); \
70 (e)->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET((e), VCS); \
71 (e)->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET((e), BCS); \
72 (e)->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET((e), VECS); \
73 (e)->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET((e), VCS2); \
74 (e)->semaphore.signal_ggtt[(e)->id] = MI_SEMAPHORE_SYNC_INVALID; \
75 } while(0)
76
77enum intel_ring_hangcheck_action { 65enum intel_ring_hangcheck_action {
78 HANGCHECK_IDLE = 0, 66 HANGCHECK_IDLE = 0,
79 HANGCHECK_WAIT, 67 HANGCHECK_WAIT,
@@ -86,8 +74,8 @@ enum intel_ring_hangcheck_action {
86 74
87struct intel_ring_hangcheck { 75struct intel_ring_hangcheck {
88 u64 acthd; 76 u64 acthd;
77 unsigned long user_interrupts;
89 u32 seqno; 78 u32 seqno;
90 unsigned user_interrupts;
91 int score; 79 int score;
92 enum intel_ring_hangcheck_action action; 80 enum intel_ring_hangcheck_action action;
93 int deadlock; 81 int deadlock;
@@ -141,6 +129,8 @@ struct i915_ctx_workarounds {
141 struct drm_i915_gem_object *obj; 129 struct drm_i915_gem_object *obj;
142}; 130};
143 131
132struct drm_i915_gem_request;
133
144struct intel_engine_cs { 134struct intel_engine_cs {
145 struct drm_i915_private *i915; 135 struct drm_i915_private *i915;
146 const char *name; 136 const char *name;
@@ -160,6 +150,39 @@ struct intel_engine_cs {
160 struct intel_ringbuffer *buffer; 150 struct intel_ringbuffer *buffer;
161 struct list_head buffers; 151 struct list_head buffers;
162 152
153 /* Rather than have every client wait upon all user interrupts,
154 * with the herd waking after every interrupt and each doing the
155 * heavyweight seqno dance, we delegate the task (of being the
156 * bottom-half of the user interrupt) to the first client. After
157 * every interrupt, we wake up one client, who does the heavyweight
158 * coherent seqno read and either goes back to sleep (if incomplete),
159 * or wakes up all the completed clients in parallel, before then
160 * transferring the bottom-half status to the next client in the queue.
161 *
162 * Compared to walking the entire list of waiters in a single dedicated
163 * bottom-half, we reduce the latency of the first waiter by avoiding
164 * a context switch, but incur additional coherent seqno reads when
165 * following the chain of request breadcrumbs. Since it is most likely
166 * that we have a single client waiting on each seqno, then reducing
167 * the overhead of waking that client is much preferred.
168 */
169 struct intel_breadcrumbs {
170 struct task_struct *irq_seqno_bh; /* bh for user interrupts */
171 unsigned long irq_wakeups;
172 bool irq_posted;
173
174 spinlock_t lock; /* protects the lists of requests */
175 struct rb_root waiters; /* sorted by retirement, priority */
176 struct rb_root signals; /* sorted by retirement */
177 struct intel_wait *first_wait; /* oldest waiter by retirement */
178 struct task_struct *signaler; /* used for fence signalling */
179 struct drm_i915_gem_request *first_signal;
180 struct timer_list fake_irq; /* used after a missed interrupt */
181
182 bool irq_enabled : 1;
183 bool rpm_wakelock : 1;
184 } breadcrumbs;
185
163 /* 186 /*
164 * A pool of objects to use as shadow copies of client batch buffers 187 * A pool of objects to use as shadow copies of client batch buffers
165 * when the command parser is enabled. Prevents the client from 188 * when the command parser is enabled. Prevents the client from
@@ -170,11 +193,10 @@ struct intel_engine_cs {
170 struct intel_hw_status_page status_page; 193 struct intel_hw_status_page status_page;
171 struct i915_ctx_workarounds wa_ctx; 194 struct i915_ctx_workarounds wa_ctx;
172 195
173 unsigned irq_refcount; /* protected by dev_priv->irq_lock */ 196 u32 irq_keep_mask; /* always keep these interrupts */
174 u32 irq_enable_mask; /* bitmask to enable ring interrupt */ 197 u32 irq_enable_mask; /* bitmask to enable ring interrupt */
175 struct drm_i915_gem_request *trace_irq_req; 198 void (*irq_enable)(struct intel_engine_cs *ring);
176 bool __must_check (*irq_get)(struct intel_engine_cs *ring); 199 void (*irq_disable)(struct intel_engine_cs *ring);
177 void (*irq_put)(struct intel_engine_cs *ring);
178 200
179 int (*init_hw)(struct intel_engine_cs *ring); 201 int (*init_hw)(struct intel_engine_cs *ring);
180 202
@@ -193,9 +215,6 @@ struct intel_engine_cs {
193 * monotonic, even if not coherent. 215 * monotonic, even if not coherent.
194 */ 216 */
195 void (*irq_seqno_barrier)(struct intel_engine_cs *ring); 217 void (*irq_seqno_barrier)(struct intel_engine_cs *ring);
196 u32 (*get_seqno)(struct intel_engine_cs *ring);
197 void (*set_seqno)(struct intel_engine_cs *ring,
198 u32 seqno);
199 int (*dispatch_execbuffer)(struct drm_i915_gem_request *req, 218 int (*dispatch_execbuffer)(struct drm_i915_gem_request *req,
200 u64 offset, u32 length, 219 u64 offset, u32 length,
201 unsigned dispatch_flags); 220 unsigned dispatch_flags);
@@ -272,7 +291,6 @@ struct intel_engine_cs {
272 unsigned int idle_lite_restore_wa; 291 unsigned int idle_lite_restore_wa;
273 bool disable_lite_restore_wa; 292 bool disable_lite_restore_wa;
274 u32 ctx_desc_template; 293 u32 ctx_desc_template;
275 u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */
276 int (*emit_request)(struct drm_i915_gem_request *request); 294 int (*emit_request)(struct drm_i915_gem_request *request);
277 int (*emit_flush)(struct drm_i915_gem_request *request, 295 int (*emit_flush)(struct drm_i915_gem_request *request,
278 u32 invalidate_domains, 296 u32 invalidate_domains,
@@ -304,12 +322,9 @@ struct intel_engine_cs {
304 * inspecting request list. 322 * inspecting request list.
305 */ 323 */
306 u32 last_submitted_seqno; 324 u32 last_submitted_seqno;
307 unsigned user_interrupts;
308 325
309 bool gpu_caches_dirty; 326 bool gpu_caches_dirty;
310 327
311 wait_queue_head_t irq_queue;
312
313 struct i915_gem_context *last_context; 328 struct i915_gem_context *last_context;
314 329
315 struct intel_ring_hangcheck hangcheck; 330 struct intel_ring_hangcheck hangcheck;
@@ -317,7 +332,6 @@ struct intel_engine_cs {
317 struct { 332 struct {
318 struct drm_i915_gem_object *obj; 333 struct drm_i915_gem_object *obj;
319 u32 gtt_offset; 334 u32 gtt_offset;
320 volatile u32 *cpu_page;
321 } scratch; 335 } scratch;
322 336
323 bool needs_cmd_parser; 337 bool needs_cmd_parser;
@@ -348,13 +362,13 @@ struct intel_engine_cs {
348}; 362};
349 363
350static inline bool 364static inline bool
351intel_engine_initialized(struct intel_engine_cs *engine) 365intel_engine_initialized(const struct intel_engine_cs *engine)
352{ 366{
353 return engine->i915 != NULL; 367 return engine->i915 != NULL;
354} 368}
355 369
356static inline unsigned 370static inline unsigned
357intel_engine_flag(struct intel_engine_cs *engine) 371intel_engine_flag(const struct intel_engine_cs *engine)
358{ 372{
359 return 1 << engine->id; 373 return 1 << engine->id;
360} 374}
@@ -456,15 +470,14 @@ static inline void intel_ring_advance(struct intel_engine_cs *engine)
456} 470}
457int __intel_ring_space(int head, int tail, int size); 471int __intel_ring_space(int head, int tail, int size);
458void intel_ring_update_space(struct intel_ringbuffer *ringbuf); 472void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
459bool intel_engine_stopped(struct intel_engine_cs *engine);
460 473
461int __must_check intel_engine_idle(struct intel_engine_cs *engine); 474int __must_check intel_engine_idle(struct intel_engine_cs *engine);
462void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno); 475void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno);
463int intel_ring_flush_all_caches(struct drm_i915_gem_request *req); 476int intel_ring_flush_all_caches(struct drm_i915_gem_request *req);
464int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req); 477int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req);
465 478
479int intel_init_pipe_control(struct intel_engine_cs *engine, int size);
466void intel_fini_pipe_control(struct intel_engine_cs *engine); 480void intel_fini_pipe_control(struct intel_engine_cs *engine);
467int intel_init_pipe_control(struct intel_engine_cs *engine);
468 481
469int intel_init_render_ring_buffer(struct drm_device *dev); 482int intel_init_render_ring_buffer(struct drm_device *dev);
470int intel_init_bsd_ring_buffer(struct drm_device *dev); 483int intel_init_bsd_ring_buffer(struct drm_device *dev);
@@ -473,6 +486,10 @@ int intel_init_blt_ring_buffer(struct drm_device *dev);
473int intel_init_vebox_ring_buffer(struct drm_device *dev); 486int intel_init_vebox_ring_buffer(struct drm_device *dev);
474 487
475u64 intel_ring_get_active_head(struct intel_engine_cs *engine); 488u64 intel_ring_get_active_head(struct intel_engine_cs *engine);
489static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine)
490{
491 return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
492}
476 493
477int init_workarounds_ring(struct intel_engine_cs *engine); 494int init_workarounds_ring(struct intel_engine_cs *engine);
478 495
@@ -495,4 +512,62 @@ static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
495 return engine->status_page.gfx_addr + I915_GEM_HWS_INDEX_ADDR; 512 return engine->status_page.gfx_addr + I915_GEM_HWS_INDEX_ADDR;
496} 513}
497 514
515/* intel_breadcrumbs.c -- user interrupt bottom-half for waiters */
516struct intel_wait {
517 struct rb_node node;
518 struct task_struct *tsk;
519 u32 seqno;
520};
521
522struct intel_signal_node {
523 struct rb_node node;
524 struct intel_wait wait;
525};
526
527int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
528
529static inline void intel_wait_init(struct intel_wait *wait, u32 seqno)
530{
531 wait->tsk = current;
532 wait->seqno = seqno;
533}
534
535static inline bool intel_wait_complete(const struct intel_wait *wait)
536{
537 return RB_EMPTY_NODE(&wait->node);
538}
539
540bool intel_engine_add_wait(struct intel_engine_cs *engine,
541 struct intel_wait *wait);
542void intel_engine_remove_wait(struct intel_engine_cs *engine,
543 struct intel_wait *wait);
544void intel_engine_enable_signaling(struct drm_i915_gem_request *request);
545
546static inline bool intel_engine_has_waiter(struct intel_engine_cs *engine)
547{
548 return READ_ONCE(engine->breadcrumbs.irq_seqno_bh);
549}
550
551static inline bool intel_engine_wakeup(struct intel_engine_cs *engine)
552{
553 bool wakeup = false;
554 struct task_struct *tsk = READ_ONCE(engine->breadcrumbs.irq_seqno_bh);
555 /* Note that for this not to dangerously chase a dangling pointer,
556 * the caller is responsible for ensure that the task remain valid for
557 * wake_up_process() i.e. that the RCU grace period cannot expire.
558 *
559 * Also note that tsk is likely to be in !TASK_RUNNING state so an
560 * early test for tsk->state != TASK_RUNNING before wake_up_process()
561 * is unlikely to be beneficial.
562 */
563 if (tsk)
564 wakeup = wake_up_process(tsk);
565 return wakeup;
566}
567
568void intel_engine_enable_fake_irq(struct intel_engine_cs *engine);
569void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
570unsigned int intel_kick_waiters(struct drm_i915_private *i915);
571unsigned int intel_kick_signalers(struct drm_i915_private *i915);
572
498#endif /* _INTEL_RINGBUFFER_H_ */ 573#endif /* _INTEL_RINGBUFFER_H_ */