| @@ -208,9 +208,9 @@ · 207 unmodified lines |
| 208 | | 208 | |
| 209 | /* Typical size of the average request (2 pipecontrols and a MI_BB) */ | 209 | /* Typical size of the average request (2 pipecontrols and a MI_BB) */ |
| 210 | #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ | 210 | #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ |
| 211 | | | |
| 212 | #define WA_TAIL_DWORDS 2 | 211 | #define WA_TAIL_DWORDS 2 |
| 213 | #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) | 212 | #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) |
| | 213 | #define PREEMPT_ID 0x1 |
| 214 | | 214 | |
| 215 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, | 215 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, |
| 216 | struct intel_engine_cs *engine); | 216 | struct intel_engine_cs *engine); |
| @@ -429,6 +429,12 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq) · 212 unmodified lines |
| 429 | return ce->lrc_desc; | 429 | return ce->lrc_desc; |
| 430 | } | 430 | } |
| 431 | | 431 | |
| | 432 | static inline void elsp_write(u64 desc, u32 __iomem *elsp) |
| | 433 | { |
| | 434 | writel(upper_32_bits(desc), elsp); |
| | 435 | writel(lower_32_bits(desc), elsp); |
| | 436 | } |
| | 437 | |
| 432 | static void execlists_submit_ports(struct intel_engine_cs *engine) | 438 | static void execlists_submit_ports(struct intel_engine_cs *engine) |
| 433 | { | 439 | { |
| 434 | struct execlist_port *port = engine->execlists.port; | 440 | struct execlist_port *port = engine->execlists.port; |
| @@ -454,8 +460,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) · 19 unmodified lines |
| 454 | desc = 0; | 460 | desc = 0; |
| 455 | } | 461 | } |
| 456 | | 462 | |
| 457 | writel(upper_32_bits(desc), elsp); | 463 | elsp_write(desc, elsp); |
| 458 | writel(lower_32_bits(desc), elsp); | | |
| 459 | } | 464 | } |
| 460 | } | 465 | } |
| 461 | | 466 | |
| @@ -488,26 +493,43 @@ static void port_assign(struct execlist_port *port, · 26 unmodified lines |
| 488 | port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); | 493 | port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); |
| 489 | } | 494 | } |
| 490 | | 495 | |
| | 496 | static void inject_preempt_context(struct intel_engine_cs *engine) |
| | 497 | { |
| | 498 | struct intel_context *ce = |
| | 499 | &engine->i915->preempt_context->engine[engine->id]; |
| | 500 | u32 __iomem *elsp = |
| | 501 | engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); |
| | 502 | unsigned int n; |
| | 503 | |
| | 504 | GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); |
| | 505 | GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); |
| | 506 | |
| | 507 | memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); |
| | 508 | ce->ring->tail += WA_TAIL_BYTES; |
| | 509 | ce->ring->tail &= (ce->ring->size - 1); |
| | 510 | ce->lrc_reg_state[CTX_RING_TAIL+1] = ce->ring->tail; |
| | 511 | |
| | 512 | for (n = execlists_num_ports(&engine->execlists); --n; ) |
| | 513 | elsp_write(0, elsp); |
| | 514 | |
| | 515 | elsp_write(ce->lrc_desc, elsp); |
| | 516 | } |
| | 517 | |
| | 518 | static bool can_preempt(struct intel_engine_cs *engine) |
| | 519 | { |
| | 520 | return INTEL_INFO(engine->i915)->has_logical_ring_preemption; |
| | 521 | } |
| | 522 | |
| 491 | static void execlists_dequeue(struct intel_engine_cs *engine) | 523 | static void execlists_dequeue(struct intel_engine_cs *engine) |
| 492 | { | 524 | { |
| 493 | struct drm_i915_gem_request *last; | | |
| 494 | struct intel_engine_execlists * const execlists = &engine->execlists; | 525 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 495 | struct execlist_port *port = execlists->port; | 526 | struct execlist_port *port = execlists->port; |
| 496 | const struct execlist_port * const last_port = | 527 | const struct execlist_port * const last_port = |
| 497 | &execlists->port[execlists->port_mask]; | 528 | &execlists->port[execlists->port_mask]; |
| | 529 | struct drm_i915_gem_request *last = port_request(port); |
| 498 | struct rb_node *rb; | 530 | struct rb_node *rb; |
| 499 | bool submit = false; | 531 | bool submit = false; |
| 500 | | 532 | |
| 501 | last = port_request(port); | | |
| 502 | if (last) | | |
| 503 | /* WaIdleLiteRestore:bdw,skl | | |
| 504 | * Apply the wa NOOPs to prevent ring:HEAD == req:TAIL | | |
| 505 | * as we resubmit the request. See gen8_emit_breadcrumb() | | |
| 506 | * for where we prepare the padding after the end of the | | |
| 507 | * request. | | |
| 508 | */ | | |
| 509 | last->tail = last->wa_tail; | | |
| 510 | | | |
| 511 | /* Hardware submission is through 2 ports. Conceptually each port | 533 | /* Hardware submission is through 2 ports. Conceptually each port |
| 512 | * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is | 534 | * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is |
| 513 | * static for a context, and unique to each, so we only execute | 535 | * static for a context, and unique to each, so we only execute |
| @@ -532,7 +554,65 @@ static void execlists_dequeue(struct intel_engine_cs *engine) · 18 unmodified lines |
| 532 | spin_lock_irq(&engine->timeline->lock); | 554 | spin_lock_irq(&engine->timeline->lock); |
| 533 | rb = execlists->first; | 555 | rb = execlists->first; |
| 534 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); | 556 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
| 535 | while (rb) { | 557 | if (!rb) |
| | 558 | goto unlock; |
| | 559 | |
| | 560 | if (last) { |
| | 561 | /* |
| | 562 | * Don't resubmit or switch until all outstanding |
| | 563 | * preemptions (lite-restore) are seen. Then we |
| | 564 | * know the next preemption status we see corresponds |
| | 565 | * to this ELSP update. |
| | 566 | */ |
| | 567 | if (port_count(&port[0]) > 1) |
| | 568 | goto unlock; |
| | 569 | |
| | 570 | if (can_preempt(engine) && |
| | 571 | rb_entry(rb, struct i915_priolist, node)->priority > |
| | 572 | max(last->priotree.priority, 0)) { |
| | 573 | /* |
| | 574 | * Switch to our empty preempt context so |
| | 575 | * the state of the GPU is known (idle). |
| | 576 | */ |
| | 577 | inject_preempt_context(engine); |
| | 578 | execlists->preempt = true; |
| | 579 | goto unlock; |
| | 580 | } else { |
| | 581 | /* |
| | 582 | * In theory, we could coalesce more requests onto |
| | 583 | * the second port (the first port is active, with |
| | 584 | * no preemptions pending). However, that means we |
| | 585 | * then have to deal with the possible lite-restore |
| | 586 | * of the second port (as we submit the ELSP, there |
| | 587 | * may be a context-switch) but also we may complete |
| | 588 | * the resubmission before the context-switch. Ergo, |
| | 589 | * coalescing onto the second port will cause a |
| | 590 | * preemption event, but we cannot predict whether |
| | 591 | * that will affect port[0] or port[1]. |
| | 592 | * |
| | 593 | * If the second port is already active, we can wait |
| | 594 | * until the next context-switch before contemplating |
| | 595 | * new requests. The GPU will be busy and we should be |
| | 596 | * able to resubmit the new ELSP before it idles, |
| | 597 | * avoiding pipeline bubbles (momentary pauses where |
| | 598 | * the driver is unable to keep up the supply of new |
| | 599 | * work). |
| | 600 | */ |
| | 601 | if (port_count(&port[1])) |
| | 602 | goto unlock; |
| | 603 | |
| | 604 | /* WaIdleLiteRestore:bdw,skl |
| | 605 | * Apply the wa NOOPs to prevent |
| | 606 | * ring:HEAD == req:TAIL as we resubmit the |
| | 607 | * request. See gen8_emit_breadcrumb() for |
| | 608 | * where we prepare the padding after the |
| | 609 | * end of the request. |
| | 610 | */ |
| | 611 | last->tail = last->wa_tail; |
| | 612 | } |
| | 613 | } |
| | 614 | |
| | 615 | do { |
| 536 | struct i915_priolist *p = rb_entry(rb, typeof(*p), node); | 616 | struct i915_priolist *p = rb_entry(rb, typeof(*p), node); |
| 537 | struct drm_i915_gem_request *rq, *rn; | 617 | struct drm_i915_gem_request *rq, *rn; |
| 538 | | 618 | |
| @@ -595,11 +675,12 @@ static void execlists_dequeue(struct intel_engine_cs *engine) · 56 unmodified lines |
| 595 | INIT_LIST_HEAD(&p->requests); | 675 | INIT_LIST_HEAD(&p->requests); |
| 596 | if (p->priority != I915_PRIORITY_NORMAL) | 676 | if (p->priority != I915_PRIORITY_NORMAL) |
| 597 | kmem_cache_free(engine->i915->priorities, p); | 677 | kmem_cache_free(engine->i915->priorities, p); |
| 598 | } | 678 | } while (rb); |
| 599 | done: | 679 | done: |
| 600 | execlists->first = rb; | 680 | execlists->first = rb; |
| 601 | if (submit) | 681 | if (submit) |
| 602 | port_assign(port, last); | 682 | port_assign(port, last); |
| | 683 | unlock: |
| 603 | spin_unlock_irq(&engine->timeline->lock); | 684 | spin_unlock_irq(&engine->timeline->lock); |
| 604 | | 685 | |
| 605 | if (submit) | 686 | if (submit) |
| @@ -680,13 +761,6 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) · 74 unmodified lines |
| 680 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 761 | spin_unlock_irqrestore(&engine->timeline->lock, flags); |
| 681 | } | 762 | } |
| 682 | | 763 | |
| 683 | static bool execlists_elsp_ready(const struct intel_engine_cs *engine) | | |
| 684 | { | | |
| 685 | const struct execlist_port *port = engine->execlists.port; | | |
| 686 | | | |
| 687 | return port_count(&port[0]) + port_count(&port[1]) < 2; | | |
| 688 | } | | |
| 689 | | | |
| 690 | /* | 764 | /* |
| 691 | * Check the unread Context Status Buffers and manage the submission of new | 765 | * Check the unread Context Status Buffers and manage the submission of new |
| 692 | * contexts to the ELSP accordingly. | 766 | * contexts to the ELSP accordingly. |
| @@ -695,7 +769,7 @@ static void intel_lrc_irq_handler(unsigned long data) · 2 unmodified lines |
| 695 | { | 769 | { |
| 696 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; | 770 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; |
| 697 | struct intel_engine_execlists * const execlists = &engine->execlists; | 771 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 698 | struct execlist_port *port = execlists->port; | 772 | struct execlist_port * const port = execlists->port; |
| 699 | struct drm_i915_private *dev_priv = engine->i915; | 773 | struct drm_i915_private *dev_priv = engine->i915; |
| 700 | | 774 | |
| 701 | /* We can skip acquiring intel_runtime_pm_get() here as it was taken | 775 | /* We can skip acquiring intel_runtime_pm_get() here as it was taken |
| @@ -780,6 +854,23 @@ static void intel_lrc_irq_handler(unsigned long data) · 78 unmodified lines |
| 780 | if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) | 854 | if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) |
| 781 | continue; | 855 | continue; |
| 782 | | 856 | |
| | 857 | if (status & GEN8_CTX_STATUS_ACTIVE_IDLE && |
| | 858 | buf[2*head + 1] == PREEMPT_ID) { |
| | 859 | execlist_cancel_port_requests(execlists); |
| | 860 | |
| | 861 | spin_lock_irq(&engine->timeline->lock); |
| | 862 | unwind_incomplete_requests(engine); |
| | 863 | spin_unlock_irq(&engine->timeline->lock); |
| | 864 | |
| | 865 | GEM_BUG_ON(!execlists->preempt); |
| | 866 | execlists->preempt = false; |
| | 867 | continue; |
| | 868 | } |
| | 869 | |
| | 870 | if (status & GEN8_CTX_STATUS_PREEMPTED && |
| | 871 | execlists->preempt) |
| | 872 | continue; |
| | 873 | |
| 783 | /* Check the context/desc id for this event matches */ | 874 | /* Check the context/desc id for this event matches */ |
| 784 | GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); | 875 | GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); |
| 785 | | 876 | |
| @@ -811,7 +902,7 @@ static void intel_lrc_irq_handler(unsigned long data) · 25 unmodified lines |
| 811 | } | 902 | } |
| 812 | } | 903 | } |
| 813 | | 904 | |
| 814 | if (execlists_elsp_ready(engine)) | 905 | if (!execlists->preempt) |
| 815 | execlists_dequeue(engine); | 906 | execlists_dequeue(engine); |
| 816 | | 907 | |
| 817 | intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); | 908 | intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); |
| @@ -824,7 +915,7 @@ static void insert_request(struct intel_engine_cs *engine, · 6 unmodified lines |
| 824 | struct i915_priolist *p = lookup_priolist(engine, pt, prio); | 915 | struct i915_priolist *p = lookup_priolist(engine, pt, prio); |
| 825 | | 916 | |
| 826 | list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); | 917 | list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); |
| 827 | if (ptr_unmask_bits(p, 1) && execlists_elsp_ready(engine)) | 918 | if (ptr_unmask_bits(p, 1)) |
| 828 | tasklet_hi_schedule(&engine->execlists.irq_tasklet); | 919 | tasklet_hi_schedule(&engine->execlists.irq_tasklet); |
| 829 | } | 920 | } |
| 830 | | 921 | |
| @@ -954,8 +1045,6 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) · 123 unmodified lines |
| 954 | } | 1045 | } |
| 955 | | 1046 | |
| 956 | spin_unlock_irq(&engine->timeline->lock); | 1047 | spin_unlock_irq(&engine->timeline->lock); |
| 957 | | | |
| 958 | /* XXX Do we need to preempt to make room for us and our deps? */ | | |
| 959 | } | 1048 | } |
| 960 | | 1049 | |
| 961 | static struct intel_ring * | 1050 | static struct intel_ring * |
| @@ -1151,6 +1240,8 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) · 189 unmodified lines |
| 1151 | i915_ggtt_offset(engine->scratch) + | 1240 | i915_ggtt_offset(engine->scratch) + |
| 1152 | 2 * CACHELINE_BYTES); | 1241 | 2 * CACHELINE_BYTES); |
| 1153 | | 1242 | |
| | 1243 | *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; |
| | 1244 | |
| 1154 | /* Pad to end of cacheline */ | 1245 | /* Pad to end of cacheline */ |
| 1155 | while ((unsigned long)batch % CACHELINE_BYTES) | 1246 | while ((unsigned long)batch % CACHELINE_BYTES) |
| 1156 | *batch++ = MI_NOOP; | 1247 | *batch++ = MI_NOOP; |
| @@ -1166,6 +1257,8 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) · 9 unmodified lines |
| 1166 | | 1257 | |
| 1167 | static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) | 1258 | static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) |
| 1168 | { | 1259 | { |
| | 1260 | *batch++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; |
| | 1261 | |
| 1169 | /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */ | 1262 | /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */ |
| 1170 | batch = gen8_emit_flush_coherentl3_wa(engine, batch); | 1263 | batch = gen8_emit_flush_coherentl3_wa(engine, batch); |
| 1171 | | 1264 | |
| @@ -1211,6 +1304,8 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) · 39 unmodified lines |
| 1211 | *batch++ = 0; | 1304 | *batch++ = 0; |
| 1212 | } | 1305 | } |
| 1213 | | 1306 | |
| | 1307 | *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; |
| | 1308 | |
| 1214 | /* Pad to end of cacheline */ | 1309 | /* Pad to end of cacheline */ |
| 1215 | while ((unsigned long)batch % CACHELINE_BYTES) | 1310 | while ((unsigned long)batch % CACHELINE_BYTES) |
| 1216 | *batch++ = MI_NOOP; | 1311 | *batch++ = MI_NOOP; |
| @@ -1364,6 +1459,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) · 147 unmodified lines |
| 1364 | GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); | 1459 | GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); |
| 1365 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 1460 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); |
| 1366 | execlists->csb_head = -1; | 1461 | execlists->csb_head = -1; |
| | 1462 | execlists->preempt = false; |
| 1367 | | 1463 | |
| 1368 | /* After a GPU reset, we may have requests to replay */ | 1464 | /* After a GPU reset, we may have requests to replay */ |
| 1369 | if (!i915_modparams.enable_guc_submission && execlists->first) | 1465 | if (!i915_modparams.enable_guc_submission && execlists->first) |
| @@ -1659,7 +1755,8 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, · 289 unmodified lines |
| 1659 | */ | 1755 | */ |
| 1660 | static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *cs) | 1756 | static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *cs) |
| 1661 | { | 1757 | { |
| 1662 | *cs++ = MI_NOOP; | 1758 | /* Ensure there's always at least one preemption point per-request. */ |
| | 1759 | *cs++ = MI_ARB_CHECK; |
| 1663 | *cs++ = MI_NOOP; | 1760 | *cs++ = MI_NOOP; |
| 1664 | request->wa_tail = intel_ring_offset(request, cs); | 1761 | request->wa_tail = intel_ring_offset(request, cs); |
| 1665 | } | 1762 | } |
| @@ -1680,7 +1777,6 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs) · 14 unmodified lines |
| 1680 | | 1777 | |
| 1681 | gen8_emit_wa_tail(request, cs); | 1778 | gen8_emit_wa_tail(request, cs); |
| 1682 | } | 1779 | } |
| 1683 | | | |
| 1684 | static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; | 1780 | static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; |
| 1685 | | 1781 | |
| 1686 | static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, | 1782 | static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, |
| @@ -1708,7 +1804,6 @@ static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, · 21 unmodified lines |
| 1708 | | 1804 | |
| 1709 | gen8_emit_wa_tail(request, cs); | 1805 | gen8_emit_wa_tail(request, cs); |
| 1710 | } | 1806 | } |
| 1711 | | | |
| 1712 | static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; | 1807 | static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; |
| 1713 | | 1808 | |
| 1714 | static int gen8_init_rcs_context(struct drm_i915_gem_request *req) | 1809 | static int gen8_init_rcs_context(struct drm_i915_gem_request *req) |