diff options
author | Thomas Hellstrom <unichrome@shipmail.org> | 2006-02-26 04:46:35 +0000 |
---|---|---|
committer | Thomas Hellstrom <unichrome@shipmail.org> | 2006-02-26 04:46:35 +0000 |
commit | 6c086f1975399cd51046ad04cb77a9cb32d6b11b (patch) | |
tree | 842714056b85dfe218a31e45126abf3370c5a0ad | |
parent | 5ffd44d7611b5c20faa614f350fd86c280430a7c (diff) |
ttm: Fix lockup on premature client exit (fencing problem). Unmap backdoor
pages before unbinding. Really unbind pages when destroying a TTM.
-rw-r--r-- | linux-core/drm_ttm.c | 15 | ||||
-rw-r--r-- | shared-core/drm.h | 2 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 10 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 4 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 38 |
5 files changed, 49 insertions, 20 deletions
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 432a848c..20aa2f92 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -148,6 +148,7 @@ static void drm_change_protection(struct vm_area_struct *vma, continue; change_pud_range(mm, pgd, addr, next, newprot, unmap); } while (pgd++, addr = next, addr != end); + global_flush_tlb(); } /* @@ -415,8 +416,10 @@ void drm_unbind_ttm_region(drm_ttm_backend_list_t * entry) if (be) { switch (entry->state) { case ttm_bound: - be->unbind(entry->be); - /* Fall through */ + if (ttm && be->needs_cache_adjust(be)) + unmap_vma_pages(ttm, entry->page_offset, entry->num_pages); + be->unbind(entry->be); + /* Fall through */ case ttm_evicted: if (ttm && be->needs_cache_adjust(be)) { drm_set_caching(ttm, entry->page_offset, @@ -442,6 +445,7 @@ void drm_destroy_ttm_region(drm_ttm_backend_list_t * entry) list_del(&entry->head); remove_ttm_region(entry); + drm_unbind_ttm_region(entry); if (be) { be->clear(entry->be); if (be->needs_cache_adjust(be)) { @@ -571,9 +575,7 @@ int drm_bind_ttm_region(drm_ttm_backend_list_t * region, if (ttm && be->needs_cache_adjust(be)) { drm_set_caching(ttm, region->page_offset, region->num_pages, DRM_TTM_PAGE_UNCACHED); - } else { - flush_cache_all(); - } + } if ((ret = be->bind(be, aper_offset))) { drm_unbind_ttm_region(region); @@ -615,9 +617,6 @@ int drm_evict_ttm_region(drm_ttm_backend_list_t * entry) if (ttm && be->needs_cache_adjust(be)) { unmap_vma_pages(ttm, entry->page_offset, entry->num_pages); - /* - * FIXME: Add partial tlb flush here. - */ } if (0 != (ret = entry->be->unbind(entry->be))) { diff --git a/shared-core/drm.h b/shared-core/drm.h index 29ae21e4..342976c4 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -638,7 +638,7 @@ typedef struct drm_set_version { #define DRM_TTM_FLAG_PINNED 0x02 #define DRM_TTM_FLAG_CACHED 0x04 -#define DRM_TTM_MAX_BUF_BATCH 20 +#define DRM_TTM_MAX_BUF_BATCH 32 typedef struct drm_ttm_buf_arg { diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 1f8e7df8..100c55e2 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -805,18 +805,20 @@ void i915_emit_mi_flush(drm_device_t *dev, int flush) flush_cmd |= MI_READ_FLUSH; if (!(flush & DRM_FLUSH_WRITE)) flush_cmd |= MI_NO_WRITE_FLUSH; + if (flush & DRM_FLUSH_EXE) + flush_cmd |= MI_EXE_FLUSH; dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; - BEGIN_LP_RING(4); + i915_kernel_lost_context(dev); + + BEGIN_LP_RING(8); OUT_RING(flush_cmd); OUT_RING(0); + OUT_RING(0); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(20); OUT_RING(dev_priv->counter); OUT_RING(0); - OUT_RING(0); - OUT_RING(GFX_OP_USER_INTERRUPT); ADVANCE_LP_RING(); } - diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 157a8bd3..f99fcec3 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -115,7 +115,6 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern void i915_emit_mi_flush(drm_device_t *dev, int flush); - /* i915_irq.c */ extern int i915_irq_emit(DRM_IOCTL_ARGS); extern int i915_irq_wait(DRM_IOCTL_ARGS); @@ -195,6 +194,7 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define CMD_MI_FLUSH (0x04 << 23) #define MI_NO_WRITE_FLUSH (1 << 2) #define MI_READ_FLUSH (1 << 0) +#define MI_EXE_FLUSH (1 << 1) #define BB1_START_ADDR_MASK (~0x7) #define BB1_PROTECTED (1<<0) @@ -284,6 +284,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) -#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) +#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5]) #endif diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 5b58d979..e7048d90 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -212,19 +212,47 @@ void i915_driver_irq_uninstall(drm_device_t * dev) uint32_t i915_emit_fence(drm_device_t * dev) { - return i915_emit_irq(dev); + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (!dev_priv) + return 0; + + i915_emit_mi_flush(dev, DRM_FLUSH_READ | DRM_FLUSH_EXE); + return dev_priv->counter; + } int i915_test_fence(drm_device_t * dev, uint32_t fence) { + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - return ((((uint32_t)(READ_BREADCRUMB(dev_priv))) - fence) < (1 << 23)); + uint32_t test; + + if (!dev_priv) + return TRUE; + + test = (((uint32_t)(READ_BREADCRUMB(dev_priv))) - fence); + return (test < (1 << 23)); } +/* + * Temporarily use polling here: + */ + int i915_wait_fence(drm_device_t * dev, uint32_t fence) { - if (i915_test_fence( dev, fence)) + int i; + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (dev_priv) return 0; - i915_emit_irq(dev); - return i915_wait_irq(dev, fence); + + for (i=0; i<10000000; ++i) { + if ( i915_test_fence( dev, fence)) + return 0; + } + + DRM_ERROR("Fence timeout %d %d\n", READ_BREADCRUMB(dev_priv), fence); + + return 1; } |