diff options
author | Ben Widawsky <benjamin.widawsky@intel.com> | 2013-11-03 00:07:23 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-11-08 12:09:46 -0500 |
commit | 459108b8cccfeeb965653b51be0160784e51fdc0 (patch) | |
tree | c44a6e796110d4ae0795c763c58351f8be9f8852 | |
parent | b1fe6673298113636f356dce8e8ac2a93a579882 (diff) |
drm/i915/bdw: Implement PPGTT clear range
GEN8 PPGTT range clearing is very similar to GEN6 if we assume that our
PDEs are all valid, which they should be.
v2: Rebase on top of the address space refactoring.
v3: Rebase on top of the bool use_scratch addition to the clear_range interface.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net> (v1)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9bee72c2c3b1..2f138ed3730e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -59,6 +59,7 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t; | |||
59 | #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) | 59 | #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) |
60 | #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) | 60 | #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) |
61 | 61 | ||
62 | #define GEN8_PTES_PER_PAGE (PAGE_SIZE / sizeof(gen8_gtt_pte_t)) | ||
62 | #define GEN8_PDES_PER_PAGE (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t)) | 63 | #define GEN8_PDES_PER_PAGE (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t)) |
63 | #define GEN8_LEGACY_PDPS 4 | 64 | #define GEN8_LEGACY_PDPS 4 |
64 | 65 | ||
@@ -194,6 +195,41 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, | |||
194 | return pte; | 195 | return pte; |
195 | } | 196 | } |
196 | 197 | ||
198 | static void gen8_ppgtt_clear_range(struct i915_address_space *vm, | ||
199 | unsigned first_entry, | ||
200 | unsigned num_entries, | ||
201 | bool use_scratch) | ||
202 | { | ||
203 | struct i915_hw_ppgtt *ppgtt = | ||
204 | container_of(vm, struct i915_hw_ppgtt, base); | ||
205 | gen8_gtt_pte_t *pt_vaddr, scratch_pte; | ||
206 | unsigned act_pt = first_entry / GEN8_PTES_PER_PAGE; | ||
207 | unsigned first_pte = first_entry % GEN8_PTES_PER_PAGE; | ||
208 | unsigned last_pte, i; | ||
209 | |||
210 | scratch_pte = gen8_pte_encode(ppgtt->base.scratch.addr, | ||
211 | I915_CACHE_LLC, use_scratch); | ||
212 | |||
213 | while (num_entries) { | ||
214 | struct page *page_table = &ppgtt->gen8_pt_pages[act_pt]; | ||
215 | |||
216 | last_pte = first_pte + num_entries; | ||
217 | if (last_pte > GEN8_PTES_PER_PAGE) | ||
218 | last_pte = GEN8_PTES_PER_PAGE; | ||
219 | |||
220 | pt_vaddr = kmap_atomic(page_table); | ||
221 | |||
222 | for (i = first_pte; i < last_pte; i++) | ||
223 | pt_vaddr[i] = scratch_pte; | ||
224 | |||
225 | kunmap_atomic(pt_vaddr); | ||
226 | |||
227 | num_entries -= last_pte - first_pte; | ||
228 | first_pte = 0; | ||
229 | act_pt++; | ||
230 | } | ||
231 | } | ||
232 | |||
197 | static void gen8_ppgtt_cleanup(struct i915_address_space *vm) | 233 | static void gen8_ppgtt_cleanup(struct i915_address_space *vm) |
198 | { | 234 | { |
199 | struct i915_hw_ppgtt *ppgtt = | 235 | struct i915_hw_ppgtt *ppgtt = |
@@ -259,7 +295,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) | |||
259 | ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT); | 295 | ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT); |
260 | ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT); | 296 | ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT); |
261 | ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE; | 297 | ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE; |
262 | ppgtt->base.clear_range = NULL; | 298 | ppgtt->base.clear_range = gen8_ppgtt_clear_range; |
263 | ppgtt->base.insert_entries = NULL; | 299 | ppgtt->base.insert_entries = NULL; |
264 | ppgtt->base.cleanup = gen8_ppgtt_cleanup; | 300 | ppgtt->base.cleanup = gen8_ppgtt_cleanup; |
265 | 301 | ||
@@ -312,6 +348,10 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) | |||
312 | kunmap_atomic(pd_vaddr); | 348 | kunmap_atomic(pd_vaddr); |
313 | } | 349 | } |
314 | 350 | ||
351 | ppgtt->base.clear_range(&ppgtt->base, 0, | ||
352 | ppgtt->num_pd_entries * GEN8_PTES_PER_PAGE, | ||
353 | true); | ||
354 | |||
315 | DRM_DEBUG_DRIVER("Allocated %d pages for page directories (%d wasted)\n", | 355 | DRM_DEBUG_DRIVER("Allocated %d pages for page directories (%d wasted)\n", |
316 | ppgtt->num_pd_pages, ppgtt->num_pd_pages - max_pdp); | 356 | ppgtt->num_pd_pages, ppgtt->num_pd_pages - max_pdp); |
317 | DRM_DEBUG_DRIVER("Allocated %d pages for page tables (%lld wasted)\n", | 357 | DRM_DEBUG_DRIVER("Allocated %d pages for page tables (%lld wasted)\n", |