[PATCH 4/5] drm/radeon: add userptr flag to register MMU notifier v3
From: Christian K?nigWhenever 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
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
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
From: Christian K?nigWhenever 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 +++