summaryrefslogtreecommitdiff
path: root/linux-core/drm_ttm.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2008-04-28 12:10:44 +0200
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2008-04-28 12:10:44 +0200
commit7f269bec7ed49385de394fdbd970f463ef2060f0 (patch)
tree8c45f8c2e11cf101350272f81892cf4cf7678c3a /linux-core/drm_ttm.c
parent55a9941977953d16b36bbf3e1dcad392ac70e1ef (diff)
parent7f8e4060859651993921281445ec00940c577222 (diff)
Merge branch 'master' into modesetting-101
Conflicts: linux-core/Makefile.kernel linux-core/drm_compat.c linux-core/drm_fops.c linux-core/drm_lock.c shared-core/drm.h shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c
Diffstat (limited to 'linux-core/drm_ttm.c')
-rw-r--r--linux-core/drm_ttm.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index e991254f..80a8ff5d 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -30,13 +30,48 @@
#include "drmP.h"
+#if defined( CONFIG_X86 ) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+static void drm_clflush_page(struct page *page)
+{
+ uint8_t *page_virtual;
+ unsigned int i;
+
+ if (unlikely(page == NULL))
+ return;
+
+ page_virtual = kmap_atomic(page, KM_USER0);
+
+ for (i=0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+ clflush(page_virtual + i);
+
+ kunmap_atomic(page_virtual, KM_USER0);
+}
+
+static void drm_ttm_cache_flush_clflush(struct page *pages[], unsigned long num_pages)
+{
+ unsigned long i;
+
+ mb();
+ for (i=0; i < num_pages; ++i)
+ drm_clflush_page(*pages++);
+ mb();
+}
+#endif
+
static void drm_ttm_ipi_handler(void *null)
{
flush_agp_cache();
}
-void drm_ttm_cache_flush(void)
+void drm_ttm_cache_flush(struct page *pages[], unsigned long num_pages)
{
+
+#if defined( CONFIG_X86 ) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ if (cpu_has_clflush) {
+ drm_ttm_cache_flush_clflush(pages, num_pages);
+ return;
+ }
+#endif
if (on_each_cpu(drm_ttm_ipi_handler, NULL, 1, 1) != 0)
DRM_ERROR("Timed out waiting for drm cache flush.\n");
}
@@ -114,7 +149,7 @@ static int drm_ttm_set_caching(struct drm_ttm *ttm, int noncached)
return 0;
if (noncached)
- drm_ttm_cache_flush();
+ drm_ttm_cache_flush(ttm->pages, ttm->num_pages);
for (i = 0; i < ttm->num_pages; ++i) {
cur_page = ttm->pages + i;
@@ -228,12 +263,16 @@ struct page *drm_ttm_get_page(struct drm_ttm *ttm, int index)
struct page *p;
struct drm_buffer_manager *bm = &ttm->dev->bm;
- p = ttm->pages[index];
- if (!p) {
+ while(NULL == (p = ttm->pages[index])) {
p = drm_ttm_alloc_page();
if (!p)
return NULL;
- ttm->pages[index] = p;
+
+ if (PageHighMem(p))
+ ttm->pages[--ttm->first_himem_page] = p;
+ else
+ ttm->pages[++ttm->last_lomem_page] = p;
+
++bm->cur_pages;
}
return p;
@@ -341,6 +380,8 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size,
ttm->destroy = 0;
ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ ttm->first_himem_page = ttm->num_pages;
+ ttm->last_lomem_page = -1;
ttm->page_flags = page_flags;