Line data Source code
1 : /*
2 : * Copyright © 2008 Intel Corporation
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
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
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
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
13 : * Software.
14 : *
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,
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
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
21 : * IN THE SOFTWARE.
22 : *
23 : * Authors:
24 : * Eric Anholt <eric@anholt.net>
25 : *
26 : */
27 :
28 : #ifdef __linux__
29 : #include <linux/string.h>
30 : #include <linux/bitops.h>
31 : #endif
32 : #include <dev/pci/drm/drmP.h>
33 : #include <dev/pci/drm/i915_drm.h>
34 : #include "i915_drv.h"
35 :
36 : /**
37 : * DOC: buffer object tiling
38 : *
39 : * i915_gem_set_tiling() and i915_gem_get_tiling() is the userspace interface to
40 : * declare fence register requirements.
41 : *
42 : * In principle GEM doesn't care at all about the internal data layout of an
43 : * object, and hence it also doesn't care about tiling or swizzling. There's two
44 : * exceptions:
45 : *
46 : * - For X and Y tiling the hardware provides detilers for CPU access, so called
47 : * fences. Since there's only a limited amount of them the kernel must manage
48 : * these, and therefore userspace must tell the kernel the object tiling if it
49 : * wants to use fences for detiling.
50 : * - On gen3 and gen4 platforms have a swizzling pattern for tiled objects which
51 : * depends upon the physical page frame number. When swapping such objects the
52 : * page frame number might change and the kernel must be able to fix this up
53 : * and hence now the tiling. Note that on a subset of platforms with
54 : * asymmetric memory channel population the swizzling pattern changes in an
55 : * unknown way, and for those the kernel simply forbids swapping completely.
56 : *
57 : * Since neither of this applies for new tiling layouts on modern platforms like
58 : * W, Ys and Yf tiling GEM only allows object tiling to be set to X or Y tiled.
59 : * Anything else can be handled in userspace entirely without the kernel's
60 : * invovlement.
61 : */
62 :
63 : /* Check pitch constriants for all chips & tiling formats */
64 : static bool
65 0 : i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
66 : {
67 : int tile_width;
68 :
69 : /* Linear is always fine */
70 0 : if (tiling_mode == I915_TILING_NONE)
71 0 : return true;
72 :
73 0 : if (IS_GEN2(dev) ||
74 0 : (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
75 0 : tile_width = 128;
76 : else
77 : tile_width = 512;
78 :
79 : /* check maximum stride & object size */
80 : /* i965+ stores the end address of the gtt mapping in the fence
81 : * reg, so dont bother to check the size */
82 0 : if (INTEL_INFO(dev)->gen >= 7) {
83 0 : if (stride / 128 > GEN7_FENCE_MAX_PITCH_VAL)
84 0 : return false;
85 0 : } else if (INTEL_INFO(dev)->gen >= 4) {
86 0 : if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
87 0 : return false;
88 : } else {
89 0 : if (stride > 8192)
90 0 : return false;
91 :
92 0 : if (IS_GEN3(dev)) {
93 0 : if (size > I830_FENCE_MAX_SIZE_VAL << 20)
94 0 : return false;
95 : } else {
96 0 : if (size > I830_FENCE_MAX_SIZE_VAL << 19)
97 0 : return false;
98 : }
99 : }
100 :
101 0 : if (stride < tile_width)
102 0 : return false;
103 :
104 : /* 965+ just needs multiples of tile width */
105 0 : if (INTEL_INFO(dev)->gen >= 4) {
106 0 : if (stride & (tile_width - 1))
107 0 : return false;
108 0 : return true;
109 : }
110 :
111 : /* Pre-965 needs power of two tile widths */
112 0 : if (stride & (stride - 1))
113 0 : return false;
114 :
115 0 : return true;
116 0 : }
117 :
118 : /* Is the current GTT allocation valid for the change in tiling? */
119 : static bool
120 0 : i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode)
121 : {
122 : u32 size;
123 :
124 0 : if (tiling_mode == I915_TILING_NONE)
125 0 : return true;
126 :
127 0 : if (INTEL_INFO(obj->base.dev)->gen >= 4)
128 0 : return true;
129 :
130 0 : if (INTEL_INFO(obj->base.dev)->gen == 3) {
131 0 : if (i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK)
132 0 : return false;
133 : } else {
134 0 : if (i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK)
135 0 : return false;
136 : }
137 :
138 0 : size = i915_gem_get_gtt_size(obj->base.dev, obj->base.size, tiling_mode);
139 0 : if (i915_gem_obj_ggtt_size(obj) != size)
140 0 : return false;
141 :
142 0 : if (i915_gem_obj_ggtt_offset(obj) & (size - 1))
143 0 : return false;
144 :
145 0 : return true;
146 0 : }
147 :
148 : /**
149 : * i915_gem_set_tiling - IOCTL handler to set tiling mode
150 : * @dev: DRM device
151 : * @data: data pointer for the ioctl
152 : * @file: DRM file for the ioctl call
153 : *
154 : * Sets the tiling mode of an object, returning the required swizzling of
155 : * bit 6 of addresses in the object.
156 : *
157 : * Called by the user via ioctl.
158 : *
159 : * Returns:
160 : * Zero on success, negative errno on failure.
161 : */
162 : int
163 0 : i915_gem_set_tiling(struct drm_device *dev, void *data,
164 : struct drm_file *file)
165 : {
166 0 : struct drm_i915_gem_set_tiling *args = data;
167 0 : struct drm_i915_private *dev_priv = dev->dev_private;
168 : struct drm_i915_gem_object *obj;
169 : int ret = 0;
170 :
171 0 : obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
172 0 : if (&obj->base == NULL)
173 0 : return -ENOENT;
174 :
175 0 : if (!i915_tiling_ok(dev,
176 0 : args->stride, obj->base.size, args->tiling_mode)) {
177 0 : drm_gem_object_unreference_unlocked(&obj->base);
178 0 : return -EINVAL;
179 : }
180 :
181 0 : mutex_lock(&dev->struct_mutex);
182 0 : if (obj->pin_display || obj->framebuffer_references) {
183 : ret = -EBUSY;
184 0 : goto err;
185 : }
186 :
187 0 : if (args->tiling_mode == I915_TILING_NONE) {
188 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
189 0 : args->stride = 0;
190 0 : } else {
191 0 : if (args->tiling_mode == I915_TILING_X)
192 0 : args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
193 : else
194 0 : args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
195 :
196 : /* Hide bit 17 swizzling from the user. This prevents old Mesa
197 : * from aborting the application on sw fallbacks to bit 17,
198 : * and we use the pread/pwrite bit17 paths to swizzle for it.
199 : * If there was a user that was relying on the swizzle
200 : * information for drm_intel_bo_map()ed reads/writes this would
201 : * break it, but we don't have any of those.
202 : */
203 0 : if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
204 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
205 0 : if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
206 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
207 :
208 : /* If we can't handle the swizzling, make it untiled. */
209 0 : if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
210 0 : args->tiling_mode = I915_TILING_NONE;
211 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
212 0 : args->stride = 0;
213 0 : }
214 : }
215 :
216 0 : if (args->tiling_mode != obj->tiling_mode ||
217 0 : args->stride != obj->stride) {
218 : /* We need to rebind the object if its current allocation
219 : * no longer meets the alignment restrictions for its new
220 : * tiling mode. Otherwise we can just leave it alone, but
221 : * need to ensure that any fence register is updated before
222 : * the next fenced (either through the GTT or by the BLT unit
223 : * on older GPUs) access.
224 : *
225 : * After updating the tiling parameters, we then flag whether
226 : * we need to update an associated fence register. Note this
227 : * has to also include the unfenced register the GPU uses
228 : * whilst executing a fenced command for an untiled object.
229 : */
230 0 : if (obj->map_and_fenceable &&
231 0 : !i915_gem_object_fence_ok(obj, args->tiling_mode))
232 0 : ret = i915_gem_object_ggtt_unbind(obj);
233 :
234 0 : if (ret == 0) {
235 0 : if (obj->pages &&
236 0 : obj->madv == I915_MADV_WILLNEED &&
237 0 : dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
238 0 : if (args->tiling_mode == I915_TILING_NONE)
239 0 : i915_gem_object_unpin_pages(obj);
240 0 : if (obj->tiling_mode == I915_TILING_NONE)
241 0 : i915_gem_object_pin_pages(obj);
242 : }
243 :
244 0 : obj->fence_dirty =
245 0 : obj->last_fenced_req ||
246 0 : obj->fence_reg != I915_FENCE_REG_NONE;
247 :
248 0 : obj->tiling_mode = args->tiling_mode;
249 0 : obj->stride = args->stride;
250 :
251 : /* Force the fence to be reacquired for GTT access */
252 0 : i915_gem_release_mmap(obj);
253 0 : }
254 : }
255 : /* we have to maintain this existing ABI... */
256 0 : args->stride = obj->stride;
257 0 : args->tiling_mode = obj->tiling_mode;
258 :
259 : /* Try to preallocate memory required to save swizzling on put-pages */
260 0 : if (i915_gem_object_needs_bit17_swizzle(obj)) {
261 0 : if (obj->bit_17 == NULL) {
262 0 : obj->bit_17 = kcalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT),
263 : sizeof(long), GFP_KERNEL);
264 0 : }
265 : } else {
266 0 : kfree(obj->bit_17);
267 0 : obj->bit_17 = NULL;
268 : }
269 :
270 : err:
271 0 : drm_gem_object_unreference(&obj->base);
272 0 : mutex_unlock(&dev->struct_mutex);
273 :
274 0 : return ret;
275 0 : }
276 :
277 : /**
278 : * i915_gem_get_tiling - IOCTL handler to get tiling mode
279 : * @dev: DRM device
280 : * @data: data pointer for the ioctl
281 : * @file: DRM file for the ioctl call
282 : *
283 : * Returns the current tiling mode and required bit 6 swizzling for the object.
284 : *
285 : * Called by the user via ioctl.
286 : *
287 : * Returns:
288 : * Zero on success, negative errno on failure.
289 : */
290 : int
291 0 : i915_gem_get_tiling(struct drm_device *dev, void *data,
292 : struct drm_file *file)
293 : {
294 0 : struct drm_i915_gem_get_tiling *args = data;
295 0 : struct drm_i915_private *dev_priv = dev->dev_private;
296 : struct drm_i915_gem_object *obj;
297 :
298 0 : obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
299 0 : if (&obj->base == NULL)
300 0 : return -ENOENT;
301 :
302 0 : mutex_lock(&dev->struct_mutex);
303 :
304 0 : args->tiling_mode = obj->tiling_mode;
305 0 : switch (obj->tiling_mode) {
306 : case I915_TILING_X:
307 0 : args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
308 0 : break;
309 : case I915_TILING_Y:
310 0 : args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
311 0 : break;
312 : case I915_TILING_NONE:
313 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
314 0 : break;
315 : default:
316 0 : DRM_ERROR("unknown tiling mode\n");
317 0 : }
318 :
319 : /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
320 0 : if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
321 0 : args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
322 : else
323 0 : args->phys_swizzle_mode = args->swizzle_mode;
324 0 : if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
325 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
326 0 : if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
327 0 : args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
328 :
329 0 : drm_gem_object_unreference(&obj->base);
330 0 : mutex_unlock(&dev->struct_mutex);
331 :
332 0 : return 0;
333 0 : }
|