diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-02-19 16:30:15 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-19 16:30:15 -0500 |
commit | f0e2f38befa787f0267419082b33e8ac72269d77 (patch) | |
tree | ed969423484e055c04bdb8b0a49097c8fdd1ca98 /drivers | |
parent | 6a660f06e8120977b25d30ace354c8f9dc3aff2a (diff) |
drm/ttm: fix caching problem on non-PAT systems.
http://bugzilla.kernel.org/show_bug.cgi?id=15328
This fixes a serious regression on AGP/non-PAT systems, where
pages were ending up in the wrong state and slowing down the
whole system.
[airlied: taken this from the bug as the other option is to revert
the change which caused it].
Tested-by: John W. Linville (in bug).
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_tt.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index e2123af7775a..3d47a2c12322 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
@@ -196,14 +196,15 @@ EXPORT_SYMBOL(ttm_tt_populate); | |||
196 | 196 | ||
197 | #ifdef CONFIG_X86 | 197 | #ifdef CONFIG_X86 |
198 | static inline int ttm_tt_set_page_caching(struct page *p, | 198 | static inline int ttm_tt_set_page_caching(struct page *p, |
199 | enum ttm_caching_state c_state) | 199 | enum ttm_caching_state c_old, |
200 | enum ttm_caching_state c_new) | ||
200 | { | 201 | { |
201 | int ret = 0; | 202 | int ret = 0; |
202 | 203 | ||
203 | if (PageHighMem(p)) | 204 | if (PageHighMem(p)) |
204 | return 0; | 205 | return 0; |
205 | 206 | ||
206 | if (get_page_memtype(p) != -1) { | 207 | if (c_old != tt_cached) { |
207 | /* p isn't in the default caching state, set it to | 208 | /* p isn't in the default caching state, set it to |
208 | * writeback first to free its current memtype. */ | 209 | * writeback first to free its current memtype. */ |
209 | 210 | ||
@@ -212,16 +213,17 @@ static inline int ttm_tt_set_page_caching(struct page *p, | |||
212 | return ret; | 213 | return ret; |
213 | } | 214 | } |
214 | 215 | ||
215 | if (c_state == tt_wc) | 216 | if (c_new == tt_wc) |
216 | ret = set_memory_wc((unsigned long) page_address(p), 1); | 217 | ret = set_memory_wc((unsigned long) page_address(p), 1); |
217 | else if (c_state == tt_uncached) | 218 | else if (c_new == tt_uncached) |
218 | ret = set_pages_uc(p, 1); | 219 | ret = set_pages_uc(p, 1); |
219 | 220 | ||
220 | return ret; | 221 | return ret; |
221 | } | 222 | } |
222 | #else /* CONFIG_X86 */ | 223 | #else /* CONFIG_X86 */ |
223 | static inline int ttm_tt_set_page_caching(struct page *p, | 224 | static inline int ttm_tt_set_page_caching(struct page *p, |
224 | enum ttm_caching_state c_state) | 225 | enum ttm_caching_state c_old, |
226 | enum ttm_caching_state c_new) | ||
225 | { | 227 | { |
226 | return 0; | 228 | return 0; |
227 | } | 229 | } |
@@ -254,7 +256,9 @@ static int ttm_tt_set_caching(struct ttm_tt *ttm, | |||
254 | for (i = 0; i < ttm->num_pages; ++i) { | 256 | for (i = 0; i < ttm->num_pages; ++i) { |
255 | cur_page = ttm->pages[i]; | 257 | cur_page = ttm->pages[i]; |
256 | if (likely(cur_page != NULL)) { | 258 | if (likely(cur_page != NULL)) { |
257 | ret = ttm_tt_set_page_caching(cur_page, c_state); | 259 | ret = ttm_tt_set_page_caching(cur_page, |
260 | ttm->caching_state, | ||
261 | c_state); | ||
258 | if (unlikely(ret != 0)) | 262 | if (unlikely(ret != 0)) |
259 | goto out_err; | 263 | goto out_err; |
260 | } | 264 | } |
@@ -268,7 +272,7 @@ out_err: | |||
268 | for (j = 0; j < i; ++j) { | 272 | for (j = 0; j < i; ++j) { |
269 | cur_page = ttm->pages[j]; | 273 | cur_page = ttm->pages[j]; |
270 | if (likely(cur_page != NULL)) { | 274 | if (likely(cur_page != NULL)) { |
271 | (void)ttm_tt_set_page_caching(cur_page, | 275 | (void)ttm_tt_set_page_caching(cur_page, c_state, |
272 | ttm->caching_state); | 276 | ttm->caching_state); |
273 | } | 277 | } |
274 | } | 278 | } |