1235783Skib/*
2235783Skib * Copyright �� 2008 Intel Corporation
3235783Skib *
4235783Skib * Permission is hereby granted, free of charge, to any person obtaining a
5235783Skib * copy of this software and associated documentation files (the "Software"),
6235783Skib * to deal in the Software without restriction, including without limitation
7235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8235783Skib * and/or sell copies of the Software, and to permit persons to whom the
9235783Skib * Software is furnished to do so, subject to the following conditions:
10235783Skib *
11235783Skib * The above copyright notice and this permission notice (including the next
12235783Skib * paragraph) shall be included in all copies or substantial portions of the
13235783Skib * Software.
14235783Skib *
15235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18235783Skib * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19235783Skib * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20235783Skib * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21235783Skib * IN THE SOFTWARE.
22235783Skib *
23235783Skib * Authors:
24235783Skib *    Eric Anholt <eric@anholt.net>
25235783Skib *
26235783Skib */
27235783Skib
28235783Skib#include <sys/cdefs.h>
29235783Skib__FBSDID("$FreeBSD$");
30235783Skib
31235783Skib#include <dev/drm2/drmP.h>
32235783Skib#include <dev/drm2/drm.h>
33235783Skib#include <dev/drm2/i915/i915_drm.h>
34235783Skib#include <dev/drm2/i915/i915_drv.h>
35235783Skib
36235783Skib#include <sys/sf_buf.h>
37235783Skib
38235783Skib/** @file i915_gem_tiling.c
39235783Skib *
40235783Skib * Support for managing tiling state of buffer objects.
41235783Skib *
42235783Skib * The idea behind tiling is to increase cache hit rates by rearranging
43235783Skib * pixel data so that a group of pixel accesses are in the same cacheline.
44235783Skib * Performance improvement from doing this on the back/depth buffer are on
45235783Skib * the order of 30%.
46235783Skib *
47235783Skib * Intel architectures make this somewhat more complicated, though, by
48235783Skib * adjustments made to addressing of data when the memory is in interleaved
49235783Skib * mode (matched pairs of DIMMS) to improve memory bandwidth.
50235783Skib * For interleaved memory, the CPU sends every sequential 64 bytes
51235783Skib * to an alternate memory channel so it can get the bandwidth from both.
52235783Skib *
53235783Skib * The GPU also rearranges its accesses for increased bandwidth to interleaved
54235783Skib * memory, and it matches what the CPU does for non-tiled.  However, when tiled
55235783Skib * it does it a little differently, since one walks addresses not just in the
56235783Skib * X direction but also Y.  So, along with alternating channels when bit
57235783Skib * 6 of the address flips, it also alternates when other bits flip --  Bits 9
58235783Skib * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
59235783Skib * are common to both the 915 and 965-class hardware.
60235783Skib *
61235783Skib * The CPU also sometimes XORs in higher bits as well, to improve
62235783Skib * bandwidth doing strided access like we do so frequently in graphics.  This
63235783Skib * is called "Channel XOR Randomization" in the MCH documentation.  The result
64235783Skib * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
65235783Skib * decode.
66235783Skib *
67235783Skib * All of this bit 6 XORing has an effect on our memory management,
68235783Skib * as we need to make sure that the 3d driver can correctly address object
69235783Skib * contents.
70235783Skib *
71235783Skib * If we don't have interleaved memory, all tiling is safe and no swizzling is
72235783Skib * required.
73235783Skib *
74235783Skib * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
75235783Skib * 17 is not just a page offset, so as we page an objet out and back in,
76235783Skib * individual pages in it will have different bit 17 addresses, resulting in
77235783Skib * each 64 bytes being swapped with its neighbor!
78235783Skib *
79235783Skib * Otherwise, if interleaved, we have to tell the 3d driver what the address
80235783Skib * swizzling it needs to do is, since it's writing with the CPU to the pages
81235783Skib * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
82235783Skib * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
83235783Skib * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
84235783Skib * to match what the GPU expects.
85235783Skib */
86235783Skib
87235783Skib/**
88235783Skib * Detects bit 6 swizzling of address lookup between IGD access and CPU
89235783Skib * access through main memory.
90235783Skib */
91235783Skibvoid
92235783Skibi915_gem_detect_bit_6_swizzle(struct drm_device *dev)
93235783Skib{
94235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
95235783Skib	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
96235783Skib	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
97235783Skib
98235783Skib	if (INTEL_INFO(dev)->gen >= 6) {
99235783Skib		uint32_t dimm_c0, dimm_c1;
100235783Skib		dimm_c0 = I915_READ(MAD_DIMM_C0);
101235783Skib		dimm_c1 = I915_READ(MAD_DIMM_C1);
102235783Skib		dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
103235783Skib		dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
104235783Skib		/* Enable swizzling when the channels are populated with
105235783Skib		 * identically sized dimms. We don't need to check the 3rd
106235783Skib		 * channel because no cpu with gpu attached ships in that
107235783Skib		 * configuration. Also, swizzling only makes sense for 2
108235783Skib		 * channels anyway. */
109235783Skib		if (dimm_c0 == dimm_c1) {
110235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_9_10;
111235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_9;
112235783Skib		} else {
113235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
114235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
115235783Skib		}
116235783Skib	} else if (IS_GEN5(dev)) {
117235783Skib		/* On Ironlake whatever DRAM config, GPU always do
118235783Skib		 * same swizzling setup.
119235783Skib		 */
120235783Skib		swizzle_x = I915_BIT_6_SWIZZLE_9_10;
121235783Skib		swizzle_y = I915_BIT_6_SWIZZLE_9;
122235783Skib	} else if (IS_GEN2(dev)) {
123235783Skib		/* As far as we know, the 865 doesn't have these bit 6
124235783Skib		 * swizzling issues.
125235783Skib		 */
126235783Skib		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
127235783Skib		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
128235783Skib	} else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) {
129235783Skib		uint32_t dcc;
130235783Skib
131235783Skib		/* On 9xx chipsets, channel interleave by the CPU is
132235783Skib		 * determined by DCC.  For single-channel, neither the CPU
133235783Skib		 * nor the GPU do swizzling.  For dual channel interleaved,
134235783Skib		 * the GPU's interleave is bit 9 and 10 for X tiled, and bit
135235783Skib		 * 9 for Y tiled.  The CPU's interleave is independent, and
136235783Skib		 * can be based on either bit 11 (haven't seen this yet) or
137235783Skib		 * bit 17 (common).
138235783Skib		 */
139235783Skib		dcc = I915_READ(DCC);
140235783Skib		switch (dcc & DCC_ADDRESSING_MODE_MASK) {
141235783Skib		case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
142235783Skib		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
143235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
144235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
145235783Skib			break;
146235783Skib		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
147235783Skib			if (dcc & DCC_CHANNEL_XOR_DISABLE) {
148235783Skib				/* This is the base swizzling by the GPU for
149235783Skib				 * tiled buffers.
150235783Skib				 */
151235783Skib				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
152235783Skib				swizzle_y = I915_BIT_6_SWIZZLE_9;
153235783Skib			} else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
154235783Skib				/* Bit 11 swizzling by the CPU in addition. */
155235783Skib				swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
156235783Skib				swizzle_y = I915_BIT_6_SWIZZLE_9_11;
157235783Skib			} else {
158235783Skib				/* Bit 17 swizzling by the CPU in addition. */
159235783Skib				swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
160235783Skib				swizzle_y = I915_BIT_6_SWIZZLE_9_17;
161235783Skib			}
162235783Skib			break;
163235783Skib		}
164235783Skib		if (dcc == 0xffffffff) {
165235783Skib			DRM_ERROR("Couldn't read from MCHBAR.  "
166235783Skib				  "Disabling tiling.\n");
167235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
168235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
169235783Skib		}
170235783Skib	} else {
171235783Skib		/* The 965, G33, and newer, have a very flexible memory
172235783Skib		 * configuration.  It will enable dual-channel mode
173235783Skib		 * (interleaving) on as much memory as it can, and the GPU
174235783Skib		 * will additionally sometimes enable different bit 6
175235783Skib		 * swizzling for tiled objects from the CPU.
176235783Skib		 *
177235783Skib		 * Here's what I found on the G965:
178235783Skib		 *    slot fill         memory size  swizzling
179235783Skib		 * 0A   0B   1A   1B    1-ch   2-ch
180235783Skib		 * 512  0    0    0     512    0     O
181235783Skib		 * 512  0    512  0     16     1008  X
182235783Skib		 * 512  0    0    512   16     1008  X
183235783Skib		 * 0    512  0    512   16     1008  X
184235783Skib		 * 1024 1024 1024 0     2048   1024  O
185235783Skib		 *
186235783Skib		 * We could probably detect this based on either the DRB
187235783Skib		 * matching, which was the case for the swizzling required in
188235783Skib		 * the table above, or from the 1-ch value being less than
189235783Skib		 * the minimum size of a rank.
190235783Skib		 */
191235783Skib		if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
192235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
193235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
194235783Skib		} else {
195235783Skib			swizzle_x = I915_BIT_6_SWIZZLE_9_10;
196235783Skib			swizzle_y = I915_BIT_6_SWIZZLE_9;
197235783Skib		}
198235783Skib	}
199235783Skib
200235783Skib	dev_priv->mm.bit_6_swizzle_x = swizzle_x;
201235783Skib	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
202235783Skib}
203235783Skib
204235783Skib/* Check pitch constriants for all chips & tiling formats */
205235783Skibstatic bool
206235783Skibi915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
207235783Skib{
208235783Skib	int tile_width;
209235783Skib
210235783Skib	/* Linear is always fine */
211235783Skib	if (tiling_mode == I915_TILING_NONE)
212235783Skib		return (true);
213235783Skib
214235783Skib	if (IS_GEN2(dev) ||
215235783Skib	    (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
216235783Skib		tile_width = 128;
217235783Skib	else
218235783Skib		tile_width = 512;
219235783Skib
220235783Skib	/* check maximum stride & object size */
221235783Skib	if (INTEL_INFO(dev)->gen >= 4) {
222235783Skib		/* i965 stores the end address of the gtt mapping in the fence
223235783Skib		 * reg, so dont bother to check the size */
224235783Skib		if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
225235783Skib			return (false);
226235783Skib	} else {
227235783Skib		if (stride > 8192)
228235783Skib			return (false);
229235783Skib
230235783Skib		if (IS_GEN3(dev)) {
231235783Skib			if (size > I830_FENCE_MAX_SIZE_VAL << 20)
232235783Skib				return (false);
233235783Skib		} else {
234235783Skib			if (size > I830_FENCE_MAX_SIZE_VAL << 19)
235235783Skib				return (false);
236235783Skib		}
237235783Skib	}
238235783Skib
239235783Skib	/* 965+ just needs multiples of tile width */
240235783Skib	if (INTEL_INFO(dev)->gen >= 4) {
241235783Skib		if (stride & (tile_width - 1))
242235783Skib			return (false);
243235783Skib		return (true);
244235783Skib	}
245235783Skib
246235783Skib	/* Pre-965 needs power of two tile widths */
247235783Skib	if (stride < tile_width)
248235783Skib		return (false);
249235783Skib
250235783Skib	if (stride & (stride - 1))
251235783Skib		return (false);
252235783Skib
253235783Skib	return (true);
254235783Skib}
255235783Skib
256235783Skib/* Is the current GTT allocation valid for the change in tiling? */
257235783Skibstatic bool
258235783Skibi915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode)
259235783Skib{
260235783Skib	u32 size;
261235783Skib
262235783Skib	if (tiling_mode == I915_TILING_NONE)
263235783Skib		return (true);
264235783Skib
265235783Skib	if (INTEL_INFO(obj->base.dev)->gen >= 4)
266235783Skib		return (true);
267235783Skib
268235783Skib	if (INTEL_INFO(obj->base.dev)->gen == 3) {
269235783Skib		if (obj->gtt_offset & ~I915_FENCE_START_MASK)
270235783Skib			return (false);
271235783Skib	} else {
272235783Skib		if (obj->gtt_offset & ~I830_FENCE_START_MASK)
273235783Skib			return (false);
274235783Skib	}
275235783Skib
276235783Skib	/*
277235783Skib	 * Previous chips need to be aligned to the size of the smallest
278235783Skib	 * fence register that can contain the object.
279235783Skib	 */
280235783Skib	if (INTEL_INFO(obj->base.dev)->gen == 3)
281235783Skib		size = 1024*1024;
282235783Skib	else
283235783Skib		size = 512*1024;
284235783Skib
285235783Skib	while (size < obj->base.size)
286235783Skib		size <<= 1;
287235783Skib
288235783Skib	if (obj->gtt_space->size != size)
289235783Skib		return (false);
290235783Skib
291235783Skib	if (obj->gtt_offset & (size - 1))
292235783Skib		return (false);
293235783Skib
294235783Skib	return (true);
295235783Skib}
296235783Skib
297235783Skib/**
298235783Skib * Sets the tiling mode of an object, returning the required swizzling of
299235783Skib * bit 6 of addresses in the object.
300235783Skib */
301235783Skibint
302235783Skibi915_gem_set_tiling(struct drm_device *dev, void *data,
303235783Skib		   struct drm_file *file)
304235783Skib{
305235783Skib	struct drm_i915_gem_set_tiling *args = data;
306235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
307235783Skib	struct drm_i915_gem_object *obj;
308235783Skib	int ret;
309235783Skib
310235783Skib	ret = 0;
311235783Skib	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
312235783Skib	if (&obj->base == NULL)
313235783Skib		return -ENOENT;
314235783Skib
315235783Skib	if (!i915_tiling_ok(dev,
316235783Skib			    args->stride, obj->base.size, args->tiling_mode)) {
317235783Skib		drm_gem_object_unreference(&obj->base);
318235783Skib		return -EINVAL;
319235783Skib	}
320235783Skib
321235783Skib	if (obj->pin_count) {
322235783Skib		drm_gem_object_unreference(&obj->base);
323235783Skib		return -EBUSY;
324235783Skib	}
325235783Skib
326235783Skib	if (args->tiling_mode == I915_TILING_NONE) {
327235783Skib		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
328235783Skib		args->stride = 0;
329235783Skib	} else {
330235783Skib		if (args->tiling_mode == I915_TILING_X)
331235783Skib			args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
332235783Skib		else
333235783Skib			args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
334235783Skib
335235783Skib		/* Hide bit 17 swizzling from the user.  This prevents old Mesa
336235783Skib		 * from aborting the application on sw fallbacks to bit 17,
337235783Skib		 * and we use the pread/pwrite bit17 paths to swizzle for it.
338235783Skib		 * If there was a user that was relying on the swizzle
339235783Skib		 * information for drm_intel_bo_map()ed reads/writes this would
340235783Skib		 * break it, but we don't have any of those.
341235783Skib		 */
342235783Skib		if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
343235783Skib			args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
344235783Skib		if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
345235783Skib			args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
346235783Skib
347235783Skib		/* If we can't handle the swizzling, make it untiled. */
348235783Skib		if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
349235783Skib			args->tiling_mode = I915_TILING_NONE;
350235783Skib			args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
351235783Skib			args->stride = 0;
352235783Skib		}
353235783Skib	}
354235783Skib
355235783Skib	if (args->tiling_mode != obj->tiling_mode ||
356235783Skib	    args->stride != obj->stride) {
357235783Skib		/* We need to rebind the object if its current allocation
358235783Skib		 * no longer meets the alignment restrictions for its new
359235783Skib		 * tiling mode. Otherwise we can just leave it alone, but
360235783Skib		 * need to ensure that any fence register is cleared.
361235783Skib		 */
362235783Skib		i915_gem_release_mmap(obj);
363235783Skib
364235783Skib		obj->map_and_fenceable = obj->gtt_space == NULL ||
365235783Skib		    (obj->gtt_offset + obj->base.size <=
366235783Skib		    dev_priv->mm.gtt_mappable_end &&
367235783Skib		    i915_gem_object_fence_ok(obj, args->tiling_mode));
368235783Skib
369235783Skib		/* Rebind if we need a change of alignment */
370235783Skib		if (!obj->map_and_fenceable) {
371235783Skib			uint32_t unfenced_alignment =
372235783Skib			    i915_gem_get_unfenced_gtt_alignment(dev,
373235783Skib				obj->base.size, args->tiling_mode);
374235783Skib			if (obj->gtt_offset & (unfenced_alignment - 1))
375235783Skib				ret = i915_gem_object_unbind(obj);
376235783Skib		}
377235783Skib		if (ret == 0) {
378235783Skib			obj->tiling_changed = true;
379235783Skib			obj->tiling_mode = args->tiling_mode;
380235783Skib			obj->stride = args->stride;
381235783Skib		}
382235783Skib 	}
383235783Skib	/* we have to maintain this existing ABI... */
384235783Skib	args->stride = obj->stride;
385235783Skib	args->tiling_mode = obj->tiling_mode;
386235783Skib	drm_gem_object_unreference(&obj->base);
387235783Skib
388235783Skib	return (ret);
389235783Skib}
390235783Skib
391235783Skib/**
392235783Skib * Returns the current tiling mode and required bit 6 swizzling for the object.
393235783Skib */
394235783Skibint
395235783Skibi915_gem_get_tiling(struct drm_device *dev, void *data,
396235783Skib		   struct drm_file *file)
397235783Skib{
398235783Skib	struct drm_i915_gem_get_tiling *args = data;
399235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
400235783Skib	struct drm_i915_gem_object *obj;
401235783Skib
402235783Skib	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
403235783Skib	if (&obj->base == NULL)
404235783Skib		return -ENOENT;
405235783Skib
406235783Skib	args->tiling_mode = obj->tiling_mode;
407235783Skib	switch (obj->tiling_mode) {
408235783Skib	case I915_TILING_X:
409235783Skib		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
410235783Skib		break;
411235783Skib	case I915_TILING_Y:
412235783Skib		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
413235783Skib		break;
414235783Skib	case I915_TILING_NONE:
415235783Skib		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
416235783Skib		break;
417235783Skib	default:
418235783Skib		DRM_ERROR("unknown tiling mode\n");
419235783Skib	}
420235783Skib
421235783Skib	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
422235783Skib	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
423235783Skib		args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
424235783Skib	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
425235783Skib		args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
426235783Skib
427235783Skib	drm_gem_object_unreference(&obj->base);
428235783Skib
429235783Skib	return 0;
430235783Skib}
431235783Skib
432235783Skib/**
433235783Skib * Swap every 64 bytes of this page around, to account for it having a new
434235783Skib * bit 17 of its physical address and therefore being interpreted differently
435235783Skib * by the GPU.
436235783Skib */
437235783Skibstatic void
438235783Skibi915_gem_swizzle_page(vm_page_t m)
439235783Skib{
440235783Skib	char temp[64];
441235783Skib	char *vaddr;
442235783Skib	struct sf_buf *sf;
443235783Skib	int i;
444235783Skib
445235783Skib	/* XXXKIB sleep */
446235783Skib	sf = sf_buf_alloc(m, SFB_DEFAULT);
447235783Skib	vaddr = (char *)sf_buf_kva(sf);
448235783Skib
449235783Skib	for (i = 0; i < PAGE_SIZE; i += 128) {
450235783Skib		memcpy(temp, &vaddr[i], 64);
451235783Skib		memcpy(&vaddr[i], &vaddr[i + 64], 64);
452235783Skib		memcpy(&vaddr[i + 64], temp, 64);
453235783Skib	}
454235783Skib
455235783Skib	sf_buf_free(sf);
456235783Skib}
457235783Skib
458235783Skibvoid
459235783Skibi915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
460235783Skib{
461235783Skib	int page_count = obj->base.size >> PAGE_SHIFT;
462235783Skib	int i;
463235783Skib
464235783Skib	if (obj->bit_17 == NULL)
465235783Skib		return;
466235783Skib
467235783Skib	for (i = 0; i < page_count; i++) {
468235783Skib		char new_bit_17 = VM_PAGE_TO_PHYS(obj->pages[i]) >> 17;
469235783Skib		if ((new_bit_17 & 0x1) !=
470235783Skib		    (test_bit(i, obj->bit_17) != 0)) {
471235783Skib			i915_gem_swizzle_page(obj->pages[i]);
472235783Skib			vm_page_dirty(obj->pages[i]);
473235783Skib		}
474235783Skib	}
475235783Skib}
476235783Skib
477235783Skibvoid
478235783Skibi915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
479235783Skib{
480235783Skib	int page_count = obj->base.size >> PAGE_SHIFT;
481235783Skib	int i;
482235783Skib
483235783Skib	if (obj->bit_17 == NULL) {
484235783Skib		obj->bit_17 = malloc(BITS_TO_LONGS(page_count) *
485235783Skib		    sizeof(long), DRM_I915_GEM, M_WAITOK);
486235783Skib	}
487235783Skib
488235783Skib	/* XXXKIB: review locking, atomics might be not needed there */
489235783Skib	for (i = 0; i < page_count; i++) {
490235783Skib		if (VM_PAGE_TO_PHYS(obj->pages[i]) & (1 << 17))
491235783Skib			set_bit(i, obj->bit_17);
492235783Skib		else
493235783Skib			clear_bit(i, obj->bit_17);
494235783Skib	}
495235783Skib}
496