Merge branch 'stable/ttm.pci-api.v5' of git://git.kernel.org/pub/scm/linux/kernel...
authorDave Airlie <airlied@redhat.com>
Wed, 23 Feb 2011 02:06:39 +0000 (12:06 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 23 Feb 2011 02:06:39 +0000 (12:06 +1000)
* 'stable/ttm.pci-api.v5' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  ttm: Include the 'struct dev' when using the DMA API.
  nouveau/ttm/PCIe: Use dma_addr if TTM has set it.
  radeon/ttm/PCIe: Use dma_addr if TTM has set it.
  ttm: Expand (*populate) to support an array of DMA addresses.
  ttm: Utilize the DMA API for pages that have TTM_PAGE_FLAG_DMA32 set.
  ttm: Introduce a placeholder for DMA (bus) addresses.

1  2 
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
include/drm/ttm/ttm_bo_driver.h

  #include "drmP.h"
  #include "drm.h"
  #include "drm_sarea.h"
 -#include "nouveau_drv.h"
  
 -#define MIN(a,b) a < b ? a : b
 +#include "nouveau_drv.h"
 +#include "nouveau_pm.h"
 +#include "nouveau_mm.h"
 +#include "nouveau_vm.h"
  
  /*
   * NV10-NV40 tiling helpers
   */
  
  static void
 -nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
 -                         uint32_t size, uint32_t pitch)
 +nv10_mem_update_tile_region(struct drm_device *dev,
 +                          struct nouveau_tile_reg *tile, uint32_t addr,
 +                          uint32_t size, uint32_t pitch, uint32_t flags)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
        struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
        struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 -      struct nouveau_tile_reg *tile = &dev_priv->tile[i];
 +      int i = tile - dev_priv->tile.reg;
 +      unsigned long save;
 +
 +      nouveau_fence_unref(&tile->fence);
  
 -      tile->addr = addr;
 -      tile->size = size;
 -      tile->used = !!pitch;
 -      nouveau_fence_unref((void **)&tile->fence);
 +      if (tile->pitch)
 +              pfb->free_tile_region(dev, i);
  
 +      if (pitch)
 +              pfb->init_tile_region(dev, i, addr, size, pitch, flags);
 +
 +      spin_lock_irqsave(&dev_priv->context_switch_lock, save);
        pfifo->reassign(dev, false);
        pfifo->cache_pull(dev, false);
  
        nouveau_wait_for_idle(dev);
  
 -      pgraph->set_region_tiling(dev, i, addr, size, pitch);
 -      pfb->set_region_tiling(dev, i, addr, size, pitch);
 +      pfb->set_tile_region(dev, i);
 +      pgraph->set_tile_region(dev, i);
  
        pfifo->cache_pull(dev, true);
        pfifo->reassign(dev, true);
 +      spin_unlock_irqrestore(&dev_priv->context_switch_lock, save);
  }
  
 -struct nouveau_tile_reg *
 -nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
 -                  uint32_t pitch)
 +static struct nouveau_tile_reg *
 +nv10_mem_get_tile_region(struct drm_device *dev, int i)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 -      struct nouveau_tile_reg *found = NULL;
 -      unsigned long i, flags;
 -
 -      spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 -
 -      for (i = 0; i < pfb->num_tiles; i++) {
 -              struct nouveau_tile_reg *tile = &dev_priv->tile[i];
 +      struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  
 -              if (tile->used)
 -                      /* Tile region in use. */
 -                      continue;
 -
 -              if (tile->fence &&
 -                  !nouveau_fence_signalled(tile->fence, NULL))
 -                      /* Pending tile region. */
 -                      continue;
 -
 -              if (max(tile->addr, addr) <
 -                  min(tile->addr + tile->size, addr + size))
 -                      /* Kill an intersecting tile region. */
 -                      nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
 -
 -              if (pitch && !found) {
 -                      /* Free tile region. */
 -                      nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
 -                      found = tile;
 -              }
 -      }
 +      spin_lock(&dev_priv->tile.lock);
  
 -      spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 +      if (!tile->used &&
 +          (!tile->fence || nouveau_fence_signalled(tile->fence)))
 +              tile->used = true;
 +      else
 +              tile = NULL;
  
 -      return found;
 +      spin_unlock(&dev_priv->tile.lock);
 +      return tile;
  }
  
  void
 -nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
 -                     struct nouveau_fence *fence)
 -{
 -      if (fence) {
 -              /* Mark it as pending. */
 -              tile->fence = fence;
 -              nouveau_fence_ref(fence);
 -      }
 -
 -      tile->used = false;
 -}
 -
 -/*
 - * NV50 VM helpers
 - */
 -int
 -nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
 -                      uint32_t flags, uint64_t phys)
 +nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile,
 +                       struct nouveau_fence *fence)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      struct nouveau_gpuobj *pgt;
 -      unsigned block;
 -      int i;
  
 -      virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
 -      size = (size >> 16) << 1;
 -
 -      phys |= ((uint64_t)flags << 32);
 -      phys |= 1;
 -      if (dev_priv->vram_sys_base) {
 -              phys += dev_priv->vram_sys_base;
 -              phys |= 0x30;
 -      }
 -
 -      while (size) {
 -              unsigned offset_h = upper_32_bits(phys);
 -              unsigned offset_l = lower_32_bits(phys);
 -              unsigned pte, end;
 -
 -              for (i = 7; i >= 0; i--) {
 -                      block = 1 << (i + 1);
 -                      if (size >= block && !(virt & (block - 1)))
 -                              break;
 +      if (tile) {
 +              spin_lock(&dev_priv->tile.lock);
 +              if (fence) {
 +                      /* Mark it as pending. */
 +                      tile->fence = fence;
 +                      nouveau_fence_ref(fence);
                }
 -              offset_l |= (i << 7);
 -
 -              phys += block << 15;
 -              size -= block;
 -
 -              while (block) {
 -                      pgt = dev_priv->vm_vram_pt[virt >> 14];
 -                      pte = virt & 0x3ffe;
 -
 -                      end = pte + block;
 -                      if (end > 16384)
 -                              end = 16384;
 -                      block -= (end - pte);
 -                      virt  += (end - pte);
 -
 -                      while (pte < end) {
 -                              nv_wo32(pgt, (pte * 4) + 0, offset_l);
 -                              nv_wo32(pgt, (pte * 4) + 4, offset_h);
 -                              pte += 2;
 -                      }
 -              }
 -      }
 -      dev_priv->engine.instmem.flush(dev);
  
 -      nv50_vm_flush(dev, 5);
 -      nv50_vm_flush(dev, 0);
 -      nv50_vm_flush(dev, 4);
 -      nv50_vm_flush(dev, 6);
 -      return 0;
 +              tile->used = false;
 +              spin_unlock(&dev_priv->tile.lock);
 +      }
  }
  
 -void
 -nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
 +struct nouveau_tile_reg *
 +nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
 +                  uint32_t pitch, uint32_t flags)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      struct nouveau_gpuobj *pgt;
 -      unsigned pages, pte, end;
 -
 -      virt -= dev_priv->vm_vram_base;
 -      pages = (size >> 16) << 1;
 +      struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 +      struct nouveau_tile_reg *tile, *found = NULL;
 +      int i;
  
 -      while (pages) {
 -              pgt = dev_priv->vm_vram_pt[virt >> 29];
 -              pte = (virt & 0x1ffe0000ULL) >> 15;
 +      for (i = 0; i < pfb->num_tiles; i++) {
 +              tile = nv10_mem_get_tile_region(dev, i);
  
 -              end = pte + pages;
 -              if (end > 16384)
 -                      end = 16384;
 -              pages -= (end - pte);
 -              virt  += (end - pte) << 15;
 +              if (pitch && !found) {
 +                      found = tile;
 +                      continue;
  
 -              while (pte < end) {
 -                      nv_wo32(pgt, (pte * 4), 0);
 -                      pte++;
 +              } else if (tile && tile->pitch) {
 +                      /* Kill an unused tile region. */
 +                      nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0);
                }
 +
 +              nv10_mem_put_tile_region(dev, tile, NULL);
        }
 -      dev_priv->engine.instmem.flush(dev);
  
 -      nv50_vm_flush(dev, 5);
 -      nv50_vm_flush(dev, 0);
 -      nv50_vm_flush(dev, 4);
 -      nv50_vm_flush(dev, 6);
 +      if (found)
 +              nv10_mem_update_tile_region(dev, found, addr, size,
 +                                          pitch, flags);
 +      return found;
  }
  
  /*
@@@ -241,7 -314,62 +241,7 @@@ nouveau_mem_detect_nforce(struct drm_de
        return 0;
  }
  
 -static void
 -nv50_vram_preinit(struct drm_device *dev)
 -{
 -      struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      int i, parts, colbits, rowbitsa, rowbitsb, banks;
 -      u64 rowsize, predicted;
 -      u32 r0, r4, rt, ru;
 -
 -      r0 = nv_rd32(dev, 0x100200);
 -      r4 = nv_rd32(dev, 0x100204);
 -      rt = nv_rd32(dev, 0x100250);
 -      ru = nv_rd32(dev, 0x001540);
 -      NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
 -
 -      for (i = 0, parts = 0; i < 8; i++) {
 -              if (ru & (0x00010000 << i))
 -                      parts++;
 -      }
 -
 -      colbits  =  (r4 & 0x0000f000) >> 12;
 -      rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
 -      rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
 -      banks    = ((r4 & 0x01000000) ? 8 : 4);
 -
 -      rowsize = parts * banks * (1 << colbits) * 8;
 -      predicted = rowsize << rowbitsa;
 -      if (r0 & 0x00000004)
 -              predicted += rowsize << rowbitsb;
 -
 -      if (predicted != dev_priv->vram_size) {
 -              NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
 -                      (u32)(dev_priv->vram_size >> 20));
 -              NV_WARN(dev, "we calculated %dMiB VRAM\n",
 -                      (u32)(predicted >> 20));
 -      }
 -
 -      dev_priv->vram_rblock_size = rowsize >> 12;
 -      if (rt & 1)
 -              dev_priv->vram_rblock_size *= 3;
 -
 -      NV_DEBUG(dev, "rblock %lld bytes\n",
 -               (u64)dev_priv->vram_rblock_size << 12);
 -}
 -
 -static void
 -nvaa_vram_preinit(struct drm_device *dev)
 -{
 -      struct drm_nouveau_private *dev_priv = dev->dev_private;
 -
 -      /* To our knowledge, there's no large scale reordering of pages
 -       * that occurs on IGP chipsets.
 -       */
 -      dev_priv->vram_rblock_size = 1;
 -}
 -
 -static int
 +int
  nouveau_mem_detect(struct drm_device *dev)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        if (dev_priv->card_type < NV_50) {
                dev_priv->vram_size  = nv_rd32(dev, NV04_PFB_FIFO_DATA);
                dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
 -      } else
 -      if (dev_priv->card_type < NV_C0) {
 -              dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
 -              dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
 -              dev_priv->vram_size &= 0xffffffff00ll;
 -
 -              switch (dev_priv->chipset) {
 -              case 0xaa:
 -              case 0xac:
 -              case 0xaf:
 -                      dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
 -                      dev_priv->vram_sys_base <<= 12;
 -                      nvaa_vram_preinit(dev);
 -                      break;
 -              default:
 -                      nv50_vram_preinit(dev);
 -                      break;
 -              }
 -      } else {
 -              dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
 -              dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
 -      }
 -
 -      NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
 -      if (dev_priv->vram_sys_base) {
 -              NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
 -                      dev_priv->vram_sys_base);
        }
  
        if (dev_priv->vram_size)
        return -ENOMEM;
  }
  
 +bool
 +nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags)
 +{
 +      if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
 +              return true;
 +
 +      return false;
 +}
 +
  #if __OS_HAS_AGP
  static unsigned long
  get_agp_mode(struct drm_device *dev, unsigned long mode)
@@@ -403,12 -549,17 +403,13 @@@ nouveau_mem_vram_init(struct drm_devic
        if (ret)
                return ret;
  
 -      ret = nouveau_mem_detect(dev);
 -      if (ret)
 -              return ret;
 -
        dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
  
        ret = nouveau_ttm_global_init(dev_priv);
        if (ret)
                return ret;
  
+       dev_priv->ttm.bdev.dev = dev->dev;
        ret = ttm_bo_device_init(&dev_priv->ttm.bdev,
                                 dev_priv->ttm.bo_global_ref.ref.object,
                                 &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET,
                return ret;
        }
  
 -      dev_priv->fb_available_size = dev_priv->vram_size;
 -      dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
 -      if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
 -              dev_priv->fb_mappable_pages =
 -                      pci_resource_len(dev->pdev, 1);
 -      dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
 -
        /* reserve space at end of VRAM for PRAMIN */
        if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
            dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
        else
                dev_priv->ramin_rsvd_vram = (512 * 1024);
  
 +      ret = dev_priv->engine.vram.init(dev);
 +      if (ret)
 +              return ret;
 +
 +      NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
 +      if (dev_priv->vram_sys_base) {
 +              NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
 +                      dev_priv->vram_sys_base);
 +      }
 +
 +      dev_priv->fb_available_size = dev_priv->vram_size;
 +      dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
 +      if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
 +              dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1);
 +      dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
 +
        dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
        dev_priv->fb_aper_free = dev_priv->fb_available_size;
  
@@@ -480,7 -622,7 +481,7 @@@ nouveau_mem_gart_init(struct drm_devic
        dev_priv->gart_info.type = NOUVEAU_GART_NONE;
  
  #if !defined(__powerpc__) && !defined(__ia64__)
 -      if (drm_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
 +      if (drm_pci_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
                ret = nouveau_mem_init_agp(dev);
                if (ret)
                        NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
  void
  nouveau_mem_timing_init(struct drm_device *dev)
  {
 +      /* cards < NVC0 only */
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
                tUNK_19 = 1;
                tUNK_20 = 0;
                tUNK_21 = 0;
 -              switch (MIN(recordlen,21)) {
 -              case 21:
 +              switch (min(recordlen, 22)) {
 +              case 22:
                        tUNK_21 = entry[21];
 -              case 20:
 +              case 21:
                        tUNK_20 = entry[20];
 -              case 19:
 +              case 20:
                        tUNK_19 = entry[19];
 -              case 18:
 +              case 19:
                        tUNK_18 = entry[18];
                default:
                        tUNK_0  = entry[0];
                timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
                if(recordlen > 19) {
                        timing->reg_100228 += (tUNK_19 - 1) << 24;
 -              } else {
 +              }/* I cannot back-up this else-statement right now
 +                       else {
                        timing->reg_100228 += tUNK_12 << 24;
 -              }
 +              }*/
  
                /* XXX: reg_10022c */
 +              timing->reg_10022c = tUNK_2 - 1;
  
                timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
                                      tUNK_13 << 8  | tUNK_13);
  
                /* XXX: +6? */
                timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
 -              if(tUNK_10 > tUNK_11) {
 -                      timing->reg_100234 += tUNK_10 << 16;
 -              } else {
 -                      timing->reg_100234 += tUNK_11 << 16;
 +              timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
 +
 +              /* XXX; reg_100238, reg_10023c
 +               * reg: 0x00??????
 +               * reg_10023c:
 +               *      0 for pre-NV50 cards
 +               *      0x????0202 for NV50+ cards (empirical evidence) */
 +              if(dev_priv->card_type >= NV_50) {
 +                      timing->reg_10023c = 0x202;
                }
  
 -              /* XXX; reg_100238, reg_10023c */
                NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
                         timing->reg_100220, timing->reg_100224,
                         timing->reg_100228, timing->reg_10022c);
@@@ -660,112 -795,3 +661,112 @@@ nouveau_mem_timing_fini(struct drm_devi
  
        kfree(mem->timing);
  }
 +
 +static int
 +nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
 +{
 +      struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 +      struct nouveau_mm *mm;
 +      u32 b_size;
 +      int ret;
 +
 +      p_size = (p_size << PAGE_SHIFT) >> 12;
 +      b_size = dev_priv->vram_rblock_size >> 12;
 +
 +      ret = nouveau_mm_init(&mm, 0, p_size, b_size);
 +      if (ret)
 +              return ret;
 +
 +      man->priv = mm;
 +      return 0;
 +}
 +
 +static int
 +nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
 +{
 +      struct nouveau_mm *mm = man->priv;
 +      int ret;
 +
 +      ret = nouveau_mm_fini(&mm);
 +      if (ret)
 +              return ret;
 +
 +      man->priv = NULL;
 +      return 0;
 +}
 +
 +static void
 +nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
 +                       struct ttm_mem_reg *mem)
 +{
 +      struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 +      struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 +      struct drm_device *dev = dev_priv->dev;
 +
 +      vram->put(dev, (struct nouveau_vram **)&mem->mm_node);
 +}
 +
 +static int
 +nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 +                       struct ttm_buffer_object *bo,
 +                       struct ttm_placement *placement,
 +                       struct ttm_mem_reg *mem)
 +{
 +      struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 +      struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 +      struct drm_device *dev = dev_priv->dev;
 +      struct nouveau_bo *nvbo = nouveau_bo(bo);
 +      struct nouveau_vram *node;
 +      u32 size_nc = 0;
 +      int ret;
 +
 +      if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
 +              size_nc = 1 << nvbo->vma.node->type;
 +
 +      ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
 +                      mem->page_alignment << PAGE_SHIFT, size_nc,
 +                      (nvbo->tile_flags >> 8) & 0xff, &node);
 +      if (ret)
 +              return ret;
 +
 +      node->page_shift = 12;
 +      if (nvbo->vma.node)
 +              node->page_shift = nvbo->vma.node->type;
 +
 +      mem->mm_node = node;
 +      mem->start   = node->offset >> PAGE_SHIFT;
 +      return 0;
 +}
 +
 +void
 +nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
 +{
 +      struct nouveau_mm *mm = man->priv;
 +      struct nouveau_mm_node *r;
 +      u32 total = 0, free = 0;
 +
 +      mutex_lock(&mm->mutex);
 +      list_for_each_entry(r, &mm->nodes, nl_entry) {
 +              printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n",
 +                     prefix, r->type, ((u64)r->offset << 12),
 +                     (((u64)r->offset + r->length) << 12));
 +
 +              total += r->length;
 +              if (!r->type)
 +                      free += r->length;
 +      }
 +      mutex_unlock(&mm->mutex);
 +
 +      printk(KERN_DEBUG "%s  total: 0x%010llx free: 0x%010llx\n",
 +             prefix, (u64)total << 12, (u64)free << 12);
 +      printk(KERN_DEBUG "%s  block: 0x%08x\n",
 +             prefix, mm->block_size << 12);
 +}
 +
 +const struct ttm_mem_type_manager_func nouveau_vram_manager = {
 +      nouveau_vram_manager_init,
 +      nouveau_vram_manager_fini,
 +      nouveau_vram_manager_new,
 +      nouveau_vram_manager_del,
 +      nouveau_vram_manager_debug
 +};
@@@ -12,15 -12,17 +12,17 @@@ struct nouveau_sgdma_be 
        struct drm_device *dev;
  
        dma_addr_t *pages;
+       bool *ttm_alloced;
        unsigned nr_pages;
  
 -      unsigned pte_start;
 +      u64 offset;
        bool bound;
  };
  
  static int
  nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
-                      struct page **pages, struct page *dummy_read_page)
+                      struct page **pages, struct page *dummy_read_page,
+                      dma_addr_t *dma_addrs)
  {
        struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
        struct drm_device *dev = nvbe->dev;
        if (!nvbe->pages)
                return -ENOMEM;
  
+       nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
+       if (!nvbe->ttm_alloced)
+               return -ENOMEM;
        nvbe->nr_pages = 0;
        while (num_pages--) {
-               nvbe->pages[nvbe->nr_pages] =
-                       pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
+               if (dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE) {
+                       nvbe->pages[nvbe->nr_pages] =
+                                       dma_addrs[nvbe->nr_pages];
+                       nvbe->ttm_alloced[nvbe->nr_pages] = true;
+               } else {
+                       nvbe->pages[nvbe->nr_pages] =
+                               pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
                                     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(dev->pdev,
-                                         nvbe->pages[nvbe->nr_pages])) {
-                       be->func->clear(be);
-                       return -EFAULT;
+                       if (pci_dma_mapping_error(dev->pdev,
+                                                 nvbe->pages[nvbe->nr_pages])) {
+                               be->func->clear(be);
+                               return -EFAULT;
+                       }
                }
  
                nvbe->nr_pages++;
@@@ -65,15 -77,30 +77,18 @@@ nouveau_sgdma_clear(struct ttm_backend 
                        be->func->unbind(be);
  
                while (nvbe->nr_pages--) {
-                       pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+                       if (!nvbe->ttm_alloced[nvbe->nr_pages])
+                               pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
                                       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                }
                kfree(nvbe->pages);
+               kfree(nvbe->ttm_alloced);
                nvbe->pages = NULL;
+               nvbe->ttm_alloced = NULL;
                nvbe->nr_pages = 0;
        }
  }
  
 -static inline unsigned
 -nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset)
 -{
 -      struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
 -
 -      if (dev_priv->card_type < NV_50)
 -              return pte + 2;
 -
 -      return pte << 1;
 -}
 -
  static int
  nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
  {
  
        NV_DEBUG(dev, "pg=0x%lx\n", mem->start);
  
 -      pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT);
 -      nvbe->pte_start = pte;
 +      nvbe->offset = mem->start << PAGE_SHIFT;
 +      pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
        for (i = 0; i < nvbe->nr_pages; i++) {
                dma_addr_t dma_offset = nvbe->pages[i];
                uint32_t offset_l = lower_32_bits(dma_offset);
 -              uint32_t offset_h = upper_32_bits(dma_offset);
 -
 -              for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
 -                      if (dev_priv->card_type < NV_50) {
 -                              nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3);
 -                              pte += 1;
 -                      } else {
 -                              nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21);
 -                              nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff);
 -                              pte += 2;
 -                      }
  
 +              for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) {
 +                      nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3);
                        dma_offset += NV_CTXDMA_PAGE_SIZE;
                }
        }
 -      dev_priv->engine.instmem.flush(nvbe->dev);
 -
 -      if (dev_priv->card_type == NV_50) {
 -              nv50_vm_flush(dev, 5); /* PGRAPH */
 -              nv50_vm_flush(dev, 0); /* PFIFO */
 -      }
  
        nvbe->bound = true;
        return 0;
@@@ -115,10 -157,28 +130,10 @@@ nouveau_sgdma_unbind(struct ttm_backen
        if (!nvbe->bound)
                return 0;
  
 -      pte = nvbe->pte_start;
 +      pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
        for (i = 0; i < nvbe->nr_pages; i++) {
 -              dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
 -
 -              for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
 -                      if (dev_priv->card_type < NV_50) {
 -                              nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3);
 -                              pte += 1;
 -                      } else {
 -                              nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000);
 -                              nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000);
 -                              pte += 2;
 -                      }
 -
 -                      dma_offset += NV_CTXDMA_PAGE_SIZE;
 -              }
 -      }
 -      dev_priv->engine.instmem.flush(nvbe->dev);
 -
 -      if (dev_priv->card_type == NV_50) {
 -              nv50_vm_flush(dev, 5);
 -              nv50_vm_flush(dev, 0);
 +              for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++)
 +                      nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000);
        }
  
        nvbe->bound = false;
@@@ -141,35 -201,6 +156,35 @@@ nouveau_sgdma_destroy(struct ttm_backen
        }
  }
  
 +static int
 +nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 +{
 +      struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 +      struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
 +
 +      nvbe->offset = mem->start << PAGE_SHIFT;
 +
 +      nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset,
 +                        nvbe->nr_pages << PAGE_SHIFT, nvbe->pages);
 +      nvbe->bound = true;
 +      return 0;
 +}
 +
 +static int
 +nv50_sgdma_unbind(struct ttm_backend *be)
 +{
 +      struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 +      struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
 +
 +      if (!nvbe->bound)
 +              return 0;
 +
 +      nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset,
 +                          nvbe->nr_pages << PAGE_SHIFT);
 +      nvbe->bound = false;
 +      return 0;
 +}
 +
  static struct ttm_backend_func nouveau_sgdma_backend = {
        .populate               = nouveau_sgdma_populate,
        .clear                  = nouveau_sgdma_clear,
        .destroy                = nouveau_sgdma_destroy
  };
  
 +static struct ttm_backend_func nv50_sgdma_backend = {
 +      .populate               = nouveau_sgdma_populate,
 +      .clear                  = nouveau_sgdma_clear,
 +      .bind                   = nv50_sgdma_bind,
 +      .unbind                 = nv50_sgdma_unbind,
 +      .destroy                = nouveau_sgdma_destroy
 +};
 +
  struct ttm_backend *
  nouveau_sgdma_init_ttm(struct drm_device *dev)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_sgdma_be *nvbe;
  
 -      if (!dev_priv->gart_info.sg_ctxdma)
 -              return NULL;
 -
        nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
        if (!nvbe)
                return NULL;
  
        nvbe->dev = dev;
  
 -      nvbe->backend.func      = &nouveau_sgdma_backend;
 -
 +      if (dev_priv->card_type < NV_50)
 +              nvbe->backend.func = &nouveau_sgdma_backend;
 +      else
 +              nvbe->backend.func = &nv50_sgdma_backend;
        return &nvbe->backend;
  }
  
@@@ -209,52 -233,77 +224,52 @@@ in
  nouveau_sgdma_init(struct drm_device *dev)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 -      struct pci_dev *pdev = dev->pdev;
        struct nouveau_gpuobj *gpuobj = NULL;
        uint32_t aper_size, obj_size;
        int i, ret;
  
        if (dev_priv->card_type < NV_50) {
 -              aper_size = (64 * 1024 * 1024);
 +              if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024)
 +                      aper_size = 64 * 1024 * 1024;
 +              else
 +                      aper_size = 512 * 1024 * 1024;
 +
                obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
                obj_size += 8; /* ctxdma header */
 -      } else {
 -              /* 1 entire VM page table */
 -              aper_size = (512 * 1024 * 1024);
 -              obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
 -      }
  
 -      ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
 -                                    NVOBJ_FLAG_ZERO_ALLOC |
 -                                    NVOBJ_FLAG_ZERO_FREE, &gpuobj);
 -      if (ret) {
 -              NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
 -              return ret;
 -      }
 -
 -      dev_priv->gart_info.sg_dummy_page =
 -              alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO);
 -      if (!dev_priv->gart_info.sg_dummy_page) {
 -              nouveau_gpuobj_ref(NULL, &gpuobj);
 -              return -ENOMEM;
 -      }
 -
 -      set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
 -      dev_priv->gart_info.sg_dummy_bus =
 -              pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0,
 -                           PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 -      if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) {
 -              nouveau_gpuobj_ref(NULL, &gpuobj);
 -              return -EFAULT;
 -      }
 +              ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
 +                                            NVOBJ_FLAG_ZERO_ALLOC |
 +                                            NVOBJ_FLAG_ZERO_FREE, &gpuobj);
 +              if (ret) {
 +                      NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
 +                      return ret;
 +              }
  
 -      if (dev_priv->card_type < NV_50) {
 -              /* special case, allocated from global instmem heap so
 -               * cinst is invalid, we use it on all channels though so
 -               * cinst needs to be valid, set it the same as pinst
 -               */
 -              gpuobj->cinst = gpuobj->pinst;
 -
 -              /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
 -               * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
 -               * on those cards? */
                nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
                                   (1 << 12) /* PT present */ |
                                   (0 << 13) /* PT *not* linear */ |
 -                                 (NV_DMA_ACCESS_RW  << 14) |
 -                                 (NV_DMA_TARGET_PCI << 16));
 +                                 (0 << 14) /* RW */ |
 +                                 (2 << 16) /* PCI */);
                nv_wo32(gpuobj, 4, aper_size - 1);
 -              for (i = 2; i < 2 + (aper_size >> 12); i++) {
 -                      nv_wo32(gpuobj, i * 4,
 -                              dev_priv->gart_info.sg_dummy_bus | 3);
 -              }
 -      } else {
 -              for (i = 0; i < obj_size; i += 8) {
 -                      nv_wo32(gpuobj, i + 0, 0x00000000);
 -                      nv_wo32(gpuobj, i + 4, 0x00000000);
 -              }
 +              for (i = 2; i < 2 + (aper_size >> 12); i++)
 +                      nv_wo32(gpuobj, i * 4, 0x00000000);
 +
 +              dev_priv->gart_info.sg_ctxdma = gpuobj;
 +              dev_priv->gart_info.aper_base = 0;
 +              dev_priv->gart_info.aper_size = aper_size;
 +      } else
 +      if (dev_priv->chan_vm) {
 +              ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024,
 +                                   12, NV_MEM_ACCESS_RW,
 +                                   &dev_priv->gart_info.vma);
 +              if (ret)
 +                      return ret;
 +
 +              dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset;
 +              dev_priv->gart_info.aper_size = 512 * 1024 * 1024;
        }
 -      dev_priv->engine.instmem.flush(dev);
  
        dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
 -      dev_priv->gart_info.aper_base = 0;
 -      dev_priv->gart_info.aper_size = aper_size;
 -      dev_priv->gart_info.sg_ctxdma = gpuobj;
        return 0;
  }
  
@@@ -263,19 -312,31 +278,19 @@@ nouveau_sgdma_takedown(struct drm_devic
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
  
 -      if (dev_priv->gart_info.sg_dummy_page) {
 -              pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
 -                             NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 -              unlock_page(dev_priv->gart_info.sg_dummy_page);
 -              __free_page(dev_priv->gart_info.sg_dummy_page);
 -              dev_priv->gart_info.sg_dummy_page = NULL;
 -              dev_priv->gart_info.sg_dummy_bus = 0;
 -      }
 -
        nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma);
 +      nouveau_vm_put(&dev_priv->gart_info.vma);
  }
  
 -int
 -nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
 +uint32_t
 +nouveau_sgdma_get_physical(struct drm_device *dev, uint32_t offset)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
 -      int pte;
 +      int pte = (offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
  
 -      pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2;
 -      if (dev_priv->card_type < NV_50) {
 -              *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK;
 -              return 0;
 -      }
 +      BUG_ON(dev_priv->card_type >= NV_50);
  
 -      NV_ERROR(dev, "Unimplemented on NV50\n");
 -      return -EINVAL;
 +      return (nv_ro32(gpuobj, 4 * pte) & ~NV_CTXDMA_PAGE_MASK) |
 +              (offset & NV_CTXDMA_PAGE_MASK);
  }
@@@ -69,7 -69,6 +69,7 @@@
  #include <ttm/ttm_bo_driver.h>
  #include <ttm/ttm_placement.h>
  #include <ttm/ttm_module.h>
 +#include <ttm/ttm_execbuf_util.h>
  
  #include "radeon_family.h"
  #include "radeon_mode.h"
@@@ -92,7 -91,6 +92,7 @@@ extern int radeon_tv
  extern int radeon_audio;
  extern int radeon_disp_priority;
  extern int radeon_hw_i2c;
 +extern int radeon_pcie_gen2;
  
  /*
   * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@@ -179,10 -177,9 +179,10 @@@ void radeon_combios_get_power_modes(str
  void radeon_atombios_get_power_modes(struct radeon_device *rdev);
  void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
  void rs690_pm_info(struct radeon_device *rdev);
 -extern u32 rv6xx_get_temp(struct radeon_device *rdev);
 -extern u32 rv770_get_temp(struct radeon_device *rdev);
 -extern u32 evergreen_get_temp(struct radeon_device *rdev);
 +extern int rv6xx_get_temp(struct radeon_device *rdev);
 +extern int rv770_get_temp(struct radeon_device *rdev);
 +extern int evergreen_get_temp(struct radeon_device *rdev);
 +extern int sumo_get_temp(struct radeon_device *rdev);
  
  /*
   * Fences.
@@@ -262,12 -259,13 +262,12 @@@ struct radeon_bo 
  };
  
  struct radeon_bo_list {
 -      struct list_head        list;
 +      struct ttm_validate_buffer tv;
        struct radeon_bo        *bo;
        uint64_t                gpu_offset;
        unsigned                rdomain;
        unsigned                wdomain;
        u32                     tiling_flags;
 -      bool                    reserved;
  };
  
  /*
@@@ -288,15 -286,6 +288,15 @@@ int radeon_gem_object_pin(struct drm_ge
                          uint64_t *gpu_addr);
  void radeon_gem_object_unpin(struct drm_gem_object *obj);
  
 +int radeon_mode_dumb_create(struct drm_file *file_priv,
 +                          struct drm_device *dev,
 +                          struct drm_mode_create_dumb *args);
 +int radeon_mode_dumb_mmap(struct drm_file *filp,
 +                        struct drm_device *dev,
 +                        uint32_t handle, uint64_t *offset_p);
 +int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 +                           struct drm_device *dev,
 +                           uint32_t handle);
  
  /*
   * GART structures, functions & helpers
@@@ -328,6 -317,7 +328,7 @@@ struct radeon_gart 
        union radeon_gart_table         table;
        struct page                     **pages;
        dma_addr_t                      *pages_addr;
+       bool                            *ttm_alloced;
        bool                            ready;
  };
  
@@@ -340,7 -330,8 +341,8 @@@ void radeon_gart_fini(struct radeon_dev
  void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
                        int pages);
  int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-                    int pages, struct page **pagelist);
+                    int pages, struct page **pagelist,
+                    dma_addr_t *dma_addr);
  
  
  /*
@@@ -388,56 -379,11 +390,56 @@@ void radeon_scratch_free(struct radeon_
  /*
   * IRQS.
   */
 +
 +struct radeon_unpin_work {
 +      struct work_struct work;
 +      struct radeon_device *rdev;
 +      int crtc_id;
 +      struct radeon_fence *fence;
 +      struct drm_pending_vblank_event *event;
 +      struct radeon_bo *old_rbo;
 +      u64 new_crtc_base;
 +};
 +
 +struct r500_irq_stat_regs {
 +      u32 disp_int;
 +};
 +
 +struct r600_irq_stat_regs {
 +      u32 disp_int;
 +      u32 disp_int_cont;
 +      u32 disp_int_cont2;
 +      u32 d1grph_int;
 +      u32 d2grph_int;
 +};
 +
 +struct evergreen_irq_stat_regs {
 +      u32 disp_int;
 +      u32 disp_int_cont;
 +      u32 disp_int_cont2;
 +      u32 disp_int_cont3;
 +      u32 disp_int_cont4;
 +      u32 disp_int_cont5;
 +      u32 d1grph_int;
 +      u32 d2grph_int;
 +      u32 d3grph_int;
 +      u32 d4grph_int;
 +      u32 d5grph_int;
 +      u32 d6grph_int;
 +};
 +
 +union radeon_irq_stat_regs {
 +      struct r500_irq_stat_regs r500;
 +      struct r600_irq_stat_regs r600;
 +      struct evergreen_irq_stat_regs evergreen;
 +};
 +
  struct radeon_irq {
        bool            installed;
        bool            sw_int;
        /* FIXME: use a define max crtc rather than hardcode it */
        bool            crtc_vblank_int[6];
 +      bool            pflip[6];
        wait_queue_head_t       vblank_queue;
        /* FIXME: use defines for max hpd/dacs */
        bool            hpd[6];
        bool            hdmi[2];
        spinlock_t sw_lock;
        int sw_refcount;
 +      union radeon_irq_stat_regs stat_regs;
 +      spinlock_t pflip_lock[6];
 +      int pflip_refcount[6];
  };
  
  int radeon_irq_kms_init(struct radeon_device *rdev);
  void radeon_irq_kms_fini(struct radeon_device *rdev);
  void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev);
  void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
 +void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc);
 +void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc);
  
  /*
   * CP & ring.
@@@ -748,8 -689,6 +750,8 @@@ enum radeon_int_thermal_type 
        THERMAL_TYPE_RV6XX,
        THERMAL_TYPE_RV770,
        THERMAL_TYPE_EVERGREEN,
 +      THERMAL_TYPE_SUMO,
 +      THERMAL_TYPE_NI,
  };
  
  struct radeon_voltage {
@@@ -821,7 -760,8 +823,7 @@@ struct radeon_pm 
        fixed20_12              sclk;
        fixed20_12              mclk;
        fixed20_12              needed_bandwidth;
 -      /* XXX: use a define for num power modes */
 -      struct radeon_power_state power_state[8];
 +      struct radeon_power_state *power_state;
        /* number of valid power states */
        int                     num_power_states;
        int                     current_power_state_index;
        u32                     current_sclk;
        u32                     current_mclk;
        u32                     current_vddc;
 +      u32                     default_sclk;
 +      u32                     default_mclk;
 +      u32                     default_vddc;
        struct radeon_i2c_chan *i2c_bus;
        /* selected pm method */
        enum radeon_pm_method     pm_method;
@@@ -946,10 -883,6 +948,10 @@@ struct radeon_asic 
        void (*pm_finish)(struct radeon_device *rdev);
        void (*pm_init_profile)(struct radeon_device *rdev);
        void (*pm_get_dynpm_state)(struct radeon_device *rdev);
 +      /* pageflipping */
 +      void (*pre_page_flip)(struct radeon_device *rdev, int crtc);
 +      u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
 +      void (*post_page_flip)(struct radeon_device *rdev, int crtc);
  };
  
  /*
@@@ -1044,7 -977,6 +1046,7 @@@ struct evergreen_asic 
        unsigned tiling_npipes;
        unsigned tiling_group_size;
        unsigned tile_config;
 +      struct r100_gpu_lockup  lockup;
  };
  
  union radeon_asic_config {
@@@ -1161,11 -1093,11 +1163,11 @@@ struct radeon_device 
        const struct firmware *me_fw;   /* all family ME firmware */
        const struct firmware *pfp_fw;  /* r6/700 PFP firmware */
        const struct firmware *rlc_fw;  /* r6/700 RLC firmware */
 +      const struct firmware *mc_fw;   /* NI MC firmware */
        struct r600_blit r600_blit;
        struct r700_vram_scratch vram_scratch;
        int msi_enabled; /* msi enabled */
        struct r600_ih ih; /* r6/700 interrupt ring */
 -      struct workqueue_struct *wq;
        struct work_struct hotplug_work;
        int num_crtc; /* number of crtcs */
        struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
        uint8_t                 audio_status_bits;
        uint8_t                 audio_category_code;
  
 -      bool powered_down;
        struct notifier_block acpi_nb;
 -      /* only one userspace can use Hyperz features at a time */
 +      /* only one userspace can use Hyperz features or CMASK at a time */
        struct drm_file *hyperz_filp;
 +      struct drm_file *cmask_filp;
        /* i2c buses */
        struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
  };
@@@ -1258,8 -1190,6 +1260,8 @@@ static inline void r100_io_wreg(struct 
   */
  #define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
  #define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
 +#define RREG16(reg) readw(((void __iomem *)rdev->rmmio) + (reg))
 +#define WREG16(reg, v) writew(v, ((void __iomem *)rdev->rmmio) + (reg))
  #define RREG32(reg) r100_mm_rreg(rdev, (reg))
  #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
  #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
@@@ -1333,25 -1263,10 +1335,25 @@@ void r100_pll_errata_after_index(struc
                (rdev->family == CHIP_RV410) ||                 \
                (rdev->family == CHIP_RS400) ||                 \
                (rdev->family == CHIP_RS480))
 +#define ASIC_IS_X2(rdev) ((rdev->ddev->pdev->device == 0x9441) || \
 +              (rdev->ddev->pdev->device == 0x9443) || \
 +              (rdev->ddev->pdev->device == 0x944B) || \
 +              (rdev->ddev->pdev->device == 0x9506) || \
 +              (rdev->ddev->pdev->device == 0x9509) || \
 +              (rdev->ddev->pdev->device == 0x950F) || \
 +              (rdev->ddev->pdev->device == 0x689C) || \
 +              (rdev->ddev->pdev->device == 0x689D))
  #define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
 +#define ASIC_IS_DCE2(rdev) ((rdev->family == CHIP_RS600)  ||  \
 +                          (rdev->family == CHIP_RS690)  ||    \
 +                          (rdev->family == CHIP_RS740)  ||    \
 +                          (rdev->family >= CHIP_R600))
  #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
  #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
  #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
 +#define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \
 +                           (rdev->flags & RADEON_IS_IGP))
 +#define ASIC_IS_DCE5(rdev) ((rdev->family >= CHIP_BARTS))
  
  /*
   * BIOS helpers.
@@@ -1427,9 -1342,6 +1429,9 @@@ static inline void radeon_ring_write(st
  #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev))
  #define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev))
  #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev))
 +#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc))
 +#define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base))
 +#define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc))
  
  /* Common functions */
  /* AGP */
@@@ -1458,7 -1370,67 +1460,7 @@@ extern void radeon_gtt_location(struct 
  extern int radeon_resume_kms(struct drm_device *dev);
  extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
  
 -/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
 -extern void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp);
 -extern bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_cp *cp);
 -
 -/* rv200,rv250,rv280 */
 -extern void r200_set_safe_registers(struct radeon_device *rdev);
 -
 -/* r300,r350,rv350,rv370,rv380 */
 -extern void r300_set_reg_safe(struct radeon_device *rdev);
 -extern void r300_mc_program(struct radeon_device *rdev);
 -extern void r300_mc_init(struct radeon_device *rdev);
 -extern void r300_clock_startup(struct radeon_device *rdev);
 -extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
 -extern int rv370_pcie_gart_init(struct radeon_device *rdev);
 -extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
 -extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
 -extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
 -
 -/* r420,r423,rv410 */
 -extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
 -extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 -extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
 -extern void r420_pipes_init(struct radeon_device *rdev);
 -
 -/* rv515 */
 -struct rv515_mc_save {
 -      u32 d1vga_control;
 -      u32 d2vga_control;
 -      u32 vga_render_control;
 -      u32 vga_hdp_control;
 -      u32 d1crtc_control;
 -      u32 d2crtc_control;
 -};
 -extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
 -extern void rv515_vga_render_disable(struct radeon_device *rdev);
 -extern void rv515_set_safe_registers(struct radeon_device *rdev);
 -extern void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save);
 -extern void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save);
 -extern void rv515_clock_startup(struct radeon_device *rdev);
 -extern void rv515_debugfs(struct radeon_device *rdev);
 -extern int rv515_suspend(struct radeon_device *rdev);
 -
 -/* rs400 */
 -extern int rs400_gart_init(struct radeon_device *rdev);
 -extern int rs400_gart_enable(struct radeon_device *rdev);
 -extern void rs400_gart_adjust_size(struct radeon_device *rdev);
 -extern void rs400_gart_disable(struct radeon_device *rdev);
 -extern void rs400_gart_fini(struct radeon_device *rdev);
 -
 -/* rs600 */
 -extern void rs600_set_safe_registers(struct radeon_device *rdev);
 -extern int rs600_irq_set(struct radeon_device *rdev);
 -extern void rs600_irq_disable(struct radeon_device *rdev);
 -
 -/* rs690, rs740 */
 -extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
 -                                      struct drm_display_mode *mode1,
 -                                      struct drm_display_mode *mode2);
 -
  /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
 -extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
  extern bool r600_card_posted(struct radeon_device *rdev);
  extern void r600_cp_stop(struct radeon_device *rdev);
  extern int r600_cp_start(struct radeon_device *rdev);
@@@ -1504,7 -1476,6 +1506,7 @@@ extern void r600_hdmi_setmode(struct dr
  extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
  extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
  
 +extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
  extern void r700_cp_stop(struct radeon_device *rdev);
  extern void r700_cp_fini(struct radeon_device *rdev);
  extern void evergreen_disable_interrupt_state(struct radeon_device *rdev);
@@@ -1512,9 -1483,6 +1514,9 @@@ extern int evergreen_irq_set(struct rad
  extern int evergreen_blit_init(struct radeon_device *rdev);
  extern void evergreen_blit_fini(struct radeon_device *rdev);
  
 +extern int ni_init_microcode(struct radeon_device *rdev);
 +extern int btc_mc_load_microcode(struct radeon_device *rdev);
 +
  /* radeon_acpi.c */ 
  #if defined(CONFIG_ACPI) 
  extern int radeon_acpi_init(struct radeon_device *rdev); 
@@@ -79,8 -79,8 +79,8 @@@ int radeon_gart_table_vram_alloc(struc
  
        if (rdev->gart.table.vram.robj == NULL) {
                r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
 -                                      true, RADEON_GEM_DOMAIN_VRAM,
 -                                      &rdev->gart.table.vram.robj);
 +                                   PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 +                                   &rdev->gart.table.vram.robj);
                if (r) {
                        return r;
                }
@@@ -149,8 -149,9 +149,9 @@@ void radeon_gart_unbind(struct radeon_d
        p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
        for (i = 0; i < pages; i++, p++) {
                if (rdev->gart.pages[p]) {
-                       pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
-                                      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                       if (!rdev->gart.ttm_alloced[p])
+                               pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
+                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                        rdev->gart.pages[p] = NULL;
                        rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
                        page_base = rdev->gart.pages_addr[p];
  }
  
  int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-                    int pages, struct page **pagelist)
+                    int pages, struct page **pagelist, dma_addr_t *dma_addr)
  {
        unsigned t;
        unsigned p;
        p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
  
        for (i = 0; i < pages; i++, p++) {
-               /* we need to support large memory configurations */
-               /* assume that unbind have already been call on the range */
-               rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i],
+               /* On TTM path, we only use the DMA API if TTM_PAGE_FLAG_DMA32
+                * is requested. */
+               if (dma_addr[i] != DMA_ERROR_CODE) {
+                       rdev->gart.ttm_alloced[p] = true;
+                       rdev->gart.pages_addr[p] = dma_addr[i];
+               } else {
+                       /* we need to support large memory configurations */
+                       /* assume that unbind have already been call on the range */
+                       rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i],
                                                        0, PAGE_SIZE,
                                                        PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
-                       /* FIXME: failed to map page (return -ENOMEM?) */
-                       radeon_gart_unbind(rdev, offset, pages);
-                       return -ENOMEM;
+                       if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
+                               /* FIXME: failed to map page (return -ENOMEM?) */
+                               radeon_gart_unbind(rdev, offset, pages);
+                               return -ENOMEM;
+                       }
                }
                rdev->gart.pages[p] = pagelist[i];
                page_base = rdev->gart.pages_addr[p];
@@@ -251,6 -259,12 +259,12 @@@ int radeon_gart_init(struct radeon_devi
                radeon_gart_fini(rdev);
                return -ENOMEM;
        }
+       rdev->gart.ttm_alloced = kzalloc(sizeof(bool) *
+                                        rdev->gart.num_cpu_pages, GFP_KERNEL);
+       if (rdev->gart.ttm_alloced == NULL) {
+               radeon_gart_fini(rdev);
+               return -ENOMEM;
+       }
        /* set GART entry to point to the dummy page by default */
        for (i = 0; i < rdev->gart.num_cpu_pages; i++) {
                rdev->gart.pages_addr[i] = rdev->dummy_page.addr;
@@@ -267,6 -281,8 +281,8 @@@ void radeon_gart_fini(struct radeon_dev
        rdev->gart.ready = false;
        kfree(rdev->gart.pages);
        kfree(rdev->gart.pages_addr);
+       kfree(rdev->gart.ttm_alloced);
        rdev->gart.pages = NULL;
        rdev->gart.pages_addr = NULL;
+       rdev->gart.ttm_alloced = NULL;
  }
@@@ -513,6 -513,7 +513,7 @@@ int radeon_ttm_init(struct radeon_devic
        if (r) {
                return r;
        }
+       rdev->mman.bdev.dev = rdev->dev;
        /* No others user of address space so set it to 0 */
        r = ttm_bo_device_init(&rdev->mman.bdev,
                               rdev->mman.bo_global_ref.ref.object,
                DRM_ERROR("Failed initializing VRAM heap.\n");
                return r;
        }
 -      r = radeon_bo_create(rdev, NULL, 256 * 1024, true,
 +      r = radeon_bo_create(rdev, NULL, 256 * 1024, PAGE_SIZE, true,
                                RADEON_GEM_DOMAIN_VRAM,
                                &rdev->stollen_vga_memory);
        if (r) {
@@@ -647,6 -648,7 +648,7 @@@ struct radeon_ttm_backend 
        unsigned long                   num_pages;
        struct page                     **pages;
        struct page                     *dummy_read_page;
+       dma_addr_t                      *dma_addrs;
        bool                            populated;
        bool                            bound;
        unsigned                        offset;
  static int radeon_ttm_backend_populate(struct ttm_backend *backend,
                                       unsigned long num_pages,
                                       struct page **pages,
-                                      struct page *dummy_read_page)
+                                      struct page *dummy_read_page,
+                                      dma_addr_t *dma_addrs)
  {
        struct radeon_ttm_backend *gtt;
  
        gtt = container_of(backend, struct radeon_ttm_backend, backend);
        gtt->pages = pages;
+       gtt->dma_addrs = dma_addrs;
        gtt->num_pages = num_pages;
        gtt->dummy_read_page = dummy_read_page;
        gtt->populated = true;
@@@ -673,6 -677,7 +677,7 @@@ static void radeon_ttm_backend_clear(st
  
        gtt = container_of(backend, struct radeon_ttm_backend, backend);
        gtt->pages = NULL;
+       gtt->dma_addrs = NULL;
        gtt->num_pages = 0;
        gtt->dummy_read_page = NULL;
        gtt->populated = false;
@@@ -693,7 -698,7 +698,7 @@@ static int radeon_ttm_backend_bind(stru
                     gtt->num_pages, bo_mem, backend);
        }
        r = radeon_gart_bind(gtt->rdev, gtt->offset,
-                            gtt->num_pages, gtt->pages);
+                            gtt->num_pages, gtt->pages, gtt->dma_addrs);
        if (r) {
                DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
                          gtt->num_pages, gtt->offset);
@@@ -322,7 -322,7 +322,7 @@@ static int vmw_driver_load(struct drm_d
        ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
        dev_priv->active_master = &dev_priv->fbdev_master;
  
+       dev_priv->bdev.dev = dev->dev;
        ret = ttm_bo_device_init(&dev_priv->bdev,
                                 dev_priv->bo_global_ref.ref.object,
                                 &vmw_bo_driver, VMWGFX_FILE_PAGE_OFFSET,
@@@ -909,6 -909,15 +909,6 @@@ static struct drm_driver driver = 
  #endif
                 .llseek = noop_llseek,
        },
 -      .pci_driver = {
 -               .name = VMWGFX_DRIVER_NAME,
 -               .id_table = vmw_pci_id_list,
 -               .probe = vmw_probe,
 -               .remove = vmw_remove,
 -               .driver = {
 -                       .pm = &vmw_pm_ops
 -               }
 -       },
        .name = VMWGFX_DRIVER_NAME,
        .desc = VMWGFX_DRIVER_DESC,
        .date = VMWGFX_DRIVER_DATE,
        .patchlevel = VMWGFX_DRIVER_PATCHLEVEL
  };
  
 +static struct pci_driver vmw_pci_driver = {
 +      .name = VMWGFX_DRIVER_NAME,
 +      .id_table = vmw_pci_id_list,
 +      .probe = vmw_probe,
 +      .remove = vmw_remove,
 +      .driver = {
 +              .pm = &vmw_pm_ops
 +      }
 +};
 +
  static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  {
        return drm_get_pci_dev(pdev, ent, &driver);
  static int __init vmwgfx_init(void)
  {
        int ret;
 -      ret = drm_init(&driver);
 +      ret = drm_pci_init(&driver, &vmw_pci_driver);
        if (ret)
                DRM_ERROR("Failed initializing DRM.\n");
        return ret;
  
  static void __exit vmwgfx_exit(void)
  {
 -      drm_exit(&driver);
 +      drm_pci_exit(&driver, &vmw_pci_driver);
  }
  
  module_init(vmwgfx_init);
@@@ -50,13 -50,15 +50,15 @@@ struct ttm_backend_func 
         * @pages: Array of pointers to ttm pages.
         * @dummy_read_page: Page to be used instead of NULL pages in the
         * array @pages.
+        * @dma_addrs: Array of DMA (bus) address of the ttm pages.
         *
         * Populate the backend with ttm pages. Depending on the backend,
         * it may or may not copy the @pages array.
         */
        int (*populate) (struct ttm_backend *backend,
                         unsigned long num_pages, struct page **pages,
-                        struct page *dummy_read_page);
+                        struct page *dummy_read_page,
+                        dma_addr_t *dma_addrs);
        /**
         * struct ttm_backend_func member clear
         *
@@@ -149,6 -151,7 +151,7 @@@ enum ttm_caching_state 
   * @swap_storage: Pointer to shmem struct file for swap storage.
   * @caching_state: The current caching state of the pages.
   * @state: The current binding state of the pages.
+  * @dma_address: The DMA (bus) addresses of the pages (if TTM_PAGE_FLAG_DMA32)
   *
   * This is a structure holding the pages, caching- and aperture binding
   * status for a buffer object that isn't backed by fixed (VRAM / AGP)
@@@ -173,12 -176,37 +176,13 @@@ struct ttm_tt 
                tt_unbound,
                tt_unpopulated,
        } state;
+       dma_addr_t *dma_address;
  };
  
  #define TTM_MEMTYPE_FLAG_FIXED         (1 << 0)       /* Fixed (on-card) PCI memory */
  #define TTM_MEMTYPE_FLAG_MAPPABLE      (1 << 1)       /* Memory mappable */
  #define TTM_MEMTYPE_FLAG_CMA           (1 << 3)       /* Can't map aperture */
  
 -/**
 - * struct ttm_mem_type_manager
 - *
 - * @has_type: The memory type has been initialized.
 - * @use_type: The memory type is enabled.
 - * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory
 - * managed by this memory type.
 - * @gpu_offset: If used, the GPU offset of the first managed page of
 - * fixed memory or the first managed location in an aperture.
 - * @size: Size of the managed region.
 - * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX,
 - * as defined in ttm_placement_common.h
 - * @default_caching: The default caching policy used for a buffer object
 - * placed in this memory type if the user doesn't provide one.
 - * @manager: The range manager used for this memory type. FIXME: If the aperture
 - * has a page size different from the underlying system, the granularity
 - * of this manager should take care of this. But the range allocating code
 - * in ttm_bo.c needs to be modified for this.
 - * @lru: The lru list for this memory type.
 - *
 - * This structure is used to identify and manage memory types for a device.
 - * It's set up by the ttm_bo_driver::init_mem_type method.
 - */
 -
  struct ttm_mem_type_manager;
  
  struct ttm_mem_type_manager_func {
        void (*debug)(struct ttm_mem_type_manager *man, const char *prefix);
  };
  
 +/**
 + * struct ttm_mem_type_manager
 + *
 + * @has_type: The memory type has been initialized.
 + * @use_type: The memory type is enabled.
 + * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory
 + * managed by this memory type.
 + * @gpu_offset: If used, the GPU offset of the first managed page of
 + * fixed memory or the first managed location in an aperture.
 + * @size: Size of the managed region.
 + * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX,
 + * as defined in ttm_placement_common.h
 + * @default_caching: The default caching policy used for a buffer object
 + * placed in this memory type if the user doesn't provide one.
 + * @func: structure pointer implementing the range manager. See above
 + * @priv: Driver private closure for @func.
 + * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures
 + * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions
 + * reserved by the TTM vm system.
 + * @io_reserve_lru: Optional lru list for unreserving io mem regions.
 + * @io_reserve_fastpath: Only use bdev::driver::io_mem_reserve to obtain
 + * static information. bdev::driver::io_mem_free is never used.
 + * @lru: The lru list for this memory type.
 + *
 + * This structure is used to identify and manage memory types for a device.
 + * It's set up by the ttm_bo_driver::init_mem_type method.
 + */
 +
 +
 +
  struct ttm_mem_type_manager {
        struct ttm_bo_device *bdev;
  
        uint32_t default_caching;
        const struct ttm_mem_type_manager_func *func;
        void *priv;
 +      struct mutex io_reserve_mutex;
 +      bool use_io_reserve_lru;
 +      bool io_reserve_fastpath;
 +
 +      /*
 +       * Protected by @io_reserve_mutex:
 +       */
 +
 +      struct list_head io_reserve_lru;
  
        /*
         * Protected by the global->lru_lock.
@@@ -525,12 -514,9 +529,12 @@@ struct ttm_bo_global 
   *
   * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver.
   * @man: An array of mem_type_managers.
 + * @fence_lock: Protects the synchronizing members on *all* bos belonging
 + * to this device.
   * @addr_space_mm: Range manager for the device address space.
   * lru_lock: Spinlock that protects the buffer+device lru lists and
   * ddestroy lists.
 + * @val_seq: Current validation sequence.
   * @nice_mode: Try nicely to wait for buffer idle when cleaning a manager.
   * If a GPU lockup has been detected, this is forced to 0.
   * @dev_mapping: A pointer to the struct address_space representing the
@@@ -547,9 -533,9 +551,10 @@@ struct ttm_bo_device 
        struct list_head device_list;
        struct ttm_bo_global *glob;
        struct ttm_bo_driver *driver;
+       struct device *dev;
        rwlock_t vm_lock;
        struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES];
 +      spinlock_t fence_lock;
        /*
         * Protected by the vm lock.
         */
         * Protected by the global:lru lock.
         */
        struct list_head ddestroy;
 +      uint32_t val_seq;
  
        /*
         * Protected by load / firstopen / lastclose /unload sync.
@@@ -773,6 -758,31 +778,6 @@@ extern void ttm_bo_mem_put_locked(struc
  
  extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait);
  
 -/**
 - * ttm_bo_pci_offset - Get the PCI offset for the buffer object memory.
 - *
 - * @bo Pointer to a struct ttm_buffer_object.
 - * @bus_base On return the base of the PCI region
 - * @bus_offset On return the byte offset into the PCI region
 - * @bus_size On return the byte size of the buffer object or zero if
 - * the buffer object memory is not accessible through a PCI region.
 - *
 - * Returns:
 - * -EINVAL if the buffer object is currently not mappable.
 - * 0 otherwise.
 - */
 -
 -extern int ttm_bo_pci_offset(struct ttm_bo_device *bdev,
 -                           struct ttm_mem_reg *mem,
 -                           unsigned long *bus_base,
 -                           unsigned long *bus_offset,
 -                           unsigned long *bus_size);
 -
 -extern int ttm_mem_io_reserve(struct ttm_bo_device *bdev,
 -                              struct ttm_mem_reg *mem);
 -extern void ttm_mem_io_free(struct ttm_bo_device *bdev,
 -                              struct ttm_mem_reg *mem);
 -
  extern void ttm_bo_global_release(struct drm_global_reference *ref);
  extern int ttm_bo_global_init(struct drm_global_reference *ref);
  
@@@ -804,22 -814,6 +809,22 @@@ extern int ttm_bo_device_init(struct tt
   */
  extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo);
  
 +/**
 + * ttm_bo_unmap_virtual
 + *
 + * @bo: tear down the virtual mappings for this BO
 + *
 + * The caller must take ttm_mem_io_lock before calling this function.
 + */
 +extern void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo);
 +
 +extern int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo);
 +extern void ttm_mem_io_free_vm(struct ttm_buffer_object *bo);
 +extern int ttm_mem_io_lock(struct ttm_mem_type_manager *man,
 +                         bool interruptible);
 +extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
 +
 +
  /**
   * ttm_bo_reserve:
   *
   * try again. (only if use_sequence == 1).
   * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
   * a signal. Release all buffer reservations and return to user-space.
 + * -EBUSY: The function needed to sleep, but @no_wait was true
 + * -EDEADLK: Bo already reserved using @sequence. This error code will only
 + * be returned if @use_sequence is set to true.
   */
  extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
                          bool interruptible,
                          bool no_wait, bool use_sequence, uint32_t sequence);
  
 +
 +/**
 + * ttm_bo_reserve_locked:
 + *
 + * @bo: A pointer to a struct ttm_buffer_object.
 + * @interruptible: Sleep interruptible if waiting.
 + * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY.
 + * @use_sequence: If @bo is already reserved, Only sleep waiting for
 + * it to become unreserved if @sequence < (@bo)->sequence.
 + *
 + * Must be called with struct ttm_bo_global::lru_lock held,
 + * and will not remove reserved buffers from the lru lists.
 + * The function may release the LRU spinlock if it needs to sleep.
 + * Otherwise identical to ttm_bo_reserve.
 + *
 + * Returns:
 + * -EAGAIN: The reservation may cause a deadlock.
 + * Release all buffer reservations, wait for @bo to become unreserved and
 + * try again. (only if use_sequence == 1).
 + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
 + * a signal. Release all buffer reservations and return to user-space.
 + * -EBUSY: The function needed to sleep, but @no_wait was true
 + * -EDEADLK: Bo already reserved using @sequence. This error code will only
 + * be returned if @use_sequence is set to true.
 + */
 +extern int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
 +                               bool interruptible,
 +                               bool no_wait, bool use_sequence,
 +                               uint32_t sequence);
 +
  /**
   * ttm_bo_unreserve
   *
   */
  extern void ttm_bo_unreserve(struct ttm_buffer_object *bo);
  
 +/**
 + * ttm_bo_unreserve_locked
 + *
 + * @bo: A pointer to a struct ttm_buffer_object.
 + *
 + * Unreserve a previous reservation of @bo.
 + * Needs to be called with struct ttm_bo_global::lru_lock held.
 + */
 +extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo);
 +
  /**
   * ttm_bo_wait_unreserved
   *