Merge branch 'drm-next-3.18' of git://people.freedesktop.org/~agd5f/linux into drm...
authorDave Airlie <airlied@redhat.com>
Mon, 25 Aug 2014 23:05:14 +0000 (09:05 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 25 Aug 2014 23:05:14 +0000 (09:05 +1000)
radeon userptr support.

* 'drm-next-3.18' of git://people.freedesktop.org/~agd5f/linux:
  drm/radeon: allow userptr write access under certain conditions
  drm/radeon: add userptr flag to register MMU notifier v3
  drm/radeon: add userptr flag to directly validate the BO to GTT
  drm/radeon: add userptr flag to limit it to anonymous memory v2
  drm/radeon: add userptr support v8

Conflicts:
drivers/gpu/drm/radeon/radeon_prime.c

1  2 
drivers/gpu/drm/Kconfig
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_prime.c
drivers/gpu/drm/radeon/radeon_vm.c
include/uapi/drm/radeon_drm.h

diff --combined drivers/gpu/drm/Kconfig
index e251ecce4ed2cffff4af77a4e8d17a404f068439,358b6e8697e9ce5368e99cda7f10178e39f24c10..e3500f9584ec60728ea4c3c80da61a4e9fbf560e
@@@ -8,7 -8,6 +8,7 @@@ menuconfig DR
        tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
        select HDMI
 +      select FB_CMDLINE
        select I2C
        select I2C_ALGOBIT
        select DMA_SHARED_BUFFER
@@@ -116,6 -115,7 +116,7 @@@ config DRM_RADEO
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
        select INTERVAL_TREE
+       select MMU_NOTIFIER
        help
          Choose this option if you have an ATI Radeon graphics card.  There
          are both PCI and AGP versions.  You don't need to choose this to
index f77b7135ee4cde8e07b96c619f0bca8f94cdc37b,c7fa1aeb8c3facf6cf9f32421a20d5b3b118d79c..357f09afd2222dc064a7c0f53b05c2d0807ec8b8
@@@ -76,11 -76,11 +76,11 @@@ radeon-y += radeon_device.o radeon_asic
        evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
        evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
        atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
 -      si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
 +      si_blit_shaders.o radeon_prime.o cik.o cik_blit_shaders.o \
        r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
        rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
        trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
-       ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o
+       ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o
  
  # add async DMA block
  radeon-y += \
index b281886f6f5194609caab9bddb632eadea191004,542da820867407fa5ae7ed4ede455c951c8de5d1..b321ad4dcafd1c78fea6c3cf29512c1004a3e4a9
@@@ -65,6 -65,7 +65,7 @@@
  #include <linux/list.h>
  #include <linux/kref.h>
  #include <linux/interval_tree.h>
+ #include <linux/hashtable.h>
  
  #include <ttm/ttm_bo_api.h>
  #include <ttm/ttm_bo_driver.h>
@@@ -105,7 -106,6 +106,7 @@@ extern int radeon_vm_size
  extern int radeon_vm_block_size;
  extern int radeon_deep_color;
  extern int radeon_use_pflipirq;
 +extern int radeon_bapm;
  
  /*
   * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@@ -488,6 -488,9 +489,9 @@@ struct radeon_bo 
  
        struct ttm_bo_kmap_obj          dma_buf_vmap;
        pid_t                           pid;
+       struct radeon_mn                *mn;
+       struct interval_tree_node       mn_it;
  };
  #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
  
@@@ -968,7 -971,7 +972,7 @@@ int radeon_ib_get(struct radeon_device 
                  unsigned size);
  void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib);
  int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
 -                     struct radeon_ib *const_ib);
 +                     struct radeon_ib *const_ib, bool hdp_flush);
  int radeon_ib_pool_init(struct radeon_device *rdev);
  void radeon_ib_pool_fini(struct radeon_device *rdev);
  int radeon_ib_ring_tests(struct radeon_device *rdev);
@@@ -978,10 -981,8 +982,10 @@@ bool radeon_ring_supports_scratch_reg(s
  void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp);
  int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
  int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
 -void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp);
 -void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp);
 +void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp,
 +                      bool hdp_flush);
 +void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp,
 +                             bool hdp_flush);
  void radeon_ring_undo(struct radeon_ring *ring);
  void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
  int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
@@@ -1728,6 -1729,11 +1732,11 @@@ void radeon_test_ring_sync(struct radeo
                           struct radeon_ring *cpB);
  void radeon_test_syncing(struct radeon_device *rdev);
  
+ /*
+  * MMU Notifier
+  */
+ int radeon_mn_register(struct radeon_bo *bo, unsigned long addr);
+ void radeon_mn_unregister(struct radeon_bo *bo);
  
  /*
   * Debugfs
@@@ -2141,6 -2147,8 +2150,8 @@@ int radeon_gem_info_ioctl(struct drm_de
                          struct drm_file *filp);
  int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
                            struct drm_file *filp);
+ int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *filp);
  int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
  int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
@@@ -2373,6 -2381,9 +2384,9 @@@ struct radeon_device 
        /* tracking pinned memory */
        u64 vram_pin_size;
        u64 gart_pin_size;
+       struct mutex    mn_lock;
+       DECLARE_HASHTABLE(mn_hash, 7);
  };
  
  bool radeon_is_px(struct drm_device *dev);
@@@ -2874,6 -2885,10 +2888,10 @@@ extern void radeon_legacy_set_clock_gat
  extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
  extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
  extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
+ extern int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,
+                                    uint32_t flags);
+ extern bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm);
+ extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm);
  extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
  extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
  extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
index 83f382e8e40e35cb380d4fc6fd835a7ddac9c01a,1321491cf4992a7adc170ee957ac1b2be19285b3..0669399efceac2ef3afc67e855a56ae7c90ec5e1
@@@ -78,7 -78,8 +78,8 @@@ static int radeon_cs_parser_relocs(stru
        struct radeon_cs_chunk *chunk;
        struct radeon_cs_buckets buckets;
        unsigned i, j;
-       bool duplicate;
+       bool duplicate, need_mmap_lock = false;
+       int r;
  
        if (p->chunk_relocs_idx == -1) {
                return 0;
                 * the buffers used for read only, which doubles the range
                 * to 0 to 31. 32 is reserved for the kernel driver.
                 */
 -              priority = (r->flags & 0xf) * 2 + !!r->write_domain;
 +              priority = (r->flags & RADEON_RELOC_PRIO_MASK) * 2
 +                         + !!r->write_domain;
  
                /* the first reloc of an UVD job is the msg and that must be in
                   VRAM, also but everything into VRAM on AGP cards to avoid
                        p->relocs[i].allowed_domains = domain;
                }
  
+               if (radeon_ttm_tt_has_userptr(p->relocs[i].robj->tbo.ttm)) {
+                       uint32_t domain = p->relocs[i].prefered_domains;
+                       if (!(domain & RADEON_GEM_DOMAIN_GTT)) {
+                               DRM_ERROR("Only RADEON_GEM_DOMAIN_GTT is "
+                                         "allowed for userptr BOs\n");
+                               return -EINVAL;
+                       }
+                       need_mmap_lock = true;
+                       domain = RADEON_GEM_DOMAIN_GTT;
+                       p->relocs[i].prefered_domains = domain;
+                       p->relocs[i].allowed_domains = domain;
+               }
                p->relocs[i].tv.bo = &p->relocs[i].robj->tbo;
                p->relocs[i].handle = r->handle;
  
        if (p->cs_flags & RADEON_CS_USE_VM)
                p->vm_bos = radeon_vm_get_bos(p->rdev, p->ib.vm,
                                              &p->validated);
+       if (need_mmap_lock)
+               down_read(&current->mm->mmap_sem);
+       r = radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring);
+       if (need_mmap_lock)
+               up_read(&current->mm->mmap_sem);
  
-       return radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring);
+       return r;
  }
  
  static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
@@@ -451,7 -471,7 +472,7 @@@ static int radeon_cs_ib_chunk(struct ra
                radeon_vce_note_usage(rdev);
  
        radeon_cs_sync_rings(parser);
 -      r = radeon_ib_schedule(rdev, &parser->ib, NULL);
 +      r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
        if (r) {
                DRM_ERROR("Failed to schedule IB !\n");
        }
@@@ -542,9 -562,9 +563,9 @@@ static int radeon_cs_ib_vm_chunk(struc
  
        if ((rdev->family >= CHIP_TAHITI) &&
            (parser->chunk_const_ib_idx != -1)) {
 -              r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib);
 +              r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib, true);
        } else {
 -              r = radeon_ib_schedule(rdev, &parser->ib, NULL);
 +              r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
        }
  
  out:
index 6a219bcee66d2d8a5d7b8bf49f2344584a0a36fd,c58f84f3c6a5a28f62d0b688725f8e9954ec5a25..a5d202a7c0a487932cd86b47ee4405b5f537a61c
@@@ -1270,6 -1270,8 +1270,8 @@@ int radeon_device_init(struct radeon_de
        init_rwsem(&rdev->pm.mclk_lock);
        init_rwsem(&rdev->exclusive_lock);
        init_waitqueue_head(&rdev->irq.vblank_queue);
+       mutex_init(&rdev->mn_lock);
+       hash_init(rdev->mn_hash);
        r = radeon_gem_init(rdev);
        if (r)
                return r;
@@@ -1680,8 -1682,8 +1682,8 @@@ int radeon_gpu_reset(struct radeon_devi
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
 -      radeon_pm_suspend(rdev);
        radeon_suspend(rdev);
 +      radeon_hpd_fini(rdev);
  
        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
                ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i],
@@@ -1726,39 -1728,9 +1728,39 @@@ retry
                }
        }
  
 -      radeon_pm_resume(rdev);
 +      if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
 +              /* do dpm late init */
 +              r = radeon_pm_late_init(rdev);
 +              if (r) {
 +                      rdev->pm.dpm_enabled = false;
 +                      DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
 +              }
 +      } else {
 +              /* resume old pm late */
 +              radeon_pm_resume(rdev);
 +      }
 +
 +      /* init dig PHYs, disp eng pll */
 +      if (rdev->is_atom_bios) {
 +              radeon_atom_encoder_init(rdev);
 +              radeon_atom_disp_eng_pll_init(rdev);
 +              /* turn on the BL */
 +              if (rdev->mode_info.bl_encoder) {
 +                      u8 bl_level = radeon_get_backlight_level(rdev,
 +                                                               rdev->mode_info.bl_encoder);
 +                      radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder,
 +                                                 bl_level);
 +              }
 +      }
 +      /* reset hpd state */
 +      radeon_hpd_init(rdev);
 +
        drm_helper_resume_force_mode(rdev->ddev);
  
 +      /* set the power state here in case we are a PX system or headless */
 +      if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
 +              radeon_pm_compute_clocks(rdev);
 +
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
        if (r) {
                /* bad news, how to tell it to userspace ? */
index 8df888908833f5d1a3e8d9f745edb5fe9b6143ea,5b18af926527814701a07efb8cf9212dc097b3a9..f1e96e094b00d52808e3c58da5a641909b4ba126
@@@ -114,6 -114,9 +114,9 @@@ int radeon_gem_object_open(struct drm_g
                                struct drm_file *file_priv);
  void radeon_gem_object_close(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
+ struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
+                                       struct drm_gem_object *gobj,
+                                       int flags);
  extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
                                      unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
@@@ -134,7 -137,6 +137,7 @@@ struct drm_gem_object *radeon_gem_prime
                                                        struct sg_table *sg);
  int radeon_gem_prime_pin(struct drm_gem_object *obj);
  void radeon_gem_prime_unpin(struct drm_gem_object *obj);
 +struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *);
  void *radeon_gem_prime_vmap(struct drm_gem_object *obj);
  void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
  extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd,
@@@ -180,7 -182,6 +183,7 @@@ int radeon_vm_size = 8
  int radeon_vm_block_size = -1;
  int radeon_deep_color = 0;
  int radeon_use_pflipirq = 2;
 +int radeon_bapm = -1;
  
  MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
  module_param_named(no_wb, radeon_no_wb, int, 0444);
@@@ -260,9 -261,6 +263,9 @@@ module_param_named(deep_color, radeon_d
  MODULE_PARM_DESC(use_pflipirq, "Pflip irqs for pageflip completion (0 = disable, 1 = as fallback, 2 = exclusive (default))");
  module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444);
  
 +MODULE_PARM_DESC(bapm, "BAPM support (1 = enable, 0 = disable, -1 = auto)");
 +module_param_named(bapm, radeon_bapm, int, 0444);
 +
  static struct pci_device_id pciidlist[] = {
        radeon_PCI_IDS
  };
@@@ -573,11 -571,10 +576,11 @@@ static struct drm_driver kms_driver = 
  
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = drm_gem_prime_export,
+       .gem_prime_export = radeon_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = radeon_gem_prime_pin,
        .gem_prime_unpin = radeon_gem_prime_unpin,
 +      .gem_prime_res_obj = radeon_gem_prime_res_obj,
        .gem_prime_get_sg_table = radeon_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
        .gem_prime_vmap = radeon_gem_prime_vmap,
index 0b16f2cbcf170b5a9a6d23b6683eedb827b890b4,bb18bc74b7d7d0a64bd6b596030b18ce48b92d92..d5414d42e44bf743fa289557af93bc5f02702b97
@@@ -104,10 -104,12 +104,20 @@@ void radeon_gem_prime_unpin(struct drm_
        radeon_bo_unreserve(bo);
  }
  
 +
 +struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj)
 +{
 +      struct radeon_bo *bo = gem_to_radeon_bo(obj);
 +
 +      return bo->tbo.resv;
 +}
++
+ struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
+                                       struct drm_gem_object *gobj,
+                                       int flags)
+ {
+       struct radeon_bo *bo = gem_to_radeon_bo(gobj);
+       if (radeon_ttm_tt_has_userptr(bo->tbo.ttm))
+               return ERR_PTR(-EPERM);
+       return drm_gem_prime_export(dev, gobj, flags);
+ }
index 088ffdc2f577c06519e2a31bc90bbd402c940125,0e107c5650bffcf09e7f6de141e8cb2f1734f46e..4751c6728fe9fffd2261596877754a85ffc96b1d
@@@ -420,7 -420,7 +420,7 @@@ static int radeon_vm_clear_bo(struct ra
        radeon_asic_vm_pad_ib(rdev, &ib);
        WARN_ON(ib.length_dw > 64);
  
 -      r = radeon_ib_schedule(rdev, &ib, NULL);
 +      r = radeon_ib_schedule(rdev, &ib, NULL, false);
        if (r)
                  goto error;
  
@@@ -483,10 -483,6 +483,10 @@@ int radeon_vm_bo_set_addr(struct radeon
                        /* add a clone of the bo_va to clear the old address */
                        struct radeon_bo_va *tmp;
                        tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
 +                      if (!tmp) {
 +                              mutex_unlock(&vm->mutex);
 +                              return -ENOMEM;
 +                      }
                        tmp->it.start = bo_va->it.start;
                        tmp->it.last = bo_va->it.last;
                        tmp->vm = vm;
@@@ -697,7 -693,7 +697,7 @@@ int radeon_vm_update_page_directory(str
                radeon_semaphore_sync_to(ib.semaphore, pd->tbo.sync_obj);
                radeon_semaphore_sync_to(ib.semaphore, vm->last_id_use);
                WARN_ON(ib.length_dw > ndw);
 -              r = radeon_ib_schedule(rdev, &ib, NULL);
 +              r = radeon_ib_schedule(rdev, &ib, NULL, false);
                if (r) {
                        radeon_ib_free(rdev, &ib);
                        return r;
@@@ -892,6 -888,9 +892,9 @@@ int radeon_vm_bo_update(struct radeon_d
        bo_va->flags &= ~RADEON_VM_PAGE_VALID;
        bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM;
        bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED;
+       if (bo_va->bo && radeon_ttm_tt_is_readonly(bo_va->bo->tbo.ttm))
+               bo_va->flags &= ~RADEON_VM_PAGE_WRITEABLE;
        if (mem) {
                addr = mem->start << PAGE_SHIFT;
                if (mem->mem_type != TTM_PL_SYSTEM) {
        WARN_ON(ib.length_dw > ndw);
  
        radeon_semaphore_sync_to(ib.semaphore, vm->fence);
 -      r = radeon_ib_schedule(rdev, &ib, NULL);
 +      r = radeon_ib_schedule(rdev, &ib, NULL, false);
        if (r) {
                radeon_ib_free(rdev, &ib);
                return r;
index fea6099608ef2244d2020fbf5dcfac3c7d886d91,c77495ffc44f26b8afc5a6c36b47334a002cf678..375b6e656c546eb281706b5a63d72c4585ccde49
@@@ -511,6 -511,7 +511,7 @@@ typedef struct 
  #define DRM_RADEON_GEM_BUSY           0x2a
  #define DRM_RADEON_GEM_VA             0x2b
  #define DRM_RADEON_GEM_OP             0x2c
+ #define DRM_RADEON_GEM_USERPTR                0x2d
  
  #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
  #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
  #define DRM_IOCTL_RADEON_GEM_BUSY     DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy)
  #define DRM_IOCTL_RADEON_GEM_VA               DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va)
  #define DRM_IOCTL_RADEON_GEM_OP               DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_OP, struct drm_radeon_gem_op)
+ #define DRM_IOCTL_RADEON_GEM_USERPTR  DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_USERPTR, struct drm_radeon_gem_userptr)
  
  typedef struct drm_radeon_init {
        enum {
@@@ -808,6 -810,23 +810,23 @@@ struct drm_radeon_gem_create 
        uint32_t        flags;
  };
  
+ /*
+  * This is not a reliable API and you should expect it to fail for any
+  * number of reasons and have fallback path that do not use userptr to
+  * perform any operation.
+  */
+ #define RADEON_GEM_USERPTR_READONLY   (1 << 0)
+ #define RADEON_GEM_USERPTR_ANONONLY   (1 << 1)
+ #define RADEON_GEM_USERPTR_VALIDATE   (1 << 2)
+ #define RADEON_GEM_USERPTR_REGISTER   (1 << 3)
+ struct drm_radeon_gem_userptr {
+       uint64_t                addr;
+       uint64_t                size;
+       uint32_t                flags;
+       uint32_t                handle;
+ };
  #define RADEON_TILING_MACRO                           0x1
  #define RADEON_TILING_MICRO                           0x2
  #define RADEON_TILING_SWAP_16BIT                      0x4
@@@ -944,7 -963,6 +963,7 @@@ struct drm_radeon_cs_chunk 
  };
  
  /* drm_radeon_cs_reloc.flags */
 +#define RADEON_RELOC_PRIO_MASK                (0xf << 0)
  
  struct drm_radeon_cs_reloc {
        uint32_t                handle;