aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem_gtt.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-09 11:15:46 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-09 15:25:11 -0500
commit1d2a314c97ceaf383de8e23cdde46729927d433c (patch)
tree31df6c81a19d80b3611c39cb17c613561a9f0b0b /drivers/gpu/drm/i915/i915_gem_gtt.c
parent428ccb21b740f603a6a1f08cbe6d935fb3177620 (diff)
drm/i915: initialization/teardown for the aliasing ppgtt
This just adds the setup and teardown code for the ppgtt PDE and the last-level pagetables, which are fixed for the entire lifetime, at least for the moment. v2: Kill the stray debug printk noted by and improve the pte definitions as suggested by Chris Wilson. v3: Clean up the aperture stealing code as noted by Ben Widawsky. v4: Paint the init code in a more pleasing colour as suggest by Chris Wilson. v5: Explain the magic numbers noticed by Ben Widawsky. Reviewed-by: Ben Widawsky <ben@bwidawsk.net> Tested-by: Chris Wilson <chris@chris-wilson.co.uk> Tested-by: Eugeni Dodonov <eugeni.dodonov@intel.com> Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 11bddd5a5a6..f408f8c710d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -29,6 +29,145 @@
29#include "i915_trace.h" 29#include "i915_trace.h"
30#include "intel_drv.h" 30#include "intel_drv.h"
31 31
32/* PPGTT support for Sandybdrige/Gen6 and later */
33static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
34 unsigned first_entry,
35 unsigned num_entries)
36{
37 int i, j;
38 uint32_t *pt_vaddr;
39 uint32_t scratch_pte;
40
41 scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
42 scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
43
44 for (i = 0; i < ppgtt->num_pd_entries; i++) {
45 pt_vaddr = kmap_atomic(ppgtt->pt_pages[i]);
46
47 for (j = 0; j < I915_PPGTT_PT_ENTRIES; j++)
48 pt_vaddr[j] = scratch_pte;
49
50 kunmap_atomic(pt_vaddr);
51 }
52
53}
54
55int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
56{
57 struct drm_i915_private *dev_priv = dev->dev_private;
58 struct i915_hw_ppgtt *ppgtt;
59 uint32_t pd_entry;
60 unsigned first_pd_entry_in_global_pt;
61 uint32_t __iomem *pd_addr;
62 int i;
63 int ret = -ENOMEM;
64
65 /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
66 * entries. For aliasing ppgtt support we just steal them at the end for
67 * now. */
68 first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES;
69
70 ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
71 if (!ppgtt)
72 return ret;
73
74 ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
75 ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries,
76 GFP_KERNEL);
77 if (!ppgtt->pt_pages)
78 goto err_ppgtt;
79
80 for (i = 0; i < ppgtt->num_pd_entries; i++) {
81 ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL);
82 if (!ppgtt->pt_pages[i])
83 goto err_pt_alloc;
84 }
85
86 if (dev_priv->mm.gtt->needs_dmar) {
87 ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t)
88 *ppgtt->num_pd_entries,
89 GFP_KERNEL);
90 if (!ppgtt->pt_dma_addr)
91 goto err_pt_alloc;
92 }
93
94 pd_addr = dev_priv->mm.gtt->gtt + first_pd_entry_in_global_pt;
95 for (i = 0; i < ppgtt->num_pd_entries; i++) {
96 dma_addr_t pt_addr;
97 if (dev_priv->mm.gtt->needs_dmar) {
98 pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i],
99 0, 4096,
100 PCI_DMA_BIDIRECTIONAL);
101
102 if (pci_dma_mapping_error(dev->pdev,
103 pt_addr)) {
104 ret = -EIO;
105 goto err_pd_pin;
106
107 }
108 ppgtt->pt_dma_addr[i] = pt_addr;
109 } else
110 pt_addr = page_to_phys(ppgtt->pt_pages[i]);
111
112 pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
113 pd_entry |= GEN6_PDE_VALID;
114
115 writel(pd_entry, pd_addr + i);
116 }
117 readl(pd_addr);
118
119 ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
120
121 i915_ppgtt_clear_range(ppgtt, 0,
122 ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
123
124 ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(uint32_t);
125
126 dev_priv->mm.aliasing_ppgtt = ppgtt;
127
128 return 0;
129
130err_pd_pin:
131 if (ppgtt->pt_dma_addr) {
132 for (i--; i >= 0; i--)
133 pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i],
134 4096, PCI_DMA_BIDIRECTIONAL);
135 }
136err_pt_alloc:
137 kfree(ppgtt->pt_dma_addr);
138 for (i = 0; i < ppgtt->num_pd_entries; i++) {
139 if (ppgtt->pt_pages[i])
140 __free_page(ppgtt->pt_pages[i]);
141 }
142 kfree(ppgtt->pt_pages);
143err_ppgtt:
144 kfree(ppgtt);
145
146 return ret;
147}
148
149void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
150{
151 struct drm_i915_private *dev_priv = dev->dev_private;
152 struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
153 int i;
154
155 if (!ppgtt)
156 return;
157
158 if (ppgtt->pt_dma_addr) {
159 for (i = 0; i < ppgtt->num_pd_entries; i++)
160 pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i],
161 4096, PCI_DMA_BIDIRECTIONAL);
162 }
163
164 kfree(ppgtt->pt_dma_addr);
165 for (i = 0; i < ppgtt->num_pd_entries; i++)
166 __free_page(ppgtt->pt_pages[i]);
167 kfree(ppgtt->pt_pages);
168 kfree(ppgtt);
169}
170
32/* XXX kill agp_type! */ 171/* XXX kill agp_type! */
33static unsigned int cache_level_to_agp_type(struct drm_device *dev, 172static unsigned int cache_level_to_agp_type(struct drm_device *dev,
34 enum i915_cache_level cache_level) 173 enum i915_cache_level cache_level)