Rev 4104 | Rev 4539 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4104 | Rev 4126 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright © 2010 Daniel Vetter |
2 | * Copyright © 2010 Daniel Vetter |
3 | * |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
10 | * |
11 | * The above copyright notice and this permission notice (including the next |
11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the |
12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. |
13 | * Software. |
14 | * |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
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 | */ |
24 | 24 | ||
25 | 25 | ||
26 | #define AGP_NORMAL_MEMORY 0 |
26 | #define AGP_NORMAL_MEMORY 0 |
27 | 27 | ||
28 | #define AGP_USER_TYPES (1 << 16) |
28 | #define AGP_USER_TYPES (1 << 16) |
29 | #define AGP_USER_MEMORY (AGP_USER_TYPES) |
29 | #define AGP_USER_MEMORY (AGP_USER_TYPES) |
30 | #define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) |
30 | #define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) |
31 | 31 | ||
32 | #include |
32 | #include |
33 | #include |
33 | #include |
34 | #include "i915_drv.h" |
34 | #include "i915_drv.h" |
35 | #include "i915_trace.h" |
35 | #include "i915_trace.h" |
36 | #include "intel_drv.h" |
36 | #include "intel_drv.h" |
37 | 37 | ||
38 | #define GEN6_PPGTT_PD_ENTRIES 512 |
38 | #define GEN6_PPGTT_PD_ENTRIES 512 |
39 | #define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t)) |
39 | #define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t)) |
40 | 40 | ||
41 | /* PPGTT stuff */ |
41 | /* PPGTT stuff */ |
42 | #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) |
42 | #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) |
43 | #define HSW_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0x7f0)) |
43 | #define HSW_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0x7f0)) |
44 | 44 | ||
45 | #define GEN6_PDE_VALID (1 << 0) |
45 | #define GEN6_PDE_VALID (1 << 0) |
46 | /* gen6+ has bit 11-4 for physical addr bit 39-32 */ |
46 | /* gen6+ has bit 11-4 for physical addr bit 39-32 */ |
47 | #define GEN6_PDE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
47 | #define GEN6_PDE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
48 | 48 | ||
49 | #define GEN6_PTE_VALID (1 << 0) |
49 | #define GEN6_PTE_VALID (1 << 0) |
50 | #define GEN6_PTE_UNCACHED (1 << 1) |
50 | #define GEN6_PTE_UNCACHED (1 << 1) |
51 | #define HSW_PTE_UNCACHED (0) |
51 | #define HSW_PTE_UNCACHED (0) |
52 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
52 | #define GEN6_PTE_CACHE_LLC (2 << 1) |
53 | #define GEN7_PTE_CACHE_L3_LLC (3 << 1) |
53 | #define GEN7_PTE_CACHE_L3_LLC (3 << 1) |
54 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
54 | #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) |
55 | #define HSW_PTE_ADDR_ENCODE(addr) HSW_GTT_ADDR_ENCODE(addr) |
55 | #define HSW_PTE_ADDR_ENCODE(addr) HSW_GTT_ADDR_ENCODE(addr) |
56 | 56 | ||
57 | /* Cacheability Control is a 4-bit value. The low three bits are stored in * |
57 | /* Cacheability Control is a 4-bit value. The low three bits are stored in * |
58 | * bits 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE. |
58 | * bits 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE. |
59 | */ |
59 | */ |
60 | #define HSW_CACHEABILITY_CONTROL(bits) ((((bits) & 0x7) << 1) | \ |
60 | #define HSW_CACHEABILITY_CONTROL(bits) ((((bits) & 0x7) << 1) | \ |
61 | (((bits) & 0x8) << (11 - 3))) |
61 | (((bits) & 0x8) << (11 - 3))) |
62 | #define HSW_WB_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x2) |
62 | #define HSW_WB_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x2) |
63 | #define HSW_WB_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x3) |
63 | #define HSW_WB_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x3) |
64 | #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) |
64 | #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) |
65 | #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) |
65 | #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) |
66 | 66 | ||
67 | static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, |
67 | static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, |
68 | enum i915_cache_level level) |
68 | enum i915_cache_level level) |
69 | { |
69 | { |
70 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
70 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
71 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
71 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
72 | 72 | ||
73 | switch (level) { |
73 | switch (level) { |
74 | case I915_CACHE_L3_LLC: |
74 | case I915_CACHE_L3_LLC: |
75 | case I915_CACHE_LLC: |
75 | case I915_CACHE_LLC: |
76 | pte |= GEN6_PTE_CACHE_LLC; |
76 | pte |= GEN6_PTE_CACHE_LLC; |
77 | break; |
77 | break; |
78 | case I915_CACHE_NONE: |
78 | case I915_CACHE_NONE: |
79 | pte |= GEN6_PTE_UNCACHED; |
79 | pte |= GEN6_PTE_UNCACHED; |
80 | break; |
80 | break; |
81 | default: |
81 | default: |
82 | WARN_ON(1); |
82 | WARN_ON(1); |
83 | } |
83 | } |
84 | 84 | ||
85 | return pte; |
85 | return pte; |
86 | } |
86 | } |
87 | 87 | ||
88 | static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, |
88 | static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, |
89 | enum i915_cache_level level) |
89 | enum i915_cache_level level) |
90 | { |
90 | { |
91 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
91 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
92 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
92 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
93 | 93 | ||
94 | switch (level) { |
94 | switch (level) { |
95 | case I915_CACHE_L3_LLC: |
95 | case I915_CACHE_L3_LLC: |
96 | pte |= GEN7_PTE_CACHE_L3_LLC; |
96 | pte |= GEN7_PTE_CACHE_L3_LLC; |
97 | break; |
97 | break; |
98 | case I915_CACHE_LLC: |
98 | case I915_CACHE_LLC: |
99 | pte |= GEN6_PTE_CACHE_LLC; |
99 | pte |= GEN6_PTE_CACHE_LLC; |
100 | break; |
100 | break; |
101 | case I915_CACHE_NONE: |
101 | case I915_CACHE_NONE: |
102 | pte |= GEN6_PTE_UNCACHED; |
102 | pte |= GEN6_PTE_UNCACHED; |
103 | break; |
103 | break; |
104 | default: |
104 | default: |
105 | WARN_ON(1); |
105 | WARN_ON(1); |
106 | } |
106 | } |
107 | 107 | ||
108 | return pte; |
108 | return pte; |
109 | } |
109 | } |
110 | 110 | ||
111 | #define BYT_PTE_WRITEABLE (1 << 1) |
111 | #define BYT_PTE_WRITEABLE (1 << 1) |
112 | #define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2) |
112 | #define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2) |
113 | 113 | ||
114 | static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, |
114 | static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, |
115 | enum i915_cache_level level) |
115 | enum i915_cache_level level) |
116 | { |
116 | { |
117 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
117 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
118 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
118 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
119 | 119 | ||
120 | /* Mark the page as writeable. Other platforms don't have a |
120 | /* Mark the page as writeable. Other platforms don't have a |
121 | * setting for read-only/writable, so this matches that behavior. |
121 | * setting for read-only/writable, so this matches that behavior. |
122 | */ |
122 | */ |
123 | pte |= BYT_PTE_WRITEABLE; |
123 | pte |= BYT_PTE_WRITEABLE; |
124 | 124 | ||
125 | if (level != I915_CACHE_NONE) |
125 | if (level != I915_CACHE_NONE) |
126 | pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES; |
126 | pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES; |
127 | 127 | ||
128 | return pte; |
128 | return pte; |
129 | } |
129 | } |
130 | 130 | ||
131 | static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, |
131 | static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, |
132 | enum i915_cache_level level) |
132 | enum i915_cache_level level) |
133 | { |
133 | { |
134 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
134 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
135 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
135 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
136 | 136 | ||
137 | if (level != I915_CACHE_NONE) |
137 | if (level != I915_CACHE_NONE) |
138 | pte |= HSW_WB_LLC_AGE3; |
138 | pte |= HSW_WB_LLC_AGE3; |
139 | 139 | ||
140 | return pte; |
140 | return pte; |
141 | } |
141 | } |
142 | 142 | ||
143 | static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, |
143 | static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, |
144 | enum i915_cache_level level) |
144 | enum i915_cache_level level) |
145 | { |
145 | { |
146 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
146 | gen6_gtt_pte_t pte = GEN6_PTE_VALID; |
147 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
147 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
148 | 148 | ||
149 | switch (level) { |
149 | switch (level) { |
150 | case I915_CACHE_NONE: |
150 | case I915_CACHE_NONE: |
151 | break; |
151 | break; |
152 | case I915_CACHE_WT: |
152 | case I915_CACHE_WT: |
153 | pte |= HSW_WT_ELLC_LLC_AGE0; |
153 | pte |= HSW_WT_ELLC_LLC_AGE0; |
154 | break; |
154 | break; |
155 | default: |
155 | default: |
156 | pte |= HSW_WB_ELLC_LLC_AGE0; |
156 | pte |= HSW_WB_ELLC_LLC_AGE0; |
157 | break; |
157 | break; |
158 | } |
158 | } |
159 | 159 | ||
160 | return pte; |
160 | return pte; |
161 | } |
161 | } |
162 | 162 | ||
163 | static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt) |
163 | static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt) |
164 | { |
164 | { |
165 | struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private; |
165 | struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private; |
166 | gen6_gtt_pte_t __iomem *pd_addr; |
166 | gen6_gtt_pte_t __iomem *pd_addr; |
167 | uint32_t pd_entry; |
167 | uint32_t pd_entry; |
168 | int i; |
168 | int i; |
169 | 169 | ||
170 | WARN_ON(ppgtt->pd_offset & 0x3f); |
170 | WARN_ON(ppgtt->pd_offset & 0x3f); |
171 | pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm + |
171 | pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm + |
172 | ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); |
172 | ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); |
173 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
173 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
174 | dma_addr_t pt_addr; |
174 | dma_addr_t pt_addr; |
175 | 175 | ||
176 | pt_addr = ppgtt->pt_dma_addr[i]; |
176 | pt_addr = ppgtt->pt_dma_addr[i]; |
177 | pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); |
177 | pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); |
178 | pd_entry |= GEN6_PDE_VALID; |
178 | pd_entry |= GEN6_PDE_VALID; |
179 | 179 | ||
180 | writel(pd_entry, pd_addr + i); |
180 | writel(pd_entry, pd_addr + i); |
181 | } |
181 | } |
182 | readl(pd_addr); |
182 | readl(pd_addr); |
183 | } |
183 | } |
184 | 184 | ||
185 | static int gen6_ppgtt_enable(struct drm_device *dev) |
185 | static int gen6_ppgtt_enable(struct drm_device *dev) |
186 | { |
186 | { |
187 | drm_i915_private_t *dev_priv = dev->dev_private; |
187 | drm_i915_private_t *dev_priv = dev->dev_private; |
188 | uint32_t pd_offset; |
188 | uint32_t pd_offset; |
189 | struct intel_ring_buffer *ring; |
189 | struct intel_ring_buffer *ring; |
190 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
190 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
191 | int i; |
191 | int i; |
192 | 192 | ||
193 | BUG_ON(ppgtt->pd_offset & 0x3f); |
193 | BUG_ON(ppgtt->pd_offset & 0x3f); |
194 | 194 | ||
195 | gen6_write_pdes(ppgtt); |
195 | gen6_write_pdes(ppgtt); |
196 | 196 | ||
197 | pd_offset = ppgtt->pd_offset; |
197 | pd_offset = ppgtt->pd_offset; |
198 | pd_offset /= 64; /* in cachelines, */ |
198 | pd_offset /= 64; /* in cachelines, */ |
199 | pd_offset <<= 16; |
199 | pd_offset <<= 16; |
200 | 200 | ||
201 | if (INTEL_INFO(dev)->gen == 6) { |
201 | if (INTEL_INFO(dev)->gen == 6) { |
202 | uint32_t ecochk, gab_ctl, ecobits; |
202 | uint32_t ecochk, gab_ctl, ecobits; |
203 | 203 | ||
204 | ecobits = I915_READ(GAC_ECO_BITS); |
204 | ecobits = I915_READ(GAC_ECO_BITS); |
205 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT | |
205 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT | |
206 | ECOBITS_PPGTT_CACHE64B); |
206 | ECOBITS_PPGTT_CACHE64B); |
207 | 207 | ||
208 | gab_ctl = I915_READ(GAB_CTL); |
208 | gab_ctl = I915_READ(GAB_CTL); |
209 | I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); |
209 | I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); |
210 | 210 | ||
211 | ecochk = I915_READ(GAM_ECOCHK); |
211 | ecochk = I915_READ(GAM_ECOCHK); |
212 | I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | |
212 | I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | |
213 | ECOCHK_PPGTT_CACHE64B); |
213 | ECOCHK_PPGTT_CACHE64B); |
214 | I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
214 | I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
215 | } else if (INTEL_INFO(dev)->gen >= 7) { |
215 | } else if (INTEL_INFO(dev)->gen >= 7) { |
216 | uint32_t ecochk, ecobits; |
216 | uint32_t ecochk, ecobits; |
217 | 217 | ||
218 | ecobits = I915_READ(GAC_ECO_BITS); |
218 | ecobits = I915_READ(GAC_ECO_BITS); |
219 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
219 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
220 | 220 | ||
221 | ecochk = I915_READ(GAM_ECOCHK); |
221 | ecochk = I915_READ(GAM_ECOCHK); |
222 | if (IS_HASWELL(dev)) { |
222 | if (IS_HASWELL(dev)) { |
223 | ecochk |= ECOCHK_PPGTT_WB_HSW; |
223 | ecochk |= ECOCHK_PPGTT_WB_HSW; |
224 | } else { |
224 | } else { |
225 | ecochk |= ECOCHK_PPGTT_LLC_IVB; |
225 | ecochk |= ECOCHK_PPGTT_LLC_IVB; |
226 | ecochk &= ~ECOCHK_PPGTT_GFDT_IVB; |
226 | ecochk &= ~ECOCHK_PPGTT_GFDT_IVB; |
227 | } |
227 | } |
228 | I915_WRITE(GAM_ECOCHK, ecochk); |
228 | I915_WRITE(GAM_ECOCHK, ecochk); |
229 | /* GFX_MODE is per-ring on gen7+ */ |
229 | /* GFX_MODE is per-ring on gen7+ */ |
230 | } |
230 | } |
231 | 231 | ||
232 | for_each_ring(ring, dev_priv, i) { |
232 | for_each_ring(ring, dev_priv, i) { |
233 | if (INTEL_INFO(dev)->gen >= 7) |
233 | if (INTEL_INFO(dev)->gen >= 7) |
234 | I915_WRITE(RING_MODE_GEN7(ring), |
234 | I915_WRITE(RING_MODE_GEN7(ring), |
235 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
235 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
236 | 236 | ||
237 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
237 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
238 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
238 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
239 | } |
239 | } |
240 | return 0; |
240 | return 0; |
241 | } |
241 | } |
242 | 242 | ||
243 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
243 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
244 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, |
244 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, |
245 | unsigned first_entry, |
245 | unsigned first_entry, |
246 | unsigned num_entries) |
246 | unsigned num_entries) |
247 | { |
247 | { |
248 | struct i915_hw_ppgtt *ppgtt = |
248 | struct i915_hw_ppgtt *ppgtt = |
249 | container_of(vm, struct i915_hw_ppgtt, base); |
249 | container_of(vm, struct i915_hw_ppgtt, base); |
250 | gen6_gtt_pte_t *pt_vaddr, scratch_pte; |
250 | gen6_gtt_pte_t *pt_vaddr, scratch_pte; |
251 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
251 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
252 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
252 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
253 | unsigned last_pte, i; |
253 | unsigned last_pte, i; |
254 | 254 | ||
255 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); |
255 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); |
256 | 256 | ||
257 | pt_vaddr = AllocKernelSpace(4096); |
257 | pt_vaddr = AllocKernelSpace(4096); |
258 | 258 | ||
259 | if(pt_vaddr == NULL) |
259 | if(pt_vaddr == NULL) |
260 | return; |
260 | return; |
261 | 261 | ||
262 | while (num_entries) { |
262 | while (num_entries) { |
263 | last_pte = first_pte + num_entries; |
263 | last_pte = first_pte + num_entries; |
264 | if (last_pte > I915_PPGTT_PT_ENTRIES) |
264 | if (last_pte > I915_PPGTT_PT_ENTRIES) |
265 | last_pte = I915_PPGTT_PT_ENTRIES; |
265 | last_pte = I915_PPGTT_PT_ENTRIES; |
266 | 266 | ||
267 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
267 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
268 | 268 | ||
269 | for (i = first_pte; i < last_pte; i++) |
269 | for (i = first_pte; i < last_pte; i++) |
270 | pt_vaddr[i] = scratch_pte; |
270 | pt_vaddr[i] = scratch_pte; |
271 | 271 | ||
272 | num_entries -= last_pte - first_pte; |
272 | num_entries -= last_pte - first_pte; |
273 | first_pte = 0; |
273 | first_pte = 0; |
274 | act_pt++; |
274 | act_pt++; |
275 | }; |
275 | }; |
276 | 276 | ||
277 | FreeKernelSpace(pt_vaddr); |
277 | FreeKernelSpace(pt_vaddr); |
278 | } |
278 | } |
279 | 279 | ||
280 | static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, |
280 | static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, |
281 | struct sg_table *pages, |
281 | struct sg_table *pages, |
282 | unsigned first_entry, |
282 | unsigned first_entry, |
283 | enum i915_cache_level cache_level) |
283 | enum i915_cache_level cache_level) |
284 | { |
284 | { |
285 | struct i915_hw_ppgtt *ppgtt = |
285 | struct i915_hw_ppgtt *ppgtt = |
286 | container_of(vm, struct i915_hw_ppgtt, base); |
286 | container_of(vm, struct i915_hw_ppgtt, base); |
287 | gen6_gtt_pte_t *pt_vaddr; |
287 | gen6_gtt_pte_t *pt_vaddr; |
288 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
288 | unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES; |
289 | unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
289 | unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES; |
290 | struct sg_page_iter sg_iter; |
290 | struct sg_page_iter sg_iter; |
291 | dma_addr_t page_addr; |
291 | dma_addr_t page_addr; |
292 | 292 | ||
293 | 293 | ||
294 | pt_vaddr = AllocKernelSpace(4096); |
294 | pt_vaddr = AllocKernelSpace(4096); |
295 | 295 | ||
296 | if(pt_vaddr == NULL) |
296 | if(pt_vaddr == NULL) |
297 | return; |
297 | return; |
298 | 298 | ||
299 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
299 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
300 | for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { |
300 | for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { |
301 | dma_addr_t page_addr; |
301 | dma_addr_t page_addr; |
302 | 302 | ||
303 | page_addr = sg_page_iter_dma_address(&sg_iter); |
303 | page_addr = sg_page_iter_dma_address(&sg_iter); |
304 | pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level); |
304 | pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level); |
305 | if (++act_pte == I915_PPGTT_PT_ENTRIES) { |
305 | if (++act_pte == I915_PPGTT_PT_ENTRIES) { |
306 | act_pt++; |
306 | act_pt++; |
307 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
307 | MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3); |
308 | act_pte = 0; |
308 | act_pte = 0; |
309 | 309 | ||
310 | } |
310 | } |
311 | } |
311 | } |
312 | FreeKernelSpace(pt_vaddr); |
312 | FreeKernelSpace(pt_vaddr); |
313 | } |
313 | } |
314 | 314 | ||
315 | static void gen6_ppgtt_cleanup(struct i915_address_space *vm) |
315 | static void gen6_ppgtt_cleanup(struct i915_address_space *vm) |
316 | { |
316 | { |
317 | struct i915_hw_ppgtt *ppgtt = |
317 | struct i915_hw_ppgtt *ppgtt = |
318 | container_of(vm, struct i915_hw_ppgtt, base); |
318 | container_of(vm, struct i915_hw_ppgtt, base); |
319 | int i; |
319 | int i; |
320 | 320 | ||
321 | drm_mm_takedown(&ppgtt->base.mm); |
321 | drm_mm_takedown(&ppgtt->base.mm); |
322 | 322 | ||
323 | if (ppgtt->pt_dma_addr) { |
323 | if (ppgtt->pt_dma_addr) { |
324 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
324 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
325 | pci_unmap_page(ppgtt->base.dev->pdev, |
325 | pci_unmap_page(ppgtt->base.dev->pdev, |
326 | ppgtt->pt_dma_addr[i], |
326 | ppgtt->pt_dma_addr[i], |
327 | 4096, PCI_DMA_BIDIRECTIONAL); |
327 | 4096, PCI_DMA_BIDIRECTIONAL); |
328 | } |
328 | } |
329 | 329 | ||
330 | kfree(ppgtt->pt_dma_addr); |
330 | kfree(ppgtt->pt_dma_addr); |
331 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
331 | for (i = 0; i < ppgtt->num_pd_entries; i++) |
332 | __free_page(ppgtt->pt_pages[i]); |
332 | __free_page(ppgtt->pt_pages[i]); |
333 | kfree(ppgtt->pt_pages); |
333 | kfree(ppgtt->pt_pages); |
334 | kfree(ppgtt); |
334 | kfree(ppgtt); |
335 | } |
335 | } |
336 | 336 | ||
337 | static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) |
337 | static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) |
338 | { |
338 | { |
339 | struct drm_device *dev = ppgtt->base.dev; |
339 | struct drm_device *dev = ppgtt->base.dev; |
340 | struct drm_i915_private *dev_priv = dev->dev_private; |
340 | struct drm_i915_private *dev_priv = dev->dev_private; |
341 | unsigned first_pd_entry_in_global_pt; |
341 | unsigned first_pd_entry_in_global_pt; |
342 | int i; |
342 | int i; |
343 | int ret = -ENOMEM; |
343 | int ret = -ENOMEM; |
344 | 344 | ||
345 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
345 | /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 |
346 | * entries. For aliasing ppgtt support we just steal them at the end for |
346 | * entries. For aliasing ppgtt support we just steal them at the end for |
347 | * now. */ |
347 | * now. */ |
348 | first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt); |
348 | first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt); |
349 | 349 | ||
350 | ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode; |
350 | ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode; |
351 | ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES; |
351 | ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES; |
352 | ppgtt->enable = gen6_ppgtt_enable; |
352 | ppgtt->enable = gen6_ppgtt_enable; |
353 | ppgtt->base.clear_range = gen6_ppgtt_clear_range; |
353 | ppgtt->base.clear_range = gen6_ppgtt_clear_range; |
354 | ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; |
354 | ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; |
355 | ppgtt->base.cleanup = gen6_ppgtt_cleanup; |
355 | ppgtt->base.cleanup = gen6_ppgtt_cleanup; |
356 | ppgtt->base.scratch = dev_priv->gtt.base.scratch; |
356 | ppgtt->base.scratch = dev_priv->gtt.base.scratch; |
357 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, |
357 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, |
358 | GFP_KERNEL); |
358 | GFP_KERNEL); |
359 | if (!ppgtt->pt_pages) |
359 | if (!ppgtt->pt_pages) |
360 | return -ENOMEM; |
360 | return -ENOMEM; |
361 | 361 | ||
362 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
362 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
363 | ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL); |
363 | ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL); |
364 | if (!ppgtt->pt_pages[i]) |
364 | if (!ppgtt->pt_pages[i]) |
365 | goto err_pt_alloc; |
365 | goto err_pt_alloc; |
366 | } |
366 | } |
367 | 367 | ||
368 | ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, |
368 | ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, |
369 | GFP_KERNEL); |
369 | GFP_KERNEL); |
370 | if (!ppgtt->pt_dma_addr) |
370 | if (!ppgtt->pt_dma_addr) |
371 | goto err_pt_alloc; |
371 | goto err_pt_alloc; |
372 | 372 | ||
373 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
373 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
374 | dma_addr_t pt_addr; |
374 | dma_addr_t pt_addr; |
375 | 375 | ||
376 | pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], 0, 4096, |
376 | pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], 0, 4096, |
377 | PCI_DMA_BIDIRECTIONAL); |
377 | PCI_DMA_BIDIRECTIONAL); |
378 | 378 | ||
379 | ppgtt->pt_dma_addr[i] = pt_addr; |
379 | ppgtt->pt_dma_addr[i] = pt_addr; |
380 | } |
380 | } |
381 | 381 | ||
382 | ppgtt->base.clear_range(&ppgtt->base, 0, |
382 | ppgtt->base.clear_range(&ppgtt->base, 0, |
383 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
383 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
384 | 384 | ||
385 | ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); |
385 | ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); |
386 | 386 | ||
387 | return 0; |
387 | return 0; |
388 | 388 | ||
389 | err_pd_pin: |
389 | err_pd_pin: |
390 | if (ppgtt->pt_dma_addr) { |
390 | if (ppgtt->pt_dma_addr) { |
391 | for (i--; i >= 0; i--) |
391 | for (i--; i >= 0; i--) |
392 | pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], |
392 | pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], |
393 | 4096, PCI_DMA_BIDIRECTIONAL); |
393 | 4096, PCI_DMA_BIDIRECTIONAL); |
394 | } |
394 | } |
395 | err_pt_alloc: |
395 | err_pt_alloc: |
396 | kfree(ppgtt->pt_dma_addr); |
396 | kfree(ppgtt->pt_dma_addr); |
397 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
397 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
398 | if (ppgtt->pt_pages[i]) |
398 | if (ppgtt->pt_pages[i]) |
399 | __free_page(ppgtt->pt_pages[i]); |
399 | __free_page(ppgtt->pt_pages[i]); |
400 | } |
400 | } |
401 | kfree(ppgtt->pt_pages); |
401 | kfree(ppgtt->pt_pages); |
402 | 402 | ||
403 | return ret; |
403 | return ret; |
404 | } |
404 | } |
405 | 405 | ||
406 | static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) |
406 | static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) |
407 | { |
407 | { |
408 | struct drm_i915_private *dev_priv = dev->dev_private; |
408 | struct drm_i915_private *dev_priv = dev->dev_private; |
409 | struct i915_hw_ppgtt *ppgtt; |
409 | struct i915_hw_ppgtt *ppgtt; |
410 | int ret; |
410 | int ret; |
411 | 411 | ||
412 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
412 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
413 | if (!ppgtt) |
413 | if (!ppgtt) |
414 | return -ENOMEM; |
414 | return -ENOMEM; |
415 | 415 | ||
416 | ppgtt->base.dev = dev; |
416 | ppgtt->base.dev = dev; |
417 | 417 | ||
418 | if (INTEL_INFO(dev)->gen < 8) |
418 | if (INTEL_INFO(dev)->gen < 8) |
419 | ret = gen6_ppgtt_init(ppgtt); |
419 | ret = gen6_ppgtt_init(ppgtt); |
420 | else |
420 | else |
421 | BUG(); |
421 | BUG(); |
422 | 422 | ||
423 | if (ret) |
423 | if (ret) |
424 | kfree(ppgtt); |
424 | kfree(ppgtt); |
425 | else { |
425 | else { |
426 | dev_priv->mm.aliasing_ppgtt = ppgtt; |
426 | dev_priv->mm.aliasing_ppgtt = ppgtt; |
427 | drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, |
427 | drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, |
428 | ppgtt->base.total); |
428 | ppgtt->base.total); |
429 | } |
429 | } |
430 | 430 | ||
431 | return ret; |
431 | return ret; |
432 | } |
432 | } |
433 | 433 | ||
434 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) |
434 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) |
435 | { |
435 | { |
436 | struct drm_i915_private *dev_priv = dev->dev_private; |
436 | struct drm_i915_private *dev_priv = dev->dev_private; |
437 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
437 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
438 | 438 | ||
439 | if (!ppgtt) |
439 | if (!ppgtt) |
440 | return; |
440 | return; |
441 | 441 | ||
442 | ppgtt->base.cleanup(&ppgtt->base); |
442 | ppgtt->base.cleanup(&ppgtt->base); |
443 | dev_priv->mm.aliasing_ppgtt = NULL; |
443 | dev_priv->mm.aliasing_ppgtt = NULL; |
444 | } |
444 | } |
445 | 445 | ||
446 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
446 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
447 | struct drm_i915_gem_object *obj, |
447 | struct drm_i915_gem_object *obj, |
448 | enum i915_cache_level cache_level) |
448 | enum i915_cache_level cache_level) |
449 | { |
449 | { |
450 | ppgtt->base.insert_entries(&ppgtt->base, obj->pages, |
450 | ppgtt->base.insert_entries(&ppgtt->base, obj->pages, |
451 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, |
451 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, |
452 | cache_level); |
452 | cache_level); |
453 | } |
453 | } |
454 | 454 | ||
455 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
455 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
456 | struct drm_i915_gem_object *obj) |
456 | struct drm_i915_gem_object *obj) |
457 | { |
457 | { |
458 | ppgtt->base.clear_range(&ppgtt->base, |
458 | ppgtt->base.clear_range(&ppgtt->base, |
459 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, |
459 | i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, |
460 | obj->base.size >> PAGE_SHIFT); |
460 | obj->base.size >> PAGE_SHIFT); |
461 | } |
461 | } |
462 | 462 | ||
463 | extern int intel_iommu_gfx_mapped; |
463 | extern int intel_iommu_gfx_mapped; |
464 | /* Certain Gen5 chipsets require require idling the GPU before |
464 | /* Certain Gen5 chipsets require require idling the GPU before |
465 | * unmapping anything from the GTT when VT-d is enabled. |
465 | * unmapping anything from the GTT when VT-d is enabled. |
466 | */ |
466 | */ |
467 | static inline bool needs_idle_maps(struct drm_device *dev) |
467 | static inline bool needs_idle_maps(struct drm_device *dev) |
468 | { |
468 | { |
469 | #ifdef CONFIG_INTEL_IOMMU |
469 | #ifdef CONFIG_INTEL_IOMMU |
470 | /* Query intel_iommu to see if we need the workaround. Presumably that |
470 | /* Query intel_iommu to see if we need the workaround. Presumably that |
471 | * was loaded first. |
471 | * was loaded first. |
472 | */ |
472 | */ |
473 | if (IS_GEN5(dev) && IS_MOBILE(dev) && intel_iommu_gfx_mapped) |
473 | if (IS_GEN5(dev) && IS_MOBILE(dev) && intel_iommu_gfx_mapped) |
474 | return true; |
474 | return true; |
475 | #endif |
475 | #endif |
476 | return false; |
476 | return false; |
477 | } |
477 | } |
478 | 478 | ||
479 | static bool do_idling(struct drm_i915_private *dev_priv) |
479 | static bool do_idling(struct drm_i915_private *dev_priv) |
480 | { |
480 | { |
481 | bool ret = dev_priv->mm.interruptible; |
481 | bool ret = dev_priv->mm.interruptible; |
482 | 482 | ||
483 | if (unlikely(dev_priv->gtt.do_idle_maps)) { |
483 | if (unlikely(dev_priv->gtt.do_idle_maps)) { |
484 | dev_priv->mm.interruptible = false; |
484 | dev_priv->mm.interruptible = false; |
485 | if (i915_gpu_idle(dev_priv->dev)) { |
485 | if (i915_gpu_idle(dev_priv->dev)) { |
486 | DRM_ERROR("Couldn't idle GPU\n"); |
486 | DRM_ERROR("Couldn't idle GPU\n"); |
487 | /* Wait a bit, in hopes it avoids the hang */ |
487 | /* Wait a bit, in hopes it avoids the hang */ |
488 | udelay(10); |
488 | udelay(10); |
489 | } |
489 | } |
490 | } |
490 | } |
491 | 491 | ||
492 | return ret; |
492 | return ret; |
493 | } |
493 | } |
494 | 494 | ||
495 | static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) |
495 | static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) |
496 | { |
496 | { |
497 | if (unlikely(dev_priv->gtt.do_idle_maps)) |
497 | if (unlikely(dev_priv->gtt.do_idle_maps)) |
498 | dev_priv->mm.interruptible = interruptible; |
498 | dev_priv->mm.interruptible = interruptible; |
499 | } |
499 | } |
500 | 500 | ||
501 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
501 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
502 | { |
502 | { |
503 | struct drm_i915_private *dev_priv = dev->dev_private; |
503 | struct drm_i915_private *dev_priv = dev->dev_private; |
504 | struct drm_i915_gem_object *obj; |
504 | struct drm_i915_gem_object *obj; |
505 | 505 | ||
506 | /* First fill our portion of the GTT with scratch pages */ |
506 | /* First fill our portion of the GTT with scratch pages */ |
507 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
507 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
508 | dev_priv->gtt.base.start / PAGE_SIZE, |
508 | dev_priv->gtt.base.start / PAGE_SIZE, |
509 | dev_priv->gtt.base.total / PAGE_SIZE); |
509 | dev_priv->gtt.base.total / PAGE_SIZE); |
510 | 510 | ||
511 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
511 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
512 | i915_gem_clflush_object(obj, obj->pin_display); |
512 | i915_gem_clflush_object(obj, obj->pin_display); |
513 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
513 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
514 | } |
514 | } |
515 | 515 | ||
516 | i915_gem_chipset_flush(dev); |
516 | i915_gem_chipset_flush(dev); |
517 | } |
517 | } |
518 | 518 | ||
519 | int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) |
519 | int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) |
520 | { |
520 | { |
521 | if (obj->has_dma_mapping) |
521 | if (obj->has_dma_mapping) |
522 | return 0; |
522 | return 0; |
523 | 523 | ||
524 | if (!dma_map_sg(&obj->base.dev->pdev->dev, |
524 | if (!dma_map_sg(&obj->base.dev->pdev->dev, |
525 | obj->pages->sgl, obj->pages->nents, |
525 | obj->pages->sgl, obj->pages->nents, |
526 | PCI_DMA_BIDIRECTIONAL)) |
526 | PCI_DMA_BIDIRECTIONAL)) |
527 | return -ENOSPC; |
527 | return -ENOSPC; |
528 | 528 | ||
529 | return 0; |
529 | return 0; |
530 | } |
530 | } |
531 | 531 | ||
532 | /* |
532 | /* |
533 | * Binds an object into the global gtt with the specified cache level. The object |
533 | * Binds an object into the global gtt with the specified cache level. The object |
534 | * will be accessible to the GPU via commands whose operands reference offsets |
534 | * will be accessible to the GPU via commands whose operands reference offsets |
535 | * within the global GTT as well as accessible by the GPU through the GMADR |
535 | * within the global GTT as well as accessible by the GPU through the GMADR |
536 | * mapped BAR (dev_priv->mm.gtt->gtt). |
536 | * mapped BAR (dev_priv->mm.gtt->gtt). |
537 | */ |
537 | */ |
538 | static void gen6_ggtt_insert_entries(struct i915_address_space *vm, |
538 | static void gen6_ggtt_insert_entries(struct i915_address_space *vm, |
539 | struct sg_table *st, |
539 | struct sg_table *st, |
540 | unsigned int first_entry, |
540 | unsigned int first_entry, |
541 | enum i915_cache_level level) |
541 | enum i915_cache_level level) |
542 | { |
542 | { |
543 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
543 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
544 | gen6_gtt_pte_t __iomem *gtt_entries = |
544 | gen6_gtt_pte_t __iomem *gtt_entries = |
545 | (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; |
545 | (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; |
546 | int i = 0; |
546 | int i = 0; |
547 | struct sg_page_iter sg_iter; |
547 | struct sg_page_iter sg_iter; |
548 | dma_addr_t addr; |
548 | dma_addr_t addr; |
549 | 549 | ||
550 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { |
550 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { |
551 | addr = sg_page_iter_dma_address(&sg_iter); |
551 | addr = sg_page_iter_dma_address(&sg_iter); |
552 | iowrite32(vm->pte_encode(addr, level), >t_entries[i]); |
552 | iowrite32(vm->pte_encode(addr, level), >t_entries[i]); |
553 | i++; |
553 | i++; |
554 | } |
554 | } |
555 | 555 | ||
556 | /* XXX: This serves as a posting read to make sure that the PTE has |
556 | /* XXX: This serves as a posting read to make sure that the PTE has |
557 | * actually been updated. There is some concern that even though |
557 | * actually been updated. There is some concern that even though |
558 | * registers and PTEs are within the same BAR that they are potentially |
558 | * registers and PTEs are within the same BAR that they are potentially |
559 | * of NUMA access patterns. Therefore, even with the way we assume |
559 | * of NUMA access patterns. Therefore, even with the way we assume |
560 | * hardware should work, we must keep this posting read for paranoia. |
560 | * hardware should work, we must keep this posting read for paranoia. |
561 | */ |
561 | */ |
562 | if (i != 0) |
562 | if (i != 0) |
563 | WARN_ON(readl(>t_entries[i-1]) != |
563 | WARN_ON(readl(>t_entries[i-1]) != |
564 | vm->pte_encode(addr, level)); |
564 | vm->pte_encode(addr, level)); |
565 | 565 | ||
566 | /* This next bit makes the above posting read even more important. We |
566 | /* This next bit makes the above posting read even more important. We |
567 | * want to flush the TLBs only after we're certain all the PTE updates |
567 | * want to flush the TLBs only after we're certain all the PTE updates |
568 | * have finished. |
568 | * have finished. |
569 | */ |
569 | */ |
570 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
570 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
571 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
571 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
572 | } |
572 | } |
573 | 573 | ||
574 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, |
574 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, |
575 | unsigned int first_entry, |
575 | unsigned int first_entry, |
576 | unsigned int num_entries) |
576 | unsigned int num_entries) |
577 | { |
577 | { |
578 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
578 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
579 | gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = |
579 | gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = |
580 | (gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; |
580 | (gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; |
581 | const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; |
581 | const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; |
582 | int i; |
582 | int i; |
583 | 583 | ||
584 | // if (WARN(num_entries > max_entries, |
584 | if (WARN(num_entries > max_entries, |
585 | // "First entry = %d; Num entries = %d (max=%d)\n", |
585 | "First entry = %d; Num entries = %d (max=%d)\n", |
586 | // first_entry, num_entries, max_entries)) |
- | |
587 | if (num_entries > max_entries) |
586 | first_entry, num_entries, max_entries)) |
588 | num_entries = max_entries; |
587 | num_entries = max_entries; |
589 | 588 | ||
590 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); |
589 | scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); |
591 | for (i = 0; i < num_entries; i++) |
590 | for (i = 0; i < num_entries; i++) |
592 | iowrite32(scratch_pte, >t_base[i]); |
591 | iowrite32(scratch_pte, >t_base[i]); |
593 | readl(gtt_base); |
592 | readl(gtt_base); |
594 | } |
593 | } |
595 | 594 | ||
596 | 595 | ||
597 | static void i915_ggtt_insert_entries(struct i915_address_space *vm, |
596 | static void i915_ggtt_insert_entries(struct i915_address_space *vm, |
598 | struct sg_table *st, |
597 | struct sg_table *st, |
599 | unsigned int pg_start, |
598 | unsigned int pg_start, |
600 | enum i915_cache_level cache_level) |
599 | enum i915_cache_level cache_level) |
601 | { |
600 | { |
602 | unsigned int flags = (cache_level == I915_CACHE_NONE) ? |
601 | unsigned int flags = (cache_level == I915_CACHE_NONE) ? |
603 | AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; |
602 | AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; |
604 | 603 | ||
605 | intel_gtt_insert_sg_entries(st, pg_start, flags); |
604 | intel_gtt_insert_sg_entries(st, pg_start, flags); |
606 | 605 | ||
607 | } |
606 | } |
608 | 607 | ||
609 | static void i915_ggtt_clear_range(struct i915_address_space *vm, |
608 | static void i915_ggtt_clear_range(struct i915_address_space *vm, |
610 | unsigned int first_entry, |
609 | unsigned int first_entry, |
611 | unsigned int num_entries) |
610 | unsigned int num_entries) |
612 | { |
611 | { |
613 | intel_gtt_clear_range(first_entry, num_entries); |
612 | intel_gtt_clear_range(first_entry, num_entries); |
614 | } |
613 | } |
615 | 614 | ||
616 | 615 | ||
617 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, |
616 | void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, |
618 | enum i915_cache_level cache_level) |
617 | enum i915_cache_level cache_level) |
619 | { |
618 | { |
620 | struct drm_device *dev = obj->base.dev; |
619 | struct drm_device *dev = obj->base.dev; |
621 | struct drm_i915_private *dev_priv = dev->dev_private; |
620 | struct drm_i915_private *dev_priv = dev->dev_private; |
622 | const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; |
621 | const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; |
623 | 622 | ||
624 | dev_priv->gtt.base.insert_entries(&dev_priv->gtt.base, obj->pages, |
623 | dev_priv->gtt.base.insert_entries(&dev_priv->gtt.base, obj->pages, |
625 | entry, |
624 | entry, |
626 | cache_level); |
625 | cache_level); |
627 | 626 | ||
628 | obj->has_global_gtt_mapping = 1; |
627 | obj->has_global_gtt_mapping = 1; |
629 | } |
628 | } |
630 | 629 | ||
631 | void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) |
630 | void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) |
632 | { |
631 | { |
633 | struct drm_device *dev = obj->base.dev; |
632 | struct drm_device *dev = obj->base.dev; |
634 | struct drm_i915_private *dev_priv = dev->dev_private; |
633 | struct drm_i915_private *dev_priv = dev->dev_private; |
635 | const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; |
634 | const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; |
636 | 635 | ||
637 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
636 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
638 | entry, |
637 | entry, |
639 | obj->base.size >> PAGE_SHIFT); |
638 | obj->base.size >> PAGE_SHIFT); |
640 | 639 | ||
641 | obj->has_global_gtt_mapping = 0; |
640 | obj->has_global_gtt_mapping = 0; |
642 | } |
641 | } |
643 | 642 | ||
644 | void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) |
643 | void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) |
645 | { |
644 | { |
646 | struct drm_device *dev = obj->base.dev; |
645 | struct drm_device *dev = obj->base.dev; |
647 | struct drm_i915_private *dev_priv = dev->dev_private; |
646 | struct drm_i915_private *dev_priv = dev->dev_private; |
648 | bool interruptible; |
647 | bool interruptible; |
649 | 648 | ||
650 | interruptible = do_idling(dev_priv); |
649 | interruptible = do_idling(dev_priv); |
651 | 650 | ||
652 | if (!obj->has_dma_mapping) |
651 | if (!obj->has_dma_mapping) |
653 | dma_unmap_sg(&dev->pdev->dev, |
652 | dma_unmap_sg(&dev->pdev->dev, |
654 | obj->pages->sgl, obj->pages->nents, |
653 | obj->pages->sgl, obj->pages->nents, |
655 | PCI_DMA_BIDIRECTIONAL); |
654 | PCI_DMA_BIDIRECTIONAL); |
656 | 655 | ||
657 | undo_idling(dev_priv, interruptible); |
656 | undo_idling(dev_priv, interruptible); |
658 | } |
657 | } |
659 | 658 | ||
660 | static void i915_gtt_color_adjust(struct drm_mm_node *node, |
659 | static void i915_gtt_color_adjust(struct drm_mm_node *node, |
661 | unsigned long color, |
660 | unsigned long color, |
662 | unsigned long *start, |
661 | unsigned long *start, |
663 | unsigned long *end) |
662 | unsigned long *end) |
664 | { |
663 | { |
665 | if (node->color != color) |
664 | if (node->color != color) |
666 | *start += 4096; |
665 | *start += 4096; |
667 | 666 | ||
668 | if (!list_empty(&node->node_list)) { |
667 | if (!list_empty(&node->node_list)) { |
669 | node = list_entry(node->node_list.next, |
668 | node = list_entry(node->node_list.next, |
670 | struct drm_mm_node, |
669 | struct drm_mm_node, |
671 | node_list); |
670 | node_list); |
672 | if (node->allocated && node->color != color) |
671 | if (node->allocated && node->color != color) |
673 | *end -= 4096; |
672 | *end -= 4096; |
674 | } |
673 | } |
675 | } |
674 | } |
676 | void i915_gem_setup_global_gtt(struct drm_device *dev, |
675 | void i915_gem_setup_global_gtt(struct drm_device *dev, |
677 | unsigned long start, |
676 | unsigned long start, |
678 | unsigned long mappable_end, |
677 | unsigned long mappable_end, |
679 | unsigned long end) |
678 | unsigned long end) |
680 | { |
679 | { |
681 | /* Let GEM Manage all of the aperture. |
680 | /* Let GEM Manage all of the aperture. |
682 | * |
681 | * |
683 | * However, leave one page at the end still bound to the scratch page. |
682 | * However, leave one page at the end still bound to the scratch page. |
684 | * There are a number of places where the hardware apparently prefetches |
683 | * There are a number of places where the hardware apparently prefetches |
685 | * past the end of the object, and we've seen multiple hangs with the |
684 | * past the end of the object, and we've seen multiple hangs with the |
686 | * GPU head pointer stuck in a batchbuffer bound at the last page of the |
685 | * GPU head pointer stuck in a batchbuffer bound at the last page of the |
687 | * aperture. One page should be enough to keep any prefetching inside |
686 | * aperture. One page should be enough to keep any prefetching inside |
688 | * of the aperture. |
687 | * of the aperture. |
689 | */ |
688 | */ |
690 | struct drm_i915_private *dev_priv = dev->dev_private; |
689 | struct drm_i915_private *dev_priv = dev->dev_private; |
691 | struct i915_address_space *ggtt_vm = &dev_priv->gtt.base; |
690 | struct i915_address_space *ggtt_vm = &dev_priv->gtt.base; |
692 | struct drm_mm_node *entry; |
691 | struct drm_mm_node *entry; |
693 | struct drm_i915_gem_object *obj; |
692 | struct drm_i915_gem_object *obj; |
694 | unsigned long hole_start, hole_end; |
693 | unsigned long hole_start, hole_end; |
695 | 694 | ||
696 | BUG_ON(mappable_end > end); |
695 | BUG_ON(mappable_end > end); |
697 | 696 | ||
698 | /* Subtract the guard page ... */ |
697 | /* Subtract the guard page ... */ |
699 | drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); |
698 | drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); |
700 | if (!HAS_LLC(dev)) |
699 | if (!HAS_LLC(dev)) |
701 | dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; |
700 | dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; |
702 | 701 | ||
703 | /* Mark any preallocated objects as occupied */ |
702 | /* Mark any preallocated objects as occupied */ |
704 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
703 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
705 | struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm); |
704 | struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm); |
706 | int ret; |
705 | int ret; |
707 | DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n", |
706 | DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n", |
708 | i915_gem_obj_ggtt_offset(obj), obj->base.size); |
707 | i915_gem_obj_ggtt_offset(obj), obj->base.size); |
709 | 708 | ||
710 | WARN_ON(i915_gem_obj_ggtt_bound(obj)); |
709 | WARN_ON(i915_gem_obj_ggtt_bound(obj)); |
711 | ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node); |
710 | ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node); |
712 | if (ret) |
711 | if (ret) |
713 | DRM_DEBUG_KMS("Reservation failed\n"); |
712 | DRM_DEBUG_KMS("Reservation failed\n"); |
714 | obj->has_global_gtt_mapping = 1; |
713 | obj->has_global_gtt_mapping = 1; |
715 | list_add(&vma->vma_link, &obj->vma_list); |
714 | list_add(&vma->vma_link, &obj->vma_list); |
716 | } |
715 | } |
717 | 716 | ||
718 | dev_priv->gtt.base.start = start; |
717 | dev_priv->gtt.base.start = start; |
719 | dev_priv->gtt.base.total = end - start; |
718 | dev_priv->gtt.base.total = end - start; |
720 | 719 | ||
721 | /* Clear any non-preallocated blocks */ |
720 | /* Clear any non-preallocated blocks */ |
722 | drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) { |
721 | drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) { |
723 | const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; |
722 | const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; |
724 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", |
723 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", |
725 | hole_start, hole_end); |
724 | hole_start, hole_end); |
726 | ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); |
725 | ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); |
727 | } |
726 | } |
728 | 727 | ||
729 | /* And finally clear the reserved guard page */ |
728 | /* And finally clear the reserved guard page */ |
730 | ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); |
729 | ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); |
731 | } |
730 | } |
732 | 731 | ||
733 | static bool |
732 | static bool |
734 | intel_enable_ppgtt(struct drm_device *dev) |
733 | intel_enable_ppgtt(struct drm_device *dev) |
735 | { |
734 | { |
736 | if (i915_enable_ppgtt >= 0) |
735 | if (i915_enable_ppgtt >= 0) |
737 | return i915_enable_ppgtt; |
736 | return i915_enable_ppgtt; |
738 | 737 | ||
739 | #ifdef CONFIG_INTEL_IOMMU |
738 | #ifdef CONFIG_INTEL_IOMMU |
740 | /* Disable ppgtt on SNB if VT-d is on. */ |
739 | /* Disable ppgtt on SNB if VT-d is on. */ |
741 | if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) |
740 | if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) |
742 | return false; |
741 | return false; |
743 | #endif |
742 | #endif |
744 | 743 | ||
745 | return true; |
744 | return true; |
746 | } |
745 | } |
747 | 746 | ||
748 | void i915_gem_init_global_gtt(struct drm_device *dev) |
747 | void i915_gem_init_global_gtt(struct drm_device *dev) |
749 | { |
748 | { |
750 | struct drm_i915_private *dev_priv = dev->dev_private; |
749 | struct drm_i915_private *dev_priv = dev->dev_private; |
751 | unsigned long gtt_size, mappable_size; |
750 | unsigned long gtt_size, mappable_size; |
752 | 751 | ||
753 | gtt_size = dev_priv->gtt.base.total; |
752 | gtt_size = dev_priv->gtt.base.total; |
754 | mappable_size = dev_priv->gtt.mappable_end; |
753 | mappable_size = dev_priv->gtt.mappable_end; |
755 | 754 | ||
756 | #if 0 |
755 | #if 0 |
757 | if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { |
756 | if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { |
758 | int ret; |
757 | int ret; |
759 | 758 | ||
760 | if (INTEL_INFO(dev)->gen <= 7) { |
759 | if (INTEL_INFO(dev)->gen <= 7) { |
761 | /* PPGTT pdes are stolen from global gtt ptes, so shrink the |
760 | /* PPGTT pdes are stolen from global gtt ptes, so shrink the |
762 | * aperture accordingly when using aliasing ppgtt. */ |
761 | * aperture accordingly when using aliasing ppgtt. */ |
763 | gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; |
762 | gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; |
764 | } |
763 | } |
765 | 764 | ||
766 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE); |
765 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE); |
767 | 766 | ||
768 | ret = i915_gem_init_aliasing_ppgtt(dev); |
767 | ret = i915_gem_init_aliasing_ppgtt(dev); |
769 | if (!ret) |
768 | if (!ret) |
770 | return; |
769 | return; |
771 | 770 | ||
772 | DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); |
771 | DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); |
773 | drm_mm_takedown(&dev_priv->gtt.base.mm); |
772 | drm_mm_takedown(&dev_priv->gtt.base.mm); |
774 | gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; |
773 | gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; |
775 | } |
774 | } |
776 | #endif |
775 | #endif |
777 | 776 | ||
778 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE); |
777 | i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE); |
779 | } |
778 | } |
780 | 779 | ||
781 | static int setup_scratch_page(struct drm_device *dev) |
780 | static int setup_scratch_page(struct drm_device *dev) |
782 | { |
781 | { |
783 | struct drm_i915_private *dev_priv = dev->dev_private; |
782 | struct drm_i915_private *dev_priv = dev->dev_private; |
784 | struct page *page; |
783 | struct page *page; |
785 | dma_addr_t dma_addr; |
784 | dma_addr_t dma_addr; |
786 | 785 | ||
787 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
786 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
788 | if (page == NULL) |
787 | if (page == NULL) |
789 | return -ENOMEM; |
788 | return -ENOMEM; |
790 | get_page(page); |
789 | get_page(page); |
791 | set_pages_uc(page, 1); |
790 | set_pages_uc(page, 1); |
792 | 791 | ||
793 | #ifdef CONFIG_INTEL_IOMMU |
792 | #ifdef CONFIG_INTEL_IOMMU |
794 | dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE, |
793 | dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE, |
795 | PCI_DMA_BIDIRECTIONAL); |
794 | PCI_DMA_BIDIRECTIONAL); |
796 | if (pci_dma_mapping_error(dev->pdev, dma_addr)) |
795 | if (pci_dma_mapping_error(dev->pdev, dma_addr)) |
797 | return -EINVAL; |
796 | return -EINVAL; |
798 | #else |
797 | #else |
799 | dma_addr = page_to_phys(page); |
798 | dma_addr = page_to_phys(page); |
800 | #endif |
799 | #endif |
801 | dev_priv->gtt.base.scratch.page = page; |
800 | dev_priv->gtt.base.scratch.page = page; |
802 | dev_priv->gtt.base.scratch.addr = dma_addr; |
801 | dev_priv->gtt.base.scratch.addr = dma_addr; |
803 | 802 | ||
804 | return 0; |
803 | return 0; |
805 | } |
804 | } |
806 | 805 | ||
807 | static void teardown_scratch_page(struct drm_device *dev) |
806 | static void teardown_scratch_page(struct drm_device *dev) |
808 | { |
807 | { |
809 | struct drm_i915_private *dev_priv = dev->dev_private; |
808 | struct drm_i915_private *dev_priv = dev->dev_private; |
810 | struct page *page = dev_priv->gtt.base.scratch.page; |
809 | struct page *page = dev_priv->gtt.base.scratch.page; |
811 | 810 | ||
812 | set_pages_wb(page, 1); |
811 | set_pages_wb(page, 1); |
813 | pci_unmap_page(dev->pdev, dev_priv->gtt.base.scratch.addr, |
812 | pci_unmap_page(dev->pdev, dev_priv->gtt.base.scratch.addr, |
814 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
813 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
815 | put_page(page); |
814 | put_page(page); |
816 | __free_page(page); |
815 | __free_page(page); |
817 | } |
816 | } |
818 | 817 | ||
819 | static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) |
818 | static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) |
820 | { |
819 | { |
821 | snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; |
820 | snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; |
822 | snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; |
821 | snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; |
823 | return snb_gmch_ctl << 20; |
822 | return snb_gmch_ctl << 20; |
824 | } |
823 | } |
825 | 824 | ||
826 | static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) |
825 | static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) |
827 | { |
826 | { |
828 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
827 | snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; |
829 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
828 | snb_gmch_ctl &= SNB_GMCH_GMS_MASK; |
830 | return snb_gmch_ctl << 25; /* 32 MB units */ |
829 | return snb_gmch_ctl << 25; /* 32 MB units */ |
831 | } |
830 | } |
832 | 831 | ||
833 | static int gen6_gmch_probe(struct drm_device *dev, |
832 | static int gen6_gmch_probe(struct drm_device *dev, |
834 | size_t *gtt_total, |
833 | size_t *gtt_total, |
835 | size_t *stolen, |
834 | size_t *stolen, |
836 | phys_addr_t *mappable_base, |
835 | phys_addr_t *mappable_base, |
837 | unsigned long *mappable_end) |
836 | unsigned long *mappable_end) |
838 | { |
837 | { |
839 | struct drm_i915_private *dev_priv = dev->dev_private; |
838 | struct drm_i915_private *dev_priv = dev->dev_private; |
840 | phys_addr_t gtt_bus_addr; |
839 | phys_addr_t gtt_bus_addr; |
841 | unsigned int gtt_size; |
840 | unsigned int gtt_size; |
842 | u16 snb_gmch_ctl; |
841 | u16 snb_gmch_ctl; |
843 | int ret; |
842 | int ret; |
844 | 843 | ||
845 | *mappable_base = pci_resource_start(dev->pdev, 2); |
844 | *mappable_base = pci_resource_start(dev->pdev, 2); |
846 | *mappable_end = pci_resource_len(dev->pdev, 2); |
845 | *mappable_end = pci_resource_len(dev->pdev, 2); |
847 | 846 | ||
848 | /* 64/512MB is the current min/max we actually know of, but this is just |
847 | /* 64/512MB is the current min/max we actually know of, but this is just |
849 | * a coarse sanity check. |
848 | * a coarse sanity check. |
850 | */ |
849 | */ |
851 | if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { |
850 | if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { |
852 | DRM_ERROR("Unknown GMADR size (%lx)\n", |
851 | DRM_ERROR("Unknown GMADR size (%lx)\n", |
853 | dev_priv->gtt.mappable_end); |
852 | dev_priv->gtt.mappable_end); |
854 | return -ENXIO; |
853 | return -ENXIO; |
855 | } |
854 | } |
856 | 855 | ||
857 | if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) |
856 | if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) |
858 | pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); |
857 | pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); |
859 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
858 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
860 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
859 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
861 | 860 | ||
862 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
861 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
863 | *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; |
862 | *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; |
864 | 863 | ||
865 | /* For Modern GENs the PTEs and register space are split in the BAR */ |
864 | /* For Modern GENs the PTEs and register space are split in the BAR */ |
866 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + |
865 | gtt_bus_addr = pci_resource_start(dev->pdev, 0) + |
867 | (pci_resource_len(dev->pdev, 0) / 2); |
866 | (pci_resource_len(dev->pdev, 0) / 2); |
868 | 867 | ||
869 | dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); |
868 | dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); |
870 | if (!dev_priv->gtt.gsm) { |
869 | if (!dev_priv->gtt.gsm) { |
871 | DRM_ERROR("Failed to map the gtt page table\n"); |
870 | DRM_ERROR("Failed to map the gtt page table\n"); |
872 | return -ENOMEM; |
871 | return -ENOMEM; |
873 | } |
872 | } |
874 | 873 | ||
875 | ret = setup_scratch_page(dev); |
874 | ret = setup_scratch_page(dev); |
876 | if (ret) |
875 | if (ret) |
877 | DRM_ERROR("Scratch setup failed\n"); |
876 | DRM_ERROR("Scratch setup failed\n"); |
878 | 877 | ||
879 | dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; |
878 | dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; |
880 | dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; |
879 | dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; |
881 | 880 | ||
882 | return ret; |
881 | return ret; |
883 | } |
882 | } |
884 | 883 | ||
885 | static void gen6_gmch_remove(struct i915_address_space *vm) |
884 | static void gen6_gmch_remove(struct i915_address_space *vm) |
886 | { |
885 | { |
887 | 886 | ||
888 | struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); |
887 | struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); |
889 | iounmap(gtt->gsm); |
888 | iounmap(gtt->gsm); |
890 | teardown_scratch_page(vm->dev); |
889 | teardown_scratch_page(vm->dev); |
891 | } |
890 | } |
892 | 891 | ||
893 | static int i915_gmch_probe(struct drm_device *dev, |
892 | static int i915_gmch_probe(struct drm_device *dev, |
894 | size_t *gtt_total, |
893 | size_t *gtt_total, |
895 | size_t *stolen, |
894 | size_t *stolen, |
896 | phys_addr_t *mappable_base, |
895 | phys_addr_t *mappable_base, |
897 | unsigned long *mappable_end) |
896 | unsigned long *mappable_end) |
898 | { |
897 | { |
899 | struct drm_i915_private *dev_priv = dev->dev_private; |
898 | struct drm_i915_private *dev_priv = dev->dev_private; |
900 | int ret; |
899 | int ret; |
901 | 900 | ||
902 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); |
901 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); |
903 | if (!ret) { |
902 | if (!ret) { |
904 | DRM_ERROR("failed to set up gmch\n"); |
903 | DRM_ERROR("failed to set up gmch\n"); |
905 | return -EIO; |
904 | return -EIO; |
906 | } |
905 | } |
907 | 906 | ||
908 | intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); |
907 | intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); |
909 | 908 | ||
910 | dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); |
909 | dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); |
911 | dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; |
910 | dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; |
912 | dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries; |
911 | dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries; |
913 | 912 | ||
914 | return 0; |
913 | return 0; |
915 | } |
914 | } |
916 | 915 | ||
917 | static void i915_gmch_remove(struct i915_address_space *vm) |
916 | static void i915_gmch_remove(struct i915_address_space *vm) |
918 | { |
917 | { |
919 | // intel_gmch_remove(); |
918 | // intel_gmch_remove(); |
920 | } |
919 | } |
921 | 920 | ||
922 | int i915_gem_gtt_init(struct drm_device *dev) |
921 | int i915_gem_gtt_init(struct drm_device *dev) |
923 | { |
922 | { |
924 | struct drm_i915_private *dev_priv = dev->dev_private; |
923 | struct drm_i915_private *dev_priv = dev->dev_private; |
925 | struct i915_gtt *gtt = &dev_priv->gtt; |
924 | struct i915_gtt *gtt = &dev_priv->gtt; |
926 | int ret; |
925 | int ret; |
927 | 926 | ||
928 | if (INTEL_INFO(dev)->gen <= 5) { |
927 | if (INTEL_INFO(dev)->gen <= 5) { |
929 | gtt->gtt_probe = i915_gmch_probe; |
928 | gtt->gtt_probe = i915_gmch_probe; |
930 | gtt->base.cleanup = i915_gmch_remove; |
929 | gtt->base.cleanup = i915_gmch_remove; |
931 | } else { |
930 | } else { |
932 | gtt->gtt_probe = gen6_gmch_probe; |
931 | gtt->gtt_probe = gen6_gmch_probe; |
933 | gtt->base.cleanup = gen6_gmch_remove; |
932 | gtt->base.cleanup = gen6_gmch_remove; |
934 | if (IS_HASWELL(dev) && dev_priv->ellc_size) |
933 | if (IS_HASWELL(dev) && dev_priv->ellc_size) |
935 | gtt->base.pte_encode = iris_pte_encode; |
934 | gtt->base.pte_encode = iris_pte_encode; |
936 | else if (IS_HASWELL(dev)) |
935 | else if (IS_HASWELL(dev)) |
937 | gtt->base.pte_encode = hsw_pte_encode; |
936 | gtt->base.pte_encode = hsw_pte_encode; |
938 | else if (IS_VALLEYVIEW(dev)) |
937 | else if (IS_VALLEYVIEW(dev)) |
939 | gtt->base.pte_encode = byt_pte_encode; |
938 | gtt->base.pte_encode = byt_pte_encode; |
940 | else if (INTEL_INFO(dev)->gen >= 7) |
939 | else if (INTEL_INFO(dev)->gen >= 7) |
941 | gtt->base.pte_encode = ivb_pte_encode; |
940 | gtt->base.pte_encode = ivb_pte_encode; |
942 | else |
941 | else |
943 | gtt->base.pte_encode = snb_pte_encode; |
942 | gtt->base.pte_encode = snb_pte_encode; |
944 | } |
943 | } |
945 | 944 | ||
946 | ret = gtt->gtt_probe(dev, >t->base.total, >t->stolen_size, |
945 | ret = gtt->gtt_probe(dev, >t->base.total, >t->stolen_size, |
947 | >t->mappable_base, >t->mappable_end); |
946 | >t->mappable_base, >t->mappable_end); |
948 | if (ret) |
947 | if (ret) |
949 | return ret; |
948 | return ret; |
950 | 949 | ||
951 | gtt->base.dev = dev; |
950 | gtt->base.dev = dev; |
952 | 951 | ||
953 | /* GMADR is the PCI mmio aperture into the global GTT. */ |
952 | /* GMADR is the PCI mmio aperture into the global GTT. */ |
954 | DRM_INFO("Memory usable by graphics device = %zdM\n", |
953 | DRM_INFO("Memory usable by graphics device = %zdM\n", |
955 | gtt->base.total >> 20); |
954 | gtt->base.total >> 20); |
956 | DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20); |
955 | DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20); |
957 | DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); |
956 | DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); |
958 | 957 | ||
959 | return 0; |
958 | return 0; |
960 | } |
959 | } |
961 | 960 | ||
962 | struct scatterlist *sg_next(struct scatterlist *sg) |
961 | struct scatterlist *sg_next(struct scatterlist *sg) |
963 | { |
962 | { |
964 | if (sg_is_last(sg)) |
963 | if (sg_is_last(sg)) |
965 | return NULL; |
964 | return NULL; |
966 | 965 | ||
967 | sg++; |
966 | sg++; |
968 | if (unlikely(sg_is_chain(sg))) |
967 | if (unlikely(sg_is_chain(sg))) |
969 | sg = sg_chain_ptr(sg); |
968 | sg = sg_chain_ptr(sg); |
970 | 969 | ||
971 | return sg; |
970 | return sg; |
972 | } |
971 | } |
973 | 972 | ||
974 | 973 | ||
975 | void __sg_free_table(struct sg_table *table, unsigned int max_ents, |
974 | void __sg_free_table(struct sg_table *table, unsigned int max_ents, |
976 | sg_free_fn *free_fn) |
975 | sg_free_fn *free_fn) |
977 | { |
976 | { |
978 | struct scatterlist *sgl, *next; |
977 | struct scatterlist *sgl, *next; |
979 | 978 | ||
980 | if (unlikely(!table->sgl)) |
979 | if (unlikely(!table->sgl)) |
981 | return; |
980 | return; |
982 | 981 | ||
983 | sgl = table->sgl; |
982 | sgl = table->sgl; |
984 | while (table->orig_nents) { |
983 | while (table->orig_nents) { |
985 | unsigned int alloc_size = table->orig_nents; |
984 | unsigned int alloc_size = table->orig_nents; |
986 | unsigned int sg_size; |
985 | unsigned int sg_size; |
987 | 986 | ||
988 | /* |
987 | /* |
989 | * If we have more than max_ents segments left, |
988 | * If we have more than max_ents segments left, |
990 | * then assign 'next' to the sg table after the current one. |
989 | * then assign 'next' to the sg table after the current one. |
991 | * sg_size is then one less than alloc size, since the last |
990 | * sg_size is then one less than alloc size, since the last |
992 | * element is the chain pointer. |
991 | * element is the chain pointer. |
993 | */ |
992 | */ |
994 | if (alloc_size > max_ents) { |
993 | if (alloc_size > max_ents) { |
995 | next = sg_chain_ptr(&sgl[max_ents - 1]); |
994 | next = sg_chain_ptr(&sgl[max_ents - 1]); |
996 | alloc_size = max_ents; |
995 | alloc_size = max_ents; |
997 | sg_size = alloc_size - 1; |
996 | sg_size = alloc_size - 1; |
998 | } else { |
997 | } else { |
999 | sg_size = alloc_size; |
998 | sg_size = alloc_size; |
1000 | next = NULL; |
999 | next = NULL; |
1001 | } |
1000 | } |
1002 | 1001 | ||
1003 | table->orig_nents -= sg_size; |
1002 | table->orig_nents -= sg_size; |
1004 | kfree(sgl); |
1003 | kfree(sgl); |
1005 | sgl = next; |
1004 | sgl = next; |
1006 | } |
1005 | } |
1007 | 1006 | ||
1008 | table->sgl = NULL; |
1007 | table->sgl = NULL; |
1009 | } |
1008 | } |
1010 | 1009 | ||
1011 | void sg_free_table(struct sg_table *table) |
1010 | void sg_free_table(struct sg_table *table) |
1012 | { |
1011 | { |
1013 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, NULL); |
1012 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, NULL); |
1014 | } |
1013 | } |
1015 | 1014 | ||
1016 | int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) |
1015 | int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) |
1017 | { |
1016 | { |
1018 | struct scatterlist *sg, *prv; |
1017 | struct scatterlist *sg, *prv; |
1019 | unsigned int left; |
1018 | unsigned int left; |
1020 | unsigned int max_ents = SG_MAX_SINGLE_ALLOC; |
1019 | unsigned int max_ents = SG_MAX_SINGLE_ALLOC; |
1021 | 1020 | ||
1022 | #ifndef ARCH_HAS_SG_CHAIN |
1021 | #ifndef ARCH_HAS_SG_CHAIN |
1023 | BUG_ON(nents > max_ents); |
1022 | BUG_ON(nents > max_ents); |
1024 | #endif |
1023 | #endif |
1025 | 1024 | ||
1026 | memset(table, 0, sizeof(*table)); |
1025 | memset(table, 0, sizeof(*table)); |
1027 | 1026 | ||
1028 | left = nents; |
1027 | left = nents; |
1029 | prv = NULL; |
1028 | prv = NULL; |
1030 | do { |
1029 | do { |
1031 | unsigned int sg_size, alloc_size = left; |
1030 | unsigned int sg_size, alloc_size = left; |
1032 | 1031 | ||
1033 | if (alloc_size > max_ents) { |
1032 | if (alloc_size > max_ents) { |
1034 | alloc_size = max_ents; |
1033 | alloc_size = max_ents; |
1035 | sg_size = alloc_size - 1; |
1034 | sg_size = alloc_size - 1; |
1036 | } else |
1035 | } else |
1037 | sg_size = alloc_size; |
1036 | sg_size = alloc_size; |
1038 | 1037 | ||
1039 | left -= sg_size; |
1038 | left -= sg_size; |
1040 | 1039 | ||
1041 | sg = kmalloc(alloc_size * sizeof(struct scatterlist), gfp_mask); |
1040 | sg = kmalloc(alloc_size * sizeof(struct scatterlist), gfp_mask); |
1042 | if (unlikely(!sg)) { |
1041 | if (unlikely(!sg)) { |
1043 | /* |
1042 | /* |
1044 | * Adjust entry count to reflect that the last |
1043 | * Adjust entry count to reflect that the last |
1045 | * entry of the previous table won't be used for |
1044 | * entry of the previous table won't be used for |
1046 | * linkage. Without this, sg_kfree() may get |
1045 | * linkage. Without this, sg_kfree() may get |
1047 | * confused. |
1046 | * confused. |
1048 | */ |
1047 | */ |
1049 | if (prv) |
1048 | if (prv) |
1050 | table->nents = ++table->orig_nents; |
1049 | table->nents = ++table->orig_nents; |
1051 | 1050 | ||
1052 | goto err; |
1051 | goto err; |
1053 | } |
1052 | } |
1054 | 1053 | ||
1055 | sg_init_table(sg, alloc_size); |
1054 | sg_init_table(sg, alloc_size); |
1056 | table->nents = table->orig_nents += sg_size; |
1055 | table->nents = table->orig_nents += sg_size; |
1057 | 1056 | ||
1058 | /* |
1057 | /* |
1059 | * If this is the first mapping, assign the sg table header. |
1058 | * If this is the first mapping, assign the sg table header. |
1060 | * If this is not the first mapping, chain previous part. |
1059 | * If this is not the first mapping, chain previous part. |
1061 | */ |
1060 | */ |
1062 | if (prv) |
1061 | if (prv) |
1063 | sg_chain(prv, max_ents, sg); |
1062 | sg_chain(prv, max_ents, sg); |
1064 | else |
1063 | else |
1065 | table->sgl = sg; |
1064 | table->sgl = sg; |
1066 | 1065 | ||
1067 | /* |
1066 | /* |
1068 | * If no more entries after this one, mark the end |
1067 | * If no more entries after this one, mark the end |
1069 | */ |
1068 | */ |
1070 | if (!left) |
1069 | if (!left) |
1071 | sg_mark_end(&sg[sg_size - 1]); |
1070 | sg_mark_end(&sg[sg_size - 1]); |
1072 | 1071 | ||
1073 | prv = sg; |
1072 | prv = sg; |
1074 | } while (left); |
1073 | } while (left); |
1075 | 1074 | ||
1076 | return 0; |
1075 | return 0; |
1077 | 1076 | ||
1078 | err: |
1077 | err: |
1079 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, NULL); |
1078 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, NULL); |
1080 | 1079 | ||
1081 | return -ENOMEM; |
1080 | return -ENOMEM; |
1082 | } |
1081 | } |
1083 | 1082 | ||
1084 | 1083 | ||
1085 | void sg_init_table(struct scatterlist *sgl, unsigned int nents) |
1084 | void sg_init_table(struct scatterlist *sgl, unsigned int nents) |
1086 | { |
1085 | { |
1087 | memset(sgl, 0, sizeof(*sgl) * nents); |
1086 | memset(sgl, 0, sizeof(*sgl) * nents); |
1088 | #ifdef CONFIG_DEBUG_SG |
1087 | #ifdef CONFIG_DEBUG_SG |
1089 | { |
1088 | { |
1090 | unsigned int i; |
1089 | unsigned int i; |
1091 | for (i = 0; i < nents; i++) |
1090 | for (i = 0; i < nents; i++) |
1092 | sgl[i].sg_magic = SG_MAGIC; |
1091 | sgl[i].sg_magic = SG_MAGIC; |
1093 | } |
1092 | } |
1094 | #endif |
1093 | #endif |
1095 | sg_mark_end(&sgl[nents - 1]); |
1094 | sg_mark_end(&sgl[nents - 1]); |
1096 | } |
1095 | } |
1097 | 1096 | ||
1098 | 1097 | ||
1099 | void __sg_page_iter_start(struct sg_page_iter *piter, |
1098 | void __sg_page_iter_start(struct sg_page_iter *piter, |
1100 | struct scatterlist *sglist, unsigned int nents, |
1099 | struct scatterlist *sglist, unsigned int nents, |
1101 | unsigned long pgoffset) |
1100 | unsigned long pgoffset) |
1102 | { |
1101 | { |
1103 | piter->__pg_advance = 0; |
1102 | piter->__pg_advance = 0; |
1104 | piter->__nents = nents; |
1103 | piter->__nents = nents; |
1105 | 1104 | ||
1106 | piter->sg = sglist; |
1105 | piter->sg = sglist; |
1107 | piter->sg_pgoffset = pgoffset; |
1106 | piter->sg_pgoffset = pgoffset; |
1108 | } |
1107 | } |
1109 | 1108 | ||
1110 | static int sg_page_count(struct scatterlist *sg) |
1109 | static int sg_page_count(struct scatterlist *sg) |
1111 | { |
1110 | { |
1112 | return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT; |
1111 | return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT; |
1113 | } |
1112 | } |
1114 | 1113 | ||
1115 | bool __sg_page_iter_next(struct sg_page_iter *piter) |
1114 | bool __sg_page_iter_next(struct sg_page_iter *piter) |
1116 | { |
1115 | { |
1117 | if (!piter->__nents || !piter->sg) |
1116 | if (!piter->__nents || !piter->sg) |
1118 | return false; |
1117 | return false; |
1119 | 1118 | ||
1120 | piter->sg_pgoffset += piter->__pg_advance; |
1119 | piter->sg_pgoffset += piter->__pg_advance; |
1121 | piter->__pg_advance = 1; |
1120 | piter->__pg_advance = 1; |
1122 | 1121 | ||
1123 | while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { |
1122 | while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { |
1124 | piter->sg_pgoffset -= sg_page_count(piter->sg); |
1123 | piter->sg_pgoffset -= sg_page_count(piter->sg); |
1125 | piter->sg = sg_next(piter->sg); |
1124 | piter->sg = sg_next(piter->sg); |
1126 | if (!--piter->__nents || !piter->sg) |
1125 | if (!--piter->__nents || !piter->sg) |
1127 | return false; |
1126 | return false; |
1128 | } |
1127 | } |
1129 | 1128 | ||
1130 | return true; |
1129 | return true; |
1131 | } |
1130 | } |
1132 | EXPORT_SYMBOL(__sg_page_iter_next);>=>><>20))))><20))))>20)><20)>>><>><>=>>>>>>>>>=><=>>><>><>><>><>><>><>><>><>><>><> |
1131 | EXPORT_SYMBOL(__sg_page_iter_next);>=>><>20))))><20))))>20)><20)>>><>><>=>>>>>>>>>=><=>>><>><>><>><>><>><>><>><>><>><> |