Commit dab74906 authored by Himal Prasad Ghimiray's avatar Himal Prasad Ghimiray Committed by Matthew Brost
Browse files

drm/gpusvm: Make drm_gpusvm_for_each_* macros public



The drm_gpusvm_for_each_notifier, drm_gpusvm_for_each_notifier_safe and
drm_gpusvm_for_each_range_safe macros are useful for locating notifiers
and ranges within a user-specified range. By making these macros public,
we enable broader access and utility for developers who need to leverage
them in their implementations.

v2 (Matthew Brost)
- drop inline __drm_gpusvm_range_find
- /s/notifier_iter_first/drm_gpusvm_notifier_find

Signed-off-by: default avatarHimal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: default avatarMatthew Brost <matthew.brost@intel.com>
Signed-off-by: default avatarMatthew Brost <matthew.brost@intel.com>
Link: https://lore.kernel.org/r/20250819162058.2777306-5-himal.prasad.ghimiray@intel.com
parent baf1638c
Loading
Loading
Loading
Loading
+25 −97
Original line number Diff line number Diff line
@@ -271,107 +271,50 @@ npages_in_range(unsigned long start, unsigned long end)
}

/**
 * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
 * @notifier: Pointer to the GPU SVM notifier structure.
 * @start: Start address of the range
 * @end: End address of the range
 * drm_gpusvm_notifier_find() - Find GPU SVM notifier from GPU SVM
 * @gpusvm: Pointer to the GPU SVM structure.
 * @start: Start address of the notifier
 * @end: End address of the notifier
 *
 * Return: A pointer to the drm_gpusvm_range if found or NULL
 * Return: A pointer to the drm_gpusvm_notifier if found or NULL
 */
struct drm_gpusvm_range *
drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
struct drm_gpusvm_notifier *
drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
			 unsigned long end)
{
	struct interval_tree_node *itree;

	itree = interval_tree_iter_first(&notifier->root, start, end - 1);
	itree = interval_tree_iter_first(&gpusvm->root, start, end - 1);

	if (itree)
		return container_of(itree, struct drm_gpusvm_range, itree);
		return container_of(itree, struct drm_gpusvm_notifier, itree);
	else
		return NULL;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_find);

/**
 * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier
 * @range__: Iterator variable for the ranges
 * @next__: Iterator variable for the ranges temporay storage
 * @notifier__: Pointer to the GPU SVM notifier
 * @start__: Start address of the range
 * @end__: End address of the range
 *
 * This macro is used to iterate over GPU SVM ranges in a notifier while
 * removing ranges from it.
 */
#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
	     (next__) = __drm_gpusvm_range_next(range__);				\
	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))
EXPORT_SYMBOL_GPL(drm_gpusvm_notifier_find);

/**
 * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list
 * @notifier: a pointer to the current drm_gpusvm_notifier
 * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
 * @notifier: Pointer to the GPU SVM notifier structure.
 * @start: Start address of the range
 * @end: End address of the range
 *
 * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if
 *         the current notifier is the last one or if the input notifier is
 *         NULL.
 * Return: A pointer to the drm_gpusvm_range if found or NULL
 */
static struct drm_gpusvm_notifier *
__drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier)
{
	if (notifier && !list_is_last(&notifier->entry,
				      &notifier->gpusvm->notifier_list))
		return list_next_entry(notifier, entry);

	return NULL;
}

static struct drm_gpusvm_notifier *
notifier_iter_first(struct rb_root_cached *root, unsigned long start,
		    unsigned long last)
struct drm_gpusvm_range *
drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
		      unsigned long end)
{
	struct interval_tree_node *itree;

	itree = interval_tree_iter_first(root, start, last);
	itree = interval_tree_iter_first(&notifier->root, start, end - 1);

	if (itree)
		return container_of(itree, struct drm_gpusvm_notifier, itree);
		return container_of(itree, struct drm_gpusvm_range, itree);
	else
		return NULL;
}

/**
 * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm
 * @notifier__: Iterator variable for the notifiers
 * @notifier__: Pointer to the GPU SVM notifier
 * @start__: Start address of the notifier
 * @end__: End address of the notifier
 *
 * This macro is used to iterate over GPU SVM notifiers in a gpusvm.
 */
#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
	for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1);	\
	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

/**
 * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm
 * @notifier__: Iterator variable for the notifiers
 * @next__: Iterator variable for the notifiers temporay storage
 * @notifier__: Pointer to the GPU SVM notifier
 * @start__: Start address of the notifier
 * @end__: End address of the notifier
 *
 * This macro is used to iterate over GPU SVM notifiers in a gpusvm while
 * removing notifiers from it.
 */
#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
	for ((notifier__) = notifier_iter_first(&(gpusvm__)->root, (start__), (end__) - 1),	\
	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))
EXPORT_SYMBOL_GPL(drm_gpusvm_range_find);

/**
 * drm_gpusvm_notifier_invalidate() - Invalidate a GPU SVM notifier.
@@ -472,22 +415,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
}
EXPORT_SYMBOL_GPL(drm_gpusvm_init);

/**
 * drm_gpusvm_notifier_find() - Find GPU SVM notifier
 * @gpusvm: Pointer to the GPU SVM structure
 * @fault_addr: Fault address
 *
 * This function finds the GPU SVM notifier associated with the fault address.
 *
 * Return: Pointer to the GPU SVM notifier on success, NULL otherwise.
 */
static struct drm_gpusvm_notifier *
drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm,
			 unsigned long fault_addr)
{
	return notifier_iter_first(&gpusvm->root, fault_addr, fault_addr + 1);
}

/**
 * to_drm_gpusvm_notifier() - retrieve the container struct for a given rbtree node
 * @node: a pointer to the rbtree node embedded within a drm_gpusvm_notifier struct
@@ -943,7 +870,7 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
	if (!mmget_not_zero(mm))
		return ERR_PTR(-EFAULT);

	notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr);
	notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr, fault_addr + 1);
	if (!notifier) {
		notifier = drm_gpusvm_notifier_alloc(gpusvm, fault_addr);
		if (IS_ERR(notifier)) {
@@ -1107,7 +1034,8 @@ void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
	drm_gpusvm_driver_lock_held(gpusvm);

	notifier = drm_gpusvm_notifier_find(gpusvm,
					    drm_gpusvm_range_start(range));
					    drm_gpusvm_range_start(range),
					    drm_gpusvm_range_start(range) + 1);
	if (WARN_ON_ONCE(!notifier))
		return;

+70 −0
Original line number Diff line number Diff line
@@ -282,6 +282,10 @@ void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
			    unsigned long end);

struct drm_gpusvm_notifier *
drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
			 unsigned long end);

struct drm_gpusvm_range *
drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
		      unsigned long end);
@@ -434,4 +438,70 @@ __drm_gpusvm_range_next(struct drm_gpusvm_range *range)
	     (range__) && (drm_gpusvm_range_start(range__) < (end__));	\
	     (range__) = __drm_gpusvm_range_next(range__))

/**
 * drm_gpusvm_for_each_range_safe() - Safely iterate over GPU SVM ranges in a notifier
 * @range__: Iterator variable for the ranges
 * @next__: Iterator variable for the ranges temporay storage
 * @notifier__: Pointer to the GPU SVM notifier
 * @start__: Start address of the range
 * @end__: End address of the range
 *
 * This macro is used to iterate over GPU SVM ranges in a notifier while
 * removing ranges from it.
 */
#define drm_gpusvm_for_each_range_safe(range__, next__, notifier__, start__, end__)	\
	for ((range__) = drm_gpusvm_range_find((notifier__), (start__), (end__)),	\
	     (next__) = __drm_gpusvm_range_next(range__);				\
	     (range__) && (drm_gpusvm_range_start(range__) < (end__));			\
	     (range__) = (next__), (next__) = __drm_gpusvm_range_next(range__))

/**
 * __drm_gpusvm_notifier_next() - get the next drm_gpusvm_notifier in the list
 * @notifier: a pointer to the current drm_gpusvm_notifier
 *
 * Return: A pointer to the next drm_gpusvm_notifier if available, or NULL if
 *         the current notifier is the last one or if the input notifier is
 *         NULL.
 */
static inline struct drm_gpusvm_notifier *
__drm_gpusvm_notifier_next(struct drm_gpusvm_notifier *notifier)
{
	if (notifier && !list_is_last(&notifier->entry,
				      &notifier->gpusvm->notifier_list))
		return list_next_entry(notifier, entry);

	return NULL;
}

/**
 * drm_gpusvm_for_each_notifier() - Iterate over GPU SVM notifiers in a gpusvm
 * @notifier__: Iterator variable for the notifiers
 * @gpusvm__: Pointer to the GPU SVM notifier
 * @start__: Start address of the notifier
 * @end__: End address of the notifier
 *
 * This macro is used to iterate over GPU SVM notifiers in a gpusvm.
 */
#define drm_gpusvm_for_each_notifier(notifier__, gpusvm__, start__, end__)		\
	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__));	\
	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
	     (notifier__) = __drm_gpusvm_notifier_next(notifier__))

/**
 * drm_gpusvm_for_each_notifier_safe() - Safely iterate over GPU SVM notifiers in a gpusvm
 * @notifier__: Iterator variable for the notifiers
 * @next__: Iterator variable for the notifiers temporay storage
 * @gpusvm__: Pointer to the GPU SVM notifier
 * @start__: Start address of the notifier
 * @end__: End address of the notifier
 *
 * This macro is used to iterate over GPU SVM notifiers in a gpusvm while
 * removing notifiers from it.
 */
#define drm_gpusvm_for_each_notifier_safe(notifier__, next__, gpusvm__, start__, end__)	\
	for ((notifier__) = drm_gpusvm_notifier_find((gpusvm__), (start__), (end__)),	\
	     (next__) = __drm_gpusvm_notifier_next(notifier__);				\
	     (notifier__) && (drm_gpusvm_notifier_start(notifier__) < (end__));		\
	     (notifier__) = (next__), (next__) = __drm_gpusvm_notifier_next(notifier__))

#endif /* __DRM_GPUSVM_H__ */