i915_gem_tiling.c revision 277487
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: head/sys/dev/drm2/i915/i915_gem_tiling.c 277487 2015-01-21 16:10:37Z kib $"); 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 360277487Skib * need to ensure that any fence register is updated before 361277487Skib * the next fenced (either through the GTT or by the BLT unit 362277487Skib * on older GPUs) access. 363277487Skib * 364277487Skib * After updating the tiling parameters, we then flag whether 365277487Skib * we need to update an associated fence register. Note this 366277487Skib * has to also include the unfenced register the GPU uses 367277487Skib * whilst executing a fenced command for an untiled object. 368235783Skib */ 369235783Skib 370277487Skib obj->map_and_fenceable = 371277487Skib obj->gtt_space == NULL || 372235783Skib (obj->gtt_offset + obj->base.size <= 373235783Skib dev_priv->mm.gtt_mappable_end && 374235783Skib i915_gem_object_fence_ok(obj, args->tiling_mode)); 375235783Skib 376235783Skib /* Rebind if we need a change of alignment */ 377235783Skib if (!obj->map_and_fenceable) { 378235783Skib uint32_t unfenced_alignment = 379235783Skib i915_gem_get_unfenced_gtt_alignment(dev, 380235783Skib obj->base.size, args->tiling_mode); 381235783Skib if (obj->gtt_offset & (unfenced_alignment - 1)) 382235783Skib ret = i915_gem_object_unbind(obj); 383235783Skib } 384277487Skib 385235783Skib if (ret == 0) { 386277487Skib obj->fence_dirty = 387277487Skib obj->fenced_gpu_access || 388277487Skib obj->fence_reg != I915_FENCE_REG_NONE; 389277487Skib 390277487Skib 391235783Skib obj->tiling_mode = args->tiling_mode; 392235783Skib obj->stride = args->stride; 393277487Skib 394277487Skib /* Force the fence to be reacquired for GTT access */ 395277487Skib i915_gem_release_mmap(obj); 396235783Skib } 397277487Skib } 398235783Skib /* we have to maintain this existing ABI... */ 399235783Skib args->stride = obj->stride; 400235783Skib args->tiling_mode = obj->tiling_mode; 401235783Skib drm_gem_object_unreference(&obj->base); 402235783Skib 403235783Skib return (ret); 404235783Skib} 405235783Skib 406235783Skib/** 407235783Skib * Returns the current tiling mode and required bit 6 swizzling for the object. 408235783Skib */ 409235783Skibint 410235783Skibi915_gem_get_tiling(struct drm_device *dev, void *data, 411235783Skib struct drm_file *file) 412235783Skib{ 413235783Skib struct drm_i915_gem_get_tiling *args = data; 414235783Skib drm_i915_private_t *dev_priv = dev->dev_private; 415235783Skib struct drm_i915_gem_object *obj; 416235783Skib 417235783Skib obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); 418235783Skib if (&obj->base == NULL) 419235783Skib return -ENOENT; 420235783Skib 421235783Skib args->tiling_mode = obj->tiling_mode; 422235783Skib switch (obj->tiling_mode) { 423235783Skib case I915_TILING_X: 424235783Skib args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; 425235783Skib break; 426235783Skib case I915_TILING_Y: 427235783Skib args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y; 428235783Skib break; 429235783Skib case I915_TILING_NONE: 430235783Skib args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 431235783Skib break; 432235783Skib default: 433235783Skib DRM_ERROR("unknown tiling mode\n"); 434235783Skib } 435235783Skib 436235783Skib /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ 437235783Skib if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17) 438235783Skib args->swizzle_mode = I915_BIT_6_SWIZZLE_9; 439235783Skib if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) 440235783Skib args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10; 441235783Skib 442235783Skib drm_gem_object_unreference(&obj->base); 443235783Skib 444235783Skib return 0; 445235783Skib} 446235783Skib 447235783Skib/** 448235783Skib * Swap every 64 bytes of this page around, to account for it having a new 449235783Skib * bit 17 of its physical address and therefore being interpreted differently 450235783Skib * by the GPU. 451235783Skib */ 452235783Skibstatic void 453235783Skibi915_gem_swizzle_page(vm_page_t m) 454235783Skib{ 455235783Skib char temp[64]; 456235783Skib char *vaddr; 457235783Skib struct sf_buf *sf; 458235783Skib int i; 459235783Skib 460235783Skib /* XXXKIB sleep */ 461235783Skib sf = sf_buf_alloc(m, SFB_DEFAULT); 462235783Skib vaddr = (char *)sf_buf_kva(sf); 463235783Skib 464235783Skib for (i = 0; i < PAGE_SIZE; i += 128) { 465235783Skib memcpy(temp, &vaddr[i], 64); 466235783Skib memcpy(&vaddr[i], &vaddr[i + 64], 64); 467235783Skib memcpy(&vaddr[i + 64], temp, 64); 468235783Skib } 469235783Skib 470235783Skib sf_buf_free(sf); 471235783Skib} 472235783Skib 473235783Skibvoid 474277487Skibi915_gem_object_do_bit_17_swizzle_page(struct drm_i915_gem_object *obj, 475277487Skib vm_page_t m) 476277487Skib{ 477277487Skib char new_bit_17; 478277487Skib 479277487Skib if (obj->bit_17 == NULL) 480277487Skib return; 481277487Skib 482277487Skib new_bit_17 = VM_PAGE_TO_PHYS(m) >> 17; 483277487Skib if ((new_bit_17 & 0x1) != (test_bit(m->pindex, obj->bit_17) != 0)) { 484277487Skib i915_gem_swizzle_page(m); 485277487Skib vm_page_dirty(m); 486277487Skib } 487277487Skib} 488277487Skib 489277487Skibvoid 490235783Skibi915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) 491235783Skib{ 492235783Skib int page_count = obj->base.size >> PAGE_SHIFT; 493235783Skib int i; 494235783Skib 495235783Skib if (obj->bit_17 == NULL) 496235783Skib return; 497235783Skib 498235783Skib for (i = 0; i < page_count; i++) { 499235783Skib char new_bit_17 = VM_PAGE_TO_PHYS(obj->pages[i]) >> 17; 500235783Skib if ((new_bit_17 & 0x1) != 501235783Skib (test_bit(i, obj->bit_17) != 0)) { 502235783Skib i915_gem_swizzle_page(obj->pages[i]); 503235783Skib vm_page_dirty(obj->pages[i]); 504235783Skib } 505235783Skib } 506235783Skib} 507235783Skib 508235783Skibvoid 509235783Skibi915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) 510235783Skib{ 511235783Skib int page_count = obj->base.size >> PAGE_SHIFT; 512235783Skib int i; 513235783Skib 514235783Skib if (obj->bit_17 == NULL) { 515235783Skib obj->bit_17 = malloc(BITS_TO_LONGS(page_count) * 516235783Skib sizeof(long), DRM_I915_GEM, M_WAITOK); 517235783Skib } 518235783Skib 519235783Skib /* XXXKIB: review locking, atomics might be not needed there */ 520235783Skib for (i = 0; i < page_count; i++) { 521235783Skib if (VM_PAGE_TO_PHYS(obj->pages[i]) & (1 << 17)) 522235783Skib set_bit(i, obj->bit_17); 523235783Skib else 524235783Skib clear_bit(i, obj->bit_17); 525235783Skib } 526235783Skib} 527