Rev 3243 | Rev 3746 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3243 | Rev 3480 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | * |
22 | * |
23 | */ |
23 | */ |
Line 24... | Line 24... | ||
24 | 24 | ||
Line -... | Line 25... | ||
- | 25 | #define iowrite32(v, addr) writel((v), (addr)) |
|
- | 26 | ||
- | 27 | #define AGP_NORMAL_MEMORY 0 |
|
- | 28 | ||
- | 29 | #define AGP_USER_TYPES (1 << 16) |
|
- | 30 | #define AGP_USER_MEMORY (AGP_USER_TYPES) |
|
25 | #define iowrite32(v, addr) writel((v), (addr)) |
31 | #define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) |
26 | 32 | ||
27 | #include |
33 | #include |
28 | #include |
34 | #include |
29 | #include "i915_drv.h" |
35 | #include "i915_drv.h" |
Line 30... | Line -... | ||
30 | #include "i915_trace.h" |
- | |
31 | #include "intel_drv.h" |
- | |
32 | - | ||
33 | #define AGP_USER_TYPES (1 << 16) |
- | |
34 | #define AGP_USER_MEMORY (AGP_USER_TYPES) |
36 | #include "i915_trace.h" |
Line 35... | Line 37... | ||
35 | #define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) |
37 | #include "intel_drv.h" |
36 | 38 | ||
Line 48... | Line 50... | ||
48 | #define HSW_PTE_UNCACHED (0) |
50 | #define HSW_PTE_UNCACHED (0) |
49 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
51 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
50 | #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) |
52 | #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) |
51 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
53 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
Line 52... | Line 54... | ||
52 | 54 | ||
53 | static inline gtt_pte_t pte_encode(struct drm_device *dev, |
55 | static inline gtt_pte_t gen6_pte_encode(struct drm_device *dev, |
54 | dma_addr_t addr, |
56 | dma_addr_t addr, |
55 | enum i915_cache_level level) |
57 | enum i915_cache_level level) |
56 | { |
58 | { |
57 | gtt_pte_t pte = GEN6_PTE_VALID; |
59 | gtt_pte_t pte = GEN6_PTE_VALID; |
Line 81... | Line 83... | ||
81 | 83 | ||
82 | return pte; |
84 | return pte; |
Line 83... | Line 85... | ||
83 | } |
85 | } |
84 | 86 | ||
85 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
87 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
86 | static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
88 | static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
87 | unsigned first_entry, |
89 | unsigned first_entry, |
88 | unsigned num_entries) |
90 | unsigned num_entries) |
89 | { |
91 | { |
90 | gtt_pte_t *pt_vaddr; |
92 | gtt_pte_t *pt_vaddr; |
91 | gtt_pte_t scratch_pte; |
93 | gtt_pte_t scratch_pte; |
92 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; |
94 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; |
Line -... | Line 95... | ||
- | 95 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
|
93 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
96 | unsigned last_pte, i; |
94 | unsigned last_pte, i; |
97 | |
Line 95... | Line 98... | ||
95 | 98 | scratch_pte = gen6_pte_encode(ppgtt->dev, |
|
Line 96... | Line 99... | ||
96 | scratch_pte = pte_encode(ppgtt->dev, ppgtt->scratch_page_dma_addr, |
99 | ppgtt->scratch_page_dma_addr, |
97 | I915_CACHE_LLC); |
100 | I915_CACHE_LLC); |
- | 101 | ||
98 | 102 | pt_vaddr = AllocKernelSpace(4096); |
|
99 | pt_vaddr = AllocKernelSpace(4096); |
- | |
100 | 103 | ||
101 | if(pt_vaddr != NULL) |
104 | if(pt_vaddr == NULL) |
102 | { |
105 | return; |
Line 103... | Line 106... | ||
103 | while (num_entries) |
106 | |
Line 112... | Line 115... | ||
112 | pt_vaddr[i] = scratch_pte; |
115 | pt_vaddr[i] = scratch_pte; |
Line 113... | Line 116... | ||
113 | 116 | ||
114 | num_entries -= last_pte - first_pte; |
117 | num_entries -= last_pte - first_pte; |
115 | first_pte = 0; |
118 | first_pte = 0; |
- | 119 | act_pd++; |
|
- | 120 | }; |
|
- | 121 | ||
- | 122 | FreeKernelSpace(pt_vaddr); |
|
- | 123 | } |
|
- | 124 | ||
- | 125 | static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, |
|
- | 126 | struct sg_table *pages, |
|
- | 127 | unsigned first_entry, |
|
- | 128 | enum i915_cache_level cache_level) |
|
- | 129 | { |
|
- | 130 | gtt_pte_t *pt_vaddr; |
|
- | 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; |
|
- | 136 | ||
- | 137 | /* init sg walking */ |
|
- | 138 | sg = pages->sgl; |
|
- | 139 | i = 0; |
|
- | 140 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; |
|
- | 141 | m = 0; |
|
- | 142 | ||
- | 143 | pt_vaddr = AllocKernelSpace(4096); |
|
- | 144 | ||
- | 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); |
|
- | 155 | ||
- | 156 | /* grab the next page */ |
|
- | 157 | if (++m == segment_len) { |
|
- | 158 | if (++i == pages->nents) |
|
- | 159 | break; |
|
- | 160 | ||
- | 161 | sg = sg_next(sg); |
|
- | 162 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; |
|
- | 163 | m = 0; |
|
- | 164 | } |
|
- | 165 | } |
|
- | 166 | ||
- | 167 | first_pte = 0; |
|
116 | act_pd++; |
168 | act_pd++; |
117 | } |
169 | } |
118 | FreeKernelSpace(pt_vaddr); |
- | |
119 | }; |
170 | FreeKernelSpace(pt_vaddr); |
Line 120... | Line 171... | ||
120 | } |
171 | } |
- | 172 | ||
- | 173 | static void gen6_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt) |
|
- | 174 | { |
|
- | 175 | int i; |
|
- | 176 | ||
- | 177 | if (ppgtt->pt_dma_addr) { |
|
- | 178 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
|
- | 179 | pci_unmap_page(ppgtt->dev->pdev, |
|
- | 180 | ppgtt->pt_dma_addr[i], |
|
- | 181 | 4096, PCI_DMA_BIDIRECTIONAL); |
|
- | 182 | } |
|
- | 183 | ||
- | 184 | kfree(ppgtt->pt_dma_addr); |
|
- | 185 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
|
- | 186 | __free_page(ppgtt->pt_pages[i]); |
|
- | 187 | kfree(ppgtt->pt_pages); |
|
- | 188 | kfree(ppgtt); |
|
- | 189 | } |
|
121 | 190 | ||
- | 191 | static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) |
|
122 | int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) |
192 | { |
123 | { |
- | |
124 | struct drm_i915_private *dev_priv = dev->dev_private; |
193 | struct drm_device *dev = ppgtt->dev; |
125 | struct i915_hw_ppgtt *ppgtt; |
194 | struct drm_i915_private *dev_priv = dev->dev_private; |
126 | unsigned first_pd_entry_in_global_pt; |
195 | unsigned first_pd_entry_in_global_pt; |
Line 127... | Line 196... | ||
127 | int i; |
196 | int i; |
128 | int ret = -ENOMEM; |
197 | int ret = -ENOMEM; |
129 | 198 | ||
130 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
199 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
131 | * entries. For aliasing ppgtt support we just steal them at the end for |
- | |
132 | * now. */ |
200 | * entries. For aliasing ppgtt support we just steal them at the end for |
133 | first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; |
- | |
134 | - | ||
Line 135... | Line 201... | ||
135 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
201 | * now. */ |
- | 202 | first_pd_entry_in_global_pt = |
|
- | 203 | gtt_total_entries(dev_priv->gtt) - I915_PPGTT_PD_ENTRIES; |
|
- | 204 | ||
136 | if (!ppgtt) |
205 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
137 | return ret; |
206 | ppgtt->clear_range = gen6_ppgtt_clear_range; |
138 | 207 | ppgtt->insert_entries = gen6_ppgtt_insert_entries; |
|
139 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
208 | ppgtt->cleanup = gen6_ppgtt_cleanup; |
Line 140... | Line 209... | ||
140 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, |
209 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, |
141 | GFP_KERNEL); |
210 | GFP_KERNEL); |
142 | if (!ppgtt->pt_pages) |
211 | if (!ppgtt->pt_pages) |
143 | goto err_ppgtt; |
212 | return -ENOMEM; |
144 | 213 | ||
Line 145... | Line -... | ||
145 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
- | |
146 | ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL); |
- | |
147 | if (!ppgtt->pt_pages[i]) |
214 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
148 | goto err_pt_alloc; |
- | |
149 | } |
215 | ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL); |
150 | 216 | if (!ppgtt->pt_pages[i]) |
|
151 | /* |
217 | goto err_pt_alloc; |
Line 152... | Line 218... | ||
152 | if (dev_priv->mm.gtt->needs_dmar) { |
218 | } |
153 | ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) |
219 | |
Line 154... | Line 220... | ||
154 | *ppgtt->num_pd_entries, |
220 | ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, |
155 | GFP_KERNEL); |
- | |
156 | if (!ppgtt->pt_dma_addr) |
221 | GFP_KERNEL); |
Line 157... | Line -... | ||
157 | goto err_pt_alloc; |
- | |
158 | - | ||
159 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
- | |
160 | dma_addr_t pt_addr; |
- | |
161 | - | ||
162 | pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], |
- | |
163 | 0, 4096, |
222 | if (!ppgtt->pt_dma_addr) |
164 | PCI_DMA_BIDIRECTIONAL); |
223 | goto err_pt_alloc; |
165 | - | ||
166 | if (pci_dma_mapping_error(dev->pdev, |
- | |
167 | pt_addr)) { |
- | |
Line -... | Line 224... | ||
- | 224 | ||
- | 225 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
|
168 | ret = -EIO; |
226 | dma_addr_t pt_addr; |
169 | goto err_pd_pin; |
227 | |
Line 170... | Line 228... | ||
170 | 228 | pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], 0, 4096, |
|
Line 171... | Line -... | ||
171 | } |
- | |
172 | ppgtt->pt_dma_addr[i] = pt_addr; |
- | |
173 | } |
229 | PCI_DMA_BIDIRECTIONAL); |
Line 174... | Line 230... | ||
174 | } |
230 | |
175 | */ |
231 | ppgtt->pt_dma_addr[i] = pt_addr; |
176 | ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma; |
232 | } |
177 | 233 | ||
178 | i915_ppgtt_clear_range(ppgtt, 0, |
234 | ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; |
179 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
235 | |
180 | 236 | ppgtt->clear_range(ppgtt, 0, |
|
181 | ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); |
237 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
182 | 238 | ||
183 | dev_priv->mm.aliasing_ppgtt = ppgtt; |
239 | ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); |
184 | 240 | ||
185 | return 0; |
241 | return 0; |
186 | 242 | ||
187 | err_pd_pin: |
- | |
188 | // if (ppgtt->pt_dma_addr) { |
- | |
Line 189... | Line 243... | ||
189 | // for (i--; i >= 0; i--) |
243 | err_pd_pin: |
190 | // pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], |
244 | if (ppgtt->pt_dma_addr) { |
Line 191... | Line 245... | ||
191 | // 4096, PCI_DMA_BIDIRECTIONAL); |
245 | for (i--; i >= 0; i--) |
192 | // } |
246 | pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], |
193 | err_pt_alloc: |
247 | 4096, PCI_DMA_BIDIRECTIONAL); |
194 | // kfree(ppgtt->pt_dma_addr); |
248 | } |
195 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
249 | err_pt_alloc: |
Line -... | Line 250... | ||
- | 250 | kfree(ppgtt->pt_dma_addr); |
|
196 | if (ppgtt->pt_pages[i]) |
251 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
197 | FreePage((addr_t)(ppgtt->pt_pages[i])); |
252 | if (ppgtt->pt_pages[i]) |
Line 198... | Line 253... | ||
198 | } |
253 | __free_page(ppgtt->pt_pages[i]); |
199 | kfree(ppgtt->pt_pages); |
- | |
200 | err_ppgtt: |
- | |
201 | kfree(ppgtt); |
- | |
202 | - | ||
Line 203... | Line 254... | ||
203 | return ret; |
254 | } |
204 | } |
- | |
205 | - | ||
206 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) |
255 | kfree(ppgtt->pt_pages); |
207 | { |
256 | |
- | 257 | return ret; |
|
- | 258 | } |
|
- | 259 | ||
- | 260 | static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) |
|
208 | struct drm_i915_private *dev_priv = dev->dev_private; |
261 | { |
Line 209... | Line 262... | ||
209 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
262 | struct drm_i915_private *dev_priv = dev->dev_private; |
210 | int i; |
- | |
211 | - | ||
212 | if (!ppgtt) |
- | |
213 | return; |
263 | struct i915_hw_ppgtt *ppgtt; |
214 | - | ||
215 | // if (ppgtt->pt_dma_addr) { |
264 | int ret; |
216 | // for (i = 0; i < ppgtt->num_pd_entries; i++) |
265 | |
217 | // pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], |
- | |
218 | // 4096, PCI_DMA_BIDIRECTIONAL); |
- | |
219 | // } |
- | |
220 | - | ||
221 | // kfree(ppgtt->pt_dma_addr); |
- | |
222 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
- | |
223 | FreePage((addr_t)(ppgtt->pt_pages[i])); |
- | |
224 | kfree(ppgtt->pt_pages); |
- | |
225 | kfree(ppgtt); |
- | |
Line 226... | Line -... | ||
226 | } |
- | |
227 | 266 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
|
228 | static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt, |
267 | if (!ppgtt) |
Line 229... | Line -... | ||
229 | const struct sg_table *pages, |
- | |
230 | unsigned first_entry, |
- | |
231 | enum i915_cache_level cache_level) |
- | |
232 | { |
- | |
233 | gtt_pte_t *pt_vaddr; |
- | |
234 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; |
- | |
235 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
- | |
236 | unsigned i, j, m, segment_len; |
- | |
237 | dma_addr_t page_addr; |
- | |
238 | struct scatterlist *sg; |
- | |
239 | - | ||
240 | /* init sg walking */ |
- | |
241 | sg = pages->sgl; |
- | |
242 | i = 0; |
268 | return -ENOMEM; |
243 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; |
- | |
244 | m = 0; |
- | |
245 | - | ||
246 | pt_vaddr = AllocKernelSpace(4096); |
- | |
247 | if( pt_vaddr == NULL) |
- | |
248 | return; |
- | |
249 | - | ||
250 | while (i < pages->nents) { |
- | |
251 | MapPage(pt_vaddr,(addr_t)ppgtt->pt_pages[act_pd], 3); |
- | |
252 | - | ||
253 | for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) { |
269 | |
Line 254... | Line 270... | ||
254 | page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
270 | ppgtt->dev = dev; |
255 | pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr, |
271 | |
256 | cache_level); |
272 | ret = gen6_ppgtt_init(ppgtt); |
257 | 273 | if (ret) |
|
258 | /* grab the next page */ |
274 | kfree(ppgtt); |
259 | if (++m == segment_len) { |
- | |
260 | if (++i == pages->nents) |
275 | else |
261 | break; |
276 | dev_priv->mm.aliasing_ppgtt = ppgtt; |
262 | 277 | ||
Line 263... | Line 278... | ||
263 | sg = sg_next(sg); |
278 | return ret; |
264 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; |
279 | } |
265 | m = 0; |
280 | |
266 | } |
281 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) |
267 | } |
282 | { |
268 | 283 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
269 | 284 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
|
Line 270... | Line 285... | ||
270 | first_pte = 0; |
285 | |
271 | act_pd++; |
286 | if (!ppgtt) |
272 | } |
287 | return; |
273 | FreeKernelSpace(pt_vaddr); |
288 | |
274 | } |
289 | ppgtt->cleanup(ppgtt); |
275 | 290 | } |
|
276 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
291 | |
277 | struct drm_i915_gem_object *obj, |
292 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
278 | enum i915_cache_level cache_level) |
293 | struct drm_i915_gem_object *obj, |
Line 279... | Line 294... | ||
279 | { |
294 | enum i915_cache_level cache_level) |
280 | i915_ppgtt_insert_sg_entries(ppgtt, |
295 | { |
Line 281... | Line 296... | ||
281 | obj->pages, |
296 | ppgtt->insert_entries(ppgtt, obj->pages, |
282 | obj->gtt_space->start >> PAGE_SHIFT, |
297 | obj->gtt_space->start >> PAGE_SHIFT, |
283 | cache_level); |
298 | cache_level); |
Line 284... | Line -... | ||
284 | } |
- | |
285 | 299 | } |
|
286 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
- | |
287 | struct drm_i915_gem_object *obj) |
- | |
288 | { |
- | |
289 | i915_ppgtt_clear_range(ppgtt, |
300 | |
290 | obj->gtt_space->start >> PAGE_SHIFT, |
301 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
Line 291... | Line 302... | ||
291 | obj->base.size >> PAGE_SHIFT); |
302 | struct drm_i915_gem_object *obj) |
292 | } |
303 | { |
Line 351... | Line 362... | ||
351 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
362 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
352 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
363 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
353 | } |
364 | } |
354 | } |
365 | } |
Line -... | Line 366... | ||
- | 366 | ||
- | 367 | extern int intel_iommu_gfx_mapped; |
|
- | 368 | /* Certain Gen5 chipsets require require idling the GPU before |
|
- | 369 | * unmapping anything from the GTT when VT-d is enabled. |
|
- | 370 | */ |
|
- | 371 | static inline bool needs_idle_maps(struct drm_device *dev) |
|
- | 372 | { |
|
- | 373 | #ifdef CONFIG_INTEL_IOMMU |
|
- | 374 | /* Query intel_iommu to see if we need the workaround. Presumably that |
|
- | 375 | * was loaded first. |
|
- | 376 | */ |
|
- | 377 | if (IS_GEN5(dev) && IS_MOBILE(dev) && intel_iommu_gfx_mapped) |
|
- | 378 | return true; |
|
- | 379 | #endif |
|
- | 380 | return false; |
|
- | 381 | } |
|
355 | 382 | ||
356 | static bool do_idling(struct drm_i915_private *dev_priv) |
383 | static bool do_idling(struct drm_i915_private *dev_priv) |
357 | { |
384 | { |
Line 358... | Line 385... | ||
358 | bool ret = dev_priv->mm.interruptible; |
385 | bool ret = dev_priv->mm.interruptible; |
359 | 386 | ||
360 | if (unlikely(dev_priv->mm.gtt->do_idle_maps)) { |
387 | if (unlikely(dev_priv->gtt.do_idle_maps)) { |
361 | dev_priv->mm.interruptible = false; |
388 | dev_priv->mm.interruptible = false; |
362 | if (i915_gpu_idle(dev_priv->dev)) { |
389 | if (i915_gpu_idle(dev_priv->dev)) { |
363 | DRM_ERROR("Couldn't idle GPU\n"); |
390 | DRM_ERROR("Couldn't idle GPU\n"); |
Line 369... | Line 396... | ||
369 | return ret; |
396 | return ret; |
370 | } |
397 | } |
Line 371... | Line 398... | ||
371 | 398 | ||
372 | static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) |
399 | static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) |
373 | { |
400 | { |
374 | if (unlikely(dev_priv->mm.gtt->do_idle_maps)) |
401 | if (unlikely(dev_priv->gtt.do_idle_maps)) |
375 | dev_priv->mm.interruptible = interruptible; |
402 | dev_priv->mm.interruptible = interruptible; |
Line 376... | Line -... | ||
376 | } |
- | |
377 | - | ||
378 | - | ||
379 | static void i915_ggtt_clear_range(struct drm_device *dev, |
- | |
380 | unsigned first_entry, |
- | |
381 | unsigned num_entries) |
- | |
382 | { |
- | |
383 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
384 | gtt_pte_t scratch_pte; |
- | |
385 | gtt_pte_t __iomem *gtt_base = dev_priv->mm.gtt->gtt + first_entry; |
- | |
386 | const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; |
- | |
387 | int i; |
- | |
388 | - | ||
389 | if (INTEL_INFO(dev)->gen < 6) { |
- | |
390 | intel_gtt_clear_range(first_entry, num_entries); |
- | |
391 | return; |
- | |
392 | } |
- | |
393 | - | ||
394 | if (WARN(num_entries > max_entries, |
- | |
395 | "First entry = %d; Num entries = %d (max=%d)\n", |
- | |
396 | first_entry, num_entries, max_entries)) |
- | |
397 | num_entries = max_entries; |
- | |
398 | - | ||
399 | scratch_pte = pte_encode(dev, dev_priv->mm.gtt->scratch_page_dma, I915_CACHE_LLC); |
- | |
400 | for (i = 0; i < num_entries; i++) |
- | |
401 | iowrite32(scratch_pte, >t_base[i]); |
- | |
402 | readl(gtt_base); |
- | |
403 | } |
- | |
404 | - | ||
405 | 403 | } |
|
406 | #if 0 |
404 | |
407 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
405 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
408 | { |
406 | { |
Line 409... | Line 407... | ||
409 | struct drm_i915_private *dev_priv = dev->dev_private; |
407 | struct drm_i915_private *dev_priv = dev->dev_private; |
410 | struct drm_i915_gem_object *obj; |
408 | struct drm_i915_gem_object *obj; |
411 | 409 | ||
Line 412... | Line 410... | ||
412 | /* First fill our portion of the GTT with scratch pages */ |
410 | /* First fill our portion of the GTT with scratch pages */ |
413 | i915_ggtt_clear_range(dev, dev_priv->mm.gtt_start / PAGE_SIZE, |
411 | dev_priv->gtt.gtt_clear_range(dev, dev_priv->gtt.start / PAGE_SIZE, |
414 | (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE); |
412 | dev_priv->gtt.total / PAGE_SIZE); |
415 | 413 | ||
Line 416... | Line 414... | ||
416 | list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) { |
414 | list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) { |
417 | i915_gem_clflush_object(obj); |
415 | i915_gem_clflush_object(obj); |
418 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
- | |
Line 419... | Line 416... | ||
419 | } |
416 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
420 | 417 | } |
|
421 | i915_gem_chipset_flush(dev); |
- | |
422 | } |
- | |
423 | #endif |
- | |
424 | - | ||
425 | int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) |
418 | |
426 | { |
419 | i915_gem_chipset_flush(dev); |
Line 427... | Line 420... | ||
427 | struct scatterlist *sg, *s; |
420 | } |
428 | unsigned int nents ; |
421 | |
429 | int i; |
- | |
430 | - | ||
431 | if (obj->has_dma_mapping) |
- | |
432 | return 0; |
- | |
433 | 422 | int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) |
|
434 | sg = obj->pages->sgl; |
423 | { |
435 | nents = obj->pages->nents; |
- | |
436 | - | ||
437 | - | ||
438 | WARN_ON(nents == 0 || sg[0].length == 0); |
- | |
Line 439... | Line 424... | ||
439 | 424 | if (obj->has_dma_mapping) |
|
440 | for_each_sg(sg, s, nents, i) { |
425 | return 0; |
Line 441... | Line 426... | ||
441 | BUG_ON(!sg_page(s)); |
426 | |
442 | s->dma_address = sg_phys(s); |
427 | if (!dma_map_sg(&obj->base.dev->pdev->dev, |
443 | } |
428 | obj->pages->sgl, obj->pages->nents, |
444 | 429 | PCI_DMA_BIDIRECTIONAL)) |
|
445 | asm volatile("lock; addl $0,0(%%esp)": : :"memory"); |
430 | return -ENOSPC; |
446 | 431 | ||
447 | return 0; |
432 | return 0; |
- | 433 | } |
|
- | 434 | ||
448 | } |
435 | /* |
449 | 436 | * Binds an object into the global gtt with the specified cache level. The object |
|
450 | /* |
- | |
451 | * Binds an object into the global gtt with the specified cache level. The object |
437 | * will be accessible to the GPU via commands whose operands reference offsets |
452 | * will be accessible to the GPU via commands whose operands reference offsets |
- | |
453 | * within the global GTT as well as accessible by the GPU through the GMADR |
438 | * within the global GTT as well as accessible by the GPU through the GMADR |
454 | * mapped BAR (dev_priv->mm.gtt->gtt). |
- | |
455 | */ |
439 | * mapped BAR (dev_priv->mm.gtt->gtt). |
456 | static void gen6_ggtt_bind_object(struct drm_i915_gem_object *obj, |
440 | */ |
457 | enum i915_cache_level level) |
441 | static void gen6_ggtt_insert_entries(struct drm_device *dev, |
458 | { |
442 | struct sg_table *st, |
459 | struct drm_device *dev = obj->base.dev; |
443 | unsigned int first_entry, |
Line 460... | Line 444... | ||
460 | struct drm_i915_private *dev_priv = dev->dev_private; |
444 | enum i915_cache_level level) |
461 | struct sg_table *st = obj->pages; |
445 | { |
462 | struct scatterlist *sg = st->sgl; |
446 | struct drm_i915_private *dev_priv = dev->dev_private; |
463 | const int first_entry = obj->gtt_space->start >> PAGE_SHIFT; |
447 | struct scatterlist *sg = st->sgl; |
464 | const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; |
448 | gtt_pte_t __iomem *gtt_entries = |
- | 449 | (gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; |
|
465 | gtt_pte_t __iomem *gtt_entries = dev_priv->mm.gtt->gtt + first_entry; |
450 | int unused, i = 0; |
466 | int unused, i = 0; |
451 | unsigned int len, m = 0; |
467 | unsigned int len, m = 0; |
452 | dma_addr_t addr; |
Line 468... | Line -... | ||
468 | dma_addr_t addr; |
- | |
469 | - | ||
470 | for_each_sg(st->sgl, sg, st->nents, unused) { |
- | |
471 | len = sg_dma_len(sg) >> PAGE_SHIFT; |
453 | |
472 | for (m = 0; m < len; m++) { |
454 | for_each_sg(st->sgl, sg, st->nents, unused) { |
473 | addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
455 | len = sg_dma_len(sg) >> PAGE_SHIFT; |
474 | iowrite32(pte_encode(dev, addr, level), >t_entries[i]); |
456 | for (m = 0; m < len; m++) { |
475 | i++; |
457 | addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
476 | } |
458 | iowrite32(gen6_pte_encode(dev, addr, level), |
477 | } |
459 | >t_entries[i]); |
- | 460 | i++; |
|
478 | 461 | } |
|
Line 479... | Line 462... | ||
479 | BUG_ON(i > max_entries); |
462 | } |
480 | BUG_ON(i != obj->base.size / PAGE_SIZE); |
463 | |
481 | 464 | /* XXX: This serves as a posting read to make sure that the PTE has |
|
482 | /* 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 |
483 | * actually been updated. There is some concern that even though |
466 | * registers and PTEs are within the same BAR that they are potentially |
484 | * registers and PTEs are within the same BAR that they are potentially |
467 | * of NUMA access patterns. Therefore, even with the way we assume |
485 | * of NUMA access patterns. Therefore, even with the way we assume |
468 | * hardware should work, we must keep this posting read for paranoia. |
Line -... | Line 469... | ||
- | 469 | */ |
|
- | 470 | if (i != 0) |
|
- | 471 | WARN_ON(readl(>t_entries[i-1]) |
|
- | 472 | != gen6_pte_encode(dev, addr, level)); |
|
- | 473 | ||
- | 474 | /* This next bit makes the above posting read even more important. We |
|
- | 475 | * want to flush the TLBs only after we're certain all the PTE updates |
|
- | 476 | * have finished. |
|
- | 477 | */ |
|
- | 478 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
|
- | 479 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
|
- | 480 | } |
|
- | 481 | ||
- | 482 | static void gen6_ggtt_clear_range(struct drm_device *dev, |
|
- | 483 | unsigned int first_entry, |
|
- | 484 | unsigned int num_entries) |
|
- | 485 | { |
|
- | 486 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 487 | gtt_pte_t scratch_pte; |
|
- | 488 | gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; |
|
- | 489 | const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; |
|
- | 490 | int i; |
|
- | 491 | ||
486 | * hardware should work, we must keep this posting read for paranoia. |
492 | if (WARN(num_entries > max_entries, |
- | 493 | "First entry = %d; Num entries = %d (max=%d)\n", |
|
- | 494 | first_entry, num_entries, max_entries)) |
|
487 | */ |
495 | num_entries = max_entries; |
488 | if (i != 0) |
496 | |
489 | WARN_ON(readl(>t_entries[i-1]) != pte_encode(dev, addr, level)); |
- | |
490 | - | ||
491 | /* This next bit makes the above posting read even more important. We |
497 | scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma, |
492 | * want to flush the TLBs only after we're certain all the PTE updates |
498 | I915_CACHE_LLC); |
- | 499 | for (i = 0; i < num_entries; i++) |
|
493 | * have finished. |
500 | iowrite32(scratch_pte, >t_base[i]); |
- | 501 | readl(gtt_base); |
|
- | 502 | } |
|
- | 503 | ||
- | 504 | ||
494 | */ |
505 | static void i915_ggtt_insert_entries(struct drm_device *dev, |
495 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
506 | struct sg_table *st, |
496 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
507 | unsigned int pg_start, |
497 | } |
508 | enum i915_cache_level cache_level) |
498 | 509 | { |
|
Line -... | Line 510... | ||
- | 510 | unsigned int flags = (cache_level == I915_CACHE_NONE) ? |
|
- | 511 | AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; |
|
- | 512 | ||
- | 513 | intel_gtt_insert_sg_entries(st, pg_start, flags); |
|
- | 514 | ||
- | 515 | } |
|
- | 516 | ||
- | 517 | static void i915_ggtt_clear_range(struct drm_device *dev, |
|
- | 518 | unsigned int first_entry, |
|
- | 519 | unsigned int num_entries) |
|
- | 520 | { |
|
499 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, |
521 | intel_gtt_clear_range(first_entry, num_entries); |
500 | enum i915_cache_level cache_level) |
522 | } |
Line 501... | Line 523... | ||
501 | { |
523 | |
502 | struct drm_device *dev = obj->base.dev; |
524 | |
- | 525 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, |
|
- | 526 | enum i915_cache_level cache_level) |
|
- | 527 | { |
|
503 | if (INTEL_INFO(dev)->gen < 6) { |
528 | struct drm_device *dev = obj->base.dev; |
504 | unsigned int flags = (cache_level == I915_CACHE_NONE) ? |
529 | struct drm_i915_private *dev_priv = dev->dev_private; |
505 | AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; |
530 | |
Line 506... | Line 531... | ||
506 | intel_gtt_insert_sg_entries(obj->pages, |
531 | dev_priv->gtt.gtt_insert_entries(dev, obj->pages, |
507 | obj->gtt_space->start >> PAGE_SHIFT, |
532 | obj->gtt_space->start >> PAGE_SHIFT, |
Line 528... | Line 553... | ||
528 | struct drm_i915_private *dev_priv = dev->dev_private; |
553 | struct drm_i915_private *dev_priv = dev->dev_private; |
529 | bool interruptible; |
554 | bool interruptible; |
Line 530... | Line 555... | ||
530 | 555 | ||
Line 531... | Line 556... | ||
531 | interruptible = do_idling(dev_priv); |
556 | interruptible = do_idling(dev_priv); |
532 | 557 | ||
533 | // if (!obj->has_dma_mapping) |
558 | if (!obj->has_dma_mapping) |
534 | // dma_unmap_sg(&dev->pdev->dev, |
559 | dma_unmap_sg(&dev->pdev->dev, |
Line 535... | Line 560... | ||
535 | // obj->pages->sgl, obj->pages->nents, |
560 | obj->pages->sgl, obj->pages->nents, |
536 | // PCI_DMA_BIDIRECTIONAL); |
561 | PCI_DMA_BIDIRECTIONAL); |
Line 537... | Line 562... | ||
537 | 562 | ||
Line 552... | Line 577... | ||
552 | node_list); |
577 | node_list); |
553 | if (node->allocated && node->color != color) |
578 | if (node->allocated && node->color != color) |
554 | *end -= 4096; |
579 | *end -= 4096; |
555 | } |
580 | } |
556 | } |
581 | } |
557 | - | ||
558 | void i915_gem_init_global_gtt(struct drm_device *dev, |
582 | void i915_gem_setup_global_gtt(struct drm_device *dev, |
559 | unsigned long start, |
583 | unsigned long start, |
560 | unsigned long mappable_end, |
584 | unsigned long mappable_end, |
561 | unsigned long end) |
585 | unsigned long end) |
562 | { |
586 | { |
- | 587 | /* Let GEM Manage all of the aperture. |
|
- | 588 | * |
|
- | 589 | * However, leave one page at the end still bound to the scratch page. |
|
- | 590 | * There are a number of places where the hardware apparently prefetches |
|
- | 591 | * past the end of the object, and we've seen multiple hangs with the |
|
- | 592 | * GPU head pointer stuck in a batchbuffer bound at the last page of the |
|
- | 593 | * aperture. One page should be enough to keep any prefetching inside |
|
- | 594 | * of the aperture. |
|
- | 595 | */ |
|
563 | drm_i915_private_t *dev_priv = dev->dev_private; |
596 | drm_i915_private_t *dev_priv = dev->dev_private; |
- | 597 | struct drm_mm_node *entry; |
|
- | 598 | struct drm_i915_gem_object *obj; |
|
- | 599 | unsigned long hole_start, hole_end; |
|
- | 600 | ||
- | 601 | BUG_ON(mappable_end > end); |
|
Line 564... | Line 602... | ||
564 | 602 | ||
565 | /* Substract the guard page ... */ |
603 | /* Subtract the guard page ... */ |
566 | drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE); |
604 | drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE); |
567 | if (!HAS_LLC(dev)) |
605 | if (!HAS_LLC(dev)) |
Line -... | Line 606... | ||
- | 606 | dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust; |
|
- | 607 | ||
- | 608 | /* Mark any preallocated objects as occupied */ |
|
- | 609 | list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) { |
|
- | 610 | DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n", |
|
- | 611 | obj->gtt_offset, obj->base.size); |
|
- | 612 | ||
- | 613 | BUG_ON(obj->gtt_space != I915_GTT_RESERVED); |
|
- | 614 | obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space, |
|
- | 615 | obj->gtt_offset, |
|
- | 616 | obj->base.size, |
|
- | 617 | false); |
|
- | 618 | obj->has_global_gtt_mapping = 1; |
|
568 | dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust; |
619 | } |
569 | 620 | ||
- | 621 | dev_priv->gtt.start = start; |
|
- | 622 | dev_priv->gtt.total = end - start; |
|
- | 623 | ||
- | 624 | /* Clear any non-preallocated blocks */ |
|
- | 625 | drm_mm_for_each_hole(entry, &dev_priv->mm.gtt_space, |
|
570 | dev_priv->mm.gtt_start = start; |
626 | hole_start, hole_end) { |
571 | dev_priv->mm.gtt_mappable_end = mappable_end; |
627 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", |
- | 628 | hole_start, hole_end); |
|
- | 629 | dev_priv->gtt.gtt_clear_range(dev, hole_start / PAGE_SIZE, |
|
- | 630 | (hole_end-hole_start) / PAGE_SIZE); |
|
- | 631 | } |
|
572 | dev_priv->mm.gtt_end = end; |
632 | |
- | 633 | /* And finally clear the reserved guard page */ |
|
- | 634 | dev_priv->gtt.gtt_clear_range(dev, end / PAGE_SIZE - 1, 1); |
|
- | 635 | } |
|
- | 636 | ||
- | 637 | static bool |
|
- | 638 | intel_enable_ppgtt(struct drm_device *dev) |
|
- | 639 | { |
|
- | 640 | if (i915_enable_ppgtt >= 0) |
|
- | 641 | return i915_enable_ppgtt; |
|
- | 642 | ||
- | 643 | #ifdef CONFIG_INTEL_IOMMU |
|
- | 644 | /* Disable ppgtt on SNB if VT-d is on. */ |
|
- | 645 | if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) |
|
- | 646 | return false; |
|
- | 647 | #endif |
|
- | 648 | ||
- | 649 | return true; |
|
- | 650 | } |
|
- | 651 | ||
- | 652 | void i915_gem_init_global_gtt(struct drm_device *dev) |
|
- | 653 | { |
|
- | 654 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 655 | unsigned long gtt_size, mappable_size; |
|
- | 656 | ||
- | 657 | gtt_size = dev_priv->gtt.total; |
|
- | 658 | mappable_size = dev_priv->gtt.mappable_end; |
|
- | 659 | ||
- | 660 | if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { |
|
- | 661 | int ret; |
|
- | 662 | /* PPGTT pdes are stolen from global gtt ptes, so shrink the |
|
- | 663 | * aperture accordingly when using aliasing ppgtt. */ |
|
- | 664 | gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
|
- | 665 | gtt_size -= LFB_SIZE; |
|
- | 666 | ||
- | 667 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size); |
|
- | 668 | ||
- | 669 | ret = i915_gem_init_aliasing_ppgtt(dev); |
|
Line 573... | Line 670... | ||
573 | dev_priv->mm.gtt_total = end - start; |
670 | if (!ret) |
- | 671 | return; |
|
- | 672 | ||
- | 673 | DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); |
|
574 | dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start; |
674 | drm_mm_takedown(&dev_priv->mm.gtt_space); |
575 | 675 | gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE; |
|
Line 576... | Line 676... | ||
576 | /* ... but ensure that we clear the entire range. */ |
676 | } |
577 | i915_ggtt_clear_range(dev, start / PAGE_SIZE, (end-start) / PAGE_SIZE); |
677 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size); |
578 | } |
678 | } |
Line 584... | Line 684... | ||
584 | dma_addr_t dma_addr; |
684 | dma_addr_t dma_addr; |
Line 585... | Line 685... | ||
585 | 685 | ||
586 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
686 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
587 | if (page == NULL) |
687 | if (page == NULL) |
- | 688 | return -ENOMEM; |
|
- | 689 | get_page(page); |
|
Line 588... | Line 690... | ||
588 | return -ENOMEM; |
690 | set_pages_uc(page, 1); |
589 | 691 | ||
590 | #ifdef CONFIG_INTEL_IOMMU |
692 | #ifdef CONFIG_INTEL_IOMMU |
591 | dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE, |
693 | dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE, |
592 | PCI_DMA_BIDIRECTIONAL); |
694 | PCI_DMA_BIDIRECTIONAL); |
593 | if (pci_dma_mapping_error(dev->pdev, dma_addr)) |
695 | if (pci_dma_mapping_error(dev->pdev, dma_addr)) |
594 | return -EINVAL; |
696 | return -EINVAL; |
595 | #else |
697 | #else |
596 | dma_addr = page_to_phys(page); |
698 | dma_addr = page_to_phys(page); |
597 | #endif |
699 | #endif |
Line 598... | Line 700... | ||
598 | dev_priv->mm.gtt->scratch_page = page; |
700 | dev_priv->gtt.scratch_page = page; |
599 | dev_priv->mm.gtt->scratch_page_dma = dma_addr; |
701 | dev_priv->gtt.scratch_page_dma = dma_addr; |
Line -... | Line 702... | ||
- | 702 | ||
- | 703 | return 0; |
|
- | 704 | } |
|
- | 705 | ||
- | 706 | static void teardown_scratch_page(struct drm_device *dev) |
|
- | 707 | { |
|
- | 708 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 709 | set_pages_wb(dev_priv->gtt.scratch_page, 1); |
|
- | 710 | pci_unmap_page(dev->pdev, dev_priv->gtt.scratch_page_dma, |
|
Line 600... | Line 711... | ||
600 | 711 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
|
601 | return 0; |
712 | put_page(dev_priv->gtt.scratch_page); |
602 | } |
713 | __free_page(dev_priv->gtt.scratch_page); |
603 | 714 | } |
|
604 | 715 | ||
605 | static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) |
716 | static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) |
Line 606... | Line 717... | ||
606 | { |
717 | { |
607 | snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; |
718 | snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; |
608 | snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; |
719 | snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; |
609 | return snb_gmch_ctl << 20; |
720 | return snb_gmch_ctl << 20; |
610 | } |
721 | } |
611 | 722 | ||
Line 612... | Line 723... | ||
612 | static inline unsigned int gen6_get_stolen_size(u16 snb_gmch_ctl) |
723 | static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) |
613 | { |
724 | { |
614 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
725 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
615 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
726 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
616 | return snb_gmch_ctl << 25; /* 32 MB units */ |
727 | return snb_gmch_ctl << 25; /* 32 MB units */ |
617 | } |
728 | } |
618 | 729 | ||
619 | static inline unsigned int gen7_get_stolen_size(u16 snb_gmch_ctl) |
730 | static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl) |
Line 620... | Line 731... | ||
620 | { |
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; |
|
621 | static const int stolen_decoder[] = { |
736 | return stolen_decoder[snb_gmch_ctl] << 20; |
622 | 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352}; |
737 | } |
623 | snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT; |
738 | |
- | 739 | static int gen6_gmch_probe(struct drm_device *dev, |
|
624 | snb_gmch_ctl &= IVB_GMCH_GMS_MASK; |
740 | size_t *gtt_total, |
625 | return stolen_decoder[snb_gmch_ctl] << 20; |
741 | size_t *stolen, |
Line 626... | Line 742... | ||
626 | } |
742 | phys_addr_t *mappable_base, |
627 | - | ||
628 | int i915_gem_gtt_init(struct drm_device *dev) |
- | |
629 | { |
- | |
630 | struct drm_i915_private *dev_priv = dev->dev_private; |
743 | unsigned long *mappable_end) |
631 | phys_addr_t gtt_bus_addr; |
- | |
632 | u16 snb_gmch_ctl; |
- | |
633 | int ret; |
- | |
634 | - | ||
Line 635... | Line 744... | ||
635 | /* On modern platforms we need not worry ourself with the legacy |
744 | { |
636 | * hostbridge query stuff. Skip it entirely |
745 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | 746 | phys_addr_t gtt_bus_addr; |
|
- | 747 | unsigned int gtt_size; |
|
637 | */ |
748 | u16 snb_gmch_ctl; |
638 | if (INTEL_INFO(dev)->gen < 6) { |
749 | int ret; |
639 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); |
- | |
640 | if (!ret) { |
750 | |
641 | DRM_ERROR("failed to set up gmch\n"); |
751 | *mappable_base = pci_resource_start(dev->pdev, 2); |
Line -... | Line 752... | ||
- | 752 | *mappable_end = pci_resource_len(dev->pdev, 2); |
|
642 | return -EIO; |
753 | |
643 | } |
754 | /* 64/512MB is the current min/max we actually know of, but this is just |
644 | 755 | * a coarse sanity check. |
|
Line -... | Line 756... | ||
- | 756 | */ |
|
- | 757 | if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { |
|
- | 758 | DRM_ERROR("Unknown GMADR size (%lx)\n", |
|
- | 759 | dev_priv->gtt.mappable_end); |
|
Line 645... | Line -... | ||
645 | dev_priv->mm.gtt = intel_gtt_get(); |
- | |
646 | if (!dev_priv->mm.gtt) { |
760 | return -ENXIO; |
647 | DRM_ERROR("Failed to initialize GTT\n"); |
- | |
Line 648... | Line 761... | ||
648 | return -ENODEV; |
761 | } |
649 | } |
762 | |
650 | return 0; |
763 | if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) |
651 | } |
- | |
652 | - | ||
653 | dev_priv->mm.gtt = kzalloc(sizeof(*dev_priv->mm.gtt), GFP_KERNEL); |
- | |
654 | if (!dev_priv->mm.gtt) |
- | |
655 | return -ENOMEM; |
- | |
656 | 764 | pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); |
|
657 | - | ||
658 | #ifdef CONFIG_INTEL_IOMMU |
- | |
659 | dev_priv->mm.gtt->needs_dmar = 1; |
- | |
660 | #endif |
- | |
661 | - | ||
662 | /* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */ |
- | |
663 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + (2<<20); |
- | |
664 | dev_priv->mm.gtt->gma_bus_addr = pci_resource_start(dev->pdev, 2); |
- | |
665 | - | ||
666 | /* i9xx_setup */ |
- | |
667 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
765 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
668 | dev_priv->mm.gtt->gtt_total_entries = |
- | |
669 | gen6_get_total_gtt_size(snb_gmch_ctl) / sizeof(gtt_pte_t); |
766 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
670 | if (INTEL_INFO(dev)->gen < 7) |
- | |
671 | dev_priv->mm.gtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl); |
767 | |
Line 672... | Line 768... | ||
672 | else |
768 | if (IS_GEN7(dev)) |
673 | dev_priv->mm.gtt->stolen_size = gen7_get_stolen_size(snb_gmch_ctl); |
769 | *stolen = gen7_get_stolen_size(snb_gmch_ctl); |
674 | 770 | else |
|
- | 771 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
|
- | 772 | ||
- | 773 | *gtt_total = (gtt_size / sizeof(gtt_pte_t)) << PAGE_SHIFT; |
|
- | 774 | ||
675 | dev_priv->mm.gtt->gtt_mappable_entries = pci_resource_len(dev->pdev, 2) >> PAGE_SHIFT; |
775 | /* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */ |
676 | /* 64/512MB is the current min/max we actually know of, but this is just a |
776 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + (2<<20); |
Line 677... | Line 777... | ||
677 | * coarse sanity check. |
777 | dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); |
- | 778 | if (!dev_priv->gtt.gsm) { |
|
678 | */ |
779 | DRM_ERROR("Failed to map the gtt page table\n"); |
679 | if ((dev_priv->mm.gtt->gtt_mappable_entries >> 8) < 64 || |
780 | return -ENOMEM; |
680 | dev_priv->mm.gtt->gtt_mappable_entries > dev_priv->mm.gtt->gtt_total_entries) { |
781 | } |
681 | DRM_ERROR("Unknown GMADR entries (%d)\n", |
- | |
682 | dev_priv->mm.gtt->gtt_mappable_entries); |
- | |
683 | ret = -ENXIO; |
782 | |
Line -... | Line 783... | ||
- | 783 | ret = setup_scratch_page(dev); |
|
- | 784 | if (ret) |
|
- | 785 | DRM_ERROR("Scratch setup failed\n"); |
|
- | 786 | ||
- | 787 | dev_priv->gtt.gtt_clear_range = gen6_ggtt_clear_range; |
|
- | 788 | dev_priv->gtt.gtt_insert_entries = gen6_ggtt_insert_entries; |
|
684 | goto err_out; |
789 | |
- | 790 | return ret; |
|
- | 791 | } |
|
685 | } |
792 | |
- | 793 | static void gen6_gmch_remove(struct drm_device *dev) |
|
- | 794 | { |
|
- | 795 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 796 | iounmap(dev_priv->gtt.gsm); |
|
- | 797 | teardown_scratch_page(dev_priv->dev); |
|
686 | 798 | } |
|
- | 799 | ||
687 | ret = setup_scratch_page(dev); |
800 | static int i915_gmch_probe(struct drm_device *dev, |
- | 801 | size_t *gtt_total, |
|
- | 802 | size_t *stolen, |
|
Line 688... | Line 803... | ||
688 | if (ret) { |
803 | phys_addr_t *mappable_base, |
- | 804 | unsigned long *mappable_end) |
|
Line -... | Line 805... | ||
- | 805 | { |
|
689 | DRM_ERROR("Scratch setup failed\n"); |
806 | struct drm_i915_private *dev_priv = dev->dev_private; |
690 | goto err_out; |
807 | int ret; |
691 | } |
- | |
692 | 808 | ||
Line -... | Line 809... | ||
- | 809 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); |
|
- | 810 | if (!ret) { |
|
- | 811 | DRM_ERROR("failed to set up gmch\n"); |
|
- | 812 | return -EIO; |
|
- | 813 | } |
|
- | 814 | ||
- | 815 | intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); |
|
- | 816 | ||
- | 817 | dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); |
|
- | 818 | dev_priv->gtt.gtt_clear_range = i915_ggtt_clear_range; |
|
- | 819 | dev_priv->gtt.gtt_insert_entries = i915_ggtt_insert_entries; |
|
- | 820 | ||
- | 821 | return 0; |
|
- | 822 | } |
|
- | 823 | ||
- | 824 | static void i915_gmch_remove(struct drm_device *dev) |
|
- | 825 | { |
|
- | 826 | // intel_gmch_remove(); |
|
- | 827 | } |
|
- | 828 | ||
- | 829 | int i915_gem_gtt_init(struct drm_device *dev) |
|
- | 830 | { |
|
- | 831 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 832 | struct i915_gtt *gtt = &dev_priv->gtt; |
|
- | 833 | unsigned long gtt_size; |
|
- | 834 | int ret; |
|
- | 835 | ||
- | 836 | if (INTEL_INFO(dev)->gen <= 5) { |
|
- | 837 | dev_priv->gtt.gtt_probe = i915_gmch_probe; |
|
- | 838 | dev_priv->gtt.gtt_remove = i915_gmch_remove; |
|
- | 839 | } else { |
|
- | 840 | dev_priv->gtt.gtt_probe = gen6_gmch_probe; |
|
- | 841 | dev_priv->gtt.gtt_remove = gen6_gmch_remove; |
|
- | 842 | } |
|
Line 693... | Line 843... | ||
693 | dev_priv->mm.gtt->gtt = ioremap(gtt_bus_addr, |
843 | |
694 | dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t)); |
844 | ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total, |
695 | if (!dev_priv->mm.gtt->gtt) { |
845 | &dev_priv->gtt.stolen_size, |
696 | DRM_ERROR("Failed to map the gtt page table\n"); |
846 | >t->mappable_base, |