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.Yang@xxxxxxx> --- 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