All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kuehling, Felix" <Felix.Kuehling@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	John Hubbard <jhubbard@nvidia.com>
Cc: "linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	Ben Skeggs <bskeggs@redhat.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	"Koenig, Christian" <Christian.Koenig@amd.com>,
	"Zhou, David(ChunMing)" <David1.Zhou@amd.com>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	Juergen Gross <jgross@suse.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	Petr Cvek <petrcvekcz@gmail.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 22:14:29 +0000	[thread overview]
Message-ID: <6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

On 2019-10-28 4:10 p.m., Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
[snip]
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;

This should return -EAGAIN. Not sure it matters much, because this whole 
function disappears in the next commit in the series. It seems to be 
only vestigial at this point.

Regards,
   Felix

>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
[snip]


WARNING: multiple messages have this Message-ID (diff)
From: "Kuehling, Felix" <Felix.Kuehling-5C7GfCeVMHo@public.gmane.org>
To: Jason Gunthorpe <jgg-uk2M96/98Pc@public.gmane.org>,
	"linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org"
	<linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>,
	Jerome Glisse <jglisse-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	Ralph Campbell
	<rcampbell-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>,
	John Hubbard <jhubbard-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Cc: Juergen Gross <jgross-IBi9RG/b67k@public.gmane.org>,
	"Zhou,
	David(ChunMing)" <David1.Zhou-5C7GfCeVMHo@public.gmane.org>,
	Mike Marciniszyn
	<mike.marciniszyn-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	Stefano Stabellini
	<sstabellini-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Oleksandr Andrushchenko
	<oleksandr_andrushchenko-uRwfk40T5oI@public.gmane.org>,
	"linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	"nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
	<nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
	Dennis Dalessandro
	<dennis.dalessandro-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	"amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
	<amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
	Christoph Hellwig <hch-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
	Jason Gunthorpe <jgg-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>,
	"dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
	<dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
	"Deucher,
	Alexander" <Alexander.Deucher-5C7GfCeVMHo@public.gmane.org>,
	"xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b@public.gmane.org"
	<xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b@public.gmane.org>,
	Boris Ostrovsky
	<boris.ostrovsky-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>,
	Petr Cvek <petrcvekcz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	"Koenig,
	Christian" <Christian.Koenig-5C7GfCeVMHo@public.gmane.org>,
	Ben Skeggs <bskegg>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 22:14:29 +0000	[thread overview]
Message-ID: <6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg-uk2M96/98Pc@public.gmane.org>

On 2019-10-28 4:10 p.m., Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
[snip]
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;

This should return -EAGAIN. Not sure it matters much, because this whole 
function disappears in the next commit in the series. It seems to be 
only vestigial at this point.

Regards,
   Felix

>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
[snip]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

WARNING: multiple messages have this Message-ID (diff)
From: "Kuehling, Felix" <Felix.Kuehling@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>
Cc: Juergen Gross <jgross@suse.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>,
	"Koenig, Christian" <Christian.Koenig@amd.com>,
	Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 22:14:29 +0000	[thread overview]
Message-ID: <6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com> (raw)
Message-ID: <20191029221429.M2Qhkz89NQrsC2xDtR1ryRNuUsjetNG1wrrpgBaezRw@z> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

On 2019-10-28 4:10 p.m., Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
[snip]
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;

This should return -EAGAIN. Not sure it matters much, because this whole 
function disappears in the next commit in the series. It seems to be 
only vestigial at this point.

Regards,
   Felix

>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
[snip]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: "Kuehling, Felix" <Felix.Kuehling@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>
Cc: Juergen Gross <jgross@suse.com>,
	"Zhou, David\(ChunMing\)" <David1.Zhou@amd.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>,
	"Koenig, Christian" <Christian.Koenig@amd.com>,
	Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [Xen-devel] [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 22:14:29 +0000	[thread overview]
Message-ID: <6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

On 2019-10-28 4:10 p.m., Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
[snip]
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;

This should return -EAGAIN. Not sure it matters much, because this whole 
function disappears in the next commit in the series. It seems to be 
only vestigial at this point.

Regards,
   Felix

>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
[snip]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

WARNING: multiple messages have this Message-ID (diff)
From: "Kuehling, Felix" <Felix.Kuehling@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>
Cc: Juergen Gross <jgross@suse.com>,
	"Zhou, David\(ChunMing\)" <David1.Zhou@amd.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>,
	"Koenig, Christian" <Christian.Koenig@amd.com>,
	Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 22:14:29 +0000	[thread overview]
Message-ID: <6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com> (raw)
Message-ID: <20191029221429.3gLfIlGD4wu3DkZORapm96ELhyhBnBLCJ3LrVU7cJPE@z> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

On 2019-10-28 4:10 p.m., Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
[snip]
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;

This should return -EAGAIN. Not sure it matters much, because this whole 
function disappears in the next commit in the series. It seems to be 
only vestigial at this point.

Regards,
   Felix

>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
[snip]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  parent reply	other threads:[~2019-10-29 22:14 UTC|newest]

Thread overview: 335+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-28 20:10 [PATCH v2 00/15] Consolidate the mmu notifier interval_tree and locking Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 01/15] mm/mmu_notifier: define the header pre-processor parts even if disabled Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-05 21:23   ` John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-05 21:23     ` [Xen-devel] " John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-06 13:36     ` Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-11-06 13:36       ` [Xen-devel] " Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 02/15] mm/mmu_notifier: add an interval tree notifier Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 22:04   ` Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:04     ` [Xen-devel] " Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:56     ` Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-10-29 22:56       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-11-07  0:23   ` John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  0:23     ` [Xen-devel] " John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  2:08     ` Jerome Glisse
2019-11-07  2:08       ` Jerome Glisse
2019-11-07  2:08       ` [Xen-devel] " Jerome Glisse
2019-11-07  2:08       ` Jerome Glisse
2019-11-07 20:11       ` Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 20:11         ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 21:04         ` Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-07 21:04           ` [Xen-devel] " Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-08  0:32           ` Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  0:32             ` [Xen-devel] " Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  2:00             ` Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08  2:00               ` [Xen-devel] " Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08 20:19               ` Jason Gunthorpe
2019-11-08 20:19                 ` Jason Gunthorpe
2019-11-08 20:19                 ` [Xen-devel] " Jason Gunthorpe
2019-11-08 20:19                 ` Jason Gunthorpe
2019-11-07 20:06     ` Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:06       ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:53       ` John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-07 20:53         ` [Xen-devel] " John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-08 15:26         ` Jason Gunthorpe
2019-11-08 15:26           ` Jason Gunthorpe
2019-11-08 15:26           ` [Xen-devel] " Jason Gunthorpe
2019-11-08 15:26           ` Jason Gunthorpe
2019-11-08  6:33       ` Christoph Hellwig
2019-11-08  6:33         ` Christoph Hellwig
2019-11-08  6:33         ` [Xen-devel] " Christoph Hellwig
2019-11-08  6:33         ` Christoph Hellwig
2019-11-08 13:43         ` Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-11-08 13:43           ` [Xen-devel] " Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-10-28 20:10 ` [PATCH v2 03/15] mm/hmm: allow hmm_range to be used with a mmu_range_notifier or hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 04/15] mm/hmm: define the pre-processor related parts of hmm.h even if disabled Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 05/15] RDMA/odp: Use mmu_range_notifier_insert() Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 06/15] RDMA/hfi1: Use mmu_range_notifier_inset for user_exp_rcv Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 12:19   ` Dennis Dalessandro
2019-10-29 12:19     ` Dennis Dalessandro
2019-10-29 12:19     ` [Xen-devel] " Dennis Dalessandro
2019-10-29 12:19     ` Dennis Dalessandro
2019-10-29 12:51     ` Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-29 12:51       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 07/15] drm/radeon: use mmu_range_notifier_insert Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:48   ` Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-29  7:48     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-28 20:10 ` [PATCH v2 08/15] xen/gntdev: Use select for DMA_SHARED_BUFFER Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-01 18:26   ` Jason Gunthorpe
2019-11-01 18:26     ` Jason Gunthorpe
2019-11-01 18:26     ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:26     ` Jason Gunthorpe
2019-11-05 14:44     ` Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-05 14:44       ` [Xen-devel] " Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-07  9:39   ` Jürgen Groß
2019-11-07  9:39     ` Jürgen Groß
2019-11-07  9:39     ` [Xen-devel] " Jürgen Groß
2019-11-07  9:39     ` Jürgen Groß
2019-10-28 20:10 ` [PATCH v2 09/15] xen/gntdev: use mmu_range_notifier_insert Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-30 16:55   ` Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-10-30 16:55     ` [Xen-devel] " Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-11-01 17:48     ` Jason Gunthorpe
2019-11-01 17:48       ` Jason Gunthorpe
2019-11-01 17:48       ` [Xen-devel] " Jason Gunthorpe
2019-11-01 17:48       ` Jason Gunthorpe
2019-11-01 18:51       ` Boris Ostrovsky
2019-11-01 18:51         ` Boris Ostrovsky
2019-11-01 18:51         ` [Xen-devel] " Boris Ostrovsky
2019-11-01 18:51         ` Boris Ostrovsky
2019-11-01 19:17         ` Jason Gunthorpe
2019-11-01 19:17           ` Jason Gunthorpe
2019-11-01 19:17           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:17           ` Jason Gunthorpe
2019-11-04 22:03   ` Boris Ostrovsky
2019-11-04 22:03     ` Boris Ostrovsky
2019-11-04 22:03     ` [Xen-devel] " Boris Ostrovsky
2019-11-04 22:03     ` Boris Ostrovsky
2019-11-05  2:31     ` Jason Gunthorpe
2019-11-05  2:31       ` Jason Gunthorpe
2019-11-05  2:31       ` [Xen-devel] " Jason Gunthorpe
2019-11-05  2:31       ` Jason Gunthorpe
2019-11-05 15:16       ` Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-05 15:16         ` [Xen-devel] " Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-07 20:36         ` Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 20:36           ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 22:54           ` Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-07 22:54             ` [Xen-devel] " Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-08 14:53             ` Jason Gunthorpe
2019-11-08 14:53               ` Jason Gunthorpe
2019-11-08 14:53               ` [Xen-devel] " Jason Gunthorpe
2019-11-08 14:53               ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 10/15] nouveau: use mmu_notifier directly for invalidate_range_start Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 11/15] nouveau: use mmu_range_notifier instead of hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 12/15] drm/amdgpu: Call find_vma under mmap_sem Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:49   ` Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29  7:49     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29 16:28   ` Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 16:28     ` [Xen-devel] " Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 13:07     ` Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 13:07       ` [Xen-devel] " Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 17:19     ` Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-29 17:19       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:51   ` Koenig, Christian
2019-10-29  7:51     ` Koenig, Christian
2019-10-29  7:51     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:51     ` Koenig, Christian
2019-10-29  7:51     ` Koenig, Christian
2019-10-29 13:59     ` Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 13:59       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 22:14   ` Kuehling, Felix [this message]
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 22:14     ` [Xen-devel] " Kuehling, Felix
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 23:09     ` Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-29 23:09       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 14/15] drm/amdgpu: Use mmu_range_notifier " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 19:22   ` Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:22     ` [Xen-devel] " Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:25     ` Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-10-29 19:25       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-11-01 14:44       ` Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 14:44         ` [Xen-devel] " Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 15:12         ` Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:12           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:59           ` Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 15:59             ` [Xen-devel] " Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 17:42             ` Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 17:42               ` [Xen-devel] " Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 19:19               ` Jason Gunthorpe
2019-11-01 19:19                 ` Jason Gunthorpe
2019-11-01 19:19                 ` Jason Gunthorpe
2019-11-01 19:45               ` Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:45                 ` [Xen-devel] " Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:50                 ` Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:50                   ` [Xen-devel] " Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:51                 ` Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 19:51                   ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 18:21         ` Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:21           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:34         ` [PATCH v2a " Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-11-01 18:34           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 15/15] mm/hmm: remove hmm_mirror and related Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-01 19:54 ` [PATCH v2 00/15] Consolidate the mmu notifier interval_tree and locking Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 19:54   ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 20:54 ` Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-01 20:54   ` [Xen-devel] " Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-04 20:40   ` Jason Gunthorpe
2019-11-04 20:40     ` Jason Gunthorpe
2019-11-04 20:40     ` [Xen-devel] " Jason Gunthorpe
2019-11-04 20:40     ` Jason Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6c511ee9-4cbf-bd33-e720-f2d2b5c3c28b@amd.com \
    --to=felix.kuehling@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=Christian.Koenig@amd.com \
    --cc=David1.Zhou@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bskeggs@redhat.com \
    --cc=dennis.dalessandro@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hch@infradead.org \
    --cc=jgg@mellanox.com \
    --cc=jgg@ziepe.ca \
    --cc=jglisse@redhat.com \
    --cc=jgross@suse.com \
    --cc=jhubbard@nvidia.com \
    --cc=linux-mm@kvack.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=mike.marciniszyn@intel.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=petrcvekcz@gmail.com \
    --cc=rcampbell@nvidia.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.