aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-09-03 11:23:04 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2018-09-03 12:55:59 -0400
commitd6acae363e63d655ba892c139ba14f24206462c0 (patch)
treef92ecf6401109a9f619448ded1dd5f49e5567e8a
parenta0e731f4e26c4d774e71f9e69fff3e88d49dd34f (diff)
drm/i915: Use a cached mapping for the physical HWS
Older gen use a physical address for the hardware status page, for which we use cache-coherent writes. As the writes are into the cpu cache, we use a normal WB mapped page to read the HWS, used for our seqno tracking. Anecdotally, I observed lost breadcrumbs writes into the HWS on i965gm, which so far have not reoccurred with this patch. How reliable that evidence is remains to be seen. v2: Explicitly pass the expected physical address to the hw v3: Also remember the wild writes we once had for HWS above 4G. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Daniel Vetter <daniel@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20180903152304.31589-2-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c25
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c7
3 files changed, 18 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9771f39d99b3..5a4da5b723fd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1666,7 +1666,6 @@ struct drm_i915_private {
1666 struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1] 1666 struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1]
1667 [MAX_ENGINE_INSTANCE + 1]; 1667 [MAX_ENGINE_INSTANCE + 1];
1668 1668
1669 struct drm_dma_handle *status_page_dmah;
1670 struct resource mch_res; 1669 struct resource mch_res;
1671 1670
1672 /* protects the irq masks */ 1671 /* protects the irq masks */
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 292eae19fce2..10cd051ba29e 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -532,11 +532,11 @@ void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
532 532
533static void cleanup_status_page(struct intel_engine_cs *engine) 533static void cleanup_status_page(struct intel_engine_cs *engine)
534{ 534{
535 struct drm_dma_handle *dmah; 535 if (HWS_NEEDS_PHYSICAL(engine->i915)) {
536 void *addr = fetch_and_zero(&engine->status_page.page_addr);
536 537
537 dmah = fetch_and_zero(&engine->i915->status_page_dmah); 538 __free_page(virt_to_page(addr));
538 if (dmah) 539 }
539 drm_pci_free(&engine->i915->drm, dmah);
540 540
541 i915_vma_unpin_and_release(&engine->status_page.vma, 541 i915_vma_unpin_and_release(&engine->status_page.vma,
542 I915_VMA_RELEASE_MAP); 542 I915_VMA_RELEASE_MAP);
@@ -605,17 +605,18 @@ err:
605 605
606static int init_phys_status_page(struct intel_engine_cs *engine) 606static int init_phys_status_page(struct intel_engine_cs *engine)
607{ 607{
608 struct drm_i915_private *dev_priv = engine->i915; 608 struct page *page;
609
610 GEM_BUG_ON(engine->id != RCS);
611 609
612 dev_priv->status_page_dmah = 610 /*
613 drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 611 * Though the HWS register does support 36bit addresses, historically
614 if (!dev_priv->status_page_dmah) 612 * we have had hangs and corruption reported due to wild writes if
613 * the HWS is placed above 4G.
614 */
615 page = alloc_page(GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO);
616 if (!page)
615 return -ENOMEM; 617 return -ENOMEM;
616 618
617 engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 619 engine->status_page.page_addr = page_address(page);
618 memset(engine->status_page.page_addr, 0, PAGE_SIZE);
619 620
620 return 0; 621 return 0;
621} 622}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 44432677160c..86604dd1c5a5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -344,11 +344,14 @@ gen7_render_ring_flush(struct i915_request *rq, u32 mode)
344static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 344static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
345{ 345{
346 struct drm_i915_private *dev_priv = engine->i915; 346 struct drm_i915_private *dev_priv = engine->i915;
347 struct page *page = virt_to_page(engine->status_page.page_addr);
348 phys_addr_t phys = PFN_PHYS(page_to_pfn(page));
347 u32 addr; 349 u32 addr;
348 350
349 addr = dev_priv->status_page_dmah->busaddr; 351 addr = lower_32_bits(phys);
350 if (INTEL_GEN(dev_priv) >= 4) 352 if (INTEL_GEN(dev_priv) >= 4)
351 addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 353 addr |= (phys >> 28) & 0xf0;
354
352 I915_WRITE(HWS_PGA, addr); 355 I915_WRITE(HWS_PGA, addr);
353} 356}
354 357