Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 #include <linux/acpi.h>
 29 #include <linux/pnp.h>
 30 #include "linux/string.h"
 31 #include "linux/bitops.h"
 32 #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 
 86 #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 */
 94 static int
 95 intel_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 #ifdef CONFIG_PNP
118         if (mchbar_addr &&
119             pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
120                 ret = 0;
121                 goto out_put;
122         }
123 #endif
124 
125         /* Get some space for it */
126         ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
127                                      MCHBAR_SIZE, MCHBAR_SIZE,
128                                      PCIBIOS_MIN_MEM,
129                                      0,   pcibios_align_resource,
130                                      bridge_dev);
131         if (ret) {
132                 DRM_DEBUG("failed bus alloc: %d\n", ret);
133                 dev_priv->mch_res.start = 0;
134                 goto out_put;
135         }
136 
137         if (IS_I965G(dev))
138                 pci_write_config_dword(bridge_dev, reg + 4,
139                                        upper_32_bits(dev_priv->mch_res.start));
140 
141         pci_write_config_dword(bridge_dev, reg,
142                                lower_32_bits(dev_priv->mch_res.start));
143 out_put:
144         pci_dev_put(bridge_dev);
145 out:
146         return ret;
147 }
148 
149 /* Setup MCHBAR if possible, return true if we should disable it again */
150 static bool
151 intel_setup_mchbar(struct drm_device *dev)
152 {
153         struct pci_dev *bridge_dev;
154         int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
155         u32 temp;
156         bool need_disable = false, enabled;
157 
158         bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
159         if (!bridge_dev) {
160                 DRM_DEBUG("no bridge dev?!\n");
161                 goto out;
162         }
163 
164         if (IS_I915G(dev) || IS_I915GM(dev)) {
165                 pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
166                 enabled = !!(temp & DEVEN_MCHBAR_EN);
167         } else {
168                 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
169                 enabled = temp & 1;
170         }
171 
172         /* If it's already enabled, don't have to do anything */
173         if (enabled)
174                 goto out_put;
175 
176         if (intel_alloc_mchbar_resource(dev))
177                 goto out_put;
178 
179         need_disable = true;
180 
181         /* Space is allocated or reserved, so enable it. */
182         if (IS_I915G(dev) || IS_I915GM(dev)) {
183                 pci_write_config_dword(bridge_dev, DEVEN_REG,
184                                        temp | DEVEN_MCHBAR_EN);
185         } else {
186                 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
187                 pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
188         }
189 out_put:
190         pci_dev_put(bridge_dev);
191 out:
192         return need_disable;
193 }
194 
195 static void
196 intel_teardown_mchbar(struct drm_device *dev, bool disable)
197 {
198         drm_i915_private_t *dev_priv = dev->dev_private;
199         struct pci_dev *bridge_dev;
200         int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
201         u32 temp;
202 
203         bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
204         if (!bridge_dev) {
205                 DRM_DEBUG("no bridge dev?!\n");
206                 return;
207         }
208 
209         if (disable) {
210                 if (IS_I915G(dev) || IS_I915GM(dev)) {
211                         pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
212                         temp &= ~DEVEN_MCHBAR_EN;
213                         pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
214                 } else {
215                         pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
216                         temp &= ~1;
217                         pci_write_config_dword(bridge_dev, mchbar_reg, temp);
218                 }
219         }
220 
221         if (dev_priv->mch_res.start)
222                 release_resource(&dev_priv->mch_res);
223 }
224 
225 /**
226  * Detects bit 6 swizzling of address lookup between IGD access and CPU
227  * access through main memory.
228  */
229 void
230 i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
231 {
232         drm_i915_private_t *dev_priv = dev->dev_private;
233         uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
234         uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
235         bool need_disable;
236 
237         if (IS_IGDNG(dev)) {
238                 /* On IGDNG whatever DRAM config, GPU always do
239                  * same swizzling setup.
240                  */
241                 swizzle_x = I915_BIT_6_SWIZZLE_9_10;
242                 swizzle_y = I915_BIT_6_SWIZZLE_9;
243         } else if (!IS_I9XX(dev)) {
244                 /* As far as we know, the 865 doesn't have these bit 6
245                  * swizzling issues.
246                  */
247                 swizzle_x = I915_BIT_6_SWIZZLE_NONE;
248                 swizzle_y = I915_BIT_6_SWIZZLE_NONE;
249         } else if (IS_MOBILE(dev)) {
250                 uint32_t dcc;
251 
252                 /* Try to make sure MCHBAR is enabled before poking at it */
253                 need_disable = intel_setup_mchbar(dev);
254 
255                 /* On mobile 9xx chipsets, channel interleave by the CPU is
256                  * determined by DCC.  For single-channel, neither the CPU
257                  * nor the GPU do swizzling.  For dual channel interleaved,
258                  * the GPU's interleave is bit 9 and 10 for X tiled, and bit
259                  * 9 for Y tiled.  The CPU's interleave is independent, and
260                  * can be based on either bit 11 (haven't seen this yet) or
261                  * bit 17 (common).
262                  */
263                 dcc = I915_READ(DCC);
264                 switch (dcc & DCC_ADDRESSING_MODE_MASK) {
265                 case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
266                 case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
267                         swizzle_x = I915_BIT_6_SWIZZLE_NONE;
268                         swizzle_y = I915_BIT_6_SWIZZLE_NONE;
269                         break;
270                 case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
271                         if (dcc & DCC_CHANNEL_XOR_DISABLE) {
272                                 /* This is the base swizzling by the GPU for
273                                  * tiled buffers.
274                                  */
275                                 swizzle_x = I915_BIT_6_SWIZZLE_9_10;
276                                 swizzle_y = I915_BIT_6_SWIZZLE_9;
277                         } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
278                                 /* Bit 11 swizzling by the CPU in addition. */
279                                 swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
280                                 swizzle_y = I915_BIT_6_SWIZZLE_9_11;
281                         } else {
282                                 /* Bit 17 swizzling by the CPU in addition. */
283                                 swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
284                                 swizzle_y = I915_BIT_6_SWIZZLE_9_17;
285                         }
286                         break;
287                 }
288                 if (dcc == 0xffffffff) {
289                         DRM_ERROR("Couldn't read from MCHBAR.  "
290                                   "Disabling tiling.\n");
291                         swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
292                         swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
293                 }
294 
295                 intel_teardown_mchbar(dev, need_disable);
296         } else {
297                 /* The 965, G33, and newer, have a very flexible memory
298                  * configuration.  It will enable dual-channel mode
299                  * (interleaving) on as much memory as it can, and the GPU
300                  * will additionally sometimes enable different bit 6
301                  * swizzling for tiled objects from the CPU.
302                  *
303                  * Here's what I found on the G965:
304                  *    slot fill         memory size  swizzling
305                  * 0A   0B   1A   1B    1-ch   2-ch
306                  * 512  0    0    0     512    0     O
307                  * 512  0    512  0     16     1008  X
308                  * 512  0    0    512   16     1008  X
309                  * 0    512  0    512   16     1008  X
310                  * 1024 1024 1024 0     2048   1024  O
311                  *
312                  * We could probably detect this based on either the DRB
313                  * matching, which was the case for the swizzling required in
314                  * the table above, or from the 1-ch value being less than
315                  * the minimum size of a rank.
316                  */
317                 if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
318                         swizzle_x = I915_BIT_6_SWIZZLE_NONE;
319                         swizzle_y = I915_BIT_6_SWIZZLE_NONE;
320                 } else {
321                         swizzle_x = I915_BIT_6_SWIZZLE_9_10;
322                         swizzle_y = I915_BIT_6_SWIZZLE_9;
323                 }
324         }
325 
326         dev_priv->mm.bit_6_swizzle_x = swizzle_x;
327         dev_priv->mm.bit_6_swizzle_y = swizzle_y;
328 }
329 
330 
331 /**
332  * Returns the size of the fence for a tiled object of the given size.
333  */
334 static int
335 i915_get_fence_size(struct drm_device *dev, int size)
336 {
337         int i;
338         int start;
339 
340         if (IS_I965G(dev)) {
341                 /* The 965 can have fences at any page boundary. */
342                 return ALIGN(size, 4096);
343         } else {
344                 /* Align the size to a power of two greater than the smallest
345                  * fence size.
346                  */
347                 if (IS_I9XX(dev))
348                         start = 1024 * 1024;
349                 else
350                         start = 512 * 1024;
351 
352                 for (i = start; i < size; i <<= 1)
353                         ;
354 
355                 return i;
356         }
357 }
358 
359 /* Check pitch constriants for all chips & tiling formats */
360 static bool
361 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
362 {
363         int tile_width;
364 
365         /* Linear is always fine */
366         if (tiling_mode == I915_TILING_NONE)
367                 return true;
368 
369         if (!IS_I9XX(dev) ||
370             (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
371                 tile_width = 128;
372         else
373                 tile_width = 512;
374 
375         /* check maximum stride & object size */
376         if (IS_I965G(dev)) {
377                 /* i965 stores the end address of the gtt mapping in the fence
378                  * reg, so dont bother to check the size */
379                 if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
380                         return false;
381         } else if (IS_I9XX(dev)) {
382                 uint32_t pitch_val = ffs(stride / tile_width) - 1;
383 
384                 /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
385                  * instead of 4 (2KB) on 945s.
386                  */
387                 if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
388                     size > (I830_FENCE_MAX_SIZE_VAL << 20))
389                         return false;
390         } else {
391                 uint32_t pitch_val = ffs(stride / tile_width) - 1;
392 
393                 if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
394                     size > (I830_FENCE_MAX_SIZE_VAL << 19))
395                         return false;
396         }
397 
398         /* 965+ just needs multiples of tile width */
399         if (IS_I965G(dev)) {
400                 if (stride & (tile_width - 1))
401                         return false;
402                 return true;
403         }
404 
405         /* Pre-965 needs power of two tile widths */
406         if (stride < tile_width)
407                 return false;
408 
409         if (stride & (stride - 1))
410                 return false;
411 
412         /* We don't 0handle the aperture area covered by the fence being bigger
413          * than the object size.
414          */
415         if (i915_get_fence_size(dev, size) != size)
416                 return false;
417 
418         return true;
419 }
420 
421 static bool
422 i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
423 {
424         struct drm_device *dev = obj->dev;
425         struct drm_i915_gem_object *obj_priv = obj->driver_private;
426 
427         if (obj_priv->gtt_space == NULL)
428                 return true;
429 
430         if (tiling_mode == I915_TILING_NONE)
431                 return true;
432 
433         if (!IS_I965G(dev)) {
434                 if (obj_priv->gtt_offset & (obj->size - 1))
435                         return false;
436                 if (IS_I9XX(dev)) {
437                         if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
438                                 return false;
439                 } else {
440                         if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
441                                 return false;
442                 }
443         }
444 
445         return true;
446 }
447 
448 /**
449  * Sets the tiling mode of an object, returning the required swizzling of
450  * bit 6 of addresses in the object.
451  */
452 int
453 i915_gem_set_tiling(struct drm_device *dev, void *data,
454                    struct drm_file *file_priv)
455 {
456         struct drm_i915_gem_set_tiling *args = data;
457         drm_i915_private_t *dev_priv = dev->dev_private;
458         struct drm_gem_object *obj;
459         struct drm_i915_gem_object *obj_priv;
460         int ret = 0;
461 
462         obj = drm_gem_object_lookup(dev, file_priv, args->handle);
463         if (obj == NULL)
464                 return -EINVAL;
465         obj_priv = obj->driver_private;
466 
467         if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
468                 mutex_lock(&dev->struct_mutex);
469                 drm_gem_object_unreference(obj);
470                 mutex_unlock(&dev->struct_mutex);
471                 return -EINVAL;
472         }
473 
474         if (args->tiling_mode == I915_TILING_NONE) {
475                 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
476                 args->stride = 0;
477         } else {
478                 if (args->tiling_mode == I915_TILING_X)
479                         args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
480                 else
481                         args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
482 
483                 /* Hide bit 17 swizzling from the user.  This prevents old Mesa
484                  * from aborting the application on sw fallbacks to bit 17,
485                  * and we use the pread/pwrite bit17 paths to swizzle for it.
486                  * If there was a user that was relying on the swizzle
487                  * information for drm_intel_bo_map()ed reads/writes this would
488                  * break it, but we don't have any of those.
489                  */
490                 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
491                         args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
492                 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
493                         args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
494 
495                 /* If we can't handle the swizzling, make it untiled. */
496                 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
497                         args->tiling_mode = I915_TILING_NONE;
498                         args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
499                         args->stride = 0;
500                 }
501         }
502 
503         mutex_lock(&dev->struct_mutex);
504         if (args->tiling_mode != obj_priv->tiling_mode ||
505             args->stride != obj_priv->stride) {
506                 /* We need to rebind the object if its current allocation
507                  * no longer meets the alignment restrictions for its new
508                  * tiling mode. Otherwise we can just leave it alone, but
509                  * need to ensure that any fence register is cleared.
510                  */
511                 if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
512                     ret = i915_gem_object_unbind(obj);
513                 else
514                     ret = i915_gem_object_put_fence_reg(obj);
515                 if (ret != 0) {
516                         WARN(ret != -ERESTARTSYS,
517                              "failed to reset object for tiling switch");
518                         args->tiling_mode = obj_priv->tiling_mode;
519                         args->stride = obj_priv->stride;
520                         goto err;
521                 }
522 
523                 /* If we've changed tiling, GTT-mappings of the object
524                  * need to re-fault to ensure that the correct fence register
525                  * setup is in place.
526                  */
527                 i915_gem_release_mmap(obj);
528 
529                 obj_priv->tiling_mode = args->tiling_mode;
530                 obj_priv->stride = args->stride;
531         }
532 err:
533         drm_gem_object_unreference(obj);
534         mutex_unlock(&dev->struct_mutex);
535 
536         return ret;
537 }
538 
539 /**
540  * Returns the current tiling mode and required bit 6 swizzling for the object.
541  */
542 int
543 i915_gem_get_tiling(struct drm_device *dev, void *data,
544                    struct drm_file *file_priv)
545 {
546         struct drm_i915_gem_get_tiling *args = data;
547         drm_i915_private_t *dev_priv = dev->dev_private;
548         struct drm_gem_object *obj;
549         struct drm_i915_gem_object *obj_priv;
550 
551         obj = drm_gem_object_lookup(dev, file_priv, args->handle);
552         if (obj == NULL)
553                 return -EINVAL;
554         obj_priv = obj->driver_private;
555 
556         mutex_lock(&dev->struct_mutex);
557 
558         args->tiling_mode = obj_priv->tiling_mode;
559         switch (obj_priv->tiling_mode) {
560         case I915_TILING_X:
561                 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
562                 break;
563         case I915_TILING_Y:
564                 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
565                 break;
566         case I915_TILING_NONE:
567                 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
568                 break;
569         default:
570                 DRM_ERROR("unknown tiling mode\n");
571         }
572 
573         /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
574         if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
575                 args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
576         if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
577                 args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
578 
579         drm_gem_object_unreference(obj);
580         mutex_unlock(&dev->struct_mutex);
581 
582         return 0;
583 }
584 
585 /**
586  * Swap every 64 bytes of this page around, to account for it having a new
587  * bit 17 of its physical address and therefore being interpreted differently
588  * by the GPU.
589  */
590 static int
591 i915_gem_swizzle_page(struct page *page)
592 {
593         char *vaddr;
594         int i;
595         char temp[64];
596 
597         vaddr = kmap(page);
598         if (vaddr == NULL)
599                 return -ENOMEM;
600 
601         for (i = 0; i < PAGE_SIZE; i += 128) {
602                 memcpy(temp, &vaddr[i], 64);
603                 memcpy(&vaddr[i], &vaddr[i + 64], 64);
604                 memcpy(&vaddr[i + 64], temp, 64);
605         }
606 
607         kunmap(page);
608 
609         return 0;
610 }
611 
612 void
613 i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
614 {
615         struct drm_device *dev = obj->dev;
616         drm_i915_private_t *dev_priv = dev->dev_private;
617         struct drm_i915_gem_object *obj_priv = obj->driver_private;
618         int page_count = obj->size >> PAGE_SHIFT;
619         int i;
620 
621         if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
622                 return;
623 
624         if (obj_priv->bit_17 == NULL)
625                 return;
626 
627         for (i = 0; i < page_count; i++) {
628                 char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
629                 if ((new_bit_17 & 0x1) !=
630                     (test_bit(i, obj_priv->bit_17) != 0)) {
631                         int ret = i915_gem_swizzle_page(obj_priv->pages[i]);
632                         if (ret != 0) {
633                                 DRM_ERROR("Failed to swizzle page\n");
634                                 return;
635                         }
636                         set_page_dirty(obj_priv->pages[i]);
637                 }
638         }
639 }
640 
641 void
642 i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
643 {
644         struct drm_device *dev = obj->dev;
645         drm_i915_private_t *dev_priv = dev->dev_private;
646         struct drm_i915_gem_object *obj_priv = obj->driver_private;
647         int page_count = obj->size >> PAGE_SHIFT;
648         int i;
649 
650         if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
651                 return;
652 
653         if (obj_priv->bit_17 == NULL) {
654                 obj_priv->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
655                                            sizeof(long), GFP_KERNEL);
656                 if (obj_priv->bit_17 == NULL) {
657                         DRM_ERROR("Failed to allocate memory for bit 17 "
658                                   "record\n");
659                         return;
660                 }
661         }
662 
663         for (i = 0; i < page_count; i++) {
664                 if (page_to_phys(obj_priv->pages[i]) & (1 << 17))
665                         __set_bit(i, obj_priv->bit_17);
666                 else
667                         __clear_bit(i, obj_priv->bit_17);
668         }
669 }
670 
  This page was automatically generated by the LXR engine.