Rev 3480 | Rev 3764 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3480 | Rev 3746 | ||
---|---|---|---|
Line 20... | Line 20... | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
21 | * IN THE SOFTWARE. |
21 | * IN THE SOFTWARE. |
22 | * |
22 | * |
23 | */ |
23 | */ |
Line 24... | Line -... | ||
24 | - | ||
Line 25... | Line 24... | ||
25 | #define iowrite32(v, addr) writel((v), (addr)) |
24 | |
Line 26... | Line 25... | ||
26 | 25 | ||
27 | #define AGP_NORMAL_MEMORY 0 |
26 | #define AGP_NORMAL_MEMORY 0 |
Line 34... | Line 33... | ||
34 | #include |
33 | #include |
35 | #include "i915_drv.h" |
34 | #include "i915_drv.h" |
36 | #include "i915_trace.h" |
35 | #include "i915_trace.h" |
37 | #include "intel_drv.h" |
36 | #include "intel_drv.h" |
Line 38... | Line 37... | ||
38 | 37 | ||
Line 39... | Line 38... | ||
39 | typedef uint32_t gtt_pte_t; |
38 | typedef uint32_t gen6_gtt_pte_t; |
40 | 39 | ||
Line 41... | Line 40... | ||
41 | /* PPGTT stuff */ |
40 | /* PPGTT stuff */ |
Line 50... | Line 49... | ||
50 | #define HSW_PTE_UNCACHED (0) |
49 | #define HSW_PTE_UNCACHED (0) |
51 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
50 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
52 | #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) |
51 | #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) |
53 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
52 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
Line 54... | Line 53... | ||
54 | 53 | ||
55 | static inline gtt_pte_t gen6_pte_encode(struct drm_device *dev, |
54 | static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev, |
56 | dma_addr_t addr, |
55 | dma_addr_t addr, |
57 | enum i915_cache_level level) |
56 | enum i915_cache_level level) |
58 | { |
57 | { |
59 | gtt_pte_t pte = GEN6_PTE_VALID; |
58 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
Line 60... | Line 59... | ||
60 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
59 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
61 | 60 | ||
62 | switch (level) { |
61 | switch (level) { |
Line 78... | Line 77... | ||
78 | break; |
77 | break; |
79 | default: |
78 | default: |
80 | BUG(); |
79 | BUG(); |
81 | } |
80 | } |
Line 82... | Line -... | ||
82 | - | ||
83 | 81 | ||
84 | return pte; |
82 | return pte; |
Line -... | Line 83... | ||
- | 83 | } |
|
- | 84 | ||
- | 85 | static int gen6_ppgtt_enable(struct drm_device *dev) |
|
- | 86 | { |
|
- | 87 | drm_i915_private_t *dev_priv = dev->dev_private; |
|
- | 88 | uint32_t pd_offset; |
|
- | 89 | struct intel_ring_buffer *ring; |
|
- | 90 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
|
- | 91 | gen6_gtt_pte_t __iomem *pd_addr; |
|
- | 92 | uint32_t pd_entry; |
|
- | 93 | int i; |
|
- | 94 | ||
- | 95 | pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm + |
|
- | 96 | ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); |
|
- | 97 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
|
- | 98 | dma_addr_t pt_addr; |
|
- | 99 | ||
- | 100 | pt_addr = ppgtt->pt_dma_addr[i]; |
|
- | 101 | pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); |
|
- | 102 | pd_entry |= GEN6_PDE_VALID; |
|
- | 103 | ||
- | 104 | writel(pd_entry, pd_addr + i); |
|
- | 105 | } |
|
- | 106 | readl(pd_addr); |
|
- | 107 | ||
- | 108 | pd_offset = ppgtt->pd_offset; |
|
- | 109 | pd_offset /= 64; /* in cachelines, */ |
|
- | 110 | pd_offset <<= 16; |
|
- | 111 | ||
- | 112 | if (INTEL_INFO(dev)->gen == 6) { |
|
- | 113 | uint32_t ecochk, gab_ctl, ecobits; |
|
- | 114 | ||
- | 115 | ecobits = I915_READ(GAC_ECO_BITS); |
|
- | 116 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT | |
|
- | 117 | ECOBITS_PPGTT_CACHE64B); |
|
- | 118 | ||
- | 119 | gab_ctl = I915_READ(GAB_CTL); |
|
- | 120 | I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); |
|
- | 121 | ||
- | 122 | ecochk = I915_READ(GAM_ECOCHK); |
|
- | 123 | I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | |
|
- | 124 | ECOCHK_PPGTT_CACHE64B); |
|
- | 125 | I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
|
- | 126 | } else if (INTEL_INFO(dev)->gen >= 7) { |
|
- | 127 | uint32_t ecochk, ecobits; |
|
- | 128 | ||
- | 129 | ecobits = I915_READ(GAC_ECO_BITS); |
|
- | 130 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
|
- | 131 | ||
- | 132 | ecochk = I915_READ(GAM_ECOCHK); |
|
- | 133 | if (IS_HASWELL(dev)) { |
|
- | 134 | ecochk |= ECOCHK_PPGTT_WB_HSW; |
|
- | 135 | } else { |
|
- | 136 | ecochk |= ECOCHK_PPGTT_LLC_IVB; |
|
- | 137 | ecochk &= ~ECOCHK_PPGTT_GFDT_IVB; |
|
- | 138 | } |
|
- | 139 | I915_WRITE(GAM_ECOCHK, ecochk); |
|
- | 140 | /* GFX_MODE is per-ring on gen7+ */ |
|
- | 141 | } |
|
- | 142 | ||
- | 143 | for_each_ring(ring, dev_priv, i) { |
|
- | 144 | if (INTEL_INFO(dev)->gen >= 7) |
|
- | 145 | I915_WRITE(RING_MODE_GEN7(ring), |
|
- | 146 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
|
- | 147 | ||
- | 148 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
|
- | 149 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
|
- | 150 | } |
|
- | 151 | return 0; |
|
85 | } |
152 | } |
86 | 153 | ||
87 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
154 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
88 | static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
155 | static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
89 | unsigned first_entry, |
156 | unsigned first_entry, |
90 | unsigned num_entries) |
- | |
91 | { |
157 | unsigned num_entries) |
92 | gtt_pte_t *pt_vaddr; |
158 | { |
93 | gtt_pte_t scratch_pte; |
159 | gen6_gtt_pte_t *pt_vaddr, scratch_pte; |
94 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; |
160 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
Line 95... | Line 161... | ||
95 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
161 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
96 | unsigned last_pte, i; |
162 | unsigned last_pte, i; |
Line 107... | Line 173... | ||
107 | while (num_entries) { |
173 | while (num_entries) { |
108 | last_pte = first_pte + num_entries; |
174 | last_pte = first_pte + num_entries; |
109 | if (last_pte > I915_PPGTT_PT_ENTRIES) |
175 | if (last_pte > I915_PPGTT_PT_ENTRIES) |
110 | last_pte = I915_PPGTT_PT_ENTRIES; |
176 | last_pte = I915_PPGTT_PT_ENTRIES; |
Line 111... | Line 177... | ||
111 | 177 | ||
Line 112... | Line 178... | ||
112 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pd]), 3); |
178 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
113 | 179 | ||
Line 114... | Line 180... | ||
114 | for (i = first_pte; i < last_pte; i++) |
180 | for (i = first_pte; i < last_pte; i++) |
115 | pt_vaddr[i] = scratch_pte; |
181 | pt_vaddr[i] = scratch_pte; |
116 | 182 | ||
117 | num_entries -= last_pte - first_pte; |
183 | num_entries -= last_pte - first_pte; |
Line 118... | Line 184... | ||
118 | first_pte = 0; |
184 | first_pte = 0; |
119 | act_pd++; |
185 | act_pt++; |
Line 120... | Line 186... | ||
120 | }; |
186 | }; |
121 | 187 | ||
122 | FreeKernelSpace(pt_vaddr); |
188 | FreeKernelSpace(pt_vaddr); |
123 | } |
189 | } |
124 | 190 | ||
125 | static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, |
191 | static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, |
126 | struct sg_table *pages, |
192 | struct sg_table *pages, |
127 | unsigned first_entry, |
193 | unsigned first_entry, |
128 | enum i915_cache_level cache_level) |
194 | enum i915_cache_level cache_level) |
129 | { |
195 | { |
130 | gtt_pte_t *pt_vaddr; |
- | |
Line 131... | Line -... | ||
131 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; |
- | |
132 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
- | |
133 | unsigned i, j, m, segment_len; |
- | |
134 | dma_addr_t page_addr; |
- | |
135 | struct scatterlist *sg; |
- | |
Line 136... | Line 196... | ||
136 | 196 | gen6_gtt_pte_t *pt_vaddr; |
|
Line 137... | Line 197... | ||
137 | /* init sg walking */ |
197 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
138 | sg = pages->sgl; |
198 | unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
Line 139... | Line -... | ||
139 | i = 0; |
- | |
140 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; |
199 | struct sg_page_iter sg_iter; |
- | 200 | dma_addr_t page_addr; |
|
- | 201 | ||
Line 141... | Line -... | ||
141 | m = 0; |
- | |
142 | 202 | ||
143 | pt_vaddr = AllocKernelSpace(4096); |
203 | pt_vaddr = AllocKernelSpace(4096); |
144 | 204 | ||
- | 205 | if(pt_vaddr == NULL) |
|
- | 206 | return; |
|
- | 207 | ||
- | 208 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
|
Line 145... | Line -... | ||
145 | if(pt_vaddr == NULL) |
- | |
146 | return; |
- | |
147 | - | ||
148 | while (i < pages->nents) { |
- | |
149 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pd]), 3); |
- | |
150 | - | ||
151 | for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) { |
- | |
152 | page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
- | |
153 | pt_vaddr[j] = gen6_pte_encode(ppgtt->dev, page_addr, |
- | |
154 | cache_level); |
209 | for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { |
155 | - | ||
156 | /* grab the next page */ |
- | |
157 | if (++m == segment_len) { |
- | |
158 | if (++i == pages->nents) |
210 | dma_addr_t page_addr; |
159 | break; |
211 | |
160 | 212 | page_addr = sg_page_iter_dma_address(&sg_iter); |
|
Line 161... | Line 213... | ||
161 | sg = sg_next(sg); |
213 | pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr, |
Line 197... | Line 249... | ||
197 | int ret = -ENOMEM; |
249 | int ret = -ENOMEM; |
Line 198... | Line 250... | ||
198 | 250 | ||
199 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
251 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
200 | * entries. For aliasing ppgtt support we just steal them at the end for |
252 | * entries. For aliasing ppgtt support we just steal them at the end for |
201 | * now. */ |
253 | * now. */ |
202 | first_pd_entry_in_global_pt = |
- | |
Line 203... | Line 254... | ||
203 | gtt_total_entries(dev_priv->gtt) - I915_PPGTT_PD_ENTRIES; |
254 | first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt); |
- | 255 | ||
204 | 256 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
|
205 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
257 | ppgtt->enable = gen6_ppgtt_enable; |
206 | ppgtt->clear_range = gen6_ppgtt_clear_range; |
258 | ppgtt->clear_range = gen6_ppgtt_clear_range; |
207 | ppgtt->insert_entries = gen6_ppgtt_insert_entries; |
259 | ppgtt->insert_entries = gen6_ppgtt_insert_entries; |
208 | ppgtt->cleanup = gen6_ppgtt_cleanup; |
260 | ppgtt->cleanup = gen6_ppgtt_cleanup; |
Line 229... | Line 281... | ||
229 | PCI_DMA_BIDIRECTIONAL); |
281 | PCI_DMA_BIDIRECTIONAL); |
Line 230... | Line 282... | ||
230 | 282 | ||
231 | ppgtt->pt_dma_addr[i] = pt_addr; |
283 | ppgtt->pt_dma_addr[i] = pt_addr; |
Line 232... | Line -... | ||
232 | } |
- | |
233 | - | ||
234 | ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; |
284 | } |
235 | 285 | ||
Line 236... | Line 286... | ||
236 | ppgtt->clear_range(ppgtt, 0, |
286 | ppgtt->clear_range(ppgtt, 0, |
Line 237... | Line 287... | ||
237 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
287 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
Line 238... | Line 288... | ||
238 | 288 | ||
239 | ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); |
289 | ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); |
Line 266... | Line 316... | ||
266 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
316 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
267 | if (!ppgtt) |
317 | if (!ppgtt) |
268 | return -ENOMEM; |
318 | return -ENOMEM; |
Line 269... | Line 319... | ||
269 | 319 | ||
- | 320 | ppgtt->dev = dev; |
|
Line -... | Line 321... | ||
- | 321 | ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; |
|
270 | ppgtt->dev = dev; |
322 | |
- | 323 | if (INTEL_INFO(dev)->gen < 8) |
|
- | 324 | ret = gen6_ppgtt_init(ppgtt); |
|
- | 325 | else |
|
271 | 326 | BUG(); |
|
272 | ret = gen6_ppgtt_init(ppgtt); |
327 | |
273 | if (ret) |
328 | if (ret) |
274 | kfree(ppgtt); |
329 | kfree(ppgtt); |
Line 285... | Line 340... | ||
285 | 340 | ||
286 | if (!ppgtt) |
341 | if (!ppgtt) |
Line 287... | Line 342... | ||
287 | return; |
342 | return; |
- | 343 | ||
288 | 344 | ppgtt->cleanup(ppgtt); |
|
Line 289... | Line 345... | ||
289 | ppgtt->cleanup(ppgtt); |
345 | dev_priv->mm.aliasing_ppgtt = NULL; |
290 | } |
346 | } |
291 | 347 | ||
Line 304... | Line 360... | ||
304 | ppgtt->clear_range(ppgtt, |
360 | ppgtt->clear_range(ppgtt, |
305 | obj->gtt_space->start >> PAGE_SHIFT, |
361 | obj->gtt_space->start >> PAGE_SHIFT, |
306 | obj->base.size >> PAGE_SHIFT); |
362 | obj->base.size >> PAGE_SHIFT); |
307 | } |
363 | } |
Line 308... | Line -... | ||
308 | - | ||
309 | void i915_gem_init_ppgtt(struct drm_device *dev) |
- | |
310 | { |
- | |
311 | drm_i915_private_t *dev_priv = dev->dev_private; |
- | |
312 | uint32_t pd_offset; |
- | |
313 | struct intel_ring_buffer *ring; |
- | |
314 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
- | |
315 | gtt_pte_t __iomem *pd_addr; |
- | |
316 | uint32_t pd_entry; |
- | |
317 | int i; |
- | |
318 | - | ||
319 | if (!dev_priv->mm.aliasing_ppgtt) |
- | |
320 | return; |
- | |
321 | - | ||
322 | - | ||
323 | pd_addr = (gtt_pte_t __iomem*)dev_priv->gtt.gsm + ppgtt->pd_offset/sizeof(gtt_pte_t); |
- | |
324 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
- | |
325 | dma_addr_t pt_addr; |
- | |
326 | - | ||
327 | pt_addr = ppgtt->pt_dma_addr[i]; |
- | |
328 | pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); |
- | |
329 | pd_entry |= GEN6_PDE_VALID; |
- | |
330 | - | ||
331 | writel(pd_entry, pd_addr + i); |
- | |
332 | } |
- | |
333 | readl(pd_addr); |
- | |
334 | - | ||
335 | pd_offset = ppgtt->pd_offset; |
- | |
336 | pd_offset /= 64; /* in cachelines, */ |
- | |
337 | pd_offset <<= 16; |
- | |
338 | - | ||
339 | if (INTEL_INFO(dev)->gen == 6) { |
- | |
340 | uint32_t ecochk, gab_ctl, ecobits; |
- | |
341 | - | ||
342 | ecobits = I915_READ(GAC_ECO_BITS); |
- | |
343 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
- | |
344 | - | ||
345 | gab_ctl = I915_READ(GAB_CTL); |
- | |
346 | I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); |
- | |
347 | - | ||
348 | ecochk = I915_READ(GAM_ECOCHK); |
- | |
349 | I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | |
- | |
350 | ECOCHK_PPGTT_CACHE64B); |
- | |
351 | I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
- | |
352 | } else if (INTEL_INFO(dev)->gen >= 7) { |
- | |
353 | I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B); |
- | |
354 | /* GFX_MODE is per-ring on gen7+ */ |
- | |
355 | } |
- | |
356 | - | ||
357 | for_each_ring(ring, dev_priv, i) { |
- | |
358 | if (INTEL_INFO(dev)->gen >= 7) |
- | |
359 | I915_WRITE(RING_MODE_GEN7(ring), |
- | |
360 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
- | |
361 | - | ||
362 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
- | |
363 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
- | |
364 | } |
- | |
365 | } |
- | |
366 | 364 | ||
367 | extern int intel_iommu_gfx_mapped; |
365 | extern int intel_iommu_gfx_mapped; |
368 | /* Certain Gen5 chipsets require require idling the GPU before |
366 | /* Certain Gen5 chipsets require require idling the GPU before |
369 | * unmapping anything from the GTT when VT-d is enabled. |
367 | * unmapping anything from the GTT when VT-d is enabled. |
370 | */ |
368 | */ |
Line 442... | Line 440... | ||
442 | struct sg_table *st, |
440 | struct sg_table *st, |
443 | unsigned int first_entry, |
441 | unsigned int first_entry, |
444 | enum i915_cache_level level) |
442 | enum i915_cache_level level) |
445 | { |
443 | { |
446 | struct drm_i915_private *dev_priv = dev->dev_private; |
444 | struct drm_i915_private *dev_priv = dev->dev_private; |
447 | struct scatterlist *sg = st->sgl; |
- | |
448 | gtt_pte_t __iomem *gtt_entries = |
445 | gen6_gtt_pte_t __iomem *gtt_entries = |
449 | (gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; |
446 | (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; |
450 | int unused, i = 0; |
447 | int i = 0; |
451 | unsigned int len, m = 0; |
448 | struct sg_page_iter sg_iter; |
452 | dma_addr_t addr; |
449 | dma_addr_t addr; |
Line 453... | Line 450... | ||
453 | 450 | ||
454 | for_each_sg(st->sgl, sg, st->nents, unused) { |
- | |
455 | len = sg_dma_len(sg) >> PAGE_SHIFT; |
- | |
456 | for (m = 0; m < len; m++) { |
451 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { |
457 | addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
452 | addr = sg_page_iter_dma_address(&sg_iter); |
458 | iowrite32(gen6_pte_encode(dev, addr, level), |
- | |
459 | >t_entries[i]); |
453 | iowrite32(gen6_pte_encode(dev, addr, level), >t_entries[i]); |
460 | i++; |
454 | i++; |
461 | } |
- | |
Line 462... | Line 455... | ||
462 | } |
455 | } |
463 | 456 | ||
464 | /* XXX: This serves as a posting read to make sure that the PTE has |
457 | /* XXX: This serves as a posting read to make sure that the PTE has |
465 | * actually been updated. There is some concern that even though |
458 | * actually been updated. There is some concern that even though |
Line 482... | Line 475... | ||
482 | static void gen6_ggtt_clear_range(struct drm_device *dev, |
475 | static void gen6_ggtt_clear_range(struct drm_device *dev, |
483 | unsigned int first_entry, |
476 | unsigned int first_entry, |
484 | unsigned int num_entries) |
477 | unsigned int num_entries) |
485 | { |
478 | { |
486 | struct drm_i915_private *dev_priv = dev->dev_private; |
479 | struct drm_i915_private *dev_priv = dev->dev_private; |
487 | gtt_pte_t scratch_pte; |
480 | gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = |
488 | gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; |
481 | (gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; |
489 | const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; |
482 | const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; |
490 | int i; |
483 | int i; |
Line 491... | Line 484... | ||
491 | 484 | ||
492 | if (WARN(num_entries > max_entries, |
485 | // if (WARN(num_entries > max_entries, |
493 | "First entry = %d; Num entries = %d (max=%d)\n", |
486 | // "First entry = %d; Num entries = %d (max=%d)\n", |
- | 487 | // first_entry, num_entries, max_entries)) |
|
494 | first_entry, num_entries, max_entries)) |
488 | if (num_entries > max_entries) |
Line 495... | Line 489... | ||
495 | num_entries = max_entries; |
489 | num_entries = max_entries; |
496 | 490 | ||
497 | scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma, |
491 | scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma, |
Line 655... | Line 649... | ||
655 | unsigned long gtt_size, mappable_size; |
649 | unsigned long gtt_size, mappable_size; |
Line 656... | Line 650... | ||
656 | 650 | ||
657 | gtt_size = dev_priv->gtt.total; |
651 | gtt_size = dev_priv->gtt.total; |
Line -... | Line 652... | ||
- | 652 | mappable_size = dev_priv->gtt.mappable_end; |
|
658 | mappable_size = dev_priv->gtt.mappable_end; |
653 | |
659 | 654 | #if 0 |
|
- | 655 | if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { |
|
- | 656 | int ret; |
|
660 | if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { |
657 | |
661 | int ret; |
658 | if (INTEL_INFO(dev)->gen <= 7) { |
662 | /* PPGTT pdes are stolen from global gtt ptes, so shrink the |
659 | /* PPGTT pdes are stolen from global gtt ptes, so shrink the |
- | 660 | * aperture accordingly when using aliasing ppgtt. */ |
|
- | 661 | gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
|
663 | * aperture accordingly when using aliasing ppgtt. */ |
662 | } |
Line 664... | Line 663... | ||
664 | gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
663 | |
Line 665... | Line 664... | ||
665 | gtt_size -= LFB_SIZE; |
664 | // gtt_size -= LFB_SIZE; |
666 | 665 | ||
Line 672... | Line 671... | ||
672 | 671 | ||
673 | DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); |
672 | DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); |
674 | drm_mm_takedown(&dev_priv->mm.gtt_space); |
673 | drm_mm_takedown(&dev_priv->mm.gtt_space); |
675 | gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
674 | gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
- | 675 | } |
|
- | 676 | #endif |
|
676 | } |
677 | |
677 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size); |
678 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size); |
Line 678... | Line 679... | ||
678 | } |
679 | } |
679 | 680 | ||
Line 725... | Line 726... | ||
725 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
726 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
726 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
727 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
727 | return snb_gmch_ctl << 25; /* 32 MB units */ |
728 | return snb_gmch_ctl << 25; /* 32 MB units */ |
728 | } |
729 | } |
Line 729... | Line -... | ||
729 | - | ||
730 | static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl) |
- | |
731 | { |
- | |
732 | static const int stolen_decoder[] = { |
- | |
733 | 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352}; |
- | |
734 | snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT; |
- | |
735 | snb_gmch_ctl &= IVB_GMCH_GMS_MASK; |
- | |
736 | return stolen_decoder[snb_gmch_ctl] << 20; |
- | |
737 | } |
- | |
738 | 730 | ||
739 | static int gen6_gmch_probe(struct drm_device *dev, |
731 | static int gen6_gmch_probe(struct drm_device *dev, |
740 | size_t *gtt_total, |
732 | size_t *gtt_total, |
741 | size_t *stolen, |
733 | size_t *stolen, |
742 | phys_addr_t *mappable_base, |
734 | phys_addr_t *mappable_base, |
Line 763... | Line 755... | ||
763 | if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) |
755 | if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) |
764 | pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); |
756 | pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); |
765 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
757 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
766 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
758 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
Line 767... | Line -... | ||
767 | - | ||
768 | if (IS_GEN7(dev)) |
- | |
769 | *stolen = gen7_get_stolen_size(snb_gmch_ctl); |
- | |
770 | else |
759 | |
- | 760 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
|
Line -... | Line 761... | ||
- | 761 | *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; |
|
771 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
762 | |
- | 763 | /* For Modern GENs the PTEs and register space are split in the BAR */ |
|
Line 772... | Line -... | ||
772 | - | ||
773 | *gtt_total = (gtt_size / sizeof(gtt_pte_t)) << PAGE_SHIFT; |
- | |
774 | 764 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + |
|
775 | /* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */ |
765 | (pci_resource_len(dev->pdev, 0) / 2); |
776 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + (2<<20); |
766 | |
777 | dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); |
767 | dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); |
778 | if (!dev_priv->gtt.gsm) { |
768 | if (!dev_priv->gtt.gsm) { |
Line 828... | Line 818... | ||
828 | 818 | ||
829 | int i915_gem_gtt_init(struct drm_device *dev) |
819 | int i915_gem_gtt_init(struct drm_device *dev) |
830 | { |
820 | { |
831 | struct drm_i915_private *dev_priv = dev->dev_private; |
821 | struct drm_i915_private *dev_priv = dev->dev_private; |
832 | struct i915_gtt *gtt = &dev_priv->gtt; |
- | |
833 | unsigned long gtt_size; |
822 | struct i915_gtt *gtt = &dev_priv->gtt; |
Line 834... | Line 823... | ||
834 | int ret; |
823 | int ret; |
835 | 824 | ||
836 | if (INTEL_INFO(dev)->gen <= 5) { |
825 | if (INTEL_INFO(dev)->gen <= 5) { |
Line 846... | Line 835... | ||
846 | >t->mappable_base, |
835 | >t->mappable_base, |
847 | >t->mappable_end); |
836 | >t->mappable_end); |
848 | if (ret) |
837 | if (ret) |
849 | return ret; |
838 | return ret; |
Line 850... | Line -... | ||
850 | - | ||
851 | gtt_size = (dev_priv->gtt.total >> PAGE_SHIFT) * sizeof(gtt_pte_t); |
- | |
852 | 839 | ||
853 | /* GMADR is the PCI mmio aperture into the global GTT. */ |
840 | /* GMADR is the PCI mmio aperture into the global GTT. */ |
854 | DRM_INFO("Memory usable by graphics device = %zdM\n", |
841 | DRM_INFO("Memory usable by graphics device = %zdM\n", |
855 | dev_priv->gtt.total >> 20); |
842 | dev_priv->gtt.total >> 20); |
856 | DRM_DEBUG_DRIVER("GMADR size = %ldM\n", |
843 | DRM_DEBUG_DRIVER("GMADR size = %ldM\n", |
Line 995... | Line 982... | ||
995 | } |
982 | } |
996 | #endif |
983 | #endif |
997 | sg_mark_end(&sgl[nents - 1]); |
984 | sg_mark_end(&sgl[nents - 1]); |
998 | }>=>20); |
985 | } |
Line -... | Line 986... | ||
- | 986 | ||
- | 987 | ||
- | 988 | void __sg_page_iter_start(struct sg_page_iter *piter, |
|
- | 989 | struct scatterlist *sglist, unsigned int nents, |
|
- | 990 | unsigned long pgoffset) |
|
- | 991 | { |
|
- | 992 | piter->__pg_advance = 0; |
|
- | 993 | piter->__nents = nents; |
|
- | 994 | ||
- | 995 | piter->sg = sglist; |
|
- | 996 | piter->sg_pgoffset = pgoffset; |
|
- | 997 | } |
|
- | 998 | ||
- | 999 | static int sg_page_count(struct scatterlist *sg) |
|
- | 1000 | { |
|
- | 1001 | return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT; |
|
- | 1002 | } |
|
- | 1003 | ||
- | 1004 | bool __sg_page_iter_next(struct sg_page_iter *piter) |
|
- | 1005 | { |
|
- | 1006 | if (!piter->__nents || !piter->sg) |
|
- | 1007 | return false; |
|
- | 1008 | ||
- | 1009 | piter->sg_pgoffset += piter->__pg_advance; |
|
- | 1010 | piter->__pg_advance = 1; |
|
- | 1011 | ||
- | 1012 | while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { |
|
- | 1013 | piter->sg_pgoffset -= sg_page_count(piter->sg); |
|
- | 1014 | piter->sg = sg_next(piter->sg); |
|
- | 1015 | if (!--piter->__nents || !piter->sg) |
|
- | 1016 | return false; |
|
- | 1017 | } |
|
- | 1018 | ||
- | 1019 | return true; |
|
- | 1020 | } |
|
- | 1021 | EXPORT_SYMBOL(__sg_page_iter_next);>=>><>20))))><20))))>20)><20)>>><>><>=>>>>>>>>>=><=>>><>><>><>><>><>><> |
|
- | 1022 |