[PATCH 17/17] drm/i915: support mixed mode for gtt pages
Matthew Auld
matthew.auld at intel.com
Wed May 24 18:25:06 UTC 2017
Signed-off-by: Matthew Auld <matthew.auld at intel.com>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 90 +++++++++++++++++++++++++++++--------
1 file changed, 72 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 5e10185dd40c..b5a64a05b1f8 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -834,6 +834,7 @@ static void gen8_ppgtt_clear_4lvl(struct i915_address_space *vm,
struct sgt_dma {
struct scatterlist *sg;
dma_addr_t dma, max;
+ unsigned int page_size;
};
struct gen8_insert_pte {
@@ -863,7 +864,8 @@ gen8_ppgtt_insert_1G_entries(struct i915_hw_ppgtt *ppgtt,
const gen8_pte_t pdpe_encode = gen8_pte_encode(GEN8_PDPE_PS_1G,
cache_level);
gen8_pte_t *vaddr;
- bool ret;
+ dma_addr_t remaining;
+ bool ret = false;
GEM_BUG_ON(idx->pte);
GEM_BUG_ON(idx->pde);
@@ -885,10 +887,23 @@ gen8_ppgtt_insert_1G_entries(struct i915_hw_ppgtt *ppgtt,
if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
idx->pdpe = 0;
+ idx->pml4e++;
+ ret = true;
+ }
+
+ remaining = iter->max - iter->dma;
+ if (remaining < I915_GTT_PAGE_SIZE_1G) {
+ if (remaining >= I915_GTT_PAGE_SIZE_2M)
+ iter->page_size = I915_GTT_PAGE_SIZE_2M;
+ else
+ iter->page_size = I915_GTT_PAGE_SIZE;
+
ret = true;
- break;
}
+ if (ret)
+ break;
+
} while (1);
kunmap_atomic(vaddr);
@@ -907,7 +922,8 @@ gen8_ppgtt_insert_2M_entries(struct i915_hw_ppgtt *ppgtt,
const gen8_pte_t pde_encode = gen8_pte_encode(GEN8_PDE_PS_2M,
cache_level);
gen8_pte_t *vaddr;
- bool ret;
+ dma_addr_t remaining;
+ bool ret = false;
GEM_BUG_ON(idx->pte);
GEM_BUG_ON(idx->pdpe >= i915_pdpes_per_pdp(&ppgtt->base));
@@ -926,19 +942,34 @@ gen8_ppgtt_insert_2M_entries(struct i915_hw_ppgtt *ppgtt,
iter->max = iter->dma + iter->sg->length;
}
+ remaining = iter->max - iter->dma;
+
if (++idx->pde == I915_PDES) {
idx->pde = 0;
if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
idx->pdpe = 0;
+ idx->pml4e++;
+ ret = true;
+ }
+
+ if (unlikely(remaining >= I915_GTT_PAGE_SIZE_1G)) {
+ iter->page_size = I915_GTT_PAGE_SIZE;
ret = true;
- break;
}
kunmap_atomic(vaddr);
vaddr = kmap_atomic_px(pdp->page_directory[idx->pdpe]);
}
+ if (remaining < I915_GTT_PAGE_SIZE_2M) {
+ iter->page_size = I915_GTT_PAGE_SIZE;
+ ret = true;
+ }
+
+ if (ret)
+ break;
+
} while (1);
kunmap_atomic(vaddr);
@@ -995,6 +1026,7 @@ gen8_ppgtt_insert_64K_entries(struct i915_hw_ppgtt *ppgtt,
if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
idx->pdpe = 0;
+ idx->pml4e++;
ret = true;
break;
}
@@ -1056,6 +1088,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
/* Limited by sg length for 3lvl */
if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
idx->pdpe = 0;
+ idx->pml4e++;
ret = true;
break;
}
@@ -1099,11 +1132,14 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
enum i915_cache_level cache_level,
u32 unused)
{
+ struct drm_i915_private *i915 = vm->i915;
+ unsigned long supported = INTEL_INFO(i915)->page_size_mask;
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct sgt_dma iter = {
.sg = pages->sgl,
.dma = sg_dma_address(iter.sg),
.max = iter.dma + iter.sg->length,
+ .page_size = page_sizes,
};
struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;
struct gen8_insert_pte idx = gen8_insert_pte(start);
@@ -1113,23 +1149,41 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
struct gen8_insert_pte *idx,
enum i915_cache_level cache_level);
- switch (page_sizes) {
- case I915_GTT_PAGE_SIZE_1G:
- insert_entries = gen8_ppgtt_insert_1G_entries;
- break;
- case I915_GTT_PAGE_SIZE_2M:
- insert_entries = gen8_ppgtt_insert_2M_entries;
- break;
- case I915_GTT_PAGE_SIZE_64K:
- insert_entries = gen8_ppgtt_insert_64K_entries;
- break;
- default:
- insert_entries = gen8_ppgtt_insert_pte_entries;
+ if (!is_power_of_2(page_sizes)) {
+ int bit;
+
+ for_each_set_bit(bit, &supported, BITS_PER_LONG) {
+ if (!IS_ALIGNED(start, BIT(bit)) ||
+ iter.sg->length < BIT(bit))
+ break;
+
+ iter.page_size = BIT(bit);
+ }
+
+ GEM_BUG_ON(iter.page_size == page_sizes);
}
- while (insert_entries(ppgtt, pdps[idx.pml4e++], &iter, &idx,
- cache_level))
+ do {
+ switch(iter.page_size & supported) {
+ case I915_GTT_PAGE_SIZE_1G:
+ insert_entries = gen8_ppgtt_insert_1G_entries;
+ break;
+ case I915_GTT_PAGE_SIZE_2M:
+ insert_entries = gen8_ppgtt_insert_2M_entries;
+ break;
+ case I915_GTT_PAGE_SIZE_64K:
+ /* We don't support 64K in mixed mode */
+ if (page_sizes == I915_GTT_PAGE_SIZE_64K)
+ insert_entries = gen8_ppgtt_insert_64K_entries;
+ /* fallthrough */
+ default:
+ insert_entries = gen8_ppgtt_insert_pte_entries;
+ }
+
GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
+
+ } while (insert_entries(ppgtt, pdps[idx.pml4e], &iter, &idx,
+ cache_level));
}
static void gen8_free_page_tables(struct i915_address_space *vm,
--
2.9.4
More information about the Intel-gfx-trybot
mailing list