From: <ai...@fr...> - 2007-10-14 23:18:10
|
linux-core/drm_objects.h | 2 +- linux-core/drm_ttm.c | 41 ++++++++++++++++++++++++++++++----------- shared-core/i915_dma.c | 37 ++++++++++++++++++++++++++++++++----- shared-core/i915_drv.h | 1 + 4 files changed, 64 insertions(+), 17 deletions(-) New commits: commit b25ae705cee390e885716fc270dabc4d65af1db3 Author: Dave Airlie <ai...@re...> Date: Mon Oct 15 09:01:32 2007 +1000 try adding sfence diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index ffee05b..058559f 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -386,9 +386,10 @@ void drm_flush_ttm_caches(struct drm_buffer_object **buffers, int num_buffers, i info.buffers = buffers; info.num_buffers = num_buffers; - if (!on_cpu) + if (!on_cpu) { drm_ttm_flush_ipi_handler(&info); - else + asm volatile("sfence" ::: "memory"); + } else if (on_each_cpu(drm_ttm_flush_ipi_handler, &info, 1, 1) != 0) DRM_ERROR("Timed out waiting for cache flush\n"); commit 17a986ae6fe3b87681aebd5e2e74a43ee1f4bf08 Author: Dave Airlie <ai...@re...> Date: Mon Oct 15 08:52:07 2007 +1000 further batchbuffer flush "hacks" diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 9748baa..bd3d467 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -392,7 +392,7 @@ struct drm_buffer_object { unsigned long bus_offset; uint32_t vm_flags; void *iomap; - + int need_flush; #ifdef DRM_ODD_MM_COMPAT /* dev->struct_mutex only protected. */ struct list_head vma_list; diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index b50733d..ffee05b 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -351,28 +351,46 @@ static void cache_flush_page(struct page *p) asm volatile("clflush (%0)" :: "r" (adr + i)); } +struct flush_info { + struct drm_buffer_object **buffers; + int num_buffers; +}; + static void drm_ttm_flush_ipi_handler(void *data) { - struct drm_ttm *ttm = (struct drm_ttm *)data; - int i; + struct flush_info *info = (struct flush_info *)data; struct page *page; + int i, j; + struct drm_ttm *ttm; if (cpu_has_clflush) { - for (i = 0; i < ttm->num_pages; i++) { - page = drm_ttm_get_page(ttm, i); - cache_flush_page(page); + for (i = 0; i < info->num_buffers; i++) { + if (info->buffers[i]->need_flush) { + ttm = info->buffers[i]->ttm; + if (!ttm) + continue; + for (j = 0; j < ttm->num_pages; j++) { + page = drm_ttm_get_page(ttm, j); + cache_flush_page(page); + } + } } } else if (boot_cpu_data.x86_model >= 4) - wbinvd(); + wbinvd(); } -void drm_flush_ttm_caches(struct drm_ttm *ttm) +void drm_flush_ttm_caches(struct drm_buffer_object **buffers, int num_buffers, int on_cpu) { - if (!ttm) - return; + struct flush_info info; + + info.buffers = buffers; + info.num_buffers = num_buffers; - if (on_each_cpu(drm_ttm_flush_ipi_handler, ttm, 1, 1) != 0) - DRM_ERROR("Timed out waiting for cache flush\n"); + if (!on_cpu) + drm_ttm_flush_ipi_handler(&info); + else + if (on_each_cpu(drm_ttm_flush_ipi_handler, &info, 1, 1) != 0) + DRM_ERROR("Timed out waiting for cache flush\n"); } EXPORT_SYMBOL(drm_flush_ttm_caches); diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index aff22ab..ed4d6cf 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -165,6 +165,7 @@ static int i915_initialize(struct drm_device * dev, dev_priv->ring.map.flags = 0; dev_priv->ring.map.mtrr = 0; + DRM_SPININIT(&dev_priv->reloc_lock,"reloc"); drm_core_ioremap(&dev_priv->ring.map, dev); if (dev_priv->ring.map.handle == NULL) { @@ -933,6 +934,8 @@ int i915_validate_buffer_list(struct drm_file *file_priv, goto out_err; } + if (buffers[buf_count]->mem.flags & DRM_BO_FLAG_CACHED) + buffers[buf_count]->need_flush = 1; next = arg.next; arg.handled = 1; @@ -969,7 +972,23 @@ int i915_validate_buffer_list(struct drm_file *file_priv, if (ret) goto out_err; + } else { + if (buffers[buf_count-1]->need_flush) { + struct drm_bo_kmap_obj my_kmap; + volatile int tmp; + char *virtp; + int is_iomem; + int i, j; + /* try to do something heinously evil.. */ + for (i = 0; i < buffers[buf_count-1]->num_pages; i++) { + drm_bo_kmap(buffers[buf_count-1], i, 1, &my_kmap); + virtp = drm_bmo_virtual(&my_kmap, &is_iomem); + for (j = 0; j < PAGE_SIZE; j += boot_cpu_data.x86_clflush_size) + tmp = virtp[j]; + drm_bo_kunmap(&my_kmap); + } + } } } while (next != 0); *num_buffers = buf_count; @@ -981,9 +1000,7 @@ out_err: *num_buffers = 0; return (ret) ? ret : rep.ret; } - -extern void drm_flush_ttm_caches(struct drm_ttm *ttm); - +extern void drm_flush_ttm_caches(struct drm_buffer_object **buffers, int num_buffers, int on_cpu); static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -998,6 +1015,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, int ret; struct drm_buffer_object **buffers; struct drm_fence_object *fence; + int i; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); @@ -1021,14 +1039,23 @@ static int i915_execbuffer(struct drm_device *dev, void *data, if (!buffers) return -ENOMEM; + //DRM_SPINLOCK(&dev_priv->reloc_lock); + preempt_disable(); /* validate buffer list + fixup relocations */ ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, buffers, &num_buffers); - if (ret) + if (ret) { + preempt_enable(); + // DRM_SPINUNLOCK(&dev_priv->reloc_lock); goto out_free; + } + buffers[num_buffers-1]->need_flush = 1; /* flush the kernel mappings for pages in this buffer */ - drm_flush_ttm_caches(buffers[num_buffers-1]->ttm); + drm_flush_ttm_caches(buffers, num_buffers, 0); + + preempt_enable(); + //DRM_SPINUNLOCK(&dev_priv->reloc_lock); /* submit buffer */ batch->start = buffers[num_buffers-1]->offset; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index e8f1879..a2a27ee 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -139,6 +139,7 @@ typedef struct drm_i915_private { #ifdef I915_HAVE_BUFFER void *agp_iomap; unsigned int max_validate_buffers; + DRM_SPINTYPE reloc_lock; #endif DRM_SPINTYPE swaps_lock; |