drm/i915: add driver cache flush entry point
authorDave Airlie <airlied@linux.ie>
Tue, 30 Oct 2007 07:51:59 +0000 (17:51 +1000)
committerDave Airlie <airlied@optimus.(none)>
Tue, 30 Oct 2007 07:52:13 +0000 (17:52 +1000)
Use clflush on Intel hardware to flush cached objects.

linux-core/drm_objects.h
linux-core/drm_ttm.c
linux-core/i915_buffer.c
linux-core/i915_drv.c
shared-core/i915_drv.h

index 8b14ac6..cea811e 100644 (file)
@@ -464,6 +464,7 @@ struct drm_bo_driver {
         uint32_t(*evict_mask) (struct drm_buffer_object *bo);
        int (*move) (struct drm_buffer_object * bo,
                     int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
+       void (*ttm_cache_flush)(struct drm_ttm *ttm);
 };
 
 /*
index 33bbe1d..df9e7e4 100644 (file)
@@ -207,6 +207,7 @@ struct page *drm_ttm_get_page(struct drm_ttm * ttm, int index)
        }
        return p;
 }
+EXPORT_SYMBOL(drm_ttm_get_page);
 
 int drm_ttm_populate(struct drm_ttm * ttm)
 {
@@ -311,7 +312,7 @@ void drm_ttm_unbind(struct drm_ttm * ttm)
 
 int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem)
 {
-
+       struct drm_bo_driver *bo_driver = ttm->dev->driver->bo_driver;
        int ret = 0;
        struct drm_ttm_backend *be;
 
@@ -328,7 +329,9 @@ int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem)
 
        if (ttm->state == ttm_unbound && !(bo_mem->flags & DRM_BO_FLAG_CACHED)) {
                drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED);
-       }
+       } else if ((bo_mem->flags & DRM_BO_FLAG_CACHED) &&
+                  bo_driver->ttm_cache_flush)
+               bo_driver->ttm_cache_flush(ttm);
 
        if ((ret = be->func->bind(be, bo_mem))) {
                ttm->state = ttm_evicted;
index f81def8..bbc7e1d 100644 (file)
@@ -249,3 +249,36 @@ int i915_move(struct drm_buffer_object * bo,
        }
        return 0;
 }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+static inline void clflush(volatile void *__p)
+{
+       asm volatile("clflush %0" : "+m" (*(char __force *)__p));
+}
+#endif
+
+static inline void drm_cache_flush_addr(void *virt)
+{ 
+        int i;
+
+       for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+               clflush(virt+i);
+}
+
+static inline void drm_cache_flush_page(struct page *p)
+{
+       drm_cache_flush_addr(page_address(p));
+}
+
+void i915_flush_ttm(struct drm_ttm *ttm)
+{
+       int i;
+
+       if (!ttm)
+               return;
+
+       DRM_MEMORYBARRIER();
+       for (i = ttm->num_pages-1; i >= 0; i--)
+               drm_cache_flush_page(drm_ttm_get_page(ttm, i));
+       DRM_MEMORYBARRIER();
+}
index f34d218..124db68 100644 (file)
@@ -66,6 +66,7 @@ static struct drm_bo_driver i915_bo_driver = {
        .init_mem_type = i915_init_mem_type,
        .evict_mask = i915_evict_mask,
        .move = i915_move,
+       .ttm_cache_flush = i915_flush_ttm,
 };
 #endif
 
index 6716f28..9f69d84 100644 (file)
@@ -310,7 +310,7 @@ extern int i915_init_mem_type(struct drm_device *dev, uint32_t type,
 extern uint32_t i915_evict_mask(struct drm_buffer_object *bo);
 extern int i915_move(struct drm_buffer_object *bo, int evict,
                int no_wait, struct drm_bo_mem_reg *new_mem);
-
+void i915_flush_ttm(struct drm_ttm *ttm);
 #endif
 
 #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))