diff options
author | Akash Goel <akash.goel@intel.com> | 2014-06-17 01:29:42 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-06-17 03:21:47 -0400 |
commit | 24f3a8cf7766e52a087904b4346794c7b410f957 (patch) | |
tree | b3aae1632b0a7acfdac0e1c4272b19cd25c77a69 /drivers/gpu/drm/i915/i915_gem_gtt.c | |
parent | 5aa8a937730940b48b70b21e05cf03e4cea31058 (diff) |
drm/i915: Added write-enable pte bit supportt
This adds support for a write-enable bit in the entry of GTT.
This is handled via a read-only flag in the GEM buffer object which
is then used to see how to set the bit when writing the GTT entries.
Currently by default the Batch buffer & Ring buffers are marked as read only.
v2: Moved the pte override code for read-only bit to 'byt_pte_encode'. (Chris)
Fixed the issue of leaving 'gt_old_ro' as unused. (Chris)
v3: Removed the 'gt_old_ro' field, now setting RO bit only for Ring Buffers(Daniel).
v4: Added a new 'flags' parameter to all the pte(gen6) encode & insert_entries functions,
in lieu of overloading the cache_level enum (Daniel).
v5: Removed the superfluous VLV check & changed the definition location of PTE_READ_ONLY flag (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6f5d5a1e7c32..743ddfcf2696 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -116,7 +116,7 @@ static inline gen8_ppgtt_pde_t gen8_pde_encode(struct drm_device *dev, | |||
116 | 116 | ||
117 | static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, | 117 | static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, |
118 | enum i915_cache_level level, | 118 | enum i915_cache_level level, |
119 | bool valid) | 119 | bool valid, u32 unused) |
120 | { | 120 | { |
121 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 121 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; |
122 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 122 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
@@ -138,7 +138,7 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, | |||
138 | 138 | ||
139 | static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, | 139 | static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, |
140 | enum i915_cache_level level, | 140 | enum i915_cache_level level, |
141 | bool valid) | 141 | bool valid, u32 unused) |
142 | { | 142 | { |
143 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 143 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; |
144 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 144 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
@@ -162,7 +162,7 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, | |||
162 | 162 | ||
163 | static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, | 163 | static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, |
164 | enum i915_cache_level level, | 164 | enum i915_cache_level level, |
165 | bool valid) | 165 | bool valid, u32 flags) |
166 | { | 166 | { |
167 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 167 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; |
168 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 168 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
@@ -170,7 +170,8 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, | |||
170 | /* Mark the page as writeable. Other platforms don't have a | 170 | /* Mark the page as writeable. Other platforms don't have a |
171 | * setting for read-only/writable, so this matches that behavior. | 171 | * setting for read-only/writable, so this matches that behavior. |
172 | */ | 172 | */ |
173 | pte |= BYT_PTE_WRITEABLE; | 173 | if (!(flags & PTE_READ_ONLY)) |
174 | pte |= BYT_PTE_WRITEABLE; | ||
174 | 175 | ||
175 | if (level != I915_CACHE_NONE) | 176 | if (level != I915_CACHE_NONE) |
176 | pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES; | 177 | pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES; |
@@ -180,7 +181,7 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, | |||
180 | 181 | ||
181 | static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, | 182 | static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, |
182 | enum i915_cache_level level, | 183 | enum i915_cache_level level, |
183 | bool valid) | 184 | bool valid, u32 unused) |
184 | { | 185 | { |
185 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 186 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; |
186 | pte |= HSW_PTE_ADDR_ENCODE(addr); | 187 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
@@ -193,7 +194,7 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, | |||
193 | 194 | ||
194 | static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, | 195 | static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, |
195 | enum i915_cache_level level, | 196 | enum i915_cache_level level, |
196 | bool valid) | 197 | bool valid, u32 unused) |
197 | { | 198 | { |
198 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 199 | gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; |
199 | pte |= HSW_PTE_ADDR_ENCODE(addr); | 200 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
@@ -307,7 +308,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, | |||
307 | static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, | 308 | static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, |
308 | struct sg_table *pages, | 309 | struct sg_table *pages, |
309 | uint64_t start, | 310 | uint64_t start, |
310 | enum i915_cache_level cache_level) | 311 | enum i915_cache_level cache_level, u32 unused) |
311 | { | 312 | { |
312 | struct i915_hw_ppgtt *ppgtt = | 313 | struct i915_hw_ppgtt *ppgtt = |
313 | container_of(vm, struct i915_hw_ppgtt, base); | 314 | container_of(vm, struct i915_hw_ppgtt, base); |
@@ -645,7 +646,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) | |||
645 | uint32_t pd_entry; | 646 | uint32_t pd_entry; |
646 | int pte, pde; | 647 | int pte, pde; |
647 | 648 | ||
648 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); | 649 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0); |
649 | 650 | ||
650 | pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + | 651 | pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + |
651 | ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); | 652 | ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); |
@@ -947,7 +948,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, | |||
947 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; | 948 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
948 | unsigned last_pte, i; | 949 | unsigned last_pte, i; |
949 | 950 | ||
950 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); | 951 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0); |
951 | 952 | ||
952 | while (num_entries) { | 953 | while (num_entries) { |
953 | last_pte = first_pte + num_entries; | 954 | last_pte = first_pte + num_entries; |
@@ -970,7 +971,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, | |||
970 | static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, | 971 | static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, |
971 | struct sg_table *pages, | 972 | struct sg_table *pages, |
972 | uint64_t start, | 973 | uint64_t start, |
973 | enum i915_cache_level cache_level) | 974 | enum i915_cache_level cache_level, u32 flags) |
974 | { | 975 | { |
975 | struct i915_hw_ppgtt *ppgtt = | 976 | struct i915_hw_ppgtt *ppgtt = |
976 | container_of(vm, struct i915_hw_ppgtt, base); | 977 | container_of(vm, struct i915_hw_ppgtt, base); |
@@ -987,7 +988,8 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, | |||
987 | 988 | ||
988 | pt_vaddr[act_pte] = | 989 | pt_vaddr[act_pte] = |
989 | vm->pte_encode(sg_page_iter_dma_address(&sg_iter), | 990 | vm->pte_encode(sg_page_iter_dma_address(&sg_iter), |
990 | cache_level, true); | 991 | cache_level, true, flags); |
992 | |||
991 | if (++act_pte == I915_PPGTT_PT_ENTRIES) { | 993 | if (++act_pte == I915_PPGTT_PT_ENTRIES) { |
992 | kunmap_atomic(pt_vaddr); | 994 | kunmap_atomic(pt_vaddr); |
993 | pt_vaddr = NULL; | 995 | pt_vaddr = NULL; |
@@ -1224,8 +1226,12 @@ ppgtt_bind_vma(struct i915_vma *vma, | |||
1224 | enum i915_cache_level cache_level, | 1226 | enum i915_cache_level cache_level, |
1225 | u32 flags) | 1227 | u32 flags) |
1226 | { | 1228 | { |
1229 | /* Currently applicable only to VLV */ | ||
1230 | if (vma->obj->gt_ro) | ||
1231 | flags |= PTE_READ_ONLY; | ||
1232 | |||
1227 | vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, | 1233 | vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, |
1228 | cache_level); | 1234 | cache_level, flags); |
1229 | } | 1235 | } |
1230 | 1236 | ||
1231 | static void ppgtt_unbind_vma(struct i915_vma *vma) | 1237 | static void ppgtt_unbind_vma(struct i915_vma *vma) |
@@ -1400,7 +1406,7 @@ static inline void gen8_set_pte(void __iomem *addr, gen8_gtt_pte_t pte) | |||
1400 | static void gen8_ggtt_insert_entries(struct i915_address_space *vm, | 1406 | static void gen8_ggtt_insert_entries(struct i915_address_space *vm, |
1401 | struct sg_table *st, | 1407 | struct sg_table *st, |
1402 | uint64_t start, | 1408 | uint64_t start, |
1403 | enum i915_cache_level level) | 1409 | enum i915_cache_level level, u32 unused) |
1404 | { | 1410 | { |
1405 | struct drm_i915_private *dev_priv = vm->dev->dev_private; | 1411 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
1406 | unsigned first_entry = start >> PAGE_SHIFT; | 1412 | unsigned first_entry = start >> PAGE_SHIFT; |
@@ -1446,7 +1452,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, | |||
1446 | static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | 1452 | static void gen6_ggtt_insert_entries(struct i915_address_space *vm, |
1447 | struct sg_table *st, | 1453 | struct sg_table *st, |
1448 | uint64_t start, | 1454 | uint64_t start, |
1449 | enum i915_cache_level level) | 1455 | enum i915_cache_level level, u32 flags) |
1450 | { | 1456 | { |
1451 | struct drm_i915_private *dev_priv = vm->dev->dev_private; | 1457 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
1452 | unsigned first_entry = start >> PAGE_SHIFT; | 1458 | unsigned first_entry = start >> PAGE_SHIFT; |
@@ -1458,7 +1464,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
1458 | 1464 | ||
1459 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { | 1465 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { |
1460 | addr = sg_page_iter_dma_address(&sg_iter); | 1466 | addr = sg_page_iter_dma_address(&sg_iter); |
1461 | iowrite32(vm->pte_encode(addr, level, true), >t_entries[i]); | 1467 | iowrite32(vm->pte_encode(addr, level, true, flags), >t_entries[i]); |
1462 | i++; | 1468 | i++; |
1463 | } | 1469 | } |
1464 | 1470 | ||
@@ -1470,7 +1476,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
1470 | */ | 1476 | */ |
1471 | if (i != 0) | 1477 | if (i != 0) |
1472 | WARN_ON(readl(>t_entries[i-1]) != | 1478 | WARN_ON(readl(>t_entries[i-1]) != |
1473 | vm->pte_encode(addr, level, true)); | 1479 | vm->pte_encode(addr, level, true, flags)); |
1474 | 1480 | ||
1475 | /* This next bit makes the above posting read even more important. We | 1481 | /* This next bit makes the above posting read even more important. We |
1476 | * want to flush the TLBs only after we're certain all the PTE updates | 1482 | * want to flush the TLBs only after we're certain all the PTE updates |
@@ -1524,7 +1530,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, | |||
1524 | first_entry, num_entries, max_entries)) | 1530 | first_entry, num_entries, max_entries)) |
1525 | num_entries = max_entries; | 1531 | num_entries = max_entries; |
1526 | 1532 | ||
1527 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch); | 1533 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch, 0); |
1528 | 1534 | ||
1529 | for (i = 0; i < num_entries; i++) | 1535 | for (i = 0; i < num_entries; i++) |
1530 | iowrite32(scratch_pte, >t_base[i]); | 1536 | iowrite32(scratch_pte, >t_base[i]); |
@@ -1573,6 +1579,10 @@ static void ggtt_bind_vma(struct i915_vma *vma, | |||
1573 | struct drm_i915_private *dev_priv = dev->dev_private; | 1579 | struct drm_i915_private *dev_priv = dev->dev_private; |
1574 | struct drm_i915_gem_object *obj = vma->obj; | 1580 | struct drm_i915_gem_object *obj = vma->obj; |
1575 | 1581 | ||
1582 | /* Currently applicable only to VLV */ | ||
1583 | if (obj->gt_ro) | ||
1584 | flags |= PTE_READ_ONLY; | ||
1585 | |||
1576 | /* If there is no aliasing PPGTT, or the caller needs a global mapping, | 1586 | /* If there is no aliasing PPGTT, or the caller needs a global mapping, |
1577 | * or we have a global mapping already but the cacheability flags have | 1587 | * or we have a global mapping already but the cacheability flags have |
1578 | * changed, set the global PTEs. | 1588 | * changed, set the global PTEs. |
@@ -1589,7 +1599,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, | |||
1589 | (cache_level != obj->cache_level)) { | 1599 | (cache_level != obj->cache_level)) { |
1590 | vma->vm->insert_entries(vma->vm, obj->pages, | 1600 | vma->vm->insert_entries(vma->vm, obj->pages, |
1591 | vma->node.start, | 1601 | vma->node.start, |
1592 | cache_level); | 1602 | cache_level, flags); |
1593 | obj->has_global_gtt_mapping = 1; | 1603 | obj->has_global_gtt_mapping = 1; |
1594 | } | 1604 | } |
1595 | } | 1605 | } |
@@ -1601,7 +1611,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, | |||
1601 | appgtt->base.insert_entries(&appgtt->base, | 1611 | appgtt->base.insert_entries(&appgtt->base, |
1602 | vma->obj->pages, | 1612 | vma->obj->pages, |
1603 | vma->node.start, | 1613 | vma->node.start, |
1604 | cache_level); | 1614 | cache_level, flags); |
1605 | vma->obj->has_aliasing_ppgtt_mapping = 1; | 1615 | vma->obj->has_aliasing_ppgtt_mapping = 1; |
1606 | } | 1616 | } |
1607 | } | 1617 | } |