drm/ttm: Avoid conflicting reserve_memtype during ttm_tt_set_page_caching.
authorFrancisco Jerez <currojerez@riseup.net>
Tue, 12 Jan 2010 17:49:43 +0000 (18:49 +0100)
committerDave Airlie <airlied@redhat.com>
Mon, 1 Feb 2010 01:15:37 +0000 (11:15 +1000)
Fixes errors like:
> reserve_ram_pages_type failed 0x15b7a000-0x15b7b000, track 0x8, req 0x10
when a BO is moved between WC and UC areas.

Reported-by: Xavier Chantry <shiningxc@gmail.com>
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Acked-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/ttm/ttm_tt.c

index 9c2b1cc5dba5a10b586d4c8b9a6dc6ffeb02a376..e2123af7775aa63482b59e4510998fe9573ceb18 100644 (file)
@@ -198,17 +198,26 @@ EXPORT_SYMBOL(ttm_tt_populate);
 static inline int ttm_tt_set_page_caching(struct page *p,
                                          enum ttm_caching_state c_state)
 {
+       int ret = 0;
+
        if (PageHighMem(p))
                return 0;
 
-       switch (c_state) {
-       case tt_cached:
-               return set_pages_wb(p, 1);
-       case tt_wc:
-           return set_memory_wc((unsigned long) page_address(p), 1);
-       default:
-               return set_pages_uc(p, 1);
+       if (get_page_memtype(p) != -1) {
+               /* p isn't in the default caching state, set it to
+                * writeback first to free its current memtype. */
+
+               ret = set_pages_wb(p, 1);
+               if (ret)
+                       return ret;
        }
+
+       if (c_state == tt_wc)
+               ret = set_memory_wc((unsigned long) page_address(p), 1);
+       else if (c_state == tt_uncached)
+               ret = set_pages_uc(p, 1);
+
+       return ret;
 }
 #else /* CONFIG_X86 */
 static inline int ttm_tt_set_page_caching(struct page *p,