aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c45
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h2
-rw-r--r--drivers/gpu/drm/i915/i915_request.c2
-rw-r--r--drivers/gpu/drm/i915/i915_request.h3
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h33
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c3
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c125
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h9
8 files changed, 66 insertions, 156 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 7ccfdbc8f9b4..ac75e0c5735c 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1712,45 +1712,6 @@ static void gen6_write_page_range(struct i915_hw_ppgtt *ppgtt,
1712 wmb(); 1712 wmb();
1713} 1713}
1714 1714
1715static inline u32 get_pd_offset(struct i915_hw_ppgtt *ppgtt)
1716{
1717 GEM_BUG_ON(ppgtt->pd.base.ggtt_offset & 0x3f);
1718 return ppgtt->pd.base.ggtt_offset << 10;
1719}
1720
1721static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
1722 struct i915_request *rq)
1723{
1724 struct intel_engine_cs *engine = rq->engine;
1725 u32 *cs;
1726
1727 /* NB: TLBs must be flushed and invalidated before a switch */
1728 cs = intel_ring_begin(rq, 6);
1729 if (IS_ERR(cs))
1730 return PTR_ERR(cs);
1731
1732 *cs++ = MI_LOAD_REGISTER_IMM(2);
1733 *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine));
1734 *cs++ = PP_DIR_DCLV_2G;
1735 *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine));
1736 *cs++ = get_pd_offset(ppgtt);
1737 *cs++ = MI_NOOP;
1738 intel_ring_advance(rq, cs);
1739
1740 return 0;
1741}
1742
1743static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
1744 struct i915_request *rq)
1745{
1746 struct intel_engine_cs *engine = rq->engine;
1747 struct drm_i915_private *dev_priv = rq->i915;
1748
1749 I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
1750 I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
1751 return 0;
1752}
1753
1754static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv) 1715static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv)
1755{ 1716{
1756 struct intel_engine_cs *engine; 1717 struct intel_engine_cs *engine;
@@ -2024,12 +1985,6 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
2024 ppgtt->vm.dma = &i915->drm.pdev->dev; 1985 ppgtt->vm.dma = &i915->drm.pdev->dev;
2025 1986
2026 ppgtt->vm.pte_encode = ggtt->vm.pte_encode; 1987 ppgtt->vm.pte_encode = ggtt->vm.pte_encode;
2027 if (IS_GEN6(i915))
2028 ppgtt->switch_mm = gen6_mm_switch;
2029 else if (IS_GEN7(i915))
2030 ppgtt->switch_mm = gen7_mm_switch;
2031 else
2032 BUG();
2033 1988
2034 err = gen6_ppgtt_alloc(ppgtt); 1989 err = gen6_ppgtt_alloc(ppgtt);
2035 if (err) 1990 if (err)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 16307ba7e303..e70f6abcd0f2 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -406,8 +406,6 @@ struct i915_hw_ppgtt {
406 406
407 gen6_pte_t __iomem *pd_addr; 407 gen6_pte_t __iomem *pd_addr;
408 408
409 int (*switch_mm)(struct i915_hw_ppgtt *ppgtt,
410 struct i915_request *rq);
411 void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m); 409 void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m);
412}; 410};
413 411
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index f187250e60c6..9092f5464c24 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -817,6 +817,8 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
817 /* Keep a second pin for the dual retirement along engine and ring */ 817 /* Keep a second pin for the dual retirement along engine and ring */
818 __intel_context_pin(ce); 818 __intel_context_pin(ce);
819 819
820 rq->infix = rq->ring->emit; /* end of header; start of user payload */
821
820 /* Check that we didn't interrupt ourselves with a new request */ 822 /* Check that we didn't interrupt ourselves with a new request */
821 GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno); 823 GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno);
822 return rq; 824 return rq;
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h
index 491ff81d0fea..0e9aba53d0e4 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -134,6 +134,9 @@ struct i915_request {
134 /** Position in the ring of the start of the request */ 134 /** Position in the ring of the start of the request */
135 u32 head; 135 u32 head;
136 136
137 /** Position in the ring of the start of the user packets */
138 u32 infix;
139
137 /** 140 /**
138 * Position in the ring of the start of the postfix. 141 * Position in the ring of the start of the postfix.
139 * This is required to calculate the maximum available ring space 142 * This is required to calculate the maximum available ring space
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 1472f48ab2e8..b50c6b829715 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -973,39 +973,6 @@ DEFINE_EVENT(i915_context, i915_context_free,
973 TP_ARGS(ctx) 973 TP_ARGS(ctx)
974); 974);
975 975
976/**
977 * DOC: switch_mm tracepoint
978 *
979 * This tracepoint allows tracking of the mm switch, which is an important point
980 * in the lifetime of the vm in the legacy submission path. This tracepoint is
981 * called only if full ppgtt is enabled.
982 */
983TRACE_EVENT(switch_mm,
984 TP_PROTO(struct intel_engine_cs *engine, struct i915_gem_context *to),
985
986 TP_ARGS(engine, to),
987
988 TP_STRUCT__entry(
989 __field(u16, class)
990 __field(u16, instance)
991 __field(struct i915_gem_context *, to)
992 __field(struct i915_address_space *, vm)
993 __field(u32, dev)
994 ),
995
996 TP_fast_assign(
997 __entry->class = engine->uabi_class;
998 __entry->instance = engine->instance;
999 __entry->to = to;
1000 __entry->vm = to->ppgtt ? &to->ppgtt->vm : NULL;
1001 __entry->dev = engine->i915->drm.primary->index;
1002 ),
1003
1004 TP_printk("dev=%u, engine=%u:%u, ctx=%p, ctx_vm=%p",
1005 __entry->dev, __entry->class, __entry->instance, __entry->to,
1006 __entry->vm)
1007);
1008
1009#endif /* _I915_TRACE_H_ */ 976#endif /* _I915_TRACE_H_ */
1010 977
1011/* This part must be outside protection */ 978/* This part must be outside protection */
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 2ec2e60dc670..d1cf8b4926ab 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1168,9 +1168,6 @@ void intel_engine_lost_context(struct intel_engine_cs *engine)
1168 1168
1169 lockdep_assert_held(&engine->i915->drm.struct_mutex); 1169 lockdep_assert_held(&engine->i915->drm.struct_mutex);
1170 1170
1171 engine->legacy_active_context = NULL;
1172 engine->legacy_active_ppgtt = NULL;
1173
1174 ce = fetch_and_zero(&engine->last_retired_context); 1171 ce = fetch_and_zero(&engine->last_retired_context);
1175 if (ce) 1172 if (ce)
1176 intel_context_unpin(ce); 1173 intel_context_unpin(ce);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 5bc53a5f4504..d72a6a5ff3ac 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -541,11 +541,23 @@ static struct i915_request *reset_prepare(struct intel_engine_cs *engine)
541 return i915_gem_find_active_request(engine); 541 return i915_gem_find_active_request(engine);
542} 542}
543 543
544static void reset_ring(struct intel_engine_cs *engine, 544static void skip_request(struct i915_request *rq)
545 struct i915_request *request)
546{ 545{
547 GEM_TRACE("%s seqno=%x\n", 546 void *vaddr = rq->ring->vaddr;
548 engine->name, request ? request->global_seqno : 0); 547 u32 head;
548
549 head = rq->infix;
550 if (rq->postfix < head) {
551 memset32(vaddr + head, MI_NOOP,
552 (rq->ring->size - head) / sizeof(u32));
553 head = 0;
554 }
555 memset32(vaddr + head, MI_NOOP, (rq->postfix - head) / sizeof(u32));
556}
557
558static void reset_ring(struct intel_engine_cs *engine, struct i915_request *rq)
559{
560 GEM_TRACE("%s seqno=%x\n", engine->name, rq ? rq->global_seqno : 0);
549 561
550 /* 562 /*
551 * RC6 must be prevented until the reset is complete and the engine 563 * RC6 must be prevented until the reset is complete and the engine
@@ -569,43 +581,11 @@ static void reset_ring(struct intel_engine_cs *engine,
569 * If the request was innocent, we try to replay the request with 581 * If the request was innocent, we try to replay the request with
570 * the restored context. 582 * the restored context.
571 */ 583 */
572 if (request) { 584 if (rq) {
573 struct drm_i915_private *dev_priv = request->i915;
574 struct intel_context *ce = request->hw_context;
575 struct i915_hw_ppgtt *ppgtt;
576
577 if (ce->state) {
578 I915_WRITE(CCID,
579 i915_ggtt_offset(ce->state) |
580 BIT(8) /* must be set! */ |
581 CCID_EXTENDED_STATE_SAVE |
582 CCID_EXTENDED_STATE_RESTORE |
583 CCID_EN);
584 }
585
586 ppgtt = request->gem_context->ppgtt ?: engine->i915->mm.aliasing_ppgtt;
587 if (ppgtt) {
588 u32 pd_offset = ppgtt->pd.base.ggtt_offset << 10;
589
590 I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
591 I915_WRITE(RING_PP_DIR_BASE(engine), pd_offset);
592
593 /* Wait for the PD reload to complete */
594 if (intel_wait_for_register(dev_priv,
595 RING_PP_DIR_BASE(engine),
596 BIT(0), 0,
597 10))
598 DRM_ERROR("Wait for reload of ppgtt page-directory timed out\n");
599
600 ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
601 }
602
603 /* If the rq hung, jump to its breadcrumb and skip the batch */ 585 /* If the rq hung, jump to its breadcrumb and skip the batch */
604 if (request->fence.error == -EIO) 586 rq->ring->head = intel_ring_wrap(rq->ring, rq->head);
605 request->ring->head = request->postfix; 587 if (rq->fence.error == -EIO)
606 } else { 588 skip_request(rq);
607 engine->legacy_active_context = NULL;
608 engine->legacy_active_ppgtt = NULL;
609 } 589 }
610} 590}
611 591
@@ -1446,6 +1426,29 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
1446 intel_ring_reset(engine->buffer, 0); 1426 intel_ring_reset(engine->buffer, 0);
1447} 1427}
1448 1428
1429static int load_pd_dir(struct i915_request *rq,
1430 const struct i915_hw_ppgtt *ppgtt)
1431{
1432 const struct intel_engine_cs * const engine = rq->engine;
1433 u32 *cs;
1434
1435 cs = intel_ring_begin(rq, 6);
1436 if (IS_ERR(cs))
1437 return PTR_ERR(cs);
1438
1439 *cs++ = MI_LOAD_REGISTER_IMM(1);
1440 *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine));
1441 *cs++ = PP_DIR_DCLV_2G;
1442
1443 *cs++ = MI_LOAD_REGISTER_IMM(1);
1444 *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine));
1445 *cs++ = ppgtt->pd.base.ggtt_offset << 10;
1446
1447 intel_ring_advance(rq, cs);
1448
1449 return 0;
1450}
1451
1449static inline int mi_set_context(struct i915_request *rq, u32 flags) 1452static inline int mi_set_context(struct i915_request *rq, u32 flags)
1450{ 1453{
1451 struct drm_i915_private *i915 = rq->i915; 1454 struct drm_i915_private *i915 = rq->i915;
@@ -1590,31 +1593,28 @@ static int remap_l3(struct i915_request *rq, int slice)
1590static int switch_context(struct i915_request *rq) 1593static int switch_context(struct i915_request *rq)
1591{ 1594{
1592 struct intel_engine_cs *engine = rq->engine; 1595 struct intel_engine_cs *engine = rq->engine;
1593 struct i915_gem_context *to_ctx = rq->gem_context; 1596 struct i915_gem_context *ctx = rq->gem_context;
1594 struct i915_hw_ppgtt *to_mm = 1597 struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt;
1595 to_ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; 1598 unsigned int unwind_mm = 0;
1596 struct i915_gem_context *from_ctx = engine->legacy_active_context;
1597 struct i915_hw_ppgtt *from_mm = engine->legacy_active_ppgtt;
1598 u32 hw_flags = 0; 1599 u32 hw_flags = 0;
1599 int ret, i; 1600 int ret, i;
1600 1601
1601 lockdep_assert_held(&rq->i915->drm.struct_mutex); 1602 lockdep_assert_held(&rq->i915->drm.struct_mutex);
1602 GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); 1603 GEM_BUG_ON(HAS_EXECLISTS(rq->i915));
1603 1604
1604 if (to_mm != from_mm || 1605 if (ppgtt) {
1605 (to_mm && intel_engine_flag(engine) & to_mm->pd_dirty_rings)) { 1606 ret = load_pd_dir(rq, ppgtt);
1606 trace_switch_mm(engine, to_ctx);
1607 ret = to_mm->switch_mm(to_mm, rq);
1608 if (ret) 1607 if (ret)
1609 goto err; 1608 goto err;
1610 1609
1611 to_mm->pd_dirty_rings &= ~intel_engine_flag(engine); 1610 if (intel_engine_flag(engine) & ppgtt->pd_dirty_rings) {
1612 engine->legacy_active_ppgtt = to_mm; 1611 unwind_mm = intel_engine_flag(engine);
1613 hw_flags = MI_FORCE_RESTORE; 1612 ppgtt->pd_dirty_rings &= ~unwind_mm;
1613 hw_flags = MI_FORCE_RESTORE;
1614 }
1614 } 1615 }
1615 1616
1616 if (rq->hw_context->state && 1617 if (rq->hw_context->state) {
1617 (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) {
1618 GEM_BUG_ON(engine->id != RCS); 1618 GEM_BUG_ON(engine->id != RCS);
1619 1619
1620 /* 1620 /*
@@ -1624,35 +1624,32 @@ static int switch_context(struct i915_request *rq)
1624 * as nothing actually executes using the kernel context; it 1624 * as nothing actually executes using the kernel context; it
1625 * is purely used for flushing user contexts. 1625 * is purely used for flushing user contexts.
1626 */ 1626 */
1627 if (i915_gem_context_is_kernel(to_ctx)) 1627 if (i915_gem_context_is_kernel(ctx))
1628 hw_flags = MI_RESTORE_INHIBIT; 1628 hw_flags = MI_RESTORE_INHIBIT;
1629 1629
1630 ret = mi_set_context(rq, hw_flags); 1630 ret = mi_set_context(rq, hw_flags);
1631 if (ret) 1631 if (ret)
1632 goto err_mm; 1632 goto err_mm;
1633
1634 engine->legacy_active_context = to_ctx;
1635 } 1633 }
1636 1634
1637 if (to_ctx->remap_slice) { 1635 if (ctx->remap_slice) {
1638 for (i = 0; i < MAX_L3_SLICES; i++) { 1636 for (i = 0; i < MAX_L3_SLICES; i++) {
1639 if (!(to_ctx->remap_slice & BIT(i))) 1637 if (!(ctx->remap_slice & BIT(i)))
1640 continue; 1638 continue;
1641 1639
1642 ret = remap_l3(rq, i); 1640 ret = remap_l3(rq, i);
1643 if (ret) 1641 if (ret)
1644 goto err_ctx; 1642 goto err_mm;
1645 } 1643 }
1646 1644
1647 to_ctx->remap_slice = 0; 1645 ctx->remap_slice = 0;
1648 } 1646 }
1649 1647
1650 return 0; 1648 return 0;
1651 1649
1652err_ctx:
1653 engine->legacy_active_context = from_ctx;
1654err_mm: 1650err_mm:
1655 engine->legacy_active_ppgtt = from_mm; 1651 if (unwind_mm)
1652 ppgtt->pd_dirty_rings |= unwind_mm;
1656err: 1653err:
1657 return ret; 1654 return ret;
1658} 1655}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index acef385c4c80..b44c67849749 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -557,15 +557,6 @@ struct intel_engine_cs {
557 */ 557 */
558 struct intel_context *last_retired_context; 558 struct intel_context *last_retired_context;
559 559
560 /* We track the current MI_SET_CONTEXT in order to eliminate
561 * redudant context switches. This presumes that requests are not
562 * reordered! Or when they are the tracking is updated along with
563 * the emission of individual requests into the legacy command
564 * stream (ring).
565 */
566 struct i915_gem_context *legacy_active_context;
567 struct i915_hw_ppgtt *legacy_active_ppgtt;
568
569 /* status_notifier: list of callbacks for context-switch changes */ 560 /* status_notifier: list of callbacks for context-switch changes */
570 struct atomic_notifier_head context_status_notifier; 561 struct atomic_notifier_head context_status_notifier;
571 562