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: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Link: https://lore.kernel.org/r/20250819162058.2777306-5-himal.prasad.ghimiray@intel.com
This commit is contained in:
Himal Prasad Ghimiray
2025-08-19 21:50:58 +05:30
committed by Matthew Brost
parent baf1638c09
commit dab7490642
2 changed files with 96 additions and 98 deletions

View File

@@ -270,6 +270,29 @@ npages_in_range(unsigned long start, unsigned long end)
return (end - start) >> PAGE_SHIFT;
}
/**
* 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_notifier if found or NULL
*/
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(&gpusvm->root, start, end - 1);
if (itree)
return container_of(itree, struct drm_gpusvm_notifier, itree);
else
return NULL;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_notifier_find);
/**
* drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
* @notifier: Pointer to the GPU SVM notifier structure.
@@ -293,86 +316,6 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
}
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__))
/**
* __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 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 interval_tree_node *itree;
itree = interval_tree_iter_first(root, start, last);
if (itree)
return container_of(itree, struct drm_gpusvm_notifier, 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__))
/**
* drm_gpusvm_notifier_invalidate() - Invalidate a GPU SVM notifier.
* @mni: Pointer to the mmu_interval_notifier structure.
@@ -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;

View File

@@ -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__ */