Unmap the svm range from cpu will unmap and remove ranges, this cannot
align the start and last address to range granularity. If we unmap
from GPUs first, the bitmap_mapped flag is updated, split may get
incorrect bitmap_mapped for the remaining ranges.

We should split the range and bitmap_mapped first, then unmap the range
from GPUs.

Signed-off-by: Philip Yang <philip.y...@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 0ee5633c8972..e1392b277399 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2672,24 +2672,32 @@ svm_range_unmap_from_cpu(struct mm_struct *mm, struct 
svm_range *prange,
 
        list_for_each_entry(pchild, &prange->child_list, child_list) {
                mutex_lock_nested(&pchild->lock, 1);
-               s = max(start, pchild->start);
-               l = min(last, pchild->last);
-               if (l >= s)
-                       svm_range_unmap_from_gpus(pchild, s, l, trigger);
                svm_range_unmap_split(mm, prange, pchild, start, last);
                mutex_unlock(&pchild->lock);
        }
-       s = max(start, prange->start);
-       l = min(last, prange->last);
-       if (l >= s)
-               svm_range_unmap_from_gpus(prange, s, l, trigger);
        svm_range_unmap_split(mm, prange, prange, start, last);
-
        if (unmap_parent)
                svm_range_add_list_work(svms, prange, mm, SVM_OP_UNMAP_RANGE);
        else
                svm_range_add_list_work(svms, prange, mm,
                                        SVM_OP_UPDATE_RANGE_NOTIFIER);
+
+       list_for_each_entry(pchild, &prange->child_list, child_list) {
+               if (pchild->work_item.op != SVM_OP_UNMAP_RANGE)
+                       continue;
+
+               s = max(start, pchild->start);
+               l = min(last, pchild->last);
+               if (l >= s)
+                       svm_range_unmap_from_gpus(pchild, s, l, trigger);
+       }
+       if (prange->work_item.op == SVM_OP_UNMAP_RANGE) {
+               s = max(start, prange->start);
+               l = min(last, prange->last);
+               if (l >= s)
+                       svm_range_unmap_from_gpus(prange, s, l, trigger);
+       }
+
        schedule_deferred_list_work(svms);
 
        kfd_unref_process(p);
-- 
2.35.1

Reply via email to