blob: 5c1ceec49f5b6daf499cb9a984cc3aabaea1bb2c [file] [log] [blame]
Eric Anholt673a3942008-07-30 12:06:12 -07001/*
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
Jesse Barnesd7658982009-06-05 14:41:29 +000028#include <linux/acpi.h>
29#include <linux/pnp.h>
Eric Anholt280b7132009-03-12 16:56:27 -070030#include "linux/string.h"
31#include "linux/bitops.h"
Eric Anholt673a3942008-07-30 12:06:12 -070032#include "drmP.h"
33#include "drm.h"
34#include "i915_drm.h"
35#include "i915_drv.h"
36
37/** @file i915_gem_tiling.c
38 *
39 * Support for managing tiling state of buffer objects.
40 *
41 * The idea behind tiling is to increase cache hit rates by rearranging
42 * pixel data so that a group of pixel accesses are in the same cacheline.
43 * Performance improvement from doing this on the back/depth buffer are on
44 * the order of 30%.
45 *
46 * Intel architectures make this somewhat more complicated, though, by
47 * adjustments made to addressing of data when the memory is in interleaved
48 * mode (matched pairs of DIMMS) to improve memory bandwidth.
49 * For interleaved memory, the CPU sends every sequential 64 bytes
50 * to an alternate memory channel so it can get the bandwidth from both.
51 *
52 * The GPU also rearranges its accesses for increased bandwidth to interleaved
53 * memory, and it matches what the CPU does for non-tiled. However, when tiled
54 * it does it a little differently, since one walks addresses not just in the
55 * X direction but also Y. So, along with alternating channels when bit
56 * 6 of the address flips, it also alternates when other bits flip -- Bits 9
57 * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
58 * are common to both the 915 and 965-class hardware.
59 *
60 * The CPU also sometimes XORs in higher bits as well, to improve
61 * bandwidth doing strided access like we do so frequently in graphics. This
62 * is called "Channel XOR Randomization" in the MCH documentation. The result
63 * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
64 * decode.
65 *
66 * All of this bit 6 XORing has an effect on our memory management,
67 * as we need to make sure that the 3d driver can correctly address object
68 * contents.
69 *
70 * If we don't have interleaved memory, all tiling is safe and no swizzling is
71 * required.
72 *
73 * When bit 17 is XORed in, we simply refuse to tile at all. Bit
74 * 17 is not just a page offset, so as we page an objet out and back in,
75 * individual pages in it will have different bit 17 addresses, resulting in
76 * each 64 bytes being swapped with its neighbor!
77 *
78 * Otherwise, if interleaved, we have to tell the 3d driver what the address
79 * swizzling it needs to do is, since it's writing with the CPU to the pages
80 * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
81 * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
82 * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
83 * to match what the GPU expects.
84 */
85
Jesse Barnesd7658982009-06-05 14:41:29 +000086#define MCHBAR_I915 0x44
87#define MCHBAR_I965 0x48
88#define MCHBAR_SIZE (4*4096)
89
90#define DEVEN_REG 0x54
91#define DEVEN_MCHBAR_EN (1 << 28)
92
93/* Allocate space for the MCH regs if needed, return nonzero on error */
94static int
95intel_alloc_mchbar_resource(struct drm_device *dev)
96{
97 struct pci_dev *bridge_dev;
98 drm_i915_private_t *dev_priv = dev->dev_private;
99 int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
100 u32 temp_lo, temp_hi = 0;
101 u64 mchbar_addr;
102 int ret = 0;
103
104 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
105 if (!bridge_dev) {
106 DRM_DEBUG("no bridge dev?!\n");
107 ret = -ENODEV;
108 goto out;
109 }
110
111 if (IS_I965G(dev))
112 pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
113 pci_read_config_dword(bridge_dev, reg, &temp_lo);
114 mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
115
116 /* If ACPI doesn't have it, assume we need to allocate it ourselves */
117 if (mchbar_addr &&
118 pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
119 ret = 0;
120 goto out_put;
121 }
122
123 /* Get some space for it */
124 ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
125 MCHBAR_SIZE, MCHBAR_SIZE,
126 PCIBIOS_MIN_MEM,
127 0, pcibios_align_resource,
128 bridge_dev);
129 if (ret) {
130 DRM_DEBUG("failed bus alloc: %d\n", ret);
131 dev_priv->mch_res.start = 0;
132 goto out_put;
133 }
134
135 if (IS_I965G(dev))
136 pci_write_config_dword(bridge_dev, reg + 4,
137 upper_32_bits(dev_priv->mch_res.start));
138
139 pci_write_config_dword(bridge_dev, reg,
140 lower_32_bits(dev_priv->mch_res.start));
141out_put:
142 pci_dev_put(bridge_dev);
143out:
144 return ret;
145}
146
147/* Setup MCHBAR if possible, return true if we should disable it again */
148static bool
149intel_setup_mchbar(struct drm_device *dev)
150{
151 struct pci_dev *bridge_dev;
152 int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
153 u32 temp;
154 bool need_disable = false, enabled;
155
156 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
157 if (!bridge_dev) {
158 DRM_DEBUG("no bridge dev?!\n");
159 goto out;
160 }
161
162 if (IS_I915G(dev) || IS_I915GM(dev)) {
163 pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
164 enabled = !!(temp & DEVEN_MCHBAR_EN);
165 } else {
166 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
167 enabled = temp & 1;
168 }
169
170 /* If it's already enabled, don't have to do anything */
171 if (enabled)
172 goto out_put;
173
174 if (intel_alloc_mchbar_resource(dev))
175 goto out_put;
176
177 need_disable = true;
178
179 /* Space is allocated or reserved, so enable it. */
180 if (IS_I915G(dev) || IS_I915GM(dev)) {
181 pci_write_config_dword(bridge_dev, DEVEN_REG,
182 temp | DEVEN_MCHBAR_EN);
183 } else {
184 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
185 pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
186 }
187out_put:
188 pci_dev_put(bridge_dev);
189out:
190 return need_disable;
191}
192
193static void
194intel_teardown_mchbar(struct drm_device *dev, bool disable)
195{
196 drm_i915_private_t *dev_priv = dev->dev_private;
197 struct pci_dev *bridge_dev;
198 int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
199 u32 temp;
200
201 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
202 if (!bridge_dev) {
203 DRM_DEBUG("no bridge dev?!\n");
204 return;
205 }
206
207 if (disable) {
208 if (IS_I915G(dev) || IS_I915GM(dev)) {
209 pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
210 temp &= ~DEVEN_MCHBAR_EN;
211 pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
212 } else {
213 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
214 temp &= ~1;
215 pci_write_config_dword(bridge_dev, mchbar_reg, temp);
216 }
217 }
218
219 if (dev_priv->mch_res.start)
220 release_resource(&dev_priv->mch_res);
221}
222
Eric Anholt673a3942008-07-30 12:06:12 -0700223/**
224 * Detects bit 6 swizzling of address lookup between IGD access and CPU
225 * access through main memory.
226 */
227void
228i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
229{
230 drm_i915_private_t *dev_priv = dev->dev_private;
231 uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
232 uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
Jesse Barnesd7658982009-06-05 14:41:29 +0000233 bool need_disable;
Eric Anholt673a3942008-07-30 12:06:12 -0700234
235 if (!IS_I9XX(dev)) {
236 /* As far as we know, the 865 doesn't have these bit 6
237 * swizzling issues.
238 */
239 swizzle_x = I915_BIT_6_SWIZZLE_NONE;
240 swizzle_y = I915_BIT_6_SWIZZLE_NONE;
Eric Anholt568d9a82009-03-12 16:27:11 -0700241 } else if (IS_MOBILE(dev)) {
Eric Anholt673a3942008-07-30 12:06:12 -0700242 uint32_t dcc;
243
Jesse Barnesd7658982009-06-05 14:41:29 +0000244 /* Try to make sure MCHBAR is enabled before poking at it */
245 need_disable = intel_setup_mchbar(dev);
246
Eric Anholt568d9a82009-03-12 16:27:11 -0700247 /* On mobile 9xx chipsets, channel interleave by the CPU is
248 * determined by DCC. For single-channel, neither the CPU
249 * nor the GPU do swizzling. For dual channel interleaved,
250 * the GPU's interleave is bit 9 and 10 for X tiled, and bit
251 * 9 for Y tiled. The CPU's interleave is independent, and
252 * can be based on either bit 11 (haven't seen this yet) or
253 * bit 17 (common).
Eric Anholt673a3942008-07-30 12:06:12 -0700254 */
255 dcc = I915_READ(DCC);
256 switch (dcc & DCC_ADDRESSING_MODE_MASK) {
257 case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
258 case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
259 swizzle_x = I915_BIT_6_SWIZZLE_NONE;
260 swizzle_y = I915_BIT_6_SWIZZLE_NONE;
261 break;
262 case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
Eric Anholt568d9a82009-03-12 16:27:11 -0700263 if (dcc & DCC_CHANNEL_XOR_DISABLE) {
264 /* This is the base swizzling by the GPU for
265 * tiled buffers.
266 */
Eric Anholt673a3942008-07-30 12:06:12 -0700267 swizzle_x = I915_BIT_6_SWIZZLE_9_10;
268 swizzle_y = I915_BIT_6_SWIZZLE_9;
Eric Anholt568d9a82009-03-12 16:27:11 -0700269 } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
270 /* Bit 11 swizzling by the CPU in addition. */
Eric Anholt673a3942008-07-30 12:06:12 -0700271 swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
272 swizzle_y = I915_BIT_6_SWIZZLE_9_11;
273 } else {
Eric Anholt568d9a82009-03-12 16:27:11 -0700274 /* Bit 17 swizzling by the CPU in addition. */
Eric Anholt280b7132009-03-12 16:56:27 -0700275 swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
276 swizzle_y = I915_BIT_6_SWIZZLE_9_17;
Eric Anholt673a3942008-07-30 12:06:12 -0700277 }
278 break;
279 }
280 if (dcc == 0xffffffff) {
281 DRM_ERROR("Couldn't read from MCHBAR. "
282 "Disabling tiling.\n");
283 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
284 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
285 }
Jesse Barnesd7658982009-06-05 14:41:29 +0000286
287 intel_teardown_mchbar(dev, need_disable);
Eric Anholt673a3942008-07-30 12:06:12 -0700288 } else {
289 /* The 965, G33, and newer, have a very flexible memory
290 * configuration. It will enable dual-channel mode
291 * (interleaving) on as much memory as it can, and the GPU
292 * will additionally sometimes enable different bit 6
293 * swizzling for tiled objects from the CPU.
294 *
295 * Here's what I found on the G965:
296 * slot fill memory size swizzling
297 * 0A 0B 1A 1B 1-ch 2-ch
298 * 512 0 0 0 512 0 O
299 * 512 0 512 0 16 1008 X
300 * 512 0 0 512 16 1008 X
301 * 0 512 0 512 16 1008 X
302 * 1024 1024 1024 0 2048 1024 O
303 *
304 * We could probably detect this based on either the DRB
305 * matching, which was the case for the swizzling required in
306 * the table above, or from the 1-ch value being less than
307 * the minimum size of a rank.
308 */
309 if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
310 swizzle_x = I915_BIT_6_SWIZZLE_NONE;
311 swizzle_y = I915_BIT_6_SWIZZLE_NONE;
312 } else {
313 swizzle_x = I915_BIT_6_SWIZZLE_9_10;
314 swizzle_y = I915_BIT_6_SWIZZLE_9;
315 }
316 }
317
Zhenyu Wang2cce0d82009-06-05 15:38:41 +0800318 /* FIXME: check with memory config on IGDNG */
319 if (IS_IGDNG(dev)) {
320 DRM_ERROR("disable tiling on IGDNG...\n");
321 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
322 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
323 }
324
Eric Anholt673a3942008-07-30 12:06:12 -0700325 dev_priv->mm.bit_6_swizzle_x = swizzle_x;
326 dev_priv->mm.bit_6_swizzle_y = swizzle_y;
327}
328
Jesse Barnes0f973f22009-01-26 17:10:45 -0800329
330/**
331 * Returns the size of the fence for a tiled object of the given size.
332 */
333static int
334i915_get_fence_size(struct drm_device *dev, int size)
335{
336 int i;
337 int start;
338
339 if (IS_I965G(dev)) {
340 /* The 965 can have fences at any page boundary. */
341 return ALIGN(size, 4096);
342 } else {
343 /* Align the size to a power of two greater than the smallest
344 * fence size.
345 */
346 if (IS_I9XX(dev))
347 start = 1024 * 1024;
348 else
349 start = 512 * 1024;
350
351 for (i = start; i < size; i <<= 1)
352 ;
353
354 return i;
355 }
356}
357
358/* Check pitch constriants for all chips & tiling formats */
359static bool
360i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
361{
362 int tile_width;
363
364 /* Linear is always fine */
365 if (tiling_mode == I915_TILING_NONE)
366 return true;
367
Eric Anholte76a16d2009-05-26 17:44:56 -0700368 if (!IS_I9XX(dev) ||
369 (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
Jesse Barnes0f973f22009-01-26 17:10:45 -0800370 tile_width = 128;
371 else
372 tile_width = 512;
373
Daniel Vetter8d7773a2009-03-29 14:09:41 +0200374 /* check maximum stride & object size */
375 if (IS_I965G(dev)) {
376 /* i965 stores the end address of the gtt mapping in the fence
377 * reg, so dont bother to check the size */
378 if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
379 return false;
380 } else if (IS_I9XX(dev)) {
Eric Anholte76a16d2009-05-26 17:44:56 -0700381 uint32_t pitch_val = ffs(stride / tile_width) - 1;
382
383 /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
384 * instead of 4 (2KB) on 945s.
385 */
386 if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
Daniel Vetter8d7773a2009-03-29 14:09:41 +0200387 size > (I830_FENCE_MAX_SIZE_VAL << 20))
388 return false;
389 } else {
Eric Anholte76a16d2009-05-26 17:44:56 -0700390 uint32_t pitch_val = ffs(stride / tile_width) - 1;
391
392 if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
Daniel Vetter8d7773a2009-03-29 14:09:41 +0200393 size > (I830_FENCE_MAX_SIZE_VAL << 19))
394 return false;
395 }
396
Jesse Barnes0f973f22009-01-26 17:10:45 -0800397 /* 965+ just needs multiples of tile width */
398 if (IS_I965G(dev)) {
399 if (stride & (tile_width - 1))
400 return false;
401 return true;
402 }
403
404 /* Pre-965 needs power of two tile widths */
405 if (stride < tile_width)
406 return false;
407
408 if (stride & (stride - 1))
409 return false;
410
Chris Wilson52dc7d32009-06-06 09:46:01 +0100411 /* We don't 0handle the aperture area covered by the fence being bigger
Jesse Barnes0f973f22009-01-26 17:10:45 -0800412 * than the object size.
413 */
414 if (i915_get_fence_size(dev, size) != size)
415 return false;
416
417 return true;
418}
419
Chris Wilson52dc7d32009-06-06 09:46:01 +0100420static bool
421i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
422{
423 struct drm_device *dev = obj->dev;
424 struct drm_i915_gem_object *obj_priv = obj->driver_private;
425
426 if (obj_priv->gtt_space == NULL)
427 return true;
428
429 if (tiling_mode == I915_TILING_NONE)
430 return true;
431
432 if (!IS_I965G(dev)) {
433 if (obj_priv->gtt_offset & (obj->size - 1))
434 return false;
435 if (IS_I9XX(dev)) {
436 if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
437 return false;
438 } else {
439 if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
440 return false;
441 }
442 }
443
444 return true;
445}
446
Eric Anholt673a3942008-07-30 12:06:12 -0700447/**
448 * Sets the tiling mode of an object, returning the required swizzling of
449 * bit 6 of addresses in the object.
450 */
451int
452i915_gem_set_tiling(struct drm_device *dev, void *data,
453 struct drm_file *file_priv)
454{
455 struct drm_i915_gem_set_tiling *args = data;
456 drm_i915_private_t *dev_priv = dev->dev_private;
457 struct drm_gem_object *obj;
458 struct drm_i915_gem_object *obj_priv;
Chris Wilson52dc7d32009-06-06 09:46:01 +0100459 int ret = 0;
Eric Anholt673a3942008-07-30 12:06:12 -0700460
461 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
462 if (obj == NULL)
463 return -EINVAL;
464 obj_priv = obj->driver_private;
465
Chris Wilson72daad42009-01-30 21:10:22 +0000466 if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
Chris Wilson52dc7d32009-06-06 09:46:01 +0100467 mutex_lock(&dev->struct_mutex);
Chris Wilson72daad42009-01-30 21:10:22 +0000468 drm_gem_object_unreference(obj);
Chris Wilson52dc7d32009-06-06 09:46:01 +0100469 mutex_unlock(&dev->struct_mutex);
Jesse Barnes0f973f22009-01-26 17:10:45 -0800470 return -EINVAL;
Chris Wilson72daad42009-01-30 21:10:22 +0000471 }
Jesse Barnes0f973f22009-01-26 17:10:45 -0800472
Eric Anholt673a3942008-07-30 12:06:12 -0700473 if (args->tiling_mode == I915_TILING_NONE) {
Eric Anholt673a3942008-07-30 12:06:12 -0700474 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
Chris Wilson52dc7d32009-06-06 09:46:01 +0100475 args->stride = 0;
Eric Anholt673a3942008-07-30 12:06:12 -0700476 } else {
477 if (args->tiling_mode == I915_TILING_X)
478 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
479 else
480 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
Eric Anholt280b7132009-03-12 16:56:27 -0700481
482 /* Hide bit 17 swizzling from the user. This prevents old Mesa
483 * from aborting the application on sw fallbacks to bit 17,
484 * and we use the pread/pwrite bit17 paths to swizzle for it.
485 * If there was a user that was relying on the swizzle
486 * information for drm_intel_bo_map()ed reads/writes this would
487 * break it, but we don't have any of those.
488 */
489 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
490 args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
491 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
492 args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
493
Eric Anholt673a3942008-07-30 12:06:12 -0700494 /* If we can't handle the swizzling, make it untiled. */
495 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
496 args->tiling_mode = I915_TILING_NONE;
497 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
Chris Wilson52dc7d32009-06-06 09:46:01 +0100498 args->stride = 0;
Eric Anholt673a3942008-07-30 12:06:12 -0700499 }
500 }
Jesse Barnes0f973f22009-01-26 17:10:45 -0800501
Chris Wilson52dc7d32009-06-06 09:46:01 +0100502 mutex_lock(&dev->struct_mutex);
503 if (args->tiling_mode != obj_priv->tiling_mode ||
504 args->stride != obj_priv->stride) {
505 /* We need to rebind the object if its current allocation
506 * no longer meets the alignment restrictions for its new
507 * tiling mode. Otherwise we can just leave it alone, but
508 * need to ensure that any fence register is cleared.
Jesse Barnes0f973f22009-01-26 17:10:45 -0800509 */
Chris Wilson52dc7d32009-06-06 09:46:01 +0100510 if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
511 ret = i915_gem_object_unbind(obj);
512 else
513 ret = i915_gem_object_put_fence_reg(obj);
Jesse Barnes0f973f22009-01-26 17:10:45 -0800514 if (ret != 0) {
515 WARN(ret != -ERESTARTSYS,
Chris Wilson52dc7d32009-06-06 09:46:01 +0100516 "failed to reset object for tiling switch");
Jesse Barnes0f973f22009-01-26 17:10:45 -0800517 args->tiling_mode = obj_priv->tiling_mode;
Chris Wilson52dc7d32009-06-06 09:46:01 +0100518 args->stride = obj_priv->stride;
519 goto err;
Jesse Barnes0f973f22009-01-26 17:10:45 -0800520 }
Eric Anholt673a3942008-07-30 12:06:12 -0700521
Chris Wilson52dc7d32009-06-06 09:46:01 +0100522 obj_priv->tiling_mode = args->tiling_mode;
523 obj_priv->stride = args->stride;
524 }
525err:
Eric Anholt673a3942008-07-30 12:06:12 -0700526 drm_gem_object_unreference(obj);
Chris Wilsond6873102009-02-08 19:07:51 +0000527 mutex_unlock(&dev->struct_mutex);
Eric Anholt673a3942008-07-30 12:06:12 -0700528
Chris Wilson52dc7d32009-06-06 09:46:01 +0100529 return ret;
Eric Anholt673a3942008-07-30 12:06:12 -0700530}
531
532/**
533 * Returns the current tiling mode and required bit 6 swizzling for the object.
534 */
535int
536i915_gem_get_tiling(struct drm_device *dev, void *data,
537 struct drm_file *file_priv)
538{
539 struct drm_i915_gem_get_tiling *args = data;
540 drm_i915_private_t *dev_priv = dev->dev_private;
541 struct drm_gem_object *obj;
542 struct drm_i915_gem_object *obj_priv;
543
544 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
545 if (obj == NULL)
546 return -EINVAL;
547 obj_priv = obj->driver_private;
548
549 mutex_lock(&dev->struct_mutex);
550
551 args->tiling_mode = obj_priv->tiling_mode;
552 switch (obj_priv->tiling_mode) {
553 case I915_TILING_X:
554 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
555 break;
556 case I915_TILING_Y:
557 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
558 break;
559 case I915_TILING_NONE:
560 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
561 break;
562 default:
563 DRM_ERROR("unknown tiling mode\n");
564 }
565
Eric Anholt280b7132009-03-12 16:56:27 -0700566 /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
567 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
568 args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
569 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
570 args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
571
Eric Anholt673a3942008-07-30 12:06:12 -0700572 drm_gem_object_unreference(obj);
Chris Wilsond6873102009-02-08 19:07:51 +0000573 mutex_unlock(&dev->struct_mutex);
Eric Anholt673a3942008-07-30 12:06:12 -0700574
575 return 0;
576}
Eric Anholt280b7132009-03-12 16:56:27 -0700577
578/**
579 * Swap every 64 bytes of this page around, to account for it having a new
580 * bit 17 of its physical address and therefore being interpreted differently
581 * by the GPU.
582 */
583static int
584i915_gem_swizzle_page(struct page *page)
585{
586 char *vaddr;
587 int i;
588 char temp[64];
589
590 vaddr = kmap(page);
591 if (vaddr == NULL)
592 return -ENOMEM;
593
594 for (i = 0; i < PAGE_SIZE; i += 128) {
595 memcpy(temp, &vaddr[i], 64);
596 memcpy(&vaddr[i], &vaddr[i + 64], 64);
597 memcpy(&vaddr[i + 64], temp, 64);
598 }
599
600 kunmap(page);
601
602 return 0;
603}
604
605void
606i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
607{
608 struct drm_device *dev = obj->dev;
609 drm_i915_private_t *dev_priv = dev->dev_private;
610 struct drm_i915_gem_object *obj_priv = obj->driver_private;
611 int page_count = obj->size >> PAGE_SHIFT;
612 int i;
613
614 if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
615 return;
616
617 if (obj_priv->bit_17 == NULL)
618 return;
619
620 for (i = 0; i < page_count; i++) {
621 char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
622 if ((new_bit_17 & 0x1) !=
623 (test_bit(i, obj_priv->bit_17) != 0)) {
624 int ret = i915_gem_swizzle_page(obj_priv->pages[i]);
625 if (ret != 0) {
626 DRM_ERROR("Failed to swizzle page\n");
627 return;
628 }
629 set_page_dirty(obj_priv->pages[i]);
630 }
631 }
632}
633
634void
635i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
636{
637 struct drm_device *dev = obj->dev;
638 drm_i915_private_t *dev_priv = dev->dev_private;
639 struct drm_i915_gem_object *obj_priv = obj->driver_private;
640 int page_count = obj->size >> PAGE_SHIFT;
641 int i;
642
643 if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
644 return;
645
646 if (obj_priv->bit_17 == NULL) {
647 obj_priv->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
648 sizeof(long), GFP_KERNEL);
649 if (obj_priv->bit_17 == NULL) {
650 DRM_ERROR("Failed to allocate memory for bit 17 "
651 "record\n");
652 return;
653 }
654 }
655
656 for (i = 0; i < page_count; i++) {
657 if (page_to_phys(obj_priv->pages[i]) & (1 << 17))
658 __set_bit(i, obj_priv->bit_17);
659 else
660 __clear_bit(i, obj_priv->bit_17);
661 }
662}