aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-24 17:44:56 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-31 05:50:05 -0500
commitdef886c3768d24c4e0aa56ff98b5a468c2b5c9bf (patch)
tree286572413c631a0bd011a94027ac9d4a2cc6e7e7
parent7faf1ab2ff816d6ea9cde099e794a4e18cf13bbc (diff)
drm/i915: vfuncs for ppgtt
Like for the global gtt we want a notch more flexibility here. Only big change (besides a few tiny function parameter adjustments) was to move gen6_ppgtt_insert_entries up (and remove _sg_ from its name, we only have one kind of insert_entries since the last gtt cleanup). We could also extract the platform ppgtt setup/teardown code a bit better, but I don't care that much. With this we have the hw details of pte writing nicely hidden away behind a bit of abstraction. Which should pave the way for different/multiple ppgtts (e.g. what we need for real ppgtt support). Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h10
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c111
2 files changed, 65 insertions, 56 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fb0815bebe0f..4be7c68bf5fd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -412,6 +412,15 @@ struct i915_hw_ppgtt {
412 uint32_t pd_offset; 412 uint32_t pd_offset;
413 dma_addr_t *pt_dma_addr; 413 dma_addr_t *pt_dma_addr;
414 dma_addr_t scratch_page_dma_addr; 414 dma_addr_t scratch_page_dma_addr;
415
416 /* pte functions, mirroring the interface of the global gtt. */
417 void (*clear_range)(struct i915_hw_ppgtt *ppgtt,
418 unsigned int first_entry,
419 unsigned int num_entries);
420 void (*insert_entries)(struct i915_hw_ppgtt *ppgtt,
421 struct sg_table *st,
422 unsigned int pg_start,
423 enum i915_cache_level cache_level);
415}; 424};
416 425
417 426
@@ -1662,7 +1671,6 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
1662 struct drm_file *file); 1671 struct drm_file *file);
1663 1672
1664/* i915_gem_gtt.c */ 1673/* i915_gem_gtt.c */
1665int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev);
1666void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); 1674void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev);
1667void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, 1675void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
1668 struct drm_i915_gem_object *obj, 1676 struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 4712626f8dc1..f63dbc7a89ce 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -77,7 +77,7 @@ static inline gtt_pte_t pte_encode(struct drm_device *dev,
77} 77}
78 78
79/* PPGTT support for Sandybdrige/Gen6 and later */ 79/* PPGTT support for Sandybdrige/Gen6 and later */
80static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, 80static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
81 unsigned first_entry, 81 unsigned first_entry,
82 unsigned num_entries) 82 unsigned num_entries)
83{ 83{
@@ -108,7 +108,51 @@ static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
108 } 108 }
109} 109}
110 110
111int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) 111static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
112 struct sg_table *pages,
113 unsigned first_entry,
114 enum i915_cache_level cache_level)
115{
116 gtt_pte_t *pt_vaddr;
117 unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
118 unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
119 unsigned i, j, m, segment_len;
120 dma_addr_t page_addr;
121 struct scatterlist *sg;
122
123 /* init sg walking */
124 sg = pages->sgl;
125 i = 0;
126 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
127 m = 0;
128
129 while (i < pages->nents) {
130 pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
131
132 for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
133 page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
134 pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr,
135 cache_level);
136
137 /* grab the next page */
138 if (++m == segment_len) {
139 if (++i == pages->nents)
140 break;
141
142 sg = sg_next(sg);
143 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
144 m = 0;
145 }
146 }
147
148 kunmap_atomic(pt_vaddr);
149
150 first_pte = 0;
151 act_pd++;
152 }
153}
154
155static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
112{ 156{
113 struct drm_i915_private *dev_priv = dev->dev_private; 157 struct drm_i915_private *dev_priv = dev->dev_private;
114 struct i915_hw_ppgtt *ppgtt; 158 struct i915_hw_ppgtt *ppgtt;
@@ -127,6 +171,8 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
127 171
128 ppgtt->dev = dev; 172 ppgtt->dev = dev;
129 ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; 173 ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
174 ppgtt->clear_range = gen6_ppgtt_clear_range;
175 ppgtt->insert_entries = gen6_ppgtt_insert_entries;
130 ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, 176 ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries,
131 GFP_KERNEL); 177 GFP_KERNEL);
132 if (!ppgtt->pt_pages) 178 if (!ppgtt->pt_pages)
@@ -159,8 +205,8 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
159 205
160 ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; 206 ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma;
161 207
162 i915_ppgtt_clear_range(ppgtt, 0, 208 ppgtt->clear_range(ppgtt, 0,
163 ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); 209 ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
164 210
165 ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); 211 ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t);
166 212
@@ -209,66 +255,21 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
209 kfree(ppgtt); 255 kfree(ppgtt);
210} 256}
211 257
212static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt,
213 const struct sg_table *pages,
214 unsigned first_entry,
215 enum i915_cache_level cache_level)
216{
217 gtt_pte_t *pt_vaddr;
218 unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
219 unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
220 unsigned i, j, m, segment_len;
221 dma_addr_t page_addr;
222 struct scatterlist *sg;
223
224 /* init sg walking */
225 sg = pages->sgl;
226 i = 0;
227 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
228 m = 0;
229
230 while (i < pages->nents) {
231 pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
232
233 for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
234 page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
235 pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr,
236 cache_level);
237
238 /* grab the next page */
239 if (++m == segment_len) {
240 if (++i == pages->nents)
241 break;
242
243 sg = sg_next(sg);
244 segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
245 m = 0;
246 }
247 }
248
249 kunmap_atomic(pt_vaddr);
250
251 first_pte = 0;
252 act_pd++;
253 }
254}
255
256void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, 258void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
257 struct drm_i915_gem_object *obj, 259 struct drm_i915_gem_object *obj,
258 enum i915_cache_level cache_level) 260 enum i915_cache_level cache_level)
259{ 261{
260 i915_ppgtt_insert_sg_entries(ppgtt, 262 ppgtt->insert_entries(ppgtt, obj->pages,
261 obj->pages, 263 obj->gtt_space->start >> PAGE_SHIFT,
262 obj->gtt_space->start >> PAGE_SHIFT, 264 cache_level);
263 cache_level);
264} 265}
265 266
266void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, 267void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
267 struct drm_i915_gem_object *obj) 268 struct drm_i915_gem_object *obj)
268{ 269{
269 i915_ppgtt_clear_range(ppgtt, 270 ppgtt->clear_range(ppgtt,
270 obj->gtt_space->start >> PAGE_SHIFT, 271 obj->gtt_space->start >> PAGE_SHIFT,
271 obj->base.size >> PAGE_SHIFT); 272 obj->base.size >> PAGE_SHIFT);
272} 273}
273 274
274void i915_gem_init_ppgtt(struct drm_device *dev) 275void i915_gem_init_ppgtt(struct drm_device *dev)