On 10.10.25 16:07, Sunil Khatri wrote:
> At times we need a bo reference for hmm and for that add
> a new struct amdgpu_hmm_range which will hold an optional
> bo member and hmm_range.
>
> Use amdgpu_hmm_range instead of hmm_range and let the bo
> as an optional argument for the caller if they want to
> the bo reference to be taken or they want to handle that
> explicitly.
>
> Signed-off-by: Sunil Khatri <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 +-
> .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 4 +--
> drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c | 36 +++++++++++++------
> drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h | 19 ++++++----
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 7 ++--
> drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 1 -
> drivers/gpu/drm/amd/amdkfd/kfd_migrate.h | 1 -
> drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 14 ++++----
> drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 1 -
> 13 files changed, 61 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> index 9e120c934cc1..8bdfcde2029b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> @@ -71,7 +71,7 @@ struct kgd_mem {
> struct mutex lock;
> struct amdgpu_bo *bo;
> struct dma_buf *dmabuf;
> - struct hmm_range *range;
> + struct amdgpu_hmm_range *range;
> struct list_head attachments;
> /* protected by amdkfd_process_info.lock */
> struct list_head validate_list;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 22c1bdc53d2e..56097fb6eecd 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -1057,7 +1057,7 @@ static int init_user_pages(struct kgd_mem *mem,
> uint64_t user_addr,
> struct amdkfd_process_info *process_info = mem->process_info;
> struct amdgpu_bo *bo = mem->bo;
> struct ttm_operation_ctx ctx = { true, false };
> - struct hmm_range *range;
> + struct amdgpu_hmm_range *range;
> int ret = 0;
>
> mutex_lock(&process_info->lock);
> @@ -1089,7 +1089,7 @@ static int init_user_pages(struct kgd_mem *mem,
> uint64_t user_addr,
> return 0;
> }
>
> - range = amdgpu_hmm_range_alloc();
> + range = amdgpu_hmm_range_alloc(NULL);
> if (unlikely(!range)) {
> ret = -ENOMEM;
> goto unregister_out;
> @@ -2574,7 +2574,7 @@ static int update_invalid_user_pages(struct
> amdkfd_process_info *process_info,
> }
> }
>
> - mem->range = amdgpu_hmm_range_alloc();
> + mem->range = amdgpu_hmm_range_alloc(NULL);
> if (unlikely(!mem->range))
> return -ENOMEM;
> /* Get updated user pages */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
> index a716c9886c74..2b5e7c46a39d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
> @@ -38,7 +38,7 @@ struct amdgpu_bo_list_entry {
> struct amdgpu_bo *bo;
> struct amdgpu_bo_va *bo_va;
> uint32_t priority;
> - struct hmm_range *range;
> + struct amdgpu_hmm_range *range;
> bool user_invalidated;
> };
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> index 087e5b5497e4..87872c0282e4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> @@ -29,7 +29,6 @@
> #include <linux/pagemap.h>
> #include <linux/sync_file.h>
> #include <linux/dma-buf.h>
> -#include <linux/hmm.h>
>
> #include <drm/amdgpu_drm.h>
> #include <drm/drm_syncobj.h>
> @@ -886,7 +885,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser
> *p,
> bool userpage_invalidated = false;
> struct amdgpu_bo *bo = e->bo;
>
> - e->range = amdgpu_hmm_range_alloc();
> + e->range = amdgpu_hmm_range_alloc(NULL);
> if (unlikely(!e->range))
> return -ENOMEM;
>
> @@ -895,7 +894,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser
> *p,
> goto out_free_user_pages;
>
> for (i = 0; i < bo->tbo.ttm->num_pages; i++) {
> - if (bo->tbo.ttm->pages[i] !=
> hmm_pfn_to_page(e->range->hmm_pfns[i])) {
> + if (bo->tbo.ttm->pages[i] !=
> +
> hmm_pfn_to_page(e->range->hmm_range.hmm_pfns[i])) {
> userpage_invalidated = true;
> break;
> }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index 82ddc8c22b64..ce073e894584 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -530,7 +530,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void
> *data,
> struct drm_amdgpu_gem_userptr *args = data;
> struct amdgpu_fpriv *fpriv = filp->driver_priv;
> struct drm_gem_object *gobj;
> - struct hmm_range *range;
> + struct amdgpu_hmm_range *range;
> struct amdgpu_bo *bo;
> uint32_t handle;
> int r;
> @@ -571,7 +571,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void
> *data,
> goto release_object;
>
> if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) {
> - range = amdgpu_hmm_range_alloc();
> + range = amdgpu_hmm_range_alloc(NULL);
> if (unlikely(!range))
> return -ENOMEM;
> r = amdgpu_ttm_tt_get_user_pages(bo, range);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
> index b582fd217bd0..9da1c5c69632 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
> @@ -168,12 +168,13 @@ void amdgpu_hmm_unregister(struct amdgpu_bo *bo)
> int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
> uint64_t start, uint64_t npages, bool readonly,
> void *owner,
> - struct hmm_range *hmm_range)
> + struct amdgpu_hmm_range *range)
> {
> unsigned long end;
> unsigned long timeout;
> unsigned long *pfns;
> int r = 0;
> + struct hmm_range *hmm_range = &range->hmm_range;
>
> pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
> if (unlikely(!pfns)) {
> @@ -226,25 +227,38 @@ int amdgpu_hmm_range_get_pages(struct
> mmu_interval_notifier *notifier,
> return r;
> }
>
> -bool amdgpu_hmm_range_valid(struct hmm_range *hmm_range)
> +bool amdgpu_hmm_range_valid(struct amdgpu_hmm_range *range)
> {
> - if (!hmm_range)
> + if (!range)
> return false;
>
> - return !mmu_interval_read_retry(hmm_range->notifier,
> - hmm_range->notifier_seq);
> + return !mmu_interval_read_retry(range->hmm_range.notifier,
> + range->hmm_range.notifier_seq);
> }
>
> -struct hmm_range *amdgpu_hmm_range_alloc(void)
> +struct amdgpu_hmm_range *amdgpu_hmm_range_alloc(struct amdgpu_bo *bo)
> {
> - return kzalloc(sizeof(struct hmm_range), GFP_KERNEL);
> + struct amdgpu_hmm_range *range;
> +
> + range = kzalloc(sizeof(struct amdgpu_hmm_range), GFP_KERNEL);
> + if (!range)
> + return NULL;
> +
> + if (bo)
> + range->bo = amdgpu_bo_ref(bo);
The functions amdgpu_bo_ref() and ...
> +
> + return range;
> }
>
> -void amdgpu_hmm_range_free(struct hmm_range *hmm_range)
> +void amdgpu_hmm_range_free(struct amdgpu_hmm_range *range)
> {
> - if (!hmm_range)
> + if (!range)
> return;
>
> - kvfree(hmm_range->hmm_pfns);
> - kfree(hmm_range);
> + kvfree(range->hmm_range.hmm_pfns);
> +
> + if (range->bo)
> + amdgpu_bo_unref(&range->bo);
... amdgpu_bo_unref() have intergrated NULL checks. So checking it here is
superflous.
It would also be helpful to have some kerneldoc on amdgpu_hmm_range_alloc() and
amdgpu_hmm_range_free(), but that is not a must have.
With that fixed the patch is Reviewed-by: Christian König
<[email protected]>
Regards,
Christian.
> +
> + kfree(range);
> }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
> index e85f912b8938..140bc9cd57b4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
> @@ -31,15 +31,20 @@
> #include <linux/interval_tree.h>
> #include <linux/mmu_notifier.h>
>
> +struct amdgpu_hmm_range {
> + struct hmm_range hmm_range;
> + struct amdgpu_bo *bo;
> +};
> +
> int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
> uint64_t start, uint64_t npages, bool readonly,
> void *owner,
> - struct hmm_range *hmm_range);
> + struct amdgpu_hmm_range *range);
>
> #if defined(CONFIG_HMM_MIRROR)
> -bool amdgpu_hmm_range_valid(struct hmm_range *hmm_range);
> -struct hmm_range *amdgpu_hmm_range_alloc(void);
> -void amdgpu_hmm_range_free(struct hmm_range *hmm_range);
> +bool amdgpu_hmm_range_valid(struct amdgpu_hmm_range *range);
> +struct amdgpu_hmm_range *amdgpu_hmm_range_alloc(struct amdgpu_bo *bo);
> +void amdgpu_hmm_range_free(struct amdgpu_hmm_range *range);
> int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr);
> void amdgpu_hmm_unregister(struct amdgpu_bo *bo);
> #else
> @@ -52,17 +57,17 @@ static inline int amdgpu_hmm_register(struct amdgpu_bo
> *bo, unsigned long addr)
>
> static inline void amdgpu_hmm_unregister(struct amdgpu_bo *bo) {}
>
> -static inline bool amdgpu_hmm_range_valid(struct hmm_range *hmm_range)
> +static inline bool amdgpu_hmm_range_valid(struct amdgpu_hmm_range *range)
> {
> return false;
> }
>
> -static inline struct hmm_range *amdgpu_hmm_range_alloc(void)
> +static inline struct amdgpu_hmm_range *amdgpu_hmm_range_alloc(struct
> amdgpu_bo *bo)
> {
> return NULL;
> }
>
> -static inline void amdgpu_hmm_range_free(struct hmm_range *hmm_range) {}
> +static inline void amdgpu_hmm_range_free(struct amdgpu_hmm_range *range) {}
> #endif
>
> #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> index 96bd0185f936..fd00ec7c99a1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> @@ -709,7 +709,7 @@ struct amdgpu_ttm_tt {
> * that range is a valid memory and it is freed too.
> */
> int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> - struct hmm_range *range)
> + struct amdgpu_hmm_range *range)
> {
> struct ttm_tt *ttm = bo->tbo.ttm;
> struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
> @@ -762,12 +762,12 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> * that backs user memory and will ultimately be mapped into the device
> * address space.
> */
> -void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct hmm_range
> *range)
> +void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct
> amdgpu_hmm_range *range)
> {
> unsigned long i;
>
> for (i = 0; i < ttm->num_pages; ++i)
> - ttm->pages[i] = range ? hmm_pfn_to_page(range->hmm_pfns[i]) :
> NULL;
> + ttm->pages[i] = range ?
> hmm_pfn_to_page(range->hmm_range.hmm_pfns[i]) : NULL;
> }
>
> /*
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> index 99c46821b961..0ebb99e8d792 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> @@ -28,6 +28,7 @@
> #include <drm/gpu_scheduler.h>
> #include <drm/ttm/ttm_placement.h>
> #include "amdgpu_vram_mgr.h"
> +#include "amdgpu_hmm.h"
>
> #define AMDGPU_PL_GDS (TTM_PL_PRIV + 0)
> #define AMDGPU_PL_GWS (TTM_PL_PRIV + 1)
> @@ -191,16 +192,16 @@ uint64_t amdgpu_ttm_domain_start(struct amdgpu_device
> *adev, uint32_t type);
>
> #if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
> int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> - struct hmm_range *range);
> + struct amdgpu_hmm_range *range);
> #else
> static inline int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> - struct hmm_range *range)
> + struct amdgpu_hmm_range *range)
> {
> return -EPERM;
> }
> #endif
>
> -void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct hmm_range
> *range);
> +void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct
> amdgpu_hmm_range *range);
> int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo,
> uint64_t *user_addr);
> int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
> b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
> index d10c6673f4de..3653c563ee9a 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
> @@ -21,7 +21,6 @@
> * OTHER DEALINGS IN THE SOFTWARE.
> */
> #include <linux/types.h>
> -#include <linux/hmm.h>
> #include <linux/dma-direction.h>
> #include <linux/dma-mapping.h>
> #include <linux/migrate.h>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
> b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
> index 2eebf67f9c2c..2b7fd442d29c 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
> @@ -31,7 +31,6 @@
> #include <linux/list.h>
> #include <linux/mutex.h>
> #include <linux/sched/mm.h>
> -#include <linux/hmm.h>
> #include "kfd_priv.h"
> #include "kfd_svm.h"
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index 91609dd5730f..f041643308ca 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1698,7 +1698,7 @@ static int svm_range_validate_and_map(struct mm_struct
> *mm,
> start = map_start << PAGE_SHIFT;
> end = (map_last + 1) << PAGE_SHIFT;
> for (addr = start; !r && addr < end; ) {
> - struct hmm_range *hmm_range = NULL;
> + struct amdgpu_hmm_range *range = NULL;
> unsigned long map_start_vma;
> unsigned long map_last_vma;
> struct vm_area_struct *vma;
> @@ -1737,13 +1737,13 @@ static int svm_range_validate_and_map(struct
> mm_struct *mm,
> }
>
> WRITE_ONCE(p->svms.faulting_task, current);
> - hmm_range = amdgpu_hmm_range_alloc();
> + range = amdgpu_hmm_range_alloc(NULL);
> r = amdgpu_hmm_range_get_pages(&prange->notifier, addr,
> npages,
> readonly, owner,
> - hmm_range);
> + range);
> WRITE_ONCE(p->svms.faulting_task, NULL);
> if (r) {
> - amdgpu_hmm_range_free(hmm_range);
> + amdgpu_hmm_range_free(range);
> pr_debug("failed %d to get svm range pages\n",
> r);
> }
> } else {
> @@ -1753,7 +1753,7 @@ static int svm_range_validate_and_map(struct mm_struct
> *mm,
> if (!r) {
> offset = (addr >> PAGE_SHIFT) - prange->start;
> r = svm_range_dma_map(prange, ctx->bitmap, offset,
> npages,
> - hmm_range->hmm_pfns);
> + range->hmm_range.hmm_pfns);
> if (r)
> pr_debug("failed %d to dma map range\n", r);
> }
> @@ -1764,12 +1764,12 @@ static int svm_range_validate_and_map(struct
> mm_struct *mm,
> * Overrride return value to TRY AGAIN only if prior returns
> * were successful
> */
> - if (hmm_range && !amdgpu_hmm_range_valid(hmm_range) && !r) {
> + if (range && !amdgpu_hmm_range_valid(range) && !r) {
> pr_debug("hmm update the range, need validate again\n");
> r = -EAGAIN;
> }
> /* Free the hmm range */
> - amdgpu_hmm_range_free(hmm_range);
> + amdgpu_hmm_range_free(range);
>
>
> if (!r && !list_empty(&prange->child_list)) {
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> index 01c7a4877904..a63dfc95b602 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> @@ -31,7 +31,6 @@
> #include <linux/list.h>
> #include <linux/mutex.h>
> #include <linux/sched/mm.h>
> -#include <linux/hmm.h>
> #include "amdgpu.h"
> #include "kfd_priv.h"
>