aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_engine_cs.c
diff options
context:
space:
mode:
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>2017-09-13 04:56:02 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2017-09-13 10:02:39 -0400
commit486e93f72abd41559b740f017717c7f6b3f8bb1f (patch)
treecfb56f31b5e28e289fdfc76103d716dccbb0367a /drivers/gpu/drm/i915/intel_engine_cs.c
parenta922c0c7a6b7b84351c4051fc9defe1222185c16 (diff)
drm/i915/lrc: allocate separate page for HWSP
On gen8+ we're currently using the PPHWSP of the kernel ctx as the global HWSP. However, when the kernel ctx gets submitted (e.g. from __intel_autoenable_gt_powersave) the HW will use that page as both HWSP and PPHWSP. This causes a conflict in the register arena of the HWSP, i.e. dword indices below 0x30. We don't current utilize this arena, but in the following patches we will take advantage of the cached register state for handling execlist's context status interrupt. To avoid the conflict, instead of re-using the PPHWSP of the kernel ctx we can allocate a separate page for the HWSP like what happens for pre-execlists platform. v2: Add a use-case for the register arena of the HWSP. Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Michel Thierry <michel.thierry@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1499357440-34688-1-git-send-email-daniele.ceraolospurio@intel.com Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Michel Thierry <michel.thierry@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-3-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/intel_engine_cs.c')
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c126
1 files changed, 125 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 3ae89a9d6241..8a5535ad6552 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -442,6 +442,114 @@ static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
442 i915_vma_unpin_and_release(&engine->scratch); 442 i915_vma_unpin_and_release(&engine->scratch);
443} 443}
444 444
445static void cleanup_phys_status_page(struct intel_engine_cs *engine)
446{
447 struct drm_i915_private *dev_priv = engine->i915;
448
449 if (!dev_priv->status_page_dmah)
450 return;
451
452 drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
453 engine->status_page.page_addr = NULL;
454}
455
456static void cleanup_status_page(struct intel_engine_cs *engine)
457{
458 struct i915_vma *vma;
459 struct drm_i915_gem_object *obj;
460
461 vma = fetch_and_zero(&engine->status_page.vma);
462 if (!vma)
463 return;
464
465 obj = vma->obj;
466
467 i915_vma_unpin(vma);
468 i915_vma_close(vma);
469
470 i915_gem_object_unpin_map(obj);
471 __i915_gem_object_release_unless_active(obj);
472}
473
474static int init_status_page(struct intel_engine_cs *engine)
475{
476 struct drm_i915_gem_object *obj;
477 struct i915_vma *vma;
478 unsigned int flags;
479 void *vaddr;
480 int ret;
481
482 obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
483 if (IS_ERR(obj)) {
484 DRM_ERROR("Failed to allocate status page\n");
485 return PTR_ERR(obj);
486 }
487
488 ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
489 if (ret)
490 goto err;
491
492 vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
493 if (IS_ERR(vma)) {
494 ret = PTR_ERR(vma);
495 goto err;
496 }
497
498 flags = PIN_GLOBAL;
499 if (!HAS_LLC(engine->i915))
500 /* On g33, we cannot place HWS above 256MiB, so
501 * restrict its pinning to the low mappable arena.
502 * Though this restriction is not documented for
503 * gen4, gen5, or byt, they also behave similarly
504 * and hang if the HWS is placed at the top of the
505 * GTT. To generalise, it appears that all !llc
506 * platforms have issues with us placing the HWS
507 * above the mappable region (even though we never
508 * actually map it).
509 */
510 flags |= PIN_MAPPABLE;
511 ret = i915_vma_pin(vma, 0, 4096, flags);
512 if (ret)
513 goto err;
514
515 vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
516 if (IS_ERR(vaddr)) {
517 ret = PTR_ERR(vaddr);
518 goto err_unpin;
519 }
520
521 engine->status_page.vma = vma;
522 engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
523 engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE);
524
525 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
526 engine->name, i915_ggtt_offset(vma));
527 return 0;
528
529err_unpin:
530 i915_vma_unpin(vma);
531err:
532 i915_gem_object_put(obj);
533 return ret;
534}
535
536static int init_phys_status_page(struct intel_engine_cs *engine)
537{
538 struct drm_i915_private *dev_priv = engine->i915;
539
540 GEM_BUG_ON(engine->id != RCS);
541
542 dev_priv->status_page_dmah =
543 drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
544 if (!dev_priv->status_page_dmah)
545 return -ENOMEM;
546
547 engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
548 memset(engine->status_page.page_addr, 0, PAGE_SIZE);
549
550 return 0;
551}
552
445/** 553/**
446 * intel_engines_init_common - initialize cengine state which might require hw access 554 * intel_engines_init_common - initialize cengine state which might require hw access
447 * @engine: Engine to initialize. 555 * @engine: Engine to initialize.
@@ -477,10 +585,21 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
477 585
478 ret = i915_gem_render_state_init(engine); 586 ret = i915_gem_render_state_init(engine);
479 if (ret) 587 if (ret)
480 goto err_unpin; 588 goto err_breadcrumbs;
589
590 if (HWS_NEEDS_PHYSICAL(engine->i915))
591 ret = init_phys_status_page(engine);
592 else
593 ret = init_status_page(engine);
594 if (ret)
595 goto err_rs_fini;
481 596
482 return 0; 597 return 0;
483 598
599err_rs_fini:
600 i915_gem_render_state_fini(engine);
601err_breadcrumbs:
602 intel_engine_fini_breadcrumbs(engine);
484err_unpin: 603err_unpin:
485 engine->context_unpin(engine, engine->i915->kernel_context); 604 engine->context_unpin(engine, engine->i915->kernel_context);
486 return ret; 605 return ret;
@@ -497,6 +616,11 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
497{ 616{
498 intel_engine_cleanup_scratch(engine); 617 intel_engine_cleanup_scratch(engine);
499 618
619 if (HWS_NEEDS_PHYSICAL(engine->i915))
620 cleanup_phys_status_page(engine);
621 else
622 cleanup_status_page(engine);
623
500 i915_gem_render_state_fini(engine); 624 i915_gem_render_state_fini(engine);
501 intel_engine_fini_breadcrumbs(engine); 625 intel_engine_fini_breadcrumbs(engine);
502 intel_engine_cleanup_cmd_parser(engine); 626 intel_engine_cleanup_cmd_parser(engine);