aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c194
1 files changed, 54 insertions, 140 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index cdf084ef5aae..8da1bde442dd 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -402,17 +402,18 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
402 */ 402 */
403 if (IS_GEN7(dev_priv)) { 403 if (IS_GEN7(dev_priv)) {
404 switch (engine->id) { 404 switch (engine->id) {
405 /*
406 * No more rings exist on Gen7. Default case is only to shut up
407 * gcc switch check warning.
408 */
409 default:
410 GEM_BUG_ON(engine->id);
405 case RCS: 411 case RCS:
406 mmio = RENDER_HWS_PGA_GEN7; 412 mmio = RENDER_HWS_PGA_GEN7;
407 break; 413 break;
408 case BCS: 414 case BCS:
409 mmio = BLT_HWS_PGA_GEN7; 415 mmio = BLT_HWS_PGA_GEN7;
410 break; 416 break;
411 /*
412 * VCS2 actually doesn't exist on Gen7. Only shut up
413 * gcc switch check warning
414 */
415 case VCS2:
416 case VCS: 417 case VCS:
417 mmio = BSD_HWS_PGA_GEN7; 418 mmio = BSD_HWS_PGA_GEN7;
418 break; 419 break;
@@ -427,6 +428,9 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
427 mmio = RING_HWS_PGA(engine->mmio_base); 428 mmio = RING_HWS_PGA(engine->mmio_base);
428 } 429 }
429 430
431 if (INTEL_GEN(dev_priv) >= 6)
432 I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
433
430 I915_WRITE(mmio, engine->status_page.ggtt_offset); 434 I915_WRITE(mmio, engine->status_page.ggtt_offset);
431 POSTING_READ(mmio); 435 POSTING_READ(mmio);
432 436
@@ -480,11 +484,6 @@ static bool stop_ring(struct intel_engine_cs *engine)
480 I915_WRITE_HEAD(engine, 0); 484 I915_WRITE_HEAD(engine, 0);
481 I915_WRITE_TAIL(engine, 0); 485 I915_WRITE_TAIL(engine, 0);
482 486
483 if (INTEL_GEN(dev_priv) > 2) {
484 (void)I915_READ_CTL(engine);
485 I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
486 }
487
488 return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 487 return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
489} 488}
490 489
@@ -566,6 +565,9 @@ static int init_ring_common(struct intel_engine_cs *engine)
566 565
567 intel_engine_init_hangcheck(engine); 566 intel_engine_init_hangcheck(engine);
568 567
568 if (INTEL_GEN(dev_priv) > 2)
569 I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
570
569out: 571out:
570 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 572 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
571 573
@@ -575,7 +577,16 @@ out:
575static void reset_ring_common(struct intel_engine_cs *engine, 577static void reset_ring_common(struct intel_engine_cs *engine,
576 struct drm_i915_gem_request *request) 578 struct drm_i915_gem_request *request)
577{ 579{
578 /* Try to restore the logical GPU state to match the continuation 580 /*
581 * RC6 must be prevented until the reset is complete and the engine
582 * reinitialised. If it occurs in the middle of this sequence, the
583 * state written to/loaded from the power context is ill-defined (e.g.
584 * the PP_BASE_DIR may be lost).
585 */
586 assert_forcewakes_active(engine->i915, FORCEWAKE_ALL);
587
588 /*
589 * Try to restore the logical GPU state to match the continuation
579 * of the request queue. If we skip the context/PD restore, then 590 * of the request queue. If we skip the context/PD restore, then
580 * the next request may try to execute assuming that its context 591 * the next request may try to execute assuming that its context
581 * is valid and loaded on the GPU and so may try to access invalid 592 * is valid and loaded on the GPU and so may try to access invalid
@@ -778,6 +789,24 @@ static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs)
778 return cs; 789 return cs;
779} 790}
780 791
792static void cancel_requests(struct intel_engine_cs *engine)
793{
794 struct drm_i915_gem_request *request;
795 unsigned long flags;
796
797 spin_lock_irqsave(&engine->timeline->lock, flags);
798
799 /* Mark all submitted requests as skipped. */
800 list_for_each_entry(request, &engine->timeline->requests, link) {
801 GEM_BUG_ON(!request->global_seqno);
802 if (!i915_gem_request_completed(request))
803 dma_fence_set_error(&request->fence, -EIO);
804 }
805 /* Remaining _unready_ requests will be nop'ed when submitted */
806
807 spin_unlock_irqrestore(&engine->timeline->lock, flags);
808}
809
781static void i9xx_submit_request(struct drm_i915_gem_request *request) 810static void i9xx_submit_request(struct drm_i915_gem_request *request)
782{ 811{
783 struct drm_i915_private *dev_priv = request->i915; 812 struct drm_i915_private *dev_priv = request->i915;
@@ -1174,113 +1203,7 @@ i915_emit_bb_start(struct drm_i915_gem_request *req,
1174 return 0; 1203 return 0;
1175} 1204}
1176 1205
1177static void cleanup_phys_status_page(struct intel_engine_cs *engine)
1178{
1179 struct drm_i915_private *dev_priv = engine->i915;
1180
1181 if (!dev_priv->status_page_dmah)
1182 return;
1183
1184 drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
1185 engine->status_page.page_addr = NULL;
1186}
1187
1188static void cleanup_status_page(struct intel_engine_cs *engine)
1189{
1190 struct i915_vma *vma;
1191 struct drm_i915_gem_object *obj;
1192
1193 vma = fetch_and_zero(&engine->status_page.vma);
1194 if (!vma)
1195 return;
1196
1197 obj = vma->obj;
1198
1199 i915_vma_unpin(vma);
1200 i915_vma_close(vma);
1201
1202 i915_gem_object_unpin_map(obj);
1203 __i915_gem_object_release_unless_active(obj);
1204}
1205
1206static int init_status_page(struct intel_engine_cs *engine)
1207{
1208 struct drm_i915_gem_object *obj;
1209 struct i915_vma *vma;
1210 unsigned int flags;
1211 void *vaddr;
1212 int ret;
1213
1214 obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
1215 if (IS_ERR(obj)) {
1216 DRM_ERROR("Failed to allocate status page\n");
1217 return PTR_ERR(obj);
1218 }
1219
1220 ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1221 if (ret)
1222 goto err;
1223
1224 vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
1225 if (IS_ERR(vma)) {
1226 ret = PTR_ERR(vma);
1227 goto err;
1228 }
1229
1230 flags = PIN_GLOBAL;
1231 if (!HAS_LLC(engine->i915))
1232 /* On g33, we cannot place HWS above 256MiB, so
1233 * restrict its pinning to the low mappable arena.
1234 * Though this restriction is not documented for
1235 * gen4, gen5, or byt, they also behave similarly
1236 * and hang if the HWS is placed at the top of the
1237 * GTT. To generalise, it appears that all !llc
1238 * platforms have issues with us placing the HWS
1239 * above the mappable region (even though we never
1240 * actualy map it).
1241 */
1242 flags |= PIN_MAPPABLE;
1243 ret = i915_vma_pin(vma, 0, 4096, flags);
1244 if (ret)
1245 goto err;
1246
1247 vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
1248 if (IS_ERR(vaddr)) {
1249 ret = PTR_ERR(vaddr);
1250 goto err_unpin;
1251 }
1252
1253 engine->status_page.vma = vma;
1254 engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
1255 engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE);
1256
1257 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
1258 engine->name, i915_ggtt_offset(vma));
1259 return 0;
1260
1261err_unpin:
1262 i915_vma_unpin(vma);
1263err:
1264 i915_gem_object_put(obj);
1265 return ret;
1266}
1267
1268static int init_phys_status_page(struct intel_engine_cs *engine)
1269{
1270 struct drm_i915_private *dev_priv = engine->i915;
1271
1272 GEM_BUG_ON(engine->id != RCS);
1273
1274 dev_priv->status_page_dmah =
1275 drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
1276 if (!dev_priv->status_page_dmah)
1277 return -ENOMEM;
1278
1279 engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
1280 memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1281 1206
1282 return 0;
1283}
1284 1207
1285int intel_ring_pin(struct intel_ring *ring, 1208int intel_ring_pin(struct intel_ring *ring,
1286 struct drm_i915_private *i915, 1209 struct drm_i915_private *i915,
@@ -1321,6 +1244,8 @@ int intel_ring_pin(struct intel_ring *ring,
1321 if (IS_ERR(addr)) 1244 if (IS_ERR(addr))
1322 goto err; 1245 goto err;
1323 1246
1247 vma->obj->pin_global++;
1248
1324 ring->vaddr = addr; 1249 ring->vaddr = addr;
1325 return 0; 1250 return 0;
1326 1251
@@ -1352,6 +1277,7 @@ void intel_ring_unpin(struct intel_ring *ring)
1352 i915_gem_object_unpin_map(ring->vma->obj); 1277 i915_gem_object_unpin_map(ring->vma->obj);
1353 ring->vaddr = NULL; 1278 ring->vaddr = NULL;
1354 1279
1280 ring->vma->obj->pin_global--;
1355 i915_vma_unpin(ring->vma); 1281 i915_vma_unpin(ring->vma);
1356} 1282}
1357 1283
@@ -1516,6 +1442,7 @@ intel_ring_context_pin(struct intel_engine_cs *engine,
1516 goto err; 1442 goto err;
1517 1443
1518 ce->state->obj->mm.dirty = true; 1444 ce->state->obj->mm.dirty = true;
1445 ce->state->obj->pin_global++;
1519 } 1446 }
1520 1447
1521 /* The kernel context is only used as a placeholder for flushing the 1448 /* The kernel context is only used as a placeholder for flushing the
@@ -1550,8 +1477,10 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine,
1550 if (--ce->pin_count) 1477 if (--ce->pin_count)
1551 return; 1478 return;
1552 1479
1553 if (ce->state) 1480 if (ce->state) {
1481 ce->state->obj->pin_global--;
1554 i915_vma_unpin(ce->state); 1482 i915_vma_unpin(ce->state);
1483 }
1555 1484
1556 i915_gem_context_put(ctx); 1485 i915_gem_context_put(ctx);
1557} 1486}
@@ -1567,17 +1496,10 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
1567 if (err) 1496 if (err)
1568 goto err; 1497 goto err;
1569 1498
1570 if (HWS_NEEDS_PHYSICAL(engine->i915))
1571 err = init_phys_status_page(engine);
1572 else
1573 err = init_status_page(engine);
1574 if (err)
1575 goto err;
1576
1577 ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); 1499 ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
1578 if (IS_ERR(ring)) { 1500 if (IS_ERR(ring)) {
1579 err = PTR_ERR(ring); 1501 err = PTR_ERR(ring);
1580 goto err_hws; 1502 goto err;
1581 } 1503 }
1582 1504
1583 /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 1505 /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
@@ -1592,11 +1514,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
1592 1514
1593err_ring: 1515err_ring:
1594 intel_ring_free(ring); 1516 intel_ring_free(ring);
1595err_hws:
1596 if (HWS_NEEDS_PHYSICAL(engine->i915))
1597 cleanup_phys_status_page(engine);
1598 else
1599 cleanup_status_page(engine);
1600err: 1517err:
1601 intel_engine_cleanup_common(engine); 1518 intel_engine_cleanup_common(engine);
1602 return err; 1519 return err;
@@ -1615,11 +1532,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
1615 if (engine->cleanup) 1532 if (engine->cleanup)
1616 engine->cleanup(engine); 1533 engine->cleanup(engine);
1617 1534
1618 if (HWS_NEEDS_PHYSICAL(dev_priv))
1619 cleanup_phys_status_page(engine);
1620 else
1621 cleanup_status_page(engine);
1622
1623 intel_engine_cleanup_common(engine); 1535 intel_engine_cleanup_common(engine);
1624 1536
1625 dev_priv->engine[engine->id] = NULL; 1537 dev_priv->engine[engine->id] = NULL;
@@ -1983,7 +1895,7 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
1983 struct drm_i915_gem_object *obj; 1895 struct drm_i915_gem_object *obj;
1984 int ret, i; 1896 int ret, i;
1985 1897
1986 if (!i915.semaphores) 1898 if (!i915_modparams.semaphores)
1987 return; 1899 return;
1988 1900
1989 if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { 1901 if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) {
@@ -2083,7 +1995,7 @@ err_obj:
2083 i915_gem_object_put(obj); 1995 i915_gem_object_put(obj);
2084err: 1996err:
2085 DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); 1997 DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n");
2086 i915.semaphores = 0; 1998 i915_modparams.semaphores = 0;
2087} 1999}
2088 2000
2089static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 2001static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
@@ -2115,11 +2027,13 @@ static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
2115static void i9xx_set_default_submission(struct intel_engine_cs *engine) 2027static void i9xx_set_default_submission(struct intel_engine_cs *engine)
2116{ 2028{
2117 engine->submit_request = i9xx_submit_request; 2029 engine->submit_request = i9xx_submit_request;
2030 engine->cancel_requests = cancel_requests;
2118} 2031}
2119 2032
2120static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) 2033static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine)
2121{ 2034{
2122 engine->submit_request = gen6_bsd_submit_request; 2035 engine->submit_request = gen6_bsd_submit_request;
2036 engine->cancel_requests = cancel_requests;
2123} 2037}
2124 2038
2125static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 2039static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
@@ -2138,7 +2052,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
2138 2052
2139 engine->emit_breadcrumb = i9xx_emit_breadcrumb; 2053 engine->emit_breadcrumb = i9xx_emit_breadcrumb;
2140 engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; 2054 engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz;
2141 if (i915.semaphores) { 2055 if (i915_modparams.semaphores) {
2142 int num_rings; 2056 int num_rings;
2143 2057
2144 engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; 2058 engine->emit_breadcrumb = gen6_sema_emit_breadcrumb;
@@ -2182,7 +2096,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
2182 engine->emit_breadcrumb = gen8_render_emit_breadcrumb; 2096 engine->emit_breadcrumb = gen8_render_emit_breadcrumb;
2183 engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; 2097 engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz;
2184 engine->emit_flush = gen8_render_ring_flush; 2098 engine->emit_flush = gen8_render_ring_flush;
2185 if (i915.semaphores) { 2099 if (i915_modparams.semaphores) {
2186 int num_rings; 2100 int num_rings;
2187 2101
2188 engine->semaphore.signal = gen8_rcs_signal; 2102 engine->semaphore.signal = gen8_rcs_signal;