aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h7
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c11
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c9
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c146
4 files changed, 167 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 03a9e49fe93d..35c8b5316396 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -850,6 +850,8 @@ struct drm_i915_gem_object {
850 850
851 unsigned int cache_level:2; 851 unsigned int cache_level:2;
852 852
853 unsigned int has_aliasing_ppgtt_mapping:1;
854
853 struct page **pages; 855 struct page **pages;
854 856
855 /** 857 /**
@@ -1249,6 +1251,11 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
1249/* i915_gem_gtt.c */ 1251/* i915_gem_gtt.c */
1250int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); 1252int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev);
1251void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); 1253void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev);
1254void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
1255 struct drm_i915_gem_object *obj,
1256 enum i915_cache_level cache_level);
1257void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
1258 struct drm_i915_gem_object *obj);
1252 1259
1253void i915_gem_restore_gtt_mappings(struct drm_device *dev); 1260void i915_gem_restore_gtt_mappings(struct drm_device *dev);
1254int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); 1261int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 27fe07a2fd33..59092997bcfb 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2020,6 +2020,7 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
2020int 2020int
2021i915_gem_object_unbind(struct drm_i915_gem_object *obj) 2021i915_gem_object_unbind(struct drm_i915_gem_object *obj)
2022{ 2022{
2023 drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
2023 int ret = 0; 2024 int ret = 0;
2024 2025
2025 if (obj->gtt_space == NULL) 2026 if (obj->gtt_space == NULL)
@@ -2064,6 +2065,11 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
2064 trace_i915_gem_object_unbind(obj); 2065 trace_i915_gem_object_unbind(obj);
2065 2066
2066 i915_gem_gtt_unbind_object(obj); 2067 i915_gem_gtt_unbind_object(obj);
2068 if (obj->has_aliasing_ppgtt_mapping) {
2069 i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
2070 obj->has_aliasing_ppgtt_mapping = 0;
2071 }
2072
2067 i915_gem_object_put_pages_gtt(obj); 2073 i915_gem_object_put_pages_gtt(obj);
2068 2074
2069 list_del_init(&obj->gtt_list); 2075 list_del_init(&obj->gtt_list);
@@ -2882,6 +2888,8 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
2882int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, 2888int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
2883 enum i915_cache_level cache_level) 2889 enum i915_cache_level cache_level)
2884{ 2890{
2891 struct drm_device *dev = obj->base.dev;
2892 drm_i915_private_t *dev_priv = dev->dev_private;
2885 int ret; 2893 int ret;
2886 2894
2887 if (obj->cache_level == cache_level) 2895 if (obj->cache_level == cache_level)
@@ -2910,6 +2918,9 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
2910 } 2918 }
2911 2919
2912 i915_gem_gtt_rebind_object(obj, cache_level); 2920 i915_gem_gtt_rebind_object(obj, cache_level);
2921 if (obj->has_aliasing_ppgtt_mapping)
2922 i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
2923 obj, cache_level);
2913 } 2924 }
2914 2925
2915 if (cache_level == I915_CACHE_NONE) { 2926 if (cache_level == I915_CACHE_NONE) {
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index b964998b5e25..9835b2efd93e 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -515,6 +515,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
515 struct drm_file *file, 515 struct drm_file *file,
516 struct list_head *objects) 516 struct list_head *objects)
517{ 517{
518 drm_i915_private_t *dev_priv = ring->dev->dev_private;
518 struct drm_i915_gem_object *obj; 519 struct drm_i915_gem_object *obj;
519 int ret, retry; 520 int ret, retry;
520 bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; 521 bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
@@ -623,6 +624,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
623 } 624 }
624 625
625 i915_gem_object_unpin(obj); 626 i915_gem_object_unpin(obj);
627
628 /* ... and ensure ppgtt mapping exist if needed. */
629 if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
630 i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
631 obj, obj->cache_level);
632
633 obj->has_aliasing_ppgtt_mapping = 1;
634 }
626 } 635 }
627 636
628 if (ret != -ENOSPC || retry > 1) 637 if (ret != -ENOSPC || retry > 1)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index f408f8c710db..2eacd78bb93b 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -34,22 +34,31 @@ static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
34 unsigned first_entry, 34 unsigned first_entry,
35 unsigned num_entries) 35 unsigned num_entries)
36{ 36{
37 int i, j;
38 uint32_t *pt_vaddr; 37 uint32_t *pt_vaddr;
39 uint32_t scratch_pte; 38 uint32_t scratch_pte;
39 unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
40 unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
41 unsigned last_pte, i;
40 42
41 scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr); 43 scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
42 scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC; 44 scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
43 45
44 for (i = 0; i < ppgtt->num_pd_entries; i++) { 46 while (num_entries) {
45 pt_vaddr = kmap_atomic(ppgtt->pt_pages[i]); 47 last_pte = first_pte + num_entries;
48 if (last_pte > I915_PPGTT_PT_ENTRIES)
49 last_pte = I915_PPGTT_PT_ENTRIES;
50
51 pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
46 52
47 for (j = 0; j < I915_PPGTT_PT_ENTRIES; j++) 53 for (i = first_pte; i < last_pte; i++)
48 pt_vaddr[j] = scratch_pte; 54 pt_vaddr[i] = scratch_pte;
49 55
50 kunmap_atomic(pt_vaddr); 56 kunmap_atomic(pt_vaddr);
51 }
52 57
58 num_entries -= last_pte - first_pte;
59 first_pte = 0;
60 act_pd++;
61 }
53} 62}
54 63
55int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) 64int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
@@ -168,6 +177,131 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
168 kfree(ppgtt); 177 kfree(ppgtt);
169} 178}
170 179
180static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt,
181 struct scatterlist *sg_list,
182 unsigned sg_len,
183 unsigned first_entry,
184 uint32_t pte_flags)
185{
186 uint32_t *pt_vaddr, pte;
187 unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
188 unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
189 unsigned i, j, m, segment_len;
190 dma_addr_t page_addr;
191 struct scatterlist *sg;
192
193 /* init sg walking */
194 sg = sg_list;
195 i = 0;
196 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
197 m = 0;
198
199 while (i < sg_len) {
200 pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
201
202 for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
203 page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
204 pte = GEN6_PTE_ADDR_ENCODE(page_addr);
205 pt_vaddr[j] = pte | pte_flags;
206
207 /* grab the next page */
208 m++;
209 if (m == segment_len) {
210 sg = sg_next(sg);
211 i++;
212 if (i == sg_len)
213 break;
214
215 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
216 m = 0;
217 }
218 }
219
220 kunmap_atomic(pt_vaddr);
221
222 first_pte = 0;
223 act_pd++;
224 }
225}
226
227static void i915_ppgtt_insert_pages(struct i915_hw_ppgtt *ppgtt,
228 unsigned first_entry, unsigned num_entries,
229 struct page **pages, uint32_t pte_flags)
230{
231 uint32_t *pt_vaddr, pte;
232 unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
233 unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
234 unsigned last_pte, i;
235 dma_addr_t page_addr;
236
237 while (num_entries) {
238 last_pte = first_pte + num_entries;
239 last_pte = min_t(unsigned, last_pte, I915_PPGTT_PT_ENTRIES);
240
241 pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
242
243 for (i = first_pte; i < last_pte; i++) {
244 page_addr = page_to_phys(*pages);
245 pte = GEN6_PTE_ADDR_ENCODE(page_addr);
246 pt_vaddr[i] = pte | pte_flags;
247
248 pages++;
249 }
250
251 kunmap_atomic(pt_vaddr);
252
253 num_entries -= last_pte - first_pte;
254 first_pte = 0;
255 act_pd++;
256 }
257}
258
259void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
260 struct drm_i915_gem_object *obj,
261 enum i915_cache_level cache_level)
262{
263 struct drm_device *dev = obj->base.dev;
264 struct drm_i915_private *dev_priv = dev->dev_private;
265 uint32_t pte_flags = GEN6_PTE_VALID;
266
267 switch (cache_level) {
268 case I915_CACHE_LLC_MLC:
269 pte_flags |= GEN6_PTE_CACHE_LLC_MLC;
270 break;
271 case I915_CACHE_LLC:
272 pte_flags |= GEN6_PTE_CACHE_LLC;
273 break;
274 case I915_CACHE_NONE:
275 pte_flags |= GEN6_PTE_UNCACHED;
276 break;
277 default:
278 BUG();
279 }
280
281 if (dev_priv->mm.gtt->needs_dmar) {
282 BUG_ON(!obj->sg_list);
283
284 i915_ppgtt_insert_sg_entries(ppgtt,
285 obj->sg_list,
286 obj->num_sg,
287 obj->gtt_space->start >> PAGE_SHIFT,
288 pte_flags);
289 } else
290 i915_ppgtt_insert_pages(ppgtt,
291 obj->gtt_space->start >> PAGE_SHIFT,
292 obj->base.size >> PAGE_SHIFT,
293 obj->pages,
294 pte_flags);
295}
296
297void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
298 struct drm_i915_gem_object *obj)
299{
300 i915_ppgtt_clear_range(ppgtt,
301 obj->gtt_space->start >> PAGE_SHIFT,
302 obj->base.size >> PAGE_SHIFT);
303}
304
171/* XXX kill agp_type! */ 305/* XXX kill agp_type! */
172static unsigned int cache_level_to_agp_type(struct drm_device *dev, 306static unsigned int cache_level_to_agp_type(struct drm_device *dev,
173 enum i915_cache_level cache_level) 307 enum i915_cache_level cache_level)