aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-07-01 12:23:15 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2016-07-01 15:58:43 -0400
commit688e6c7258164de86d626e8e983ca8d28015c263 (patch)
treeea2040fd06199f2335f7431ca2506cd4e7757fe5 /drivers/gpu/drm/i915
parent1f15b76f1ec973d1eb5d21b6d98b21aebb9025f1 (diff)
drm/i915: Slaughter the thundering i915_wait_request herd
One particularly stressful scenario consists of many independent tasks all competing for GPU time and waiting upon the results (e.g. realtime transcoding of many, many streams). One bottleneck in particular is that each client waits on its own results, but every client is woken up after every batchbuffer - hence the thunder of hooves as then every client must do its heavyweight dance to read a coherent seqno to see if it is the lucky one. Ideally, we only want one client to wake up after the interrupt and check its request for completion. Since the requests must retire in order, we can select the first client on the oldest request to be woken. Once that client has completed his wait, we can then wake up the next client and so on. However, all clients then incur latency as every process in the chain may be delayed for scheduling - this may also then cause some priority inversion. To reduce the latency, when a client is added or removed from the list, we scan the tree for completed seqno and wake up all the completed waiters in parallel. Using igt/benchmarks/gem_latency, we can demonstrate this effect. The benchmark measures the number of GPU cycles between completion of a batch and the client waking up from a call to wait-ioctl. With many concurrent waiters, with each on a different request, we observe that the wakeup latency before the patch scales nearly linearly with the number of waiters (before external factors kick in making the scaling much worse). After applying the patch, we can see that only the single waiter for the request is being woken up, providing a constant wakeup latency for every operation. However, the situation is not quite as rosy for many waiters on the same request, though to the best of my knowledge this is much less likely in practice. Here, we can observe that the concurrent waiters incur extra latency from being woken up by the solitary bottom-half, rather than directly by the interrupt. This appears to be scheduler induced (having discounted adverse effects from having a rbtree walk/erase in the wakeup path), each additional wake_up_process() costs approximately 1us on big core. Another effect of performing the secondary wakeups from the first bottom-half is the incurred delay this imposes on high priority threads - rather than immediately returning to userspace and leaving the interrupt handler to wake the others. To offset the delay incurred with additional waiters on a request, we could use a hybrid scheme that did a quick read in the interrupt handler and dequeued all the completed waiters (incurring the overhead in the interrupt handler, not the best plan either as we then incur GPU submission latency) but we would still have to wake up the bottom-half every time to do the heavyweight slow read. Or we could only kick the waiters on the seqno with the same priority as the current task (i.e. in the realtime waiter scenario, only it is woken up immediately by the interrupt and simply queues the next waiter before returning to userspace, minimising its delay at the expense of the chain, and also reducing contention on its scheduler runqueue). This is effective at avoid long pauses in the interrupt handler and at avoiding the extra latency in realtime/high-priority waiters. v2: Convert from a kworker per engine into a dedicated kthread for the bottom-half. v3: Rename request members and tweak comments. v4: Use a per-engine spinlock in the breadcrumbs bottom-half. v5: Fix race in locklessly checking waiter status and kicking the task on adding a new waiter. v6: Fix deciding when to force the timer to hide missing interrupts. v7: Move the bottom-half from the kthread to the first client process. v8: Reword a few comments v9: Break the busy loop when the interrupt is unmasked or has fired. v10: Comments, unnecessary churn, better debugging from Tvrtko v11: Wake all completed waiters on removing the current bottom-half to reduce the latency of waking up a herd of clients all waiting on the same request. v12: Rearrange missed-interrupt fault injection so that it works with igt/drv_missed_irq_hang v13: Rename intel_breadcrumb and friends to intel_wait in preparation for signal handling. v14: RCU commentary, assert_spin_locked v15: Hide BUG_ON behind the compiler; report on gem_latency findings. v16: Sort seqno-groups by priority so that first-waiter has the highest task priority (and so avoid priority inversion). v17: Add waiters to post-mortem GPU hang state. v18: Return early for a completed wait after acquiring the spinlock. Avoids adding ourselves to the tree if the is already complete, and skips the awkward question of why we don't do completion wakeups for waits earlier than or equal to ourselves. v19: Prepare for init_breadcrumbs to fail. Later patches may want to allocate during init, so be prepared to propagate back the error code. Testcase: igt/gem_concurrent_blit Testcase: igt/benchmarks/gem_latency Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Rogozhkin, Dmitry V" <dmitry.v.rogozhkin@intel.com> Cc: "Gong, Zhipeng" <zhipeng.gong@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Cc: Dave Gordon <david.s.gordon@intel.com> Cc: "Goel, Akash" <akash.goel@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> #v18 Link: http://patchwork.freedesktop.org/patch/msgid/1467390209-3576-6-git-send-email-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c16
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h40
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c143
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c60
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c20
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c380
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c7
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c12
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h79
10 files changed, 648 insertions, 110 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a3d2b789c9ec..618293c8c9d9 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -38,6 +38,7 @@ i915-y += i915_cmd_parser.o \
38 i915_gem_userptr.o \ 38 i915_gem_userptr.o \
39 i915_gpu_error.o \ 39 i915_gpu_error.o \
40 i915_trace_points.o \ 40 i915_trace_points.o \
41 intel_breadcrumbs.o \
41 intel_lrc.o \ 42 intel_lrc.o \
42 intel_mocs.o \ 43 intel_mocs.o \
43 intel_ringbuffer.o \ 44 intel_ringbuffer.o \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index f664884ad27f..f522a366223d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -788,10 +788,22 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
788static void i915_ring_seqno_info(struct seq_file *m, 788static void i915_ring_seqno_info(struct seq_file *m,
789 struct intel_engine_cs *engine) 789 struct intel_engine_cs *engine)
790{ 790{
791 struct intel_breadcrumbs *b = &engine->breadcrumbs;
792 struct rb_node *rb;
793
791 seq_printf(m, "Current sequence (%s): %x\n", 794 seq_printf(m, "Current sequence (%s): %x\n",
792 engine->name, engine->get_seqno(engine)); 795 engine->name, engine->get_seqno(engine));
793 seq_printf(m, "Current user interrupts (%s): %x\n", 796 seq_printf(m, "Current user interrupts (%s): %x\n",
794 engine->name, READ_ONCE(engine->user_interrupts)); 797 engine->name, READ_ONCE(engine->user_interrupts));
798
799 spin_lock(&b->lock);
800 for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
801 struct intel_wait *w = container_of(rb, typeof(*w), node);
802
803 seq_printf(m, "Waiting (%s): %s [%d] on %x\n",
804 engine->name, w->tsk->comm, w->tsk->pid, w->seqno);
805 }
806 spin_unlock(&b->lock);
795} 807}
796 808
797static int i915_gem_seqno_info(struct seq_file *m, void *data) 809static int i915_gem_seqno_info(struct seq_file *m, void *data)
@@ -1428,6 +1440,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
1428 engine->hangcheck.seqno, 1440 engine->hangcheck.seqno,
1429 seqno[id], 1441 seqno[id],
1430 engine->last_submitted_seqno); 1442 engine->last_submitted_seqno);
1443 seq_printf(m, "\twaiters? %d\n",
1444 intel_engine_has_waiter(engine));
1431 seq_printf(m, "\tuser interrupts = %x [current %x]\n", 1445 seq_printf(m, "\tuser interrupts = %x [current %x]\n",
1432 engine->hangcheck.user_interrupts, 1446 engine->hangcheck.user_interrupts,
1433 READ_ONCE(engine->user_interrupts)); 1447 READ_ONCE(engine->user_interrupts));
@@ -2415,7 +2429,7 @@ static int count_irq_waiters(struct drm_i915_private *i915)
2415 int count = 0; 2429 int count = 0;
2416 2430
2417 for_each_engine(engine, i915) 2431 for_each_engine(engine, i915)
2418 count += engine->irq_refcount; 2432 count += intel_engine_has_waiter(engine);
2419 2433
2420 return count; 2434 return count;
2421} 2435}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0d0e4ac4dadb..1fefa8c495f2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -506,6 +506,7 @@ struct drm_i915_error_state {
506 bool valid; 506 bool valid;
507 /* Software tracked state */ 507 /* Software tracked state */
508 bool waiting; 508 bool waiting;
509 int num_waiters;
509 int hangcheck_score; 510 int hangcheck_score;
510 enum intel_ring_hangcheck_action hangcheck_action; 511 enum intel_ring_hangcheck_action hangcheck_action;
511 int num_requests; 512 int num_requests;
@@ -551,6 +552,12 @@ struct drm_i915_error_state {
551 u32 tail; 552 u32 tail;
552 } *requests; 553 } *requests;
553 554
555 struct drm_i915_error_waiter {
556 char comm[TASK_COMM_LEN];
557 pid_t pid;
558 u32 seqno;
559 } *waiters;
560
554 struct { 561 struct {
555 u32 gfx_mode; 562 u32 gfx_mode;
556 union { 563 union {
@@ -1429,7 +1436,7 @@ struct i915_gpu_error {
1429#define I915_STOP_RING_ALLOW_WARN (1 << 30) 1436#define I915_STOP_RING_ALLOW_WARN (1 << 30)
1430 1437
1431 /* For missed irq/seqno simulation. */ 1438 /* For missed irq/seqno simulation. */
1432 unsigned int test_irq_rings; 1439 unsigned long test_irq_rings;
1433}; 1440};
1434 1441
1435enum modeset_restore { 1442enum modeset_restore {
@@ -3064,7 +3071,6 @@ ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
3064 ibx_display_interrupt_update(dev_priv, bits, 0); 3071 ibx_display_interrupt_update(dev_priv, bits, 0);
3065} 3072}
3066 3073
3067
3068/* i915_gem.c */ 3074/* i915_gem.c */
3069int i915_gem_create_ioctl(struct drm_device *dev, void *data, 3075int i915_gem_create_ioctl(struct drm_device *dev, void *data,
3070 struct drm_file *file_priv); 3076 struct drm_file *file_priv);
@@ -3975,4 +3981,34 @@ static inline void i915_trace_irq_get(struct intel_engine_cs *engine,
3975 i915_gem_request_assign(&engine->trace_irq_req, req); 3981 i915_gem_request_assign(&engine->trace_irq_req, req);
3976} 3982}
3977 3983
3984static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req)
3985{
3986 /* Ensure our read of the seqno is coherent so that we
3987 * do not "miss an interrupt" (i.e. if this is the last
3988 * request and the seqno write from the GPU is not visible
3989 * by the time the interrupt fires, we will see that the
3990 * request is incomplete and go back to sleep awaiting
3991 * another interrupt that will never come.)
3992 *
3993 * Strictly, we only need to do this once after an interrupt,
3994 * but it is easier and safer to do it every time the waiter
3995 * is woken.
3996 */
3997 if (i915_gem_request_completed(req, false))
3998 return true;
3999
4000 /* We need to check whether any gpu reset happened in between
4001 * the request being submitted and now. If a reset has occurred,
4002 * the seqno will have been advance past ours and our request
4003 * is complete. If we are in the process of handling a reset,
4004 * the request is effectively complete as the rendering will
4005 * be discarded, but we need to return in order to drop the
4006 * struct_mutex.
4007 */
4008 if (i915_reset_in_progress(&req->i915->gpu_error))
4009 return true;
4010
4011 return false;
4012}
4013
3978#endif 4014#endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b5278d117ea0..c9814572e346 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1343,17 +1343,6 @@ i915_gem_check_wedge(unsigned reset_counter, bool interruptible)
1343 return 0; 1343 return 0;
1344} 1344}
1345 1345
1346static void fake_irq(unsigned long data)
1347{
1348 wake_up_process((struct task_struct *)data);
1349}
1350
1351static bool missed_irq(struct drm_i915_private *dev_priv,
1352 struct intel_engine_cs *engine)
1353{
1354 return test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings);
1355}
1356
1357static unsigned long local_clock_us(unsigned *cpu) 1346static unsigned long local_clock_us(unsigned *cpu)
1358{ 1347{
1359 unsigned long t; 1348 unsigned long t;
@@ -1386,7 +1375,7 @@ static bool busywait_stop(unsigned long timeout, unsigned cpu)
1386 return this_cpu != cpu; 1375 return this_cpu != cpu;
1387} 1376}
1388 1377
1389static int __i915_spin_request(struct drm_i915_gem_request *req, int state) 1378static bool __i915_spin_request(struct drm_i915_gem_request *req, int state)
1390{ 1379{
1391 unsigned long timeout; 1380 unsigned long timeout;
1392 unsigned cpu; 1381 unsigned cpu;
@@ -1401,17 +1390,14 @@ static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
1401 * takes to sleep on a request, on the order of a microsecond. 1390 * takes to sleep on a request, on the order of a microsecond.
1402 */ 1391 */
1403 1392
1404 if (req->engine->irq_refcount)
1405 return -EBUSY;
1406
1407 /* Only spin if we know the GPU is processing this request */ 1393 /* Only spin if we know the GPU is processing this request */
1408 if (!i915_gem_request_started(req, true)) 1394 if (!i915_gem_request_started(req, true))
1409 return -EAGAIN; 1395 return false;
1410 1396
1411 timeout = local_clock_us(&cpu) + 5; 1397 timeout = local_clock_us(&cpu) + 5;
1412 while (!need_resched()) { 1398 do {
1413 if (i915_gem_request_completed(req, true)) 1399 if (i915_gem_request_completed(req, true))
1414 return 0; 1400 return true;
1415 1401
1416 if (signal_pending_state(state, current)) 1402 if (signal_pending_state(state, current))
1417 break; 1403 break;
@@ -1420,12 +1406,9 @@ static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
1420 break; 1406 break;
1421 1407
1422 cpu_relax_lowlatency(); 1408 cpu_relax_lowlatency();
1423 } 1409 } while (!need_resched());
1424
1425 if (i915_gem_request_completed(req, false))
1426 return 0;
1427 1410
1428 return -EAGAIN; 1411 return false;
1429} 1412}
1430 1413
1431/** 1414/**
@@ -1450,18 +1433,14 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1450 s64 *timeout, 1433 s64 *timeout,
1451 struct intel_rps_client *rps) 1434 struct intel_rps_client *rps)
1452{ 1435{
1453 struct intel_engine_cs *engine = i915_gem_request_get_engine(req);
1454 struct drm_i915_private *dev_priv = req->i915;
1455 const bool irq_test_in_progress =
1456 ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_engine_flag(engine);
1457 int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; 1436 int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
1458 DEFINE_WAIT(reset); 1437 DEFINE_WAIT(reset);
1459 DEFINE_WAIT(wait); 1438 struct intel_wait wait;
1460 unsigned long timeout_expire; 1439 unsigned long timeout_remain;
1461 s64 before = 0; /* Only to silence a compiler warning. */ 1440 s64 before = 0; /* Only to silence a compiler warning. */
1462 int ret; 1441 int ret = 0;
1463 1442
1464 WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled"); 1443 might_sleep();
1465 1444
1466 if (list_empty(&req->list)) 1445 if (list_empty(&req->list))
1467 return 0; 1446 return 0;
@@ -1469,7 +1448,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1469 if (i915_gem_request_completed(req, true)) 1448 if (i915_gem_request_completed(req, true))
1470 return 0; 1449 return 0;
1471 1450
1472 timeout_expire = 0; 1451 timeout_remain = MAX_SCHEDULE_TIMEOUT;
1473 if (timeout) { 1452 if (timeout) {
1474 if (WARN_ON(*timeout < 0)) 1453 if (WARN_ON(*timeout < 0))
1475 return -EINVAL; 1454 return -EINVAL;
@@ -1477,7 +1456,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1477 if (*timeout == 0) 1456 if (*timeout == 0)
1478 return -ETIME; 1457 return -ETIME;
1479 1458
1480 timeout_expire = jiffies + nsecs_to_jiffies_timeout(*timeout); 1459 timeout_remain = nsecs_to_jiffies_timeout(*timeout);
1481 1460
1482 /* 1461 /*
1483 * Record current time in case interrupted by signal, or wedged. 1462 * Record current time in case interrupted by signal, or wedged.
@@ -1485,55 +1464,32 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1485 before = ktime_get_raw_ns(); 1464 before = ktime_get_raw_ns();
1486 } 1465 }
1487 1466
1488 if (INTEL_INFO(dev_priv)->gen >= 6)
1489 gen6_rps_boost(dev_priv, rps, req->emitted_jiffies);
1490
1491 trace_i915_gem_request_wait_begin(req); 1467 trace_i915_gem_request_wait_begin(req);
1492 1468
1493 /* Optimistic spin for the next jiffie before touching IRQs */ 1469 if (INTEL_INFO(req->i915)->gen >= 6)
1494 ret = __i915_spin_request(req, state); 1470 gen6_rps_boost(req->i915, rps, req->emitted_jiffies);
1495 if (ret == 0)
1496 goto out;
1497 1471
1498 if (!irq_test_in_progress && WARN_ON(!engine->irq_get(engine))) { 1472 /* Optimistic spin for the next ~jiffie before touching IRQs */
1499 ret = -ENODEV; 1473 if (__i915_spin_request(req, state))
1500 goto out; 1474 goto complete;
1501 }
1502 1475
1503 add_wait_queue(&dev_priv->gpu_error.wait_queue, &reset); 1476 set_current_state(state);
1504 for (;;) { 1477 add_wait_queue(&req->i915->gpu_error.wait_queue, &reset);
1505 struct timer_list timer;
1506 1478
1507 prepare_to_wait(&engine->irq_queue, &wait, state); 1479 intel_wait_init(&wait, req->seqno);
1508 1480 if (intel_engine_add_wait(req->engine, &wait))
1509 /* We need to check whether any gpu reset happened in between 1481 /* In order to check that we haven't missed the interrupt
1510 * the request being submitted and now. If a reset has occurred, 1482 * as we enabled it, we need to kick ourselves to do a
1511 * the seqno will have been advance past ours and our request 1483 * coherent check on the seqno before we sleep.
1512 * is complete. If we are in the process of handling a reset,
1513 * the request is effectively complete as the rendering will
1514 * be discarded, but we need to return in order to drop the
1515 * struct_mutex.
1516 */ 1484 */
1517 if (i915_reset_in_progress(&dev_priv->gpu_error)) { 1485 goto wakeup;
1518 ret = 0;
1519 break;
1520 }
1521
1522 if (i915_gem_request_completed(req, false)) {
1523 ret = 0;
1524 break;
1525 }
1526 1486
1487 for (;;) {
1527 if (signal_pending_state(state, current)) { 1488 if (signal_pending_state(state, current)) {
1528 ret = -ERESTARTSYS; 1489 ret = -ERESTARTSYS;
1529 break; 1490 break;
1530 } 1491 }
1531 1492
1532 if (timeout && time_after_eq(jiffies, timeout_expire)) {
1533 ret = -ETIME;
1534 break;
1535 }
1536
1537 /* Ensure that even if the GPU hangs, we get woken up. 1493 /* Ensure that even if the GPU hangs, we get woken up.
1538 * 1494 *
1539 * However, note that if no one is waiting, we never notice 1495 * However, note that if no one is waiting, we never notice
@@ -1541,32 +1497,33 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1541 * held by the GPU and so trigger a hangcheck. In the most 1497 * held by the GPU and so trigger a hangcheck. In the most
1542 * pathological case, this will be upon memory starvation! 1498 * pathological case, this will be upon memory starvation!
1543 */ 1499 */
1544 i915_queue_hangcheck(dev_priv); 1500 i915_queue_hangcheck(req->i915);
1545
1546 timer.function = NULL;
1547 if (timeout || missed_irq(dev_priv, engine)) {
1548 unsigned long expire;
1549 1501
1550 setup_timer_on_stack(&timer, fake_irq, (unsigned long)current); 1502 timeout_remain = io_schedule_timeout(timeout_remain);
1551 expire = missed_irq(dev_priv, engine) ? jiffies + 1 : timeout_expire; 1503 if (timeout_remain == 0) {
1552 mod_timer(&timer, expire); 1504 ret = -ETIME;
1505 break;
1553 } 1506 }
1554 1507
1555 io_schedule(); 1508 if (intel_wait_complete(&wait))
1556 1509 break;
1557 if (timer.function) {
1558 del_singleshot_timer_sync(&timer);
1559 destroy_timer_on_stack(&timer);
1560 }
1561 }
1562 remove_wait_queue(&dev_priv->gpu_error.wait_queue, &reset);
1563 1510
1564 if (!irq_test_in_progress) 1511 set_current_state(state);
1565 engine->irq_put(engine);
1566 1512
1567 finish_wait(&engine->irq_queue, &wait); 1513wakeup:
1514 /* Carefully check if the request is complete, giving time
1515 * for the seqno to be visible following the interrupt.
1516 * We also have to check in case we are kicked by the GPU
1517 * reset in order to drop the struct_mutex.
1518 */
1519 if (__i915_request_irq_complete(req))
1520 break;
1521 }
1522 remove_wait_queue(&req->i915->gpu_error.wait_queue, &reset);
1568 1523
1569out: 1524 intel_engine_remove_wait(req->engine, &wait);
1525 __set_current_state(TASK_RUNNING);
1526complete:
1570 trace_i915_gem_request_wait_end(req); 1527 trace_i915_gem_request_wait_end(req);
1571 1528
1572 if (timeout) { 1529 if (timeout) {
@@ -2796,6 +2753,12 @@ i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno)
2796 } 2753 }
2797 i915_gem_retire_requests(dev_priv); 2754 i915_gem_retire_requests(dev_priv);
2798 2755
2756 /* If the seqno wraps around, we need to clear the breadcrumb rbtree */
2757 if (!i915_seqno_passed(seqno, dev_priv->next_seqno)) {
2758 while (intel_kick_waiters(dev_priv))
2759 yield();
2760 }
2761
2799 /* Finally reset hw state */ 2762 /* Finally reset hw state */
2800 for_each_engine(engine, dev_priv) 2763 for_each_engine(engine, dev_priv)
2801 intel_ring_init_seqno(engine, seqno); 2764 intel_ring_init_seqno(engine, seqno);
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 34ff2459ceea..250f0b818099 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -463,6 +463,18 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
463 } 463 }
464 } 464 }
465 465
466 if (error->ring[i].num_waiters) {
467 err_printf(m, "%s --- %d waiters\n",
468 dev_priv->engine[i].name,
469 error->ring[i].num_waiters);
470 for (j = 0; j < error->ring[i].num_waiters; j++) {
471 err_printf(m, " seqno 0x%08x for %s [%d]\n",
472 error->ring[i].waiters[j].seqno,
473 error->ring[i].waiters[j].comm,
474 error->ring[i].waiters[j].pid);
475 }
476 }
477
466 if ((obj = error->ring[i].ringbuffer)) { 478 if ((obj = error->ring[i].ringbuffer)) {
467 err_printf(m, "%s --- ringbuffer = 0x%08x\n", 479 err_printf(m, "%s --- ringbuffer = 0x%08x\n",
468 dev_priv->engine[i].name, 480 dev_priv->engine[i].name,
@@ -605,8 +617,9 @@ static void i915_error_state_free(struct kref *error_ref)
605 i915_error_object_free(error->ring[i].ringbuffer); 617 i915_error_object_free(error->ring[i].ringbuffer);
606 i915_error_object_free(error->ring[i].hws_page); 618 i915_error_object_free(error->ring[i].hws_page);
607 i915_error_object_free(error->ring[i].ctx); 619 i915_error_object_free(error->ring[i].ctx);
608 kfree(error->ring[i].requests);
609 i915_error_object_free(error->ring[i].wa_ctx); 620 i915_error_object_free(error->ring[i].wa_ctx);
621 kfree(error->ring[i].requests);
622 kfree(error->ring[i].waiters);
610 } 623 }
611 624
612 i915_error_object_free(error->semaphore_obj); 625 i915_error_object_free(error->semaphore_obj);
@@ -892,6 +905,48 @@ static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
892 } 905 }
893} 906}
894 907
908static void engine_record_waiters(struct intel_engine_cs *engine,
909 struct drm_i915_error_ring *ering)
910{
911 struct intel_breadcrumbs *b = &engine->breadcrumbs;
912 struct drm_i915_error_waiter *waiter;
913 struct rb_node *rb;
914 int count;
915
916 ering->num_waiters = 0;
917 ering->waiters = NULL;
918
919 spin_lock(&b->lock);
920 count = 0;
921 for (rb = rb_first(&b->waiters); rb != NULL; rb = rb_next(rb))
922 count++;
923 spin_unlock(&b->lock);
924
925 waiter = NULL;
926 if (count)
927 waiter = kmalloc_array(count,
928 sizeof(struct drm_i915_error_waiter),
929 GFP_ATOMIC);
930 if (!waiter)
931 return;
932
933 ering->waiters = waiter;
934
935 spin_lock(&b->lock);
936 for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
937 struct intel_wait *w = container_of(rb, typeof(*w), node);
938
939 strcpy(waiter->comm, w->tsk->comm);
940 waiter->pid = w->tsk->pid;
941 waiter->seqno = w->seqno;
942 waiter++;
943
944 if (++ering->num_waiters == count)
945 break;
946 }
947 spin_unlock(&b->lock);
948}
949
895static void i915_record_ring_state(struct drm_i915_private *dev_priv, 950static void i915_record_ring_state(struct drm_i915_private *dev_priv,
896 struct drm_i915_error_state *error, 951 struct drm_i915_error_state *error,
897 struct intel_engine_cs *engine, 952 struct intel_engine_cs *engine,
@@ -926,7 +981,7 @@ static void i915_record_ring_state(struct drm_i915_private *dev_priv,
926 ering->instdone = I915_READ(GEN2_INSTDONE); 981 ering->instdone = I915_READ(GEN2_INSTDONE);
927 } 982 }
928 983
929 ering->waiting = waitqueue_active(&engine->irq_queue); 984 ering->waiting = intel_engine_has_waiter(engine);
930 ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); 985 ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
931 ering->acthd = intel_ring_get_active_head(engine); 986 ering->acthd = intel_ring_get_active_head(engine);
932 ering->seqno = engine->get_seqno(engine); 987 ering->seqno = engine->get_seqno(engine);
@@ -1032,6 +1087,7 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
1032 error->ring[i].valid = true; 1087 error->ring[i].valid = true;
1033 1088
1034 i915_record_ring_state(dev_priv, error, engine, &error->ring[i]); 1089 i915_record_ring_state(dev_priv, error, engine, &error->ring[i]);
1090 engine_record_waiters(engine, &error->ring[i]);
1035 1091
1036 request = i915_gem_find_active_request(engine); 1092 request = i915_gem_find_active_request(engine);
1037 if (request) { 1093 if (request) {
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 6c17596d75dd..a11ab00cdee0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -976,13 +976,10 @@ static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
976 976
977static void notify_ring(struct intel_engine_cs *engine) 977static void notify_ring(struct intel_engine_cs *engine)
978{ 978{
979 if (!intel_engine_initialized(engine)) 979 if (intel_engine_wakeup(engine)) {
980 return; 980 trace_i915_gem_request_notify(engine);
981 981 engine->user_interrupts++;
982 trace_i915_gem_request_notify(engine); 982 }
983 engine->user_interrupts++;
984
985 wake_up_all(&engine->irq_queue);
986} 983}
987 984
988static void vlv_c0_read(struct drm_i915_private *dev_priv, 985static void vlv_c0_read(struct drm_i915_private *dev_priv,
@@ -1063,7 +1060,7 @@ static bool any_waiters(struct drm_i915_private *dev_priv)
1063 struct intel_engine_cs *engine; 1060 struct intel_engine_cs *engine;
1064 1061
1065 for_each_engine(engine, dev_priv) 1062 for_each_engine(engine, dev_priv)
1066 if (engine->irq_refcount) 1063 if (intel_engine_has_waiter(engine))
1067 return true; 1064 return true;
1068 1065
1069 return false; 1066 return false;
@@ -3074,13 +3071,14 @@ static unsigned kick_waiters(struct intel_engine_cs *engine)
3074 3071
3075 if (engine->hangcheck.user_interrupts == user_interrupts && 3072 if (engine->hangcheck.user_interrupts == user_interrupts &&
3076 !test_and_set_bit(engine->id, &i915->gpu_error.missed_irq_rings)) { 3073 !test_and_set_bit(engine->id, &i915->gpu_error.missed_irq_rings)) {
3077 if (!(i915->gpu_error.test_irq_rings & intel_engine_flag(engine))) 3074 if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings))
3078 DRM_ERROR("Hangcheck timer elapsed... %s idle\n", 3075 DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
3079 engine->name); 3076 engine->name);
3080 else 3077 else
3081 DRM_INFO("Fake missed irq on %s\n", 3078 DRM_INFO("Fake missed irq on %s\n",
3082 engine->name); 3079 engine->name);
3083 wake_up_all(&engine->irq_queue); 3080
3081 intel_engine_enable_fake_irq(engine);
3084 } 3082 }
3085 3083
3086 return user_interrupts; 3084 return user_interrupts;
@@ -3124,7 +3122,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
3124 intel_uncore_arm_unclaimed_mmio_detection(dev_priv); 3122 intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
3125 3123
3126 for_each_engine_id(engine, dev_priv, id) { 3124 for_each_engine_id(engine, dev_priv, id) {
3127 bool busy = waitqueue_active(&engine->irq_queue); 3125 bool busy = intel_engine_has_waiter(engine);
3128 u64 acthd; 3126 u64 acthd;
3129 u32 seqno; 3127 u32 seqno;
3130 unsigned user_interrupts; 3128 unsigned user_interrupts;
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
new file mode 100644
index 000000000000..a3bbf2d90dce
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -0,0 +1,380 @@
1/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25#include "i915_drv.h"
26
27static void intel_breadcrumbs_fake_irq(unsigned long data)
28{
29 struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
30
31 /*
32 * The timer persists in case we cannot enable interrupts,
33 * or if we have previously seen seqno/interrupt incoherency
34 * ("missed interrupt" syndrome). Here the worker will wake up
35 * every jiffie in order to kick the oldest waiter to do the
36 * coherent seqno check.
37 */
38 rcu_read_lock();
39 if (intel_engine_wakeup(engine))
40 mod_timer(&engine->breadcrumbs.fake_irq, jiffies + 1);
41 rcu_read_unlock();
42}
43
44static void irq_enable(struct intel_engine_cs *engine)
45{
46 WARN_ON(!engine->irq_get(engine));
47}
48
49static void irq_disable(struct intel_engine_cs *engine)
50{
51 engine->irq_put(engine);
52}
53
54static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
55{
56 struct intel_engine_cs *engine =
57 container_of(b, struct intel_engine_cs, breadcrumbs);
58 struct drm_i915_private *i915 = engine->i915;
59 bool irq_posted = false;
60
61 assert_spin_locked(&b->lock);
62 if (b->rpm_wakelock)
63 return false;
64
65 /* Since we are waiting on a request, the GPU should be busy
66 * and should have its own rpm reference. For completeness,
67 * record an rpm reference for ourselves to cover the
68 * interrupt we unmask.
69 */
70 intel_runtime_pm_get_noresume(i915);
71 b->rpm_wakelock = true;
72
73 /* No interrupts? Kick the waiter every jiffie! */
74 if (intel_irqs_enabled(i915)) {
75 if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings)) {
76 irq_enable(engine);
77 irq_posted = true;
78 }
79 b->irq_enabled = true;
80 }
81
82 if (!b->irq_enabled ||
83 test_bit(engine->id, &i915->gpu_error.missed_irq_rings))
84 mod_timer(&b->fake_irq, jiffies + 1);
85
86 return irq_posted;
87}
88
89static void __intel_breadcrumbs_disable_irq(struct intel_breadcrumbs *b)
90{
91 struct intel_engine_cs *engine =
92 container_of(b, struct intel_engine_cs, breadcrumbs);
93
94 assert_spin_locked(&b->lock);
95 if (!b->rpm_wakelock)
96 return;
97
98 if (b->irq_enabled) {
99 irq_disable(engine);
100 b->irq_enabled = false;
101 }
102
103 intel_runtime_pm_put(engine->i915);
104 b->rpm_wakelock = false;
105}
106
107static inline struct intel_wait *to_wait(struct rb_node *node)
108{
109 return container_of(node, struct intel_wait, node);
110}
111
112static inline void __intel_breadcrumbs_finish(struct intel_breadcrumbs *b,
113 struct intel_wait *wait)
114{
115 assert_spin_locked(&b->lock);
116
117 /* This request is completed, so remove it from the tree, mark it as
118 * complete, and *then* wake up the associated task.
119 */
120 rb_erase(&wait->node, &b->waiters);
121 RB_CLEAR_NODE(&wait->node);
122
123 wake_up_process(wait->tsk); /* implicit smp_wmb() */
124}
125
126static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
127 struct intel_wait *wait)
128{
129 struct intel_breadcrumbs *b = &engine->breadcrumbs;
130 struct rb_node **p, *parent, *completed;
131 bool first;
132 u32 seqno;
133
134 /* Insert the request into the retirement ordered list
135 * of waiters by walking the rbtree. If we are the oldest
136 * seqno in the tree (the first to be retired), then
137 * set ourselves as the bottom-half.
138 *
139 * As we descend the tree, prune completed branches since we hold the
140 * spinlock we know that the first_waiter must be delayed and can
141 * reduce some of the sequential wake up latency if we take action
142 * ourselves and wake up the completed tasks in parallel. Also, by
143 * removing stale elements in the tree, we may be able to reduce the
144 * ping-pong between the old bottom-half and ourselves as first-waiter.
145 */
146 first = true;
147 parent = NULL;
148 completed = NULL;
149 seqno = engine->get_seqno(engine);
150
151 /* If the request completed before we managed to grab the spinlock,
152 * return now before adding ourselves to the rbtree. We let the
153 * current bottom-half handle any pending wakeups and instead
154 * try and get out of the way quickly.
155 */
156 if (i915_seqno_passed(seqno, wait->seqno)) {
157 RB_CLEAR_NODE(&wait->node);
158 return first;
159 }
160
161 p = &b->waiters.rb_node;
162 while (*p) {
163 parent = *p;
164 if (wait->seqno == to_wait(parent)->seqno) {
165 /* We have multiple waiters on the same seqno, select
166 * the highest priority task (that with the smallest
167 * task->prio) to serve as the bottom-half for this
168 * group.
169 */
170 if (wait->tsk->prio > to_wait(parent)->tsk->prio) {
171 p = &parent->rb_right;
172 first = false;
173 } else {
174 p = &parent->rb_left;
175 }
176 } else if (i915_seqno_passed(wait->seqno,
177 to_wait(parent)->seqno)) {
178 p = &parent->rb_right;
179 if (i915_seqno_passed(seqno, to_wait(parent)->seqno))
180 completed = parent;
181 else
182 first = false;
183 } else {
184 p = &parent->rb_left;
185 }
186 }
187 rb_link_node(&wait->node, parent, p);
188 rb_insert_color(&wait->node, &b->waiters);
189 GEM_BUG_ON(!first && !b->tasklet);
190
191 if (completed) {
192 struct rb_node *next = rb_next(completed);
193
194 GEM_BUG_ON(!next && !first);
195 if (next && next != &wait->node) {
196 GEM_BUG_ON(first);
197 b->first_wait = to_wait(next);
198 smp_store_mb(b->tasklet, b->first_wait->tsk);
199 /* As there is a delay between reading the current
200 * seqno, processing the completed tasks and selecting
201 * the next waiter, we may have missed the interrupt
202 * and so need for the next bottom-half to wakeup.
203 *
204 * Also as we enable the IRQ, we may miss the
205 * interrupt for that seqno, so we have to wake up
206 * the next bottom-half in order to do a coherent check
207 * in case the seqno passed.
208 */
209 __intel_breadcrumbs_enable_irq(b);
210 wake_up_process(to_wait(next)->tsk);
211 }
212
213 do {
214 struct intel_wait *crumb = to_wait(completed);
215 completed = rb_prev(completed);
216 __intel_breadcrumbs_finish(b, crumb);
217 } while (completed);
218 }
219
220 if (first) {
221 GEM_BUG_ON(rb_first(&b->waiters) != &wait->node);
222 b->first_wait = wait;
223 smp_store_mb(b->tasklet, wait->tsk);
224 first = __intel_breadcrumbs_enable_irq(b);
225 }
226 GEM_BUG_ON(!b->tasklet);
227 GEM_BUG_ON(!b->first_wait);
228 GEM_BUG_ON(rb_first(&b->waiters) != &b->first_wait->node);
229
230 return first;
231}
232
233bool intel_engine_add_wait(struct intel_engine_cs *engine,
234 struct intel_wait *wait)
235{
236 struct intel_breadcrumbs *b = &engine->breadcrumbs;
237 bool first;
238
239 spin_lock(&b->lock);
240 first = __intel_engine_add_wait(engine, wait);
241 spin_unlock(&b->lock);
242
243 return first;
244}
245
246void intel_engine_enable_fake_irq(struct intel_engine_cs *engine)
247{
248 mod_timer(&engine->breadcrumbs.fake_irq, jiffies + 1);
249}
250
251static inline bool chain_wakeup(struct rb_node *rb, int priority)
252{
253 return rb && to_wait(rb)->tsk->prio <= priority;
254}
255
256void intel_engine_remove_wait(struct intel_engine_cs *engine,
257 struct intel_wait *wait)
258{
259 struct intel_breadcrumbs *b = &engine->breadcrumbs;
260
261 /* Quick check to see if this waiter was already decoupled from
262 * the tree by the bottom-half to avoid contention on the spinlock
263 * by the herd.
264 */
265 if (RB_EMPTY_NODE(&wait->node))
266 return;
267
268 spin_lock(&b->lock);
269
270 if (RB_EMPTY_NODE(&wait->node))
271 goto out_unlock;
272
273 if (b->first_wait == wait) {
274 struct rb_node *next;
275 const int priority = wait->tsk->prio;
276
277 GEM_BUG_ON(b->tasklet != wait->tsk);
278
279 /* We are the current bottom-half. Find the next candidate,
280 * the first waiter in the queue on the remaining oldest
281 * request. As multiple seqnos may complete in the time it
282 * takes us to wake up and find the next waiter, we have to
283 * wake up that waiter for it to perform its own coherent
284 * completion check.
285 */
286 next = rb_next(&wait->node);
287 if (chain_wakeup(next, priority)) {
288 /* If the next waiter is already complete,
289 * wake it up and continue onto the next waiter. So
290 * if have a small herd, they will wake up in parallel
291 * rather than sequentially, which should reduce
292 * the overall latency in waking all the completed
293 * clients.
294 *
295 * However, waking up a chain adds extra latency to
296 * the first_waiter. This is undesirable if that
297 * waiter is a high priority task.
298 */
299 u32 seqno = engine->get_seqno(engine);
300
301 while (i915_seqno_passed(seqno, to_wait(next)->seqno)) {
302 struct rb_node *n = rb_next(next);
303
304 __intel_breadcrumbs_finish(b, to_wait(next));
305 next = n;
306 if (!chain_wakeup(next, priority))
307 break;
308 }
309 }
310
311 if (next) {
312 /* In our haste, we may have completed the first waiter
313 * before we enabled the interrupt. Do so now as we
314 * have a second waiter for a future seqno. Afterwards,
315 * we have to wake up that waiter in case we missed
316 * the interrupt, or if we have to handle an
317 * exception rather than a seqno completion.
318 */
319 b->first_wait = to_wait(next);
320 smp_store_mb(b->tasklet, b->first_wait->tsk);
321 if (b->first_wait->seqno != wait->seqno)
322 __intel_breadcrumbs_enable_irq(b);
323 wake_up_process(b->tasklet);
324 } else {
325 b->first_wait = NULL;
326 WRITE_ONCE(b->tasklet, NULL);
327 __intel_breadcrumbs_disable_irq(b);
328 }
329 } else {
330 GEM_BUG_ON(rb_first(&b->waiters) == &wait->node);
331 }
332
333 GEM_BUG_ON(RB_EMPTY_NODE(&wait->node));
334 rb_erase(&wait->node, &b->waiters);
335
336out_unlock:
337 GEM_BUG_ON(b->first_wait == wait);
338 GEM_BUG_ON(rb_first(&b->waiters) !=
339 (b->first_wait ? &b->first_wait->node : NULL));
340 GEM_BUG_ON(!b->tasklet ^ RB_EMPTY_ROOT(&b->waiters));
341 spin_unlock(&b->lock);
342}
343
344int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine)
345{
346 struct intel_breadcrumbs *b = &engine->breadcrumbs;
347
348 spin_lock_init(&b->lock);
349 setup_timer(&b->fake_irq,
350 intel_breadcrumbs_fake_irq,
351 (unsigned long)engine);
352
353 return 0;
354}
355
356void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
357{
358 struct intel_breadcrumbs *b = &engine->breadcrumbs;
359
360 del_timer_sync(&b->fake_irq);
361}
362
363unsigned int intel_kick_waiters(struct drm_i915_private *i915)
364{
365 struct intel_engine_cs *engine;
366 unsigned int mask = 0;
367
368 /* To avoid the task_struct disappearing beneath us as we wake up
369 * the process, we must first inspect the task_struct->state under the
370 * RCU lock, i.e. as we call wake_up_process() we must be holding the
371 * rcu_read_lock().
372 */
373 rcu_read_lock();
374 for_each_engine(engine, i915)
375 if (unlikely(intel_engine_wakeup(engine)))
376 mask |= intel_engine_flag(engine);
377 rcu_read_unlock();
378
379 return mask;
380}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 339d8041075f..226bba22e4b4 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1961,6 +1961,8 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
1961 i915_cmd_parser_fini_ring(engine); 1961 i915_cmd_parser_fini_ring(engine);
1962 i915_gem_batch_pool_fini(&engine->batch_pool); 1962 i915_gem_batch_pool_fini(&engine->batch_pool);
1963 1963
1964 intel_engine_fini_breadcrumbs(engine);
1965
1964 if (engine->status_page.obj) { 1966 if (engine->status_page.obj) {
1965 i915_gem_object_unpin_map(engine->status_page.obj); 1967 i915_gem_object_unpin_map(engine->status_page.obj);
1966 engine->status_page.obj = NULL; 1968 engine->status_page.obj = NULL;
@@ -1998,7 +2000,6 @@ logical_ring_default_irqs(struct intel_engine_cs *engine, unsigned shift)
1998{ 2000{
1999 engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; 2001 engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
2000 engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; 2002 engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
2001 init_waitqueue_head(&engine->irq_queue);
2002} 2003}
2003 2004
2004static int 2005static int
@@ -2025,6 +2026,10 @@ logical_ring_init(struct intel_engine_cs *engine)
2025 struct i915_gem_context *dctx = engine->i915->kernel_context; 2026 struct i915_gem_context *dctx = engine->i915->kernel_context;
2026 int ret; 2027 int ret;
2027 2028
2029 ret = intel_engine_init_breadcrumbs(engine);
2030 if (ret)
2031 goto error;
2032
2028 ret = i915_cmd_parser_init_ring(engine); 2033 ret = i915_cmd_parser_init_ring(engine);
2029 if (ret) 2034 if (ret)
2030 goto error; 2035 goto error;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 24cdc920f4b4..af50aa01bcd9 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2394,7 +2394,9 @@ static int intel_init_ring_buffer(struct drm_device *dev,
2394 memset(engine->semaphore.sync_seqno, 0, 2394 memset(engine->semaphore.sync_seqno, 0,
2395 sizeof(engine->semaphore.sync_seqno)); 2395 sizeof(engine->semaphore.sync_seqno));
2396 2396
2397 init_waitqueue_head(&engine->irq_queue); 2397 ret = intel_engine_init_breadcrumbs(engine);
2398 if (ret)
2399 goto error;
2398 2400
2399 /* We may need to do things with the shrinker which 2401 /* We may need to do things with the shrinker which
2400 * require us to immediately switch back to the default 2402 * require us to immediately switch back to the default
@@ -2474,6 +2476,7 @@ void intel_cleanup_engine(struct intel_engine_cs *engine)
2474 2476
2475 i915_cmd_parser_fini_ring(engine); 2477 i915_cmd_parser_fini_ring(engine);
2476 i915_gem_batch_pool_fini(&engine->batch_pool); 2478 i915_gem_batch_pool_fini(&engine->batch_pool);
2479 intel_engine_fini_breadcrumbs(engine);
2477 2480
2478 intel_ring_context_unpin(dev_priv->kernel_context, engine); 2481 intel_ring_context_unpin(dev_priv->kernel_context, engine);
2479 2482
@@ -2676,6 +2679,13 @@ void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
2676 engine->last_submitted_seqno = seqno; 2679 engine->last_submitted_seqno = seqno;
2677 2680
2678 engine->hangcheck.seqno = seqno; 2681 engine->hangcheck.seqno = seqno;
2682
2683 /* After manually advancing the seqno, fake the interrupt in case
2684 * there are any waiters for that seqno.
2685 */
2686 rcu_read_lock();
2687 intel_engine_wakeup(engine);
2688 rcu_read_unlock();
2679} 2689}
2680 2690
2681static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, 2691static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine,
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 113d5230a6de..6fd70a56e219 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -148,6 +148,32 @@ struct intel_engine_cs {
148 struct intel_ringbuffer *buffer; 148 struct intel_ringbuffer *buffer;
149 struct list_head buffers; 149 struct list_head buffers;
150 150
151 /* Rather than have every client wait upon all user interrupts,
152 * with the herd waking after every interrupt and each doing the
153 * heavyweight seqno dance, we delegate the task (of being the
154 * bottom-half of the user interrupt) to the first client. After
155 * every interrupt, we wake up one client, who does the heavyweight
156 * coherent seqno read and either goes back to sleep (if incomplete),
157 * or wakes up all the completed clients in parallel, before then
158 * transferring the bottom-half status to the next client in the queue.
159 *
160 * Compared to walking the entire list of waiters in a single dedicated
161 * bottom-half, we reduce the latency of the first waiter by avoiding
162 * a context switch, but incur additional coherent seqno reads when
163 * following the chain of request breadcrumbs. Since it is most likely
164 * that we have a single client waiting on each seqno, then reducing
165 * the overhead of waking that client is much preferred.
166 */
167 struct intel_breadcrumbs {
168 spinlock_t lock; /* protects the lists of requests */
169 struct rb_root waiters; /* sorted by retirement, priority */
170 struct intel_wait *first_wait; /* oldest waiter by retirement */
171 struct task_struct *tasklet; /* bh for user interrupts */
172 struct timer_list fake_irq; /* used after a missed interrupt */
173 bool irq_enabled;
174 bool rpm_wakelock;
175 } breadcrumbs;
176
151 /* 177 /*
152 * A pool of objects to use as shadow copies of client batch buffers 178 * A pool of objects to use as shadow copies of client batch buffers
153 * when the command parser is enabled. Prevents the client from 179 * when the command parser is enabled. Prevents the client from
@@ -296,8 +322,6 @@ struct intel_engine_cs {
296 322
297 bool gpu_caches_dirty; 323 bool gpu_caches_dirty;
298 324
299 wait_queue_head_t irq_queue;
300
301 struct i915_gem_context *last_context; 325 struct i915_gem_context *last_context;
302 326
303 struct intel_ring_hangcheck hangcheck; 327 struct intel_ring_hangcheck hangcheck;
@@ -483,4 +507,55 @@ static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
483 return engine->status_page.gfx_addr + I915_GEM_HWS_INDEX_ADDR; 507 return engine->status_page.gfx_addr + I915_GEM_HWS_INDEX_ADDR;
484} 508}
485 509
510/* intel_breadcrumbs.c -- user interrupt bottom-half for waiters */
511struct intel_wait {
512 struct rb_node node;
513 struct task_struct *tsk;
514 u32 seqno;
515};
516
517int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
518
519static inline void intel_wait_init(struct intel_wait *wait, u32 seqno)
520{
521 wait->tsk = current;
522 wait->seqno = seqno;
523}
524
525static inline bool intel_wait_complete(const struct intel_wait *wait)
526{
527 return RB_EMPTY_NODE(&wait->node);
528}
529
530bool intel_engine_add_wait(struct intel_engine_cs *engine,
531 struct intel_wait *wait);
532void intel_engine_remove_wait(struct intel_engine_cs *engine,
533 struct intel_wait *wait);
534
535static inline bool intel_engine_has_waiter(struct intel_engine_cs *engine)
536{
537 return READ_ONCE(engine->breadcrumbs.tasklet);
538}
539
540static inline bool intel_engine_wakeup(struct intel_engine_cs *engine)
541{
542 bool wakeup = false;
543 struct task_struct *tsk = READ_ONCE(engine->breadcrumbs.tasklet);
544 /* Note that for this not to dangerously chase a dangling pointer,
545 * the caller is responsible for ensure that the task remain valid for
546 * wake_up_process() i.e. that the RCU grace period cannot expire.
547 *
548 * Also note that tsk is likely to be in !TASK_RUNNING state so an
549 * early test for tsk->state != TASK_RUNNING before wake_up_process()
550 * is unlikely to be beneficial.
551 */
552 if (tsk)
553 wakeup = wake_up_process(tsk);
554 return wakeup;
555}
556
557void intel_engine_enable_fake_irq(struct intel_engine_cs *engine);
558void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
559unsigned int intel_kick_waiters(struct drm_i915_private *i915);
560
486#endif /* _INTEL_RINGBUFFER_H_ */ 561#endif /* _INTEL_RINGBUFFER_H_ */