summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2006-02-26 04:46:35 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2006-02-26 04:46:35 +0000
commit6c086f1975399cd51046ad04cb77a9cb32d6b11b (patch)
tree842714056b85dfe218a31e45126abf3370c5a0ad
parent5ffd44d7611b5c20faa614f350fd86c280430a7c (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.c15
-rw-r--r--shared-core/drm.h2
-rw-r--r--shared-core/i915_dma.c10
-rw-r--r--shared-core/i915_drv.h4
-rw-r--r--shared-core/i915_irq.c38
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;
}