diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 111 |
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 */ |
1665 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); | ||
1666 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); | 1674 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); |
1667 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, | 1675 | void 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 */ |
80 | static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, | 80 | static 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 | ||
111 | int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) | 111 | static 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 | |||
155 | static 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 | ||
212 | static 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 | |||
256 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, | 258 | void 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 | ||
266 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, | 267 | void 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 | ||
274 | void i915_gem_init_ppgtt(struct drm_device *dev) | 275 | void i915_gem_init_ppgtt(struct drm_device *dev) |