From: Danilo Krummrich <dakr@redhat.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: matthew.brost@intel.com, thomas.hellstrom@linux.intel.com,
sarah.walker@imgtec.com, nouveau@lists.freedesktop.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
donald.robson@imgtec.com, daniel@ffwll.ch,
christian.koenig@amd.com, faith.ekstrand@collabora.com
Subject: Re: [Nouveau] [PATCH drm-misc-next v3 6/7] drm/gpuvm: generalize dma_resv/extobj handling and GEM validation
Date: Mon, 11 Sep 2023 18:23:26 +0200 [thread overview]
Message-ID: <ZP8+/gjvKFBGR/Y4@cassiopeiae> (raw)
In-Reply-To: <20230911123526.6c67feb0@collabora.com>
On Mon, Sep 11, 2023 at 12:35:26PM +0200, Boris Brezillon wrote:
> Hello Danilo,
>
> On Sat, 9 Sep 2023 17:31:13 +0200
> Danilo Krummrich <dakr@redhat.com> wrote:
>
>
> > @@ -632,6 +661,131 @@
> > * }
> > */
> >
> > +/**
> > + * get_next_vm_bo_from_list() - get the next vm_bo element
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + * @__prev_vm_bo: The previous element we got from drm_gpuvm_get_next_cached_vm_bo()
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from
> > + * the list, so list insertion deletion can happen concurrently.
> > + *
> > + * Elements popped from the original list are kept in a local list, so removal
> > + * and is_empty checks can still happen while we're iterating the list.
> > + */
> > +#define get_next_vm_bo_from_list(__gpuvm, __list_name, __local_list, __prev_vm_bo) \
> > + ({ \
> > + struct drm_gpuvm_bo *__vm_bo; \
> > + \
> > + drm_gpuvm_bo_put(__prev_vm_bo); \
> > + \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
>
> I'm tempted to add a drm_gpuvm::<list_name>::local_list field, so we
> can catch concurrent iterations with something like:
>
> if (!(__gpuvm)->__list_name.local_list)
> (__gpuvm)->__list_name.local_list = __local_list;
> else
> WARN_ON((__gpuvm)->__list_name.local_list != __local_list);
>
> with (__gpuvm)->__list_name.local_list being restored to NULL
> in restore_vm_bo_list().
>
> > + while (!list_empty(&(__gpuvm)->__list_name.list)) { \
> > + __vm_bo = list_first_entry(&(__gpuvm)->__list_name.list, \
> > + struct drm_gpuvm_bo, \
> > + list.entry.__list_name); \
> > + if (drm_gpuvm_bo_get_unless_zero(__vm_bo)) { \
> > + list_move_tail(&(__vm_bo)->list.entry.__list_name, \
> > + __local_list); \
> > + break; \
> > + } else { \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + __vm_bo = NULL; \
> > + } \
> > + } \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + \
> > + __vm_bo; \
> > + })
> > +
> > +/**
> > + * for_each_vm_bo_in_list() - internal vm_bo list iterator
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from the
> > + * list, so list insertion and deletion can happen concurrently.
> > + *
> > + * Typical use:
> > + *
> > + * struct drm_gpuvm_bo *vm_bo;
> > + * LIST_HEAD(my_local_list);
> > + *
> > + * ret = 0;
> > + * drm_gpuvm_for_each_vm_bo(gpuvm, <list_name>, &my_local_list, vm_bo) {
> > + * ret = do_something_with_vm_bo(..., vm_bo);
> > + * if (ret)
> > + * break;
> > + * }
> > + * drm_gpuvm_bo_put(vm_bo);
> > + * drm_gpuvm_restore_vm_bo_list(gpuvm, <list_name>, &my_local_list);
>
> The names in this example and the helper names don't match.
>
> > + *
> > + *
> > + * Only used for internal list iterations, not meant to be exposed to the outside
> > + * world.
> > + */
> > +#define for_each_vm_bo_in_list(__gpuvm, __list_name, __local_list, __vm_bo) \
> > + for (__vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, NULL); \
> > + __vm_bo; \
> > + __vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, __vm_bo)) \
> > +
> > +/**
> > + * restore_vm_bo_list() - move vm_bo elements back to their original list
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + *
> > + * When we're done iterating a vm_bo list, we should call restore_vm_bo_list()
> > + * to restore the original state and let new iterations take place.
> > + */
> > +#define restore_vm_bo_list(__gpuvm, __list_name, __local_list) \
> > + do { \
> > + /* Merge back the two lists, moving local list elements to the \
> > + * head to preserve previous ordering, in case it matters. \
> > + */ \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
> > + list_splice(__local_list, &(__gpuvm)->__list_name.list); \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + } while (0)
> > +/**
> > + * drm_gpuvm_bo_list_add() - insert a vm_bo into the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Inserts the given @__vm_bo into the list specified by @__list_name and
> > + * increases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_add(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_add_tail(&(__vm_bo)->list.entry.__list_name, \
> > + &(__vm_bo)->vm->__list_name.list); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +/**
> > + * drm_gpuvm_bo_list_del() - remove a vm_bo from the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Removes the given @__vm_bo from the list specified by @__list_name and
> > + * decreases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_del(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (!list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo);
>
> I see no obvious reason to have a forward declaration for this helper,
> if we decide to keep it, let's at least move the declaration here.
>
>
> > @@ -807,6 +1262,14 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> >
> > drm_gem_gpuva_assert_lock_held(vm_bo->obj);
> >
> > + spin_lock(&gpuvm->extobj.lock);
> > + list_del(&vm_bo->list.entry.extobj);
> > + spin_unlock(&gpuvm->extobj.lock);
> > +
> > + spin_lock(&gpuvm->evict.lock);
> > + list_del(&vm_bo->list.entry.evict);
> > + spin_unlock(&gpuvm->evict.lock);
> > +
> > list_del(&vm_bo->list.entry.gem);
> >
> > drm_gem_object_put(obj);
> > @@ -822,6 +1285,11 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> > * @vm_bo: the &drm_gpuvm_bo to release the reference of
> > *
> > * This releases a reference to @vm_bo.
> > + *
> > + * If the reference count drops to zero, the &gpuvm_bo is destroyed, which
> > + * includes removing it from the GEMs gpuva list. Hence, if a call to this
> > + * function can potentially let the reference count to zero the caller must
> > + * hold the dma-resv or driver specific GEM gpuva lock.
>
> Looks like this should have been part of the previous patch. I hate
> the fact we have to worry about GEM gpuva lock being held when we call
> _put() only if the ref drops to zero though. I think I'd feel more
> comfortable if the function was named differently. Maybe _return() or
> _release() to match the _obtain() function, where the object is inserted
> in the GEM vm_bo list. I would also do the lock_is_held() check
> unconditionally, move the list removal in this function with a del_init(),
> and have a WARN_ON(!list_empty) in vm_bo_destroy().
>
We can't move the list removal to drm_gpuvm_bo_put(), we need to make sure we
can't create duplicate drm_gpuvm_bo structures. Everything else pretty much goes
away with a dedicated GEM gpuva list lock, as I had in my first patch series
when I introduced the GPUVA manager. At that time it wasn't always needed, hence
the optional driver specific lock, however with the VM_BO abstraction it really
makes sense to have a dedicated one.
I agree with the other feedback from this reply and will address it in a V4.
> > */
> > void
> > drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > @@ -831,6 +1299,12 @@ drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > }
> > EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put);
> >
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo)
> > +{
> > + return kref_get_unless_zero(&vm_bo->kref);
>
> Not convinced this helper is needed. It's only used once, and I
> don't think we'll need it elsewhere.
>
> > +}
> > +
> > static struct drm_gpuvm_bo *
> > __drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
> > struct drm_gem_object *obj)
>
>
> Regards,
>
> Boris
>
WARNING: multiple messages have this Message-ID (diff)
From: Danilo Krummrich <dakr@redhat.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: matthew.brost@intel.com, thomas.hellstrom@linux.intel.com,
sarah.walker@imgtec.com, nouveau@lists.freedesktop.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
donald.robson@imgtec.com, christian.koenig@amd.com,
faith.ekstrand@collabora.com
Subject: Re: [PATCH drm-misc-next v3 6/7] drm/gpuvm: generalize dma_resv/extobj handling and GEM validation
Date: Mon, 11 Sep 2023 18:23:26 +0200 [thread overview]
Message-ID: <ZP8+/gjvKFBGR/Y4@cassiopeiae> (raw)
In-Reply-To: <20230911123526.6c67feb0@collabora.com>
On Mon, Sep 11, 2023 at 12:35:26PM +0200, Boris Brezillon wrote:
> Hello Danilo,
>
> On Sat, 9 Sep 2023 17:31:13 +0200
> Danilo Krummrich <dakr@redhat.com> wrote:
>
>
> > @@ -632,6 +661,131 @@
> > * }
> > */
> >
> > +/**
> > + * get_next_vm_bo_from_list() - get the next vm_bo element
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + * @__prev_vm_bo: The previous element we got from drm_gpuvm_get_next_cached_vm_bo()
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from
> > + * the list, so list insertion deletion can happen concurrently.
> > + *
> > + * Elements popped from the original list are kept in a local list, so removal
> > + * and is_empty checks can still happen while we're iterating the list.
> > + */
> > +#define get_next_vm_bo_from_list(__gpuvm, __list_name, __local_list, __prev_vm_bo) \
> > + ({ \
> > + struct drm_gpuvm_bo *__vm_bo; \
> > + \
> > + drm_gpuvm_bo_put(__prev_vm_bo); \
> > + \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
>
> I'm tempted to add a drm_gpuvm::<list_name>::local_list field, so we
> can catch concurrent iterations with something like:
>
> if (!(__gpuvm)->__list_name.local_list)
> (__gpuvm)->__list_name.local_list = __local_list;
> else
> WARN_ON((__gpuvm)->__list_name.local_list != __local_list);
>
> with (__gpuvm)->__list_name.local_list being restored to NULL
> in restore_vm_bo_list().
>
> > + while (!list_empty(&(__gpuvm)->__list_name.list)) { \
> > + __vm_bo = list_first_entry(&(__gpuvm)->__list_name.list, \
> > + struct drm_gpuvm_bo, \
> > + list.entry.__list_name); \
> > + if (drm_gpuvm_bo_get_unless_zero(__vm_bo)) { \
> > + list_move_tail(&(__vm_bo)->list.entry.__list_name, \
> > + __local_list); \
> > + break; \
> > + } else { \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + __vm_bo = NULL; \
> > + } \
> > + } \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + \
> > + __vm_bo; \
> > + })
> > +
> > +/**
> > + * for_each_vm_bo_in_list() - internal vm_bo list iterator
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from the
> > + * list, so list insertion and deletion can happen concurrently.
> > + *
> > + * Typical use:
> > + *
> > + * struct drm_gpuvm_bo *vm_bo;
> > + * LIST_HEAD(my_local_list);
> > + *
> > + * ret = 0;
> > + * drm_gpuvm_for_each_vm_bo(gpuvm, <list_name>, &my_local_list, vm_bo) {
> > + * ret = do_something_with_vm_bo(..., vm_bo);
> > + * if (ret)
> > + * break;
> > + * }
> > + * drm_gpuvm_bo_put(vm_bo);
> > + * drm_gpuvm_restore_vm_bo_list(gpuvm, <list_name>, &my_local_list);
>
> The names in this example and the helper names don't match.
>
> > + *
> > + *
> > + * Only used for internal list iterations, not meant to be exposed to the outside
> > + * world.
> > + */
> > +#define for_each_vm_bo_in_list(__gpuvm, __list_name, __local_list, __vm_bo) \
> > + for (__vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, NULL); \
> > + __vm_bo; \
> > + __vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, __vm_bo)) \
> > +
> > +/**
> > + * restore_vm_bo_list() - move vm_bo elements back to their original list
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + *
> > + * When we're done iterating a vm_bo list, we should call restore_vm_bo_list()
> > + * to restore the original state and let new iterations take place.
> > + */
> > +#define restore_vm_bo_list(__gpuvm, __list_name, __local_list) \
> > + do { \
> > + /* Merge back the two lists, moving local list elements to the \
> > + * head to preserve previous ordering, in case it matters. \
> > + */ \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
> > + list_splice(__local_list, &(__gpuvm)->__list_name.list); \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + } while (0)
> > +/**
> > + * drm_gpuvm_bo_list_add() - insert a vm_bo into the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Inserts the given @__vm_bo into the list specified by @__list_name and
> > + * increases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_add(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_add_tail(&(__vm_bo)->list.entry.__list_name, \
> > + &(__vm_bo)->vm->__list_name.list); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +/**
> > + * drm_gpuvm_bo_list_del() - remove a vm_bo from the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Removes the given @__vm_bo from the list specified by @__list_name and
> > + * decreases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_del(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (!list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo);
>
> I see no obvious reason to have a forward declaration for this helper,
> if we decide to keep it, let's at least move the declaration here.
>
>
> > @@ -807,6 +1262,14 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> >
> > drm_gem_gpuva_assert_lock_held(vm_bo->obj);
> >
> > + spin_lock(&gpuvm->extobj.lock);
> > + list_del(&vm_bo->list.entry.extobj);
> > + spin_unlock(&gpuvm->extobj.lock);
> > +
> > + spin_lock(&gpuvm->evict.lock);
> > + list_del(&vm_bo->list.entry.evict);
> > + spin_unlock(&gpuvm->evict.lock);
> > +
> > list_del(&vm_bo->list.entry.gem);
> >
> > drm_gem_object_put(obj);
> > @@ -822,6 +1285,11 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> > * @vm_bo: the &drm_gpuvm_bo to release the reference of
> > *
> > * This releases a reference to @vm_bo.
> > + *
> > + * If the reference count drops to zero, the &gpuvm_bo is destroyed, which
> > + * includes removing it from the GEMs gpuva list. Hence, if a call to this
> > + * function can potentially let the reference count to zero the caller must
> > + * hold the dma-resv or driver specific GEM gpuva lock.
>
> Looks like this should have been part of the previous patch. I hate
> the fact we have to worry about GEM gpuva lock being held when we call
> _put() only if the ref drops to zero though. I think I'd feel more
> comfortable if the function was named differently. Maybe _return() or
> _release() to match the _obtain() function, where the object is inserted
> in the GEM vm_bo list. I would also do the lock_is_held() check
> unconditionally, move the list removal in this function with a del_init(),
> and have a WARN_ON(!list_empty) in vm_bo_destroy().
>
We can't move the list removal to drm_gpuvm_bo_put(), we need to make sure we
can't create duplicate drm_gpuvm_bo structures. Everything else pretty much goes
away with a dedicated GEM gpuva list lock, as I had in my first patch series
when I introduced the GPUVA manager. At that time it wasn't always needed, hence
the optional driver specific lock, however with the VM_BO abstraction it really
makes sense to have a dedicated one.
I agree with the other feedback from this reply and will address it in a V4.
> > */
> > void
> > drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > @@ -831,6 +1299,12 @@ drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > }
> > EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put);
> >
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo)
> > +{
> > + return kref_get_unless_zero(&vm_bo->kref);
>
> Not convinced this helper is needed. It's only used once, and I
> don't think we'll need it elsewhere.
>
> > +}
> > +
> > static struct drm_gpuvm_bo *
> > __drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
> > struct drm_gem_object *obj)
>
>
> Regards,
>
> Boris
>
WARNING: multiple messages have this Message-ID (diff)
From: Danilo Krummrich <dakr@redhat.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: airlied@gmail.com, daniel@ffwll.ch, matthew.brost@intel.com,
thomas.hellstrom@linux.intel.com, sarah.walker@imgtec.com,
donald.robson@imgtec.com, christian.koenig@amd.com,
faith.ekstrand@collabora.com, dri-devel@lists.freedesktop.org,
nouveau@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH drm-misc-next v3 6/7] drm/gpuvm: generalize dma_resv/extobj handling and GEM validation
Date: Mon, 11 Sep 2023 18:23:26 +0200 [thread overview]
Message-ID: <ZP8+/gjvKFBGR/Y4@cassiopeiae> (raw)
In-Reply-To: <20230911123526.6c67feb0@collabora.com>
On Mon, Sep 11, 2023 at 12:35:26PM +0200, Boris Brezillon wrote:
> Hello Danilo,
>
> On Sat, 9 Sep 2023 17:31:13 +0200
> Danilo Krummrich <dakr@redhat.com> wrote:
>
>
> > @@ -632,6 +661,131 @@
> > * }
> > */
> >
> > +/**
> > + * get_next_vm_bo_from_list() - get the next vm_bo element
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + * @__prev_vm_bo: The previous element we got from drm_gpuvm_get_next_cached_vm_bo()
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from
> > + * the list, so list insertion deletion can happen concurrently.
> > + *
> > + * Elements popped from the original list are kept in a local list, so removal
> > + * and is_empty checks can still happen while we're iterating the list.
> > + */
> > +#define get_next_vm_bo_from_list(__gpuvm, __list_name, __local_list, __prev_vm_bo) \
> > + ({ \
> > + struct drm_gpuvm_bo *__vm_bo; \
> > + \
> > + drm_gpuvm_bo_put(__prev_vm_bo); \
> > + \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
>
> I'm tempted to add a drm_gpuvm::<list_name>::local_list field, so we
> can catch concurrent iterations with something like:
>
> if (!(__gpuvm)->__list_name.local_list)
> (__gpuvm)->__list_name.local_list = __local_list;
> else
> WARN_ON((__gpuvm)->__list_name.local_list != __local_list);
>
> with (__gpuvm)->__list_name.local_list being restored to NULL
> in restore_vm_bo_list().
>
> > + while (!list_empty(&(__gpuvm)->__list_name.list)) { \
> > + __vm_bo = list_first_entry(&(__gpuvm)->__list_name.list, \
> > + struct drm_gpuvm_bo, \
> > + list.entry.__list_name); \
> > + if (drm_gpuvm_bo_get_unless_zero(__vm_bo)) { \
> > + list_move_tail(&(__vm_bo)->list.entry.__list_name, \
> > + __local_list); \
> > + break; \
> > + } else { \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + __vm_bo = NULL; \
> > + } \
> > + } \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + \
> > + __vm_bo; \
> > + })
> > +
> > +/**
> > + * for_each_vm_bo_in_list() - internal vm_bo list iterator
> > + *
> > + * This helper is here to provide lockless list iteration. Lockless as in, the
> > + * iterator releases the lock immediately after picking the first element from the
> > + * list, so list insertion and deletion can happen concurrently.
> > + *
> > + * Typical use:
> > + *
> > + * struct drm_gpuvm_bo *vm_bo;
> > + * LIST_HEAD(my_local_list);
> > + *
> > + * ret = 0;
> > + * drm_gpuvm_for_each_vm_bo(gpuvm, <list_name>, &my_local_list, vm_bo) {
> > + * ret = do_something_with_vm_bo(..., vm_bo);
> > + * if (ret)
> > + * break;
> > + * }
> > + * drm_gpuvm_bo_put(vm_bo);
> > + * drm_gpuvm_restore_vm_bo_list(gpuvm, <list_name>, &my_local_list);
>
> The names in this example and the helper names don't match.
>
> > + *
> > + *
> > + * Only used for internal list iterations, not meant to be exposed to the outside
> > + * world.
> > + */
> > +#define for_each_vm_bo_in_list(__gpuvm, __list_name, __local_list, __vm_bo) \
> > + for (__vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, NULL); \
> > + __vm_bo; \
> > + __vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name, \
> > + __local_list, __vm_bo)) \
> > +
> > +/**
> > + * restore_vm_bo_list() - move vm_bo elements back to their original list
> > + * @__gpuvm: The GPU VM
> > + * @__list_name: The name of the list we're iterating on
> > + * @__local_list: A pointer to the local list used to store already iterated items
> > + *
> > + * When we're done iterating a vm_bo list, we should call restore_vm_bo_list()
> > + * to restore the original state and let new iterations take place.
> > + */
> > +#define restore_vm_bo_list(__gpuvm, __list_name, __local_list) \
> > + do { \
> > + /* Merge back the two lists, moving local list elements to the \
> > + * head to preserve previous ordering, in case it matters. \
> > + */ \
> > + spin_lock(&(__gpuvm)->__list_name.lock); \
> > + list_splice(__local_list, &(__gpuvm)->__list_name.list); \
> > + spin_unlock(&(__gpuvm)->__list_name.lock); \
> > + } while (0)
> > +/**
> > + * drm_gpuvm_bo_list_add() - insert a vm_bo into the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Inserts the given @__vm_bo into the list specified by @__list_name and
> > + * increases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_add(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_add_tail(&(__vm_bo)->list.entry.__list_name, \
> > + &(__vm_bo)->vm->__list_name.list); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +/**
> > + * drm_gpuvm_bo_list_del() - remove a vm_bo from the given list
> > + * @__vm_bo: the &drm_gpuvm_bo
> > + * @__list_name: the name of the list to insert into
> > + *
> > + * Removes the given @__vm_bo from the list specified by @__list_name and
> > + * decreases the vm_bo's reference count.
> > + */
> > +#define drm_gpuvm_bo_list_del(__vm_bo, __list_name) \
> > + do { \
> > + spin_lock(&(__vm_bo)->vm->__list_name.lock); \
> > + if (!list_empty(&(__vm_bo)->list.entry.__list_name)) \
> > + list_del_init(&(__vm_bo)->list.entry.__list_name); \
> > + spin_unlock(&(__vm_bo)->vm->__list_name.lock); \
> > + } while (0)
> > +
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo);
>
> I see no obvious reason to have a forward declaration for this helper,
> if we decide to keep it, let's at least move the declaration here.
>
>
> > @@ -807,6 +1262,14 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> >
> > drm_gem_gpuva_assert_lock_held(vm_bo->obj);
> >
> > + spin_lock(&gpuvm->extobj.lock);
> > + list_del(&vm_bo->list.entry.extobj);
> > + spin_unlock(&gpuvm->extobj.lock);
> > +
> > + spin_lock(&gpuvm->evict.lock);
> > + list_del(&vm_bo->list.entry.evict);
> > + spin_unlock(&gpuvm->evict.lock);
> > +
> > list_del(&vm_bo->list.entry.gem);
> >
> > drm_gem_object_put(obj);
> > @@ -822,6 +1285,11 @@ drm_gpuvm_bo_destroy(struct kref *kref)
> > * @vm_bo: the &drm_gpuvm_bo to release the reference of
> > *
> > * This releases a reference to @vm_bo.
> > + *
> > + * If the reference count drops to zero, the &gpuvm_bo is destroyed, which
> > + * includes removing it from the GEMs gpuva list. Hence, if a call to this
> > + * function can potentially let the reference count to zero the caller must
> > + * hold the dma-resv or driver specific GEM gpuva lock.
>
> Looks like this should have been part of the previous patch. I hate
> the fact we have to worry about GEM gpuva lock being held when we call
> _put() only if the ref drops to zero though. I think I'd feel more
> comfortable if the function was named differently. Maybe _return() or
> _release() to match the _obtain() function, where the object is inserted
> in the GEM vm_bo list. I would also do the lock_is_held() check
> unconditionally, move the list removal in this function with a del_init(),
> and have a WARN_ON(!list_empty) in vm_bo_destroy().
>
We can't move the list removal to drm_gpuvm_bo_put(), we need to make sure we
can't create duplicate drm_gpuvm_bo structures. Everything else pretty much goes
away with a dedicated GEM gpuva list lock, as I had in my first patch series
when I introduced the GPUVA manager. At that time it wasn't always needed, hence
the optional driver specific lock, however with the VM_BO abstraction it really
makes sense to have a dedicated one.
I agree with the other feedback from this reply and will address it in a V4.
> > */
> > void
> > drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > @@ -831,6 +1299,12 @@ drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> > }
> > EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put);
> >
> > +static int __must_check
> > +drm_gpuvm_bo_get_unless_zero(struct drm_gpuvm_bo *vm_bo)
> > +{
> > + return kref_get_unless_zero(&vm_bo->kref);
>
> Not convinced this helper is needed. It's only used once, and I
> don't think we'll need it elsewhere.
>
> > +}
> > +
> > static struct drm_gpuvm_bo *
> > __drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
> > struct drm_gem_object *obj)
>
>
> Regards,
>
> Boris
>
next prev parent reply other threads:[~2023-09-11 16:23 UTC|newest]
Thread overview: 213+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-09 15:31 [Nouveau] [PATCH drm-misc-next v3 0/7] [RFC] DRM GPUVA Manager GPU-VM features Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 1/7] drm/gpuvm: rename struct drm_gpuva_manager to struct drm_gpuvm Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 18:23 ` [Nouveau] " kernel test robot
2023-09-09 18:23 ` kernel test robot
2023-09-09 18:23 ` kernel test robot
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 2/7] drm/gpuvm: allow building as module Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-11 13:09 ` [Nouveau] " Christian König
2023-09-11 13:09 ` Christian König
2023-09-11 13:09 ` Christian König
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 3/7] drm/nouveau: uvmm: rename 'umgr' to 'base' Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 4/7] drm/gpuvm: common dma-resv per struct drm_gpuvm Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-11 12:00 ` Boris Brezillon
2023-09-11 12:00 ` Boris Brezillon
2023-09-11 16:16 ` [Nouveau] " Danilo Krummrich
2023-09-11 16:16 ` Danilo Krummrich
2023-09-11 16:16 ` Danilo Krummrich
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 5/7] drm/gpuvm: add an abstraction for a VM / BO combination Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-11 17:19 ` [Nouveau] " Thomas Hellström
2023-09-11 17:19 ` Thomas Hellström
2023-09-11 17:19 ` Thomas Hellström
2023-09-11 17:49 ` [Nouveau] " Danilo Krummrich
2023-09-11 17:49 ` Danilo Krummrich
2023-09-11 17:49 ` Danilo Krummrich
2023-09-11 18:37 ` [Nouveau] " Thomas Hellström
2023-09-11 18:37 ` Thomas Hellström
2023-09-11 18:37 ` Thomas Hellström
2023-09-12 7:42 ` [Nouveau] " Thomas Hellström
2023-09-12 7:42 ` Thomas Hellström
2023-09-12 7:42 ` Thomas Hellström
2023-09-12 10:06 ` [Nouveau] " Danilo Krummrich
2023-09-12 10:06 ` Danilo Krummrich
2023-09-12 10:06 ` Danilo Krummrich
2023-09-12 10:33 ` [Nouveau] " Thomas Hellström
2023-09-12 10:33 ` Thomas Hellström
2023-09-12 10:33 ` Thomas Hellström
2023-09-12 11:05 ` [Nouveau] " Danilo Krummrich
2023-09-12 11:05 ` Danilo Krummrich
2023-09-12 11:05 ` Danilo Krummrich
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 6/7] drm/gpuvm: generalize dma_resv/extobj handling and GEM validation Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 20:16 ` [Nouveau] " kernel test robot
2023-09-09 20:16 ` kernel test robot
2023-09-09 20:16 ` kernel test robot
2023-09-11 10:35 ` Boris Brezillon
2023-09-11 10:35 ` Boris Brezillon
2023-09-11 16:23 ` Danilo Krummrich [this message]
2023-09-11 16:23 ` Danilo Krummrich
2023-09-11 16:23 ` Danilo Krummrich
2023-09-11 12:54 ` Boris Brezillon
2023-09-11 12:54 ` Boris Brezillon
2023-09-11 14:45 ` Boris Brezillon
2023-09-11 14:45 ` Boris Brezillon
2023-09-11 16:30 ` [Nouveau] " Danilo Krummrich
2023-09-11 16:30 ` Danilo Krummrich
2023-09-11 16:30 ` Danilo Krummrich
2023-09-12 16:20 ` [Nouveau] " Thomas Hellström
2023-09-12 16:20 ` Thomas Hellström
2023-09-12 16:20 ` Thomas Hellström
2023-09-12 16:50 ` [Nouveau] " Danilo Krummrich
2023-09-12 16:50 ` Danilo Krummrich
2023-09-12 16:50 ` Danilo Krummrich
2023-09-12 19:23 ` [Nouveau] " Thomas Hellström
2023-09-12 19:23 ` Thomas Hellström
2023-09-12 19:23 ` Thomas Hellström
2023-09-12 23:36 ` [Nouveau] " Danilo Krummrich
2023-09-12 23:36 ` Danilo Krummrich
2023-09-12 23:36 ` Danilo Krummrich
2023-09-13 9:14 ` [Nouveau] " Thomas Hellström
2023-09-13 9:14 ` Thomas Hellström
2023-09-13 9:14 ` Thomas Hellström
2023-09-13 12:16 ` [Nouveau] " Danilo Krummrich
2023-09-13 12:16 ` Danilo Krummrich
2023-09-13 12:16 ` Danilo Krummrich
2023-09-13 14:26 ` [Nouveau] " Christian König
2023-09-13 14:26 ` Christian König
2023-09-13 14:26 ` Christian König
2023-09-13 15:13 ` [Nouveau] " Thomas Hellström
2023-09-13 15:13 ` Thomas Hellström
2023-09-13 15:13 ` Thomas Hellström
2023-09-13 15:26 ` [Nouveau] " Christian König
2023-09-13 15:26 ` Christian König
2023-09-13 15:26 ` Christian König
2023-09-13 15:15 ` [Nouveau] " Danilo Krummrich
2023-09-13 15:15 ` Danilo Krummrich
2023-09-13 15:15 ` Danilo Krummrich
2023-09-13 15:33 ` [Nouveau] " Christian König
2023-09-13 15:33 ` Christian König
2023-09-13 15:33 ` Christian König
2023-09-13 15:46 ` [Nouveau] " Danilo Krummrich
2023-09-13 15:46 ` Danilo Krummrich
2023-09-13 15:46 ` Danilo Krummrich
2023-09-19 12:07 ` [Nouveau] " Christian König
2023-09-19 12:07 ` Christian König
2023-09-19 12:07 ` Christian König
2023-09-19 12:21 ` [Nouveau] " Thomas Hellström
2023-09-19 12:21 ` Thomas Hellström
2023-09-19 12:21 ` Thomas Hellström
2023-09-19 15:16 ` [Nouveau] " Danilo Krummrich
2023-09-19 15:16 ` Danilo Krummrich
2023-09-19 15:16 ` Danilo Krummrich
2023-09-19 15:23 ` [Nouveau] " Thomas Hellström
2023-09-19 15:23 ` Thomas Hellström
2023-09-19 15:23 ` Thomas Hellström
2023-09-20 5:37 ` [Nouveau] " Christian König
2023-09-20 5:37 ` Christian König
2023-09-20 5:37 ` Christian König
2023-09-20 7:44 ` [Nouveau] " Thomas Hellström
2023-09-20 7:44 ` Thomas Hellström
2023-09-20 7:44 ` Thomas Hellström
2023-09-20 8:29 ` [Nouveau] " Thomas Hellström
2023-09-20 8:29 ` Thomas Hellström
2023-09-20 8:29 ` Thomas Hellström
2023-09-20 10:51 ` [Nouveau] " Christian König
2023-09-20 10:51 ` Christian König
2023-09-20 10:51 ` Christian König
2023-09-20 12:06 ` [Nouveau] " Thomas Hellström
2023-09-20 12:06 ` Thomas Hellström
2023-09-20 12:06 ` Thomas Hellström
2023-09-20 13:06 ` [Nouveau] " Christian König
2023-09-20 13:06 ` Christian König
2023-09-20 13:06 ` Christian König
2023-09-20 13:38 ` [Nouveau] " Thomas Hellström
2023-09-20 13:38 ` Thomas Hellström
2023-09-20 13:38 ` Thomas Hellström
2023-09-20 13:48 ` [Nouveau] " Christian König
2023-09-20 13:48 ` Christian König
2023-09-20 13:48 ` Christian König
2023-09-20 14:02 ` [Nouveau] " Thomas Hellström
2023-09-20 14:02 ` Thomas Hellström
2023-09-20 14:02 ` Thomas Hellström
2023-09-20 14:11 ` [Nouveau] " Christian König
2023-09-20 14:11 ` Christian König
2023-09-20 14:11 ` Christian König
2023-09-14 10:57 ` [Nouveau] " Danilo Krummrich
2023-09-14 10:57 ` Danilo Krummrich
2023-09-14 11:32 ` Thomas Hellström
2023-09-14 11:32 ` Thomas Hellström
2023-09-14 15:27 ` Danilo Krummrich
2023-09-14 15:27 ` Danilo Krummrich
2023-09-14 17:13 ` Thomas Hellström
2023-09-14 17:13 ` Thomas Hellström
2023-09-14 17:15 ` Danilo Krummrich
2023-09-14 17:15 ` Danilo Krummrich
2023-09-18 11:21 ` Danilo Krummrich
2023-09-18 11:21 ` Danilo Krummrich
2023-09-13 7:03 ` Boris Brezillon
2023-09-13 7:03 ` Boris Brezillon
2023-09-13 7:05 ` [Nouveau] " Dave Airlie
2023-09-13 7:05 ` Dave Airlie
2023-09-13 7:05 ` Dave Airlie
2023-09-13 7:19 ` Boris Brezillon
2023-09-13 7:19 ` Boris Brezillon
2023-09-13 10:39 ` [Nouveau] " Thomas Hellström
2023-09-13 10:39 ` Thomas Hellström
2023-09-13 10:39 ` Thomas Hellström
2023-09-13 11:33 ` Boris Brezillon
2023-09-13 11:33 ` Boris Brezillon
2023-09-13 12:01 ` [Nouveau] " Danilo Krummrich
2023-09-13 12:01 ` Danilo Krummrich
2023-09-13 12:01 ` Danilo Krummrich
2023-09-13 13:22 ` [Nouveau] " Thomas Hellström
2023-09-13 13:22 ` Thomas Hellström
2023-09-13 13:22 ` Thomas Hellström
2023-09-13 14:01 ` Boris Brezillon
2023-09-13 14:01 ` Boris Brezillon
2023-09-13 14:29 ` [Nouveau] " Thomas Hellström
2023-09-13 14:29 ` Thomas Hellström
2023-09-13 14:29 ` Thomas Hellström
2023-09-13 15:17 ` Boris Brezillon
2023-09-13 15:17 ` Boris Brezillon
2023-09-14 8:20 ` Boris Brezillon
2023-09-14 8:20 ` Boris Brezillon
2023-09-14 10:45 ` [Nouveau] " Thomas Hellström
2023-09-14 10:45 ` Thomas Hellström
2023-09-14 10:45 ` Thomas Hellström
2023-09-14 11:54 ` Boris Brezillon
2023-09-14 11:54 ` Boris Brezillon
2023-09-14 13:33 ` [Nouveau] " Thomas Hellström
2023-09-14 13:33 ` Thomas Hellström
2023-09-14 13:33 ` Thomas Hellström
2023-09-14 15:37 ` Boris Brezillon
2023-09-14 15:37 ` Boris Brezillon
2023-09-14 13:48 ` [Nouveau] " Thomas Hellström
2023-09-14 13:48 ` Thomas Hellström
2023-09-14 13:48 ` Thomas Hellström
2023-09-14 16:36 ` [Nouveau] " Danilo Krummrich
2023-09-14 16:36 ` Danilo Krummrich
2023-09-14 16:36 ` Danilo Krummrich
2023-09-14 17:21 ` [Nouveau] " Thomas Hellström
2023-09-14 17:21 ` Thomas Hellström
2023-09-14 17:21 ` Thomas Hellström
2023-09-14 17:25 ` [Nouveau] " Danilo Krummrich
2023-09-14 17:25 ` Danilo Krummrich
2023-09-14 17:25 ` Danilo Krummrich
2023-09-14 19:14 ` [Nouveau] " Thomas Hellström
2023-09-14 19:14 ` Thomas Hellström
2023-09-14 19:14 ` Thomas Hellström
2023-09-09 15:31 ` [Nouveau] [PATCH drm-misc-next v3 7/7] drm/nouveau: GPUVM dma-resv/extobj handling, " Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
2023-09-09 15:31 ` Danilo Krummrich
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=ZP8+/gjvKFBGR/Y4@cassiopeiae \
--to=dakr@redhat.com \
--cc=boris.brezillon@collabora.com \
--cc=christian.koenig@amd.com \
--cc=daniel@ffwll.ch \
--cc=donald.robson@imgtec.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=faith.ekstrand@collabora.com \
--cc=linux-kernel@vger.kernel.org \
--cc=matthew.brost@intel.com \
--cc=nouveau@lists.freedesktop.org \
--cc=sarah.walker@imgtec.com \
--cc=thomas.hellstrom@linux.intel.com \
/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.