Am 13.09.2018 um 00:02 schrieb Philip Yang: > Replace our MMU notifier with hmm_mirror_ops.sync_cpu_device_pagetables > callback. Enable CONFIG_HMM and CONFIG_HMM_MIRROR as a dependency in > DRM_AMDGPU_USERPTR Kconfig. > > It supports both KFD userptr and gfx userptr paths. > > This depends on several HMM patchset from Jérôme Glisse queued for > upstream. See > http://172.27.226.38/root/kernel_amd/commits/hmm-dev-v01 (for AMD intranet) > > Change-Id: Ie62c3c5e3c5b8521ab3b438d1eff2aa2a003835e > Signed-off-by: Philip Yang <Philip.Yang at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/Kconfig | 6 +-- > drivers/gpu/drm/amd/amdgpu/Makefile | 1 + > drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c | 78 +++++++++++++++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h | 41 +++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 50 ++++++++++++++++++++- > drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h | 7 +++ Please either fully merge amdgpu_mn.* into amdgpu_hmm.* or the other way around. Additional to that you should add documentation to all newly added functions. Regards, Christian. > 6 files changed, 178 insertions(+), 5 deletions(-) > create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c > create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h > > diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig > index 9221e54..960a633 100644 > --- a/drivers/gpu/drm/amd/amdgpu/Kconfig > +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig > @@ -26,10 +26,10 @@ config DRM_AMDGPU_CIK > config DRM_AMDGPU_USERPTR > bool "Always enable userptr write support" > depends on DRM_AMDGPU > - select MMU_NOTIFIER > + select HMM_MIRROR > help > - This option selects CONFIG_MMU_NOTIFIER if it isn't already > - selected to enabled full userptr support. > + This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it > + isn't already selected to enabled full userptr support. > > config DRM_AMDGPU_GART_DEBUGFS > bool "Allow GART access through debugfs" > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile > index 138cb78..ee691e8 100644 > --- a/drivers/gpu/drm/amd/amdgpu/Makefile > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile > @@ -172,6 +172,7 @@ amdgpu-$(CONFIG_COMPAT) += amdgpu_ioc32.o > amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o > amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o > amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o > +amdgpu-$(CONFIG_HMM) += amdgpu_hmm.o > > include $(FULL_AMD_PATH)/powerplay/Makefile > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c > new file mode 100644 > index 0000000..6c506f6 > --- /dev/null > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c > @@ -0,0 +1,78 @@ > +/* > + * Copyright 2018 Advanced Micro Devices, Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + */ > + > +#include <linux/mutex.h> > +#include <linux/slab.h> > +#include <linux/notifier.h> > +#include <linux/compat.h> > +#include <linux/mman.h> > +#include <linux/hmm.h> > +#include <asm/page.h> > +#include "amdgpu.h" > +#include "amdgpu_mn.h" > + > +static void amdgpu_hmm_release(struct hmm_mirror *mirror) > +{ > + pr_debug("mirror=%p\n", mirror); > + amdgpu_hmm_mn_release(mirror); > +} > + > +static int amdgpu_hmm_sync_cpu_device_pagetables(struct hmm_mirror *mirror, > + const struct hmm_update *update) > +{ > + struct hmm *hmm; > + struct mm_struct *mm; > + unsigned long start; > + unsigned long end; > + > + start = update->start; > + end = update->end; > + > + pr_debug("mirror %p start %lx end %lx\n", mirror, start, end); > + > + hmm = mirror->hmm; > + mm = *(struct mm_struct **)hmm; > + > + return amdgpu_mn_invalidate_range(mirror, mm, start, end, > + update->blockable); > +} > + > +static struct hmm_mirror_ops amdgpu_hmm_mirror_ops = { > + .sync_cpu_device_pagetables = amdgpu_hmm_sync_cpu_device_pagetables, > + .release = amdgpu_hmm_release > +}; > + > +int amdgpu_hmm_register(struct hmm_mirror *mirror, struct mm_struct *mm) > +{ > + pr_debug("mirror=%p\n", mirror); > + > + mirror->ops = &amdgpu_hmm_mirror_ops; > + > + return hmm_mirror_register(mirror, mm); > +} > + > +void amdgpu_hmm_unregister(struct hmm_mirror *mirror) > +{ > + pr_debug("mirror=%p\n", mirror); > + > + hmm_mirror_unregister(mirror); > +} > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h > new file mode 100644 > index 0000000..a21a5f6 > --- /dev/null > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h > @@ -0,0 +1,41 @@ > +/* > + * Copyright 2018 Advanced Micro Devices, Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + */ > + > +#ifndef __AMDGPU_HMM_H__ > +#define __AMDGPU_HMM_H__ > + > +#include <linux/mm.h> > +#include <linux/hmm.h> > + > +#if IS_ENABLED(CONFIG_HMM) > + > +int amdgpu_hmm_register(struct hmm_mirror *mirror, struct mm_struct *mm); > +void amdgpu_hmm_unregister(struct hmm_mirror *mirror); > + > +#else > + > +#define amdgpu_hmm_register(x, y) (0) > +#define amdgpu_hmm_unregister(x) > + > +#endif > + > +#endif > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c > index e55508b..2f5df5b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c > @@ -47,11 +47,13 @@ > #include <linux/module.h> > #include <linux/mmu_notifier.h> > #include <linux/interval_tree.h> > +#include <linux/hmm.h> > #include <drm/drmP.h> > #include <drm/drm.h> > > #include "amdgpu.h" > #include "amdgpu_amdkfd.h" > +#include "amdgpu_hmm.h" > > /** > * struct amdgpu_mn > @@ -66,6 +68,7 @@ > * @objects: interval tree containing amdgpu_mn_nodes > * @read_lock: mutex for recursive locking of @lock > * @recursion: depth of recursion > + * @hmm_mirror: HMM mirror function support > * > * Data for each amdgpu device and process address space. > */ > @@ -87,6 +90,9 @@ struct amdgpu_mn { > struct rb_root_cached objects; > struct mutex read_lock; > atomic_t recursion; > + > + /* HMM mirror */ > + struct hmm_mirror hmm_mirror; > }; > > /** > @@ -129,7 +135,9 @@ static void amdgpu_mn_destroy(struct work_struct *work) > } > up_write(&amn->lock); > mutex_unlock(&adev->mn_lock); > - mmu_notifier_unregister_no_release(&amn->mn, amn->mm); > + > + amdgpu_hmm_unregister(&amn->hmm_mirror); > + > kfree(amn); > } > > @@ -372,6 +380,44 @@ static const struct mmu_notifier_ops amdgpu_mn_ops[] = { > */ > #define AMDGPU_MN_KEY(mm, type) ((unsigned long)(mm) + (type)) > > +void amdgpu_hmm_mn_release(struct hmm_mirror *mirror) > +{ > + struct amdgpu_mn *amn; > + > + amn = container_of(mirror, struct amdgpu_mn, hmm_mirror); > + > + amdgpu_mn_release(&amn->mn, amn->mm); > +} > + > +int amdgpu_mn_invalidate_range(struct hmm_mirror *mirror, > + struct mm_struct *mm, > + unsigned long start, > + unsigned long end, > + bool blockable) > + > +{ > + unsigned long key; > + struct amdgpu_mn *amn; > + int r = 0; > + > + amn = container_of(mirror, struct amdgpu_mn, hmm_mirror); > + key = AMDGPU_MN_KEY(mm, amn->type); > + > + hash_for_each_possible(amn->adev->mn_hash, amn, node, key) > + if (AMDGPU_MN_KEY(amn->mm, amn->type) == key) { > + r = amn->mn.ops->invalidate_range_start(&amn->mn, mm, > + start, end, blockable); > + amn->mn.ops->invalidate_range_end(&amn->mn, mm, > + start, end); > + if (r) { > + DRM_ERROR("failed to invalidate %lx\n", start); > + break; > + } > + } > + > + return r; > +} > + > /** > * amdgpu_mn_get - create notifier context > * > @@ -413,7 +459,7 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev, > mutex_init(&amn->read_lock); > atomic_set(&amn->recursion, 0); > > - r = __mmu_notifier_register(&amn->mn, mm); > + r = amdgpu_hmm_register(&amn->hmm_mirror, mm); > if (r) > goto free_amn; > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h > index eb0f432..e7781db 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h > @@ -28,6 +28,7 @@ > * MMU Notifier > */ > struct amdgpu_mn; > +struct hmm_mirror; > > enum amdgpu_mn_type { > AMDGPU_MN_TYPE_GFX, > @@ -41,6 +42,12 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev, > enum amdgpu_mn_type type); > int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr); > void amdgpu_mn_unregister(struct amdgpu_bo *bo); > +int amdgpu_mn_invalidate_range(struct hmm_mirror *mirror, > + struct mm_struct *mm, > + unsigned long start, > + unsigned long end, > + bool blockable); > +void amdgpu_hmm_mn_release(struct hmm_mirror *mirror); > #else > static inline void amdgpu_mn_lock(struct amdgpu_mn *mn) {} > static inline void amdgpu_mn_unlock(struct amdgpu_mn *mn) {}