Merge branch 'vendor/BMAKE'
[dragonfly.git] / sys / dev / drm / i915 / i915_gem_gtt.c
1 /*
2  * Copyright © 2010 Daniel Vetter
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * $FreeBSD: src/sys/dev/drm2/i915/i915_gem_gtt.c,v 1.1 2012/05/22 11:07:44 kib Exp $
24  */
25
26 #include <sys/sfbuf.h>
27
28 #include <drm/drmP.h>
29 #include <drm/i915_drm.h>
30 #include "i915_drv.h"
31 #include "intel_drv.h"
32
33 /* PPGTT support for Sandybdrige/Gen6 and later */
34 static void
35 i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
36     unsigned first_entry, unsigned num_entries)
37 {
38         uint32_t *pt_vaddr;
39         uint32_t scratch_pte;
40         struct sf_buf *sf;
41         unsigned act_pd, first_pte, last_pte, i;
42
43         act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
44         first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
45
46         scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
47         scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
48
49         while (num_entries) {
50                 last_pte = first_pte + num_entries;
51                 if (last_pte > I915_PPGTT_PT_ENTRIES)
52                         last_pte = I915_PPGTT_PT_ENTRIES;
53
54                 sf = sf_buf_alloc(ppgtt->pt_pages[act_pd]);
55                 pt_vaddr = (uint32_t *)(uintptr_t)sf_buf_kva(sf);
56
57                 for (i = first_pte; i < last_pte; i++)
58                         pt_vaddr[i] = scratch_pte;
59
60                 sf_buf_free(sf);
61
62                 num_entries -= last_pte - first_pte;
63                 first_pte = 0;
64                 act_pd++;
65         }
66
67 }
68
69 int
70 i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
71 {
72         struct drm_i915_private *dev_priv;
73         struct i915_hw_ppgtt *ppgtt;
74         u_int first_pd_entry_in_global_pt, i;
75
76         dev_priv = dev->dev_private;
77
78         /*
79          * ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
80          * entries. For aliasing ppgtt support we just steal them at the end for
81          * now.
82          */
83         first_pd_entry_in_global_pt = 512 * 1024 - I915_PPGTT_PD_ENTRIES;
84
85         ppgtt = kmalloc(sizeof(*ppgtt), DRM_I915_GEM, M_WAITOK | M_ZERO);
86
87         ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
88         ppgtt->pt_pages = kmalloc(sizeof(vm_page_t) * ppgtt->num_pd_entries,
89             DRM_I915_GEM, M_WAITOK | M_ZERO);
90
91         for (i = 0; i < ppgtt->num_pd_entries; i++) {
92                 ppgtt->pt_pages[i] = vm_page_alloc(NULL, 0,
93                     VM_ALLOC_NORMAL | VM_ALLOC_ZERO);
94                 if (ppgtt->pt_pages[i] == NULL) {
95                         dev_priv->mm.aliasing_ppgtt = ppgtt;
96                         i915_gem_cleanup_aliasing_ppgtt(dev);
97                         return (-ENOMEM);
98                 }
99         }
100
101         ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
102
103         i915_ppgtt_clear_range(ppgtt, 0, ppgtt->num_pd_entries *
104             I915_PPGTT_PT_ENTRIES);
105         ppgtt->pd_offset = (first_pd_entry_in_global_pt) * sizeof(uint32_t);
106         dev_priv->mm.aliasing_ppgtt = ppgtt;
107         return (0);
108 }
109
110 static void
111 i915_ppgtt_insert_pages(struct i915_hw_ppgtt *ppgtt, unsigned first_entry,
112     unsigned num_entries, vm_page_t *pages, uint32_t pte_flags)
113 {
114         uint32_t *pt_vaddr, pte;
115         struct sf_buf *sf;
116         unsigned act_pd, first_pte;
117         unsigned last_pte, i;
118         vm_paddr_t page_addr;
119
120         act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
121         first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
122
123         while (num_entries) {
124                 last_pte = first_pte + num_entries;
125                 if (last_pte > I915_PPGTT_PT_ENTRIES)
126                         last_pte = I915_PPGTT_PT_ENTRIES;
127
128                 sf = sf_buf_alloc(ppgtt->pt_pages[act_pd]);
129                 pt_vaddr = (uint32_t *)(uintptr_t)sf_buf_kva(sf);
130
131                 for (i = first_pte; i < last_pte; i++) {
132                         page_addr = VM_PAGE_TO_PHYS(*pages);
133                         pte = GEN6_PTE_ADDR_ENCODE(page_addr);
134                         pt_vaddr[i] = pte | pte_flags;
135
136                         pages++;
137                 }
138
139                 sf_buf_free(sf);
140
141                 num_entries -= last_pte - first_pte;
142                 first_pte = 0;
143                 act_pd++;
144         }
145 }
146
147 void
148 i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
149     struct drm_i915_gem_object *obj, enum i915_cache_level cache_level)
150 {
151         struct drm_device *dev;
152         struct drm_i915_private *dev_priv;
153         uint32_t pte_flags;
154
155         dev = obj->base.dev;
156         dev_priv = dev->dev_private;
157         pte_flags = GEN6_PTE_VALID;
158
159         switch (cache_level) {
160         case I915_CACHE_LLC_MLC:
161                 pte_flags |= GEN6_PTE_CACHE_LLC_MLC;
162                 break;
163         case I915_CACHE_LLC:
164                 pte_flags |= GEN6_PTE_CACHE_LLC;
165                 break;
166         case I915_CACHE_NONE:
167                 pte_flags |= GEN6_PTE_UNCACHED;
168                 break;
169         default:
170                 panic("cache mode");
171         }
172
173         i915_ppgtt_insert_pages(ppgtt, obj->gtt_space->start >> PAGE_SHIFT,
174             obj->base.size >> PAGE_SHIFT, obj->pages, pte_flags);
175 }
176
177 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
178                               struct drm_i915_gem_object *obj)
179 {
180         i915_ppgtt_clear_range(ppgtt, obj->gtt_space->start >> PAGE_SHIFT,
181             obj->base.size >> PAGE_SHIFT);
182 }
183
184 void
185 i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
186 {
187         struct drm_i915_private *dev_priv;
188         struct i915_hw_ppgtt *ppgtt;
189         vm_page_t m;
190         int i;
191
192         dev_priv = dev->dev_private;
193         ppgtt = dev_priv->mm.aliasing_ppgtt;
194         if (ppgtt == NULL)
195                 return;
196         dev_priv->mm.aliasing_ppgtt = NULL;
197
198         for (i = 0; i < ppgtt->num_pd_entries; i++) {
199                 m = ppgtt->pt_pages[i];
200                 if (m != NULL) {
201                         vm_page_busy_wait(m, FALSE, "i915gem");
202                         vm_page_unwire(m, 0);
203                         vm_page_free(m);
204                 }
205         }
206         drm_free(ppgtt->pt_pages, DRM_I915_GEM);
207         drm_free(ppgtt, DRM_I915_GEM);
208 }
209
210
211 static unsigned int
212 cache_level_to_agp_type(struct drm_device *dev, enum i915_cache_level
213     cache_level)
214 {
215
216         switch (cache_level) {
217         case I915_CACHE_LLC_MLC:
218                 if (INTEL_INFO(dev)->gen >= 6)
219                         return (AGP_USER_CACHED_MEMORY_LLC_MLC);
220                 /*
221                  * Older chipsets do not have this extra level of CPU
222                  * cacheing, so fallthrough and request the PTE simply
223                  * as cached.
224                  */
225         case I915_CACHE_LLC:
226                 return (AGP_USER_CACHED_MEMORY);
227
228         default:
229         case I915_CACHE_NONE:
230                 return (AGP_USER_MEMORY);
231         }
232 }
233
234 static bool
235 do_idling(struct drm_i915_private *dev_priv)
236 {
237         bool ret = dev_priv->mm.interruptible;
238
239         if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
240                 dev_priv->mm.interruptible = false;
241                 if (i915_gpu_idle(dev_priv->dev, false)) {
242                         DRM_ERROR("Couldn't idle GPU\n");
243                         /* Wait a bit, in hopes it avoids the hang */
244                         DELAY(10);
245                 }
246         }
247
248         return ret;
249 }
250
251 static void
252 undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
253 {
254
255         if (unlikely(dev_priv->mm.gtt->do_idle_maps))
256                 dev_priv->mm.interruptible = interruptible;
257 }
258
259 void
260 i915_gem_restore_gtt_mappings(struct drm_device *dev)
261 {
262         struct drm_i915_private *dev_priv;
263         struct drm_i915_gem_object *obj;
264
265         dev_priv = dev->dev_private;
266
267         /* First fill our portion of the GTT with scratch pages */
268         intel_gtt_clear_range(dev_priv->mm.gtt_start / PAGE_SIZE,
269             (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
270
271         list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
272                 i915_gem_clflush_object(obj);
273                 i915_gem_gtt_rebind_object(obj, obj->cache_level);
274         }
275
276         intel_gtt_chipset_flush();
277 }
278
279 int
280 i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
281 {
282         unsigned int agp_type;
283
284         agp_type = cache_level_to_agp_type(obj->base.dev, obj->cache_level);
285         intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
286             obj->base.size >> PAGE_SHIFT, obj->pages, agp_type);
287         return (0);
288 }
289
290 void
291 i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
292     enum i915_cache_level cache_level)
293 {
294         struct drm_device *dev;
295         struct drm_i915_private *dev_priv;
296         unsigned int agp_type;
297
298         dev = obj->base.dev;
299         dev_priv = dev->dev_private;
300         agp_type = cache_level_to_agp_type(dev, cache_level);
301
302         intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
303             obj->base.size >> PAGE_SHIFT, obj->pages, agp_type);
304 }
305
306 void
307 i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
308 {
309         struct drm_device *dev = obj->base.dev;
310         struct drm_i915_private *dev_priv = dev->dev_private;
311         bool interruptible;
312
313         dev = obj->base.dev;
314         dev_priv = dev->dev_private;
315
316         interruptible = do_idling(dev_priv);
317
318         intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
319             obj->base.size >> PAGE_SHIFT);
320
321         undo_idling(dev_priv, interruptible);
322 }