[PATCH 4/5] drm/radeon: add userptr flag to register MMU notifier v3

2014-08-07 Thread Christian König
From: Christian K?nig 

Whenever userspace mapping related to our userptr change
we wait for it to become idle and unmap it from GTT.

v2: rebased, fix mutex unlock in error path
v3: improve commit message

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/Kconfig|   1 +
 drivers/gpu/drm/radeon/Makefile|   2 +-
 drivers/gpu/drm/radeon/radeon.h|  12 ++
 drivers/gpu/drm/radeon/radeon_device.c |   2 +
 drivers/gpu/drm/radeon/radeon_gem.c|   9 +-
 drivers/gpu/drm/radeon/radeon_mn.c | 272 +
 drivers/gpu/drm/radeon/radeon_object.c |   1 +
 include/uapi/drm/radeon_drm.h  |   1 +
 8 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/radeon_mn.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b066bb3..358b6e8 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -115,6 +115,7 @@ config DRM_RADEON
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
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 0013ad0..c7fa1ae 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.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 += \
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 6f38a23..542da82 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -65,6 +65,7 @@
 #include 
 #include 
 #include 
+#include 

 #include 
 #include 
@@ -487,6 +488,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)

@@ -1725,6 +1729,11 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
   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
@@ -2372,6 +2381,9 @@ struct radeon_device {
/* tracking pinned memory */
u64 vram_pin_size;
u64 gart_pin_size;
+
+   struct mutexmn_lock;
+   DECLARE_HASHTABLE(mn_hash, 7);
 };

 bool radeon_is_px(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index c8ea050..c58f84f 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1270,6 +1270,8 @@ int radeon_device_init(struct radeon_device *rdev,
init_rwsem(>pm.mclk_lock);
init_rwsem(>exclusive_lock);
init_waitqueue_head(>irq.vblank_queue);
+   mutex_init(>mn_lock);
+   hash_init(rdev->mn_hash);
r = radeon_gem_init(rdev);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index 4506560..2a6fbf1 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -291,7 +291,8 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
*data,

/* reject unknown flag values */
if (args->flags & ~(RADEON_GEM_USERPTR_READONLY |
-   RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE))
+   RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE |
+   RADEON_GEM_USERPTR_REGISTER))
return -EINVAL;

/* readonly pages not tested on older hardware */
@@ -312,6 +313,12 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
*data,
if (r)
goto release_object;

+   if (args->flags & RADEON_GEM_USERPTR_REGISTER) {
+   r = radeon_mn_register(bo, args->addr);
+   if (r)
+   goto release_object;
+   }
+
if (args->flags & RADEON_GEM_USERPTR_VALIDATE) {
down_read(>mm->mmap_sem);
r = radeon_bo_reserve(bo, true);
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c 
b/drivers/gpu/drm/radeon/radeon_mn.c
new file mode 100644
index 000..0157bc2
--- /dev/null
+++ 

[PATCH 4/5] drm/radeon: add userptr flag to register MMU notifier v3

2014-08-06 Thread Christian König
Am 06.08.2014 um 17:16 schrieb Jerome Glisse:
> On Tue, Aug 05, 2014 at 06:05:31PM +0200, Christian K?nig wrote:
>> From: Christian K?nig 
>>
>> Whenever userspace mapping related to our userptr change
>> we wait for it to become idle and unmap it from GTT.
>>
>> v2: rebased, fix mutex unlock in error path
>> v3: improve commit message
> Why in hell do you not register the mmu_notifier on first userptr bo ?
The MMU notifier is registered on the first userptr bo that uses it.

Using the notifier is only optional for readonly BOs because it has 
quite an overhead and most uses of userptr are snapshot like uses 
anyway. E.g. buffer uploads that just needs the data from that user 
address at a specific point in time and are not interested in further 
updates are created without registering the notifier.

Christian.

>
>> Signed-off-by: Christian K?nig 
>> ---
>>   drivers/gpu/drm/Kconfig|   1 +
>>   drivers/gpu/drm/radeon/Makefile|   2 +-
>>   drivers/gpu/drm/radeon/radeon.h|  12 ++
>>   drivers/gpu/drm/radeon/radeon_device.c |   2 +
>>   drivers/gpu/drm/radeon/radeon_gem.c|   9 +-
>>   drivers/gpu/drm/radeon/radeon_mn.c | 272 
>> +
>>   drivers/gpu/drm/radeon/radeon_object.c |   1 +
>>   include/uapi/drm/radeon_drm.h  |   1 +
>>   8 files changed, 298 insertions(+), 2 deletions(-)
>>   create mode 100644 drivers/gpu/drm/radeon/radeon_mn.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index 9b2eedc..2745284 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -115,6 +115,7 @@ config DRM_RADEON
>>  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
>> diff --git a/drivers/gpu/drm/radeon/Makefile 
>> b/drivers/gpu/drm/radeon/Makefile
>> index 0013ad0..c7fa1ae 100644
>> --- a/drivers/gpu/drm/radeon/Makefile
>> +++ b/drivers/gpu/drm/radeon/Makefile
>> @@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.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 += \
>> diff --git a/drivers/gpu/drm/radeon/radeon.h 
>> b/drivers/gpu/drm/radeon/radeon.h
>> index 3c6999e..511191f 100644
>> --- a/drivers/gpu/drm/radeon/radeon.h
>> +++ b/drivers/gpu/drm/radeon/radeon.h
>> @@ -65,6 +65,7 @@
>>   #include 
>>   #include 
>>   #include 
>> +#include 
>>   
>>   #include 
>>   #include 
>> @@ -487,6 +488,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)
>>   
>> @@ -1725,6 +1729,11 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
>> 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
>> @@ -2372,6 +2381,9 @@ struct radeon_device {
>>  /* tracking pinned memory */
>>  u64 vram_pin_size;
>>  u64 gart_pin_size;
>> +
>> +struct mutexmn_lock;
>> +DECLARE_HASHTABLE(mn_hash, 7);
>>   };
>>   
>>   bool radeon_is_px(struct drm_device *dev);
>> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
>> b/drivers/gpu/drm/radeon/radeon_device.c
>> index c8ea050..c58f84f 100644
>> --- a/drivers/gpu/drm/radeon/radeon_device.c
>> +++ b/drivers/gpu/drm/radeon/radeon_device.c
>> @@ -1270,6 +1270,8 @@ int radeon_device_init(struct radeon_device *rdev,
>>  init_rwsem(>pm.mclk_lock);
>>  init_rwsem(>exclusive_lock);
>>  init_waitqueue_head(>irq.vblank_queue);
>> +mutex_init(>mn_lock);
>> +hash_init(rdev->mn_hash);
>>  r = radeon_gem_init(rdev);
>>  if (r)
>>  return r;
>> diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
>> b/drivers/gpu/drm/radeon/radeon_gem.c
>> index 4506560..2a6fbf1 100644
>> --- a/drivers/gpu/drm/radeon/radeon_gem.c
>> +++ b/drivers/gpu/drm/radeon/radeon_gem.c
>> @@ -291,7 +291,8 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, 
>> void *data,
>>   
>>  /* reject unknown flag values */
>>  if (args->flags & ~(RADEON_GEM_USERPTR_READONLY |
>> -

[PATCH 4/5] drm/radeon: add userptr flag to register MMU notifier v3

2014-08-06 Thread Jerome Glisse
On Tue, Aug 05, 2014 at 06:05:31PM +0200, Christian K?nig wrote:
> From: Christian K?nig 
> 
> Whenever userspace mapping related to our userptr change
> we wait for it to become idle and unmap it from GTT.
> 
> v2: rebased, fix mutex unlock in error path
> v3: improve commit message

Why in hell do you not register the mmu_notifier on first userptr bo ?

> 
> Signed-off-by: Christian K?nig 
> ---
>  drivers/gpu/drm/Kconfig|   1 +
>  drivers/gpu/drm/radeon/Makefile|   2 +-
>  drivers/gpu/drm/radeon/radeon.h|  12 ++
>  drivers/gpu/drm/radeon/radeon_device.c |   2 +
>  drivers/gpu/drm/radeon/radeon_gem.c|   9 +-
>  drivers/gpu/drm/radeon/radeon_mn.c | 272 
> +
>  drivers/gpu/drm/radeon/radeon_object.c |   1 +
>  include/uapi/drm/radeon_drm.h  |   1 +
>  8 files changed, 298 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/radeon/radeon_mn.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 9b2eedc..2745284 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -115,6 +115,7 @@ config DRM_RADEON
>   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
> diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
> index 0013ad0..c7fa1ae 100644
> --- a/drivers/gpu/drm/radeon/Makefile
> +++ b/drivers/gpu/drm/radeon/Makefile
> @@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.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 += \
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 3c6999e..511191f 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -65,6 +65,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -487,6 +488,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)
>  
> @@ -1725,6 +1729,11 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
>  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
> @@ -2372,6 +2381,9 @@ struct radeon_device {
>   /* tracking pinned memory */
>   u64 vram_pin_size;
>   u64 gart_pin_size;
> +
> + struct mutexmn_lock;
> + DECLARE_HASHTABLE(mn_hash, 7);
>  };
>  
>  bool radeon_is_px(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index c8ea050..c58f84f 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -1270,6 +1270,8 @@ int radeon_device_init(struct radeon_device *rdev,
>   init_rwsem(>pm.mclk_lock);
>   init_rwsem(>exclusive_lock);
>   init_waitqueue_head(>irq.vblank_queue);
> + mutex_init(>mn_lock);
> + hash_init(rdev->mn_hash);
>   r = radeon_gem_init(rdev);
>   if (r)
>   return r;
> diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
> b/drivers/gpu/drm/radeon/radeon_gem.c
> index 4506560..2a6fbf1 100644
> --- a/drivers/gpu/drm/radeon/radeon_gem.c
> +++ b/drivers/gpu/drm/radeon/radeon_gem.c
> @@ -291,7 +291,8 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
> *data,
>  
>   /* reject unknown flag values */
>   if (args->flags & ~(RADEON_GEM_USERPTR_READONLY |
> - RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE))
> + RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE |
> + RADEON_GEM_USERPTR_REGISTER))
>   return -EINVAL;
>  
>   /* readonly pages not tested on older hardware */
> @@ -312,6 +313,12 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, 
> void *data,
>   if (r)
>   goto release_object;
>  
> + if (args->flags & RADEON_GEM_USERPTR_REGISTER) {
> + r = radeon_mn_register(bo, args->addr);
> + if (r)
> + goto release_object;
> + }
> 

[PATCH 4/5] drm/radeon: add userptr flag to register MMU notifier v3

2014-08-05 Thread Christian König
From: Christian K?nig 

Whenever userspace mapping related to our userptr change
we wait for it to become idle and unmap it from GTT.

v2: rebased, fix mutex unlock in error path
v3: improve commit message

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/Kconfig|   1 +
 drivers/gpu/drm/radeon/Makefile|   2 +-
 drivers/gpu/drm/radeon/radeon.h|  12 ++
 drivers/gpu/drm/radeon/radeon_device.c |   2 +
 drivers/gpu/drm/radeon/radeon_gem.c|   9 +-
 drivers/gpu/drm/radeon/radeon_mn.c | 272 +
 drivers/gpu/drm/radeon/radeon_object.c |   1 +
 include/uapi/drm/radeon_drm.h  |   1 +
 8 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/radeon_mn.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 9b2eedc..2745284 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -115,6 +115,7 @@ config DRM_RADEON
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
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 0013ad0..c7fa1ae 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.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 += \
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3c6999e..511191f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -65,6 +65,7 @@
 #include 
 #include 
 #include 
+#include 

 #include 
 #include 
@@ -487,6 +488,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)

@@ -1725,6 +1729,11 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
   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
@@ -2372,6 +2381,9 @@ struct radeon_device {
/* tracking pinned memory */
u64 vram_pin_size;
u64 gart_pin_size;
+
+   struct mutexmn_lock;
+   DECLARE_HASHTABLE(mn_hash, 7);
 };

 bool radeon_is_px(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index c8ea050..c58f84f 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1270,6 +1270,8 @@ int radeon_device_init(struct radeon_device *rdev,
init_rwsem(>pm.mclk_lock);
init_rwsem(>exclusive_lock);
init_waitqueue_head(>irq.vblank_queue);
+   mutex_init(>mn_lock);
+   hash_init(rdev->mn_hash);
r = radeon_gem_init(rdev);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index 4506560..2a6fbf1 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -291,7 +291,8 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
*data,

/* reject unknown flag values */
if (args->flags & ~(RADEON_GEM_USERPTR_READONLY |
-   RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE))
+   RADEON_GEM_USERPTR_ANONONLY | RADEON_GEM_USERPTR_VALIDATE |
+   RADEON_GEM_USERPTR_REGISTER))
return -EINVAL;

/* readonly pages not tested on older hardware */
@@ -312,6 +313,12 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
*data,
if (r)
goto release_object;

+   if (args->flags & RADEON_GEM_USERPTR_REGISTER) {
+   r = radeon_mn_register(bo, args->addr);
+   if (r)
+   goto release_object;
+   }
+
if (args->flags & RADEON_GEM_USERPTR_VALIDATE) {
down_read(>mm->mmap_sem);
r = radeon_bo_reserve(bo, true);
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c 
b/drivers/gpu/drm/radeon/radeon_mn.c
new file mode 100644
index 000..0157bc2
--- /dev/null
+++