amd-drm-fixes-7.1-2026-05-28:

amdgpu:
 - GEM_OP warning fix
 - GEM_OP locking fix
 - Userq fixes
 - DCN 2.1 refclk fix
 - SI fix
 - HMM fixes
 
 amdkfd:
 - svm_range_set_attr locking fix
 - CRIU restore fix
 - KFD debugger fix
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCahiwFgAKCRC93/aFa7yZ
 2AP0AQD7WzUcOOJjhHHoxKeP9AFLhbIcMvqhv9ifx3aIqf4bTwD7B/q9AYl3vUrU
 Vc67c+5BeibfOUMArCMDm7bPmPLW0Ac=
 =N6nq
 -----END PGP SIGNATURE-----

Merge tag 'amd-drm-fixes-7.1-2026-05-28' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes

amd-drm-fixes-7.1-2026-05-28:

amdgpu:
- GEM_OP warning fix
- GEM_OP locking fix
- Userq fixes
- DCN 2.1 refclk fix
- SI fix
- HMM fixes

amdkfd:
- svm_range_set_attr locking fix
- CRIU restore fix
- KFD debugger fix

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260528211843.893681-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2026-05-29 11:55:08 +10:00
commit e81d3b59f7
12 changed files with 150 additions and 213 deletions

View File

@ -1093,9 +1093,16 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
* If that number is larger than the size of the array, the ioctl must
* be retried.
*/
if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
r = -EINVAL;
goto out_exec;
}
vm_entries = kvcalloc(args->num_entries, sizeof(*vm_entries), GFP_KERNEL);
if (!vm_entries)
return -ENOMEM;
if (!vm_entries) {
r = -ENOMEM;
goto out_exec;
}
amdgpu_vm_bo_va_for_each_valid_mapping(bo_va, mapping) {
if (num_mappings < args->num_entries) {

View File

@ -51,8 +51,6 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_hmm.h"
#define MAX_WALK_BYTE (2UL << 30)
/**
* amdgpu_hmm_invalidate_gfx - callback to notify about mm change
*
@ -78,6 +76,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
mmu_interval_set_seq(mni, cur_seq);
amdgpu_vm_bo_invalidate(bo, false);
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
false, MAX_SCHEDULE_TIMEOUT);
mutex_unlock(&adev->notifier_lock);
@ -170,11 +169,13 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
void *owner,
struct amdgpu_hmm_range *range)
{
unsigned long end;
const u64 max_bytes = SZ_2G;
struct hmm_range *hmm_range = &range->hmm_range;
unsigned long timeout;
unsigned long *pfns;
int r = 0;
struct hmm_range *hmm_range = &range->hmm_range;
unsigned long end;
int r;
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
if (unlikely(!pfns)) {
@ -191,8 +192,9 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
end = start + npages * PAGE_SIZE;
hmm_range->dev_private_owner = owner;
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
do {
hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
hmm_range->end = min(hmm_range->start + max_bytes, end);
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
hmm_range->start, hmm_range->end);
@ -200,7 +202,6 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
retry:
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
r = hmm_range_fault(hmm_range);
if (unlikely(r)) {
if (r == -EBUSY && !time_after(jiffies, timeout))
@ -210,7 +211,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
if (hmm_range->end == end)
break;
hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
hmm_range->hmm_pfns += max_bytes >> PAGE_SHIFT;
hmm_range->start = hmm_range->end;
} while (hmm_range->end < end);

View File

@ -2280,7 +2280,8 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
list_for_each_entry(obj, &con->head, node) {
if (amdgpu_ras_is_supported(adev, obj->head.block) &&
(obj->attr_inuse == 1)) {
sprintf(fs_info.debugfs_name, "%s_err_inject",
snprintf(fs_info.debugfs_name, sizeof(fs_info.debugfs_name),
"%s_err_inject",
get_ras_block_str(&obj->head));
fs_info.head = obj->head;
amdgpu_ras_debugfs_create(adev, &fs_info, dir);

View File

@ -215,33 +215,15 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
xa_unlock_irqrestore(xa, flags);
}
static int amdgpu_userq_buffer_va_list_add(struct amdgpu_usermode_queue *queue,
struct amdgpu_bo_va_mapping *va_map, u64 addr)
{
struct amdgpu_userq_va_cursor *va_cursor;
struct userq_va_list;
va_cursor = kzalloc_obj(*va_cursor);
if (!va_cursor)
return -ENOMEM;
INIT_LIST_HEAD(&va_cursor->list);
va_cursor->gpu_addr = addr;
va_map->bo_va->userq_va_mapped = true;
list_add(&va_cursor->list, &queue->userq_va_list);
return 0;
}
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,
u64 addr, u64 expected_size)
u64 addr, u64 expected_size,
u64 *va_out)
{
struct amdgpu_bo_va_mapping *va_map;
struct amdgpu_vm *vm = queue->vm;
u64 user_addr;
u64 size;
int r = 0;
/* Caller must hold vm->root.bo reservation */
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
@ -250,20 +232,18 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
size = expected_size >> AMDGPU_GPU_PAGE_SHIFT;
va_map = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
if (!va_map) {
r = -EINVAL;
goto out_err;
}
if (!va_map)
return -EINVAL;
/* Only validate the userq whether resident in the VM mapping range */
if (user_addr >= va_map->start &&
va_map->last - user_addr + 1 >= size) {
amdgpu_userq_buffer_va_list_add(queue, va_map, user_addr);
va_map->bo_va->userq_va_mapped = true;
*va_out = user_addr;
return 0;
}
r = -EINVAL;
out_err:
return r;
return -EINVAL;
}
static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
@ -284,14 +264,16 @@ static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
static bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
int r = 0;
int i, r = 0;
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
r += amdgpu_userq_buffer_va_mapped(queue->vm, va_cursor->gpu_addr);
for (i = 0; i < ARRAY_SIZE(queue->userq_vas.va_array); i++) {
if (!queue->userq_vas.va_array[i])
continue;
r += amdgpu_userq_buffer_va_mapped(queue->vm,
queue->userq_vas.va_array[i]);
dev_dbg(queue->userq_mgr->adev->dev,
"validate the userq mapping:%p va:%llx r:%d\n",
queue, va_cursor->gpu_addr, r);
queue, queue->userq_vas.va_array[i], r);
}
if (r != 0)
@ -300,24 +282,7 @@ static bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_usermode_queue *queue)
return false;
}
static void amdgpu_userq_buffer_vas_list_cleanup(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
struct amdgpu_bo_va_mapping *mapping;
/* Caller must hold vm->root.bo reservation */
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, va_cursor->gpu_addr);
if (mapping)
dev_dbg(adev->dev, "delete the userq:%p va:%llx\n",
queue, va_cursor->gpu_addr);
list_del(&va_cursor->list);
kfree(va_cursor);
}
}
static int amdgpu_userq_preempt_helper(struct amdgpu_usermode_queue *queue)
{
@ -417,18 +382,14 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
const struct amdgpu_userq_funcs *uq_funcs = adev->userq_funcs[queue->queue_type];
/* Wait for mode-1 reset to complete */
down_read(&adev->reset_domain->sem);
uq_funcs->mqd_destroy(queue);
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
amdgpu_userq_fence_driver_free(queue);
queue->fence_drv = NULL;
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
up_read(&adev->reset_domain->sem);
}
@ -467,81 +428,15 @@ amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
dma_fence_put(ev_fence);
}
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj,
int size)
{
struct amdgpu_device *adev = uq_mgr->adev;
struct amdgpu_bo_param bp;
int r;
memset(&bp, 0, sizeof(bp));
bp.byte_align = PAGE_SIZE;
bp.domain = AMDGPU_GEM_DOMAIN_GTT;
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
bp.type = ttm_bo_type_kernel;
bp.size = size;
bp.resv = NULL;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
r = amdgpu_bo_create(adev, &bp, &userq_obj->obj);
if (r) {
drm_file_err(uq_mgr->file, "Failed to allocate BO for userqueue (%d)", r);
return r;
}
r = amdgpu_bo_reserve(userq_obj->obj, true);
if (r) {
drm_file_err(uq_mgr->file, "Failed to reserve BO to map (%d)", r);
goto free_obj;
}
r = amdgpu_bo_pin(userq_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
if (r)
goto unresv;
r = amdgpu_ttm_alloc_gart(&(userq_obj->obj)->tbo);
if (r) {
drm_file_err(uq_mgr->file, "Failed to alloc GART for userqueue object (%d)", r);
goto unpin_bo;
}
r = amdgpu_bo_kmap(userq_obj->obj, &userq_obj->cpu_ptr);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map BO for userqueue (%d)", r);
goto unpin_bo;
}
userq_obj->gpu_addr = amdgpu_bo_gpu_offset(userq_obj->obj);
amdgpu_bo_unreserve(userq_obj->obj);
memset(userq_obj->cpu_ptr, 0, size);
return 0;
unpin_bo:
amdgpu_bo_unpin(userq_obj->obj);
unresv:
amdgpu_bo_unreserve(userq_obj->obj);
free_obj:
amdgpu_bo_unref(&userq_obj->obj);
return r;
}
void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj)
{
amdgpu_bo_kunmap(userq_obj->obj);
amdgpu_bo_unpin(userq_obj->obj);
amdgpu_bo_unref(&userq_obj->obj);
}
uint64_t
static int
amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_db_info *db_info,
struct drm_file *filp)
struct drm_file *filp,
u64 *index)
{
uint64_t index;
u64 doorbell_index;
struct drm_gem_object *gobj;
struct amdgpu_userq_obj *db_obj = db_info->db_obj;
int r, db_size;
@ -588,12 +483,13 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
goto unpin_bo;
}
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
db_info->doorbell_offset, db_size);
doorbell_index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
db_info->doorbell_offset, db_size);
drm_dbg_driver(adev_to_drm(uq_mgr->adev),
"[Usermode queues] doorbell index=%lld\n", index);
"[Usermode queues] doorbell index=%lld\n", doorbell_index);
amdgpu_bo_unreserve(db_obj->obj);
return index;
*index = doorbell_index;
return 0;
unpin_bo:
amdgpu_bo_unpin(db_obj->obj);
@ -608,9 +504,7 @@ static int
amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
{
struct amdgpu_device *adev = uq_mgr->adev;
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
struct amdgpu_vm *vm = &fpriv->vm;
const struct amdgpu_userq_funcs *uq_funcs = adev->userq_funcs[queue->queue_type];
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
@ -618,14 +512,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
/* Cancel any pending hang detection work and cleanup */
cancel_delayed_work_sync(&queue->hang_detect_work);
r = amdgpu_bo_reserve(vm->root.bo, false);
if (r) {
drm_file_err(uq_mgr->file, "Failed to reserve root bo during userqueue destroy\n");
return r;
}
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
amdgpu_bo_unreserve(vm->root.bo);
mutex_lock(&uq_mgr->userq_mutex);
amdgpu_userq_wait_for_last_fence(queue);
@ -637,6 +523,10 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
amdgpu_userq_cleanup(queue);
mutex_unlock(&uq_mgr->userq_mutex);
cancel_delayed_work_sync(&queue->hang_detect_work);
uq_funcs->mqd_destroy(queue);
queue->userq_mgr = NULL;
amdgpu_bo_reserve(queue->db_obj.obj, true);
amdgpu_bo_unpin(queue->db_obj.obj);
amdgpu_bo_unreserve(queue->db_obj.obj);
@ -739,7 +629,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
}
kref_init(&queue->refcount);
INIT_LIST_HEAD(&queue->userq_va_list);
queue->doorbell_handle = args->in.doorbell_handle;
queue->queue_type = args->in.ip_type;
queue->vm = &fpriv->vm;
@ -748,26 +637,29 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
INIT_DELAYED_WORK(&queue->hang_detect_work,
amdgpu_userq_hang_detect_work);
mutex_init(&queue->fence_drv_lock);
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
if (r)
goto free_queue;
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
mutex_init(&queue->fence_drv_lock);
/* Make sure the queue can actually run with those virtual addresses. */
r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
if (r)
goto free_fence_drv;
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va,
args->in.queue_size) ||
args->in.queue_size,
&queue->userq_vas.va.queue_rb) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va,
AMDGPU_GPU_PAGE_SIZE) ||
AMDGPU_GPU_PAGE_SIZE,
&queue->userq_vas.va.rptr) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va,
AMDGPU_GPU_PAGE_SIZE)) {
AMDGPU_GPU_PAGE_SIZE,
&queue->userq_vas.va.wptr)) {
r = -EINVAL;
amdgpu_bo_unreserve(fpriv->vm.root.bo);
goto clean_mapping;
goto free_fence_drv;
}
amdgpu_bo_unreserve(fpriv->vm.root.bo);
@ -776,18 +668,17 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
db_info.doorbell_handle = queue->doorbell_handle;
db_info.db_obj = &queue->db_obj;
db_info.doorbell_offset = args->in.doorbell_offset;
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
if (index == (uint64_t)-EINVAL) {
r = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp, &index);
if (r) {
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
r = -EINVAL;
goto clean_mapping;
goto free_fence_drv;
}
queue->doorbell_index = index;
r = uq_funcs->mqd_create(queue, &args->in);
if (r) {
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
goto clean_mapping;
goto clean_doorbell_bo;
}
/* Update VM owner at userq submit-time for page-fault attribution. */
@ -808,7 +699,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
if (r) {
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
mutex_unlock(&uq_mgr->userq_mutex);
goto clean_doorbell;
goto erase_doorbell;
}
}
@ -831,15 +722,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
args->out.queue_id = qid;
return 0;
clean_doorbell:
erase_doorbell:
xa_erase_irq(&adev->userq_doorbell_xa, index);
clean_mqd:
uq_funcs->mqd_destroy(queue);
clean_mapping:
amdgpu_bo_reserve(fpriv->vm.root.bo, true);
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
amdgpu_bo_unreserve(fpriv->vm.root.bo);
mutex_destroy(&queue->fence_drv_lock);
clean_doorbell_bo:
amdgpu_bo_reserve(queue->db_obj.obj, true);
amdgpu_bo_unpin(queue->db_obj.obj);
amdgpu_bo_unreserve(queue->db_obj.obj);
amdgpu_bo_unref(&queue->db_obj.obj);
free_fence_drv:
amdgpu_userq_fence_driver_free(queue);
free_queue:

View File

@ -48,11 +48,6 @@ struct amdgpu_userq_obj {
struct amdgpu_bo *obj;
};
struct amdgpu_userq_va_cursor {
u64 gpu_addr;
struct list_head list;
};
struct amdgpu_usermode_queue {
int queue_type;
enum amdgpu_userq_state state;
@ -93,7 +88,17 @@ struct amdgpu_usermode_queue {
struct delayed_work hang_detect_work;
struct kref refcount;
struct list_head userq_va_list;
union {
struct {
u64 queue_rb;
u64 wptr;
u64 rptr;
u64 eop;
u64 shadow;
u64 csa;
} va;
u64 va_array[6];
} userq_vas;
};
struct amdgpu_userq_funcs {
@ -151,22 +156,11 @@ void amdgpu_userq_mgr_cancel_reset_work(struct amdgpu_device *adev);
void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr);
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj,
int size);
void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj);
void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr);
uint64_t amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_db_info *db_info,
struct drm_file *filp);
u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev);
bool amdgpu_userq_enabled(struct drm_device *dev);
@ -185,7 +179,8 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell);
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,
u64 addr, u64 expected_size);
u64 addr, u64 expected_size, u64 *va_out);
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t saddr);

View File

@ -1631,6 +1631,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
{
struct amdgpu_bo_va *bo_va;
struct dma_resv *resv;
struct amdgpu_bo *bo;
bool clear, unlock;
int r;
@ -1650,11 +1651,13 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
while (!list_empty(&vm->invalidated)) {
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
base.vm_status);
resv = bo_va->base.bo->tbo.base.resv;
bo = bo_va->base.bo;
resv = bo->tbo.base.resv;
spin_unlock(&vm->status_lock);
/* Try to reserve the BO to avoid clearing its ptes */
if (!adev->debug_vm && dma_resv_trylock(resv)) {
if (!adev->debug_vm && !amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) &&
dma_resv_trylock(resv)) {
clear = false;
unlock = true;
/* The caller is already holding the reservation lock */

View File

@ -81,7 +81,7 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
ret = amdgpu_ttm_alloc_gart(&wptr_obj->obj->tbo);
if (ret) {
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
goto fail_map;
goto fail_alloc_gart;
}
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(wptr_obj->obj);
@ -89,6 +89,8 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
drm_exec_fini(&exec);
return 0;
fail_alloc_gart:
amdgpu_bo_unpin(wptr_obj->obj);
fail_map:
amdgpu_bo_unref(&wptr_obj->obj);
fail_lock:
@ -190,12 +192,16 @@ static int mes_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
* for the same.
*/
size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_GANG_CTX_SZ;
r = amdgpu_userq_create_object(uq_mgr, ctx, size);
r = amdgpu_bo_create_kernel(uq_mgr->adev, size, 0,
AMDGPU_GEM_DOMAIN_GTT,
&ctx->obj, &ctx->gpu_addr,
&ctx->cpu_ptr);
if (r) {
DRM_ERROR("Failed to allocate ctx space bo for userqueue, err:%d\n", r);
return r;
}
memset(ctx->cpu_ptr, 0, size);
return 0;
}
@ -268,13 +274,19 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
return -ENOMEM;
}
r = amdgpu_userq_create_object(uq_mgr, &queue->mqd,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size));
r = amdgpu_bo_create_kernel(adev,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size),
0, AMDGPU_GEM_DOMAIN_GTT,
&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
if (r) {
DRM_ERROR("Failed to create MQD object for userqueue\n");
goto free_props;
}
memset(queue->mqd.cpu_ptr, 0,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size));
/* Initialize the MQD BO with user given values */
userq_props->wptr_gpu_addr = mqd_user->wptr_va;
userq_props->rptr_gpu_addr = mqd_user->rptr_va;
@ -306,8 +318,9 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
kfree(compute_mqd);
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
2048);
r = amdgpu_userq_input_va_validate(adev, queue,
compute_mqd->eop_va, 2048,
&queue->userq_vas.va.eop);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(compute_mqd);
@ -356,7 +369,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
shadow_info.shadow_size);
shadow_info.shadow_size,
&queue->userq_vas.va.shadow);
if (r) {
amdgpu_bo_unreserve(queue->vm->root.bo);
kfree(mqd_gfx_v11);
@ -364,7 +378,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
shadow_info.csa_size);
shadow_info.csa_size,
&queue->userq_vas.va.csa);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_gfx_v11);
@ -394,7 +409,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
32);
32,
&queue->userq_vas.va.csa);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_sdma_v11);
@ -430,10 +446,12 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
return 0;
free_ctx:
amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
amdgpu_bo_free_kernel(&queue->fw_obj.obj, &queue->fw_obj.gpu_addr,
&queue->fw_obj.cpu_ptr);
free_mqd:
amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
free_props:
kfree(userq_props);
@ -443,11 +461,12 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
amdgpu_bo_free_kernel(&queue->fw_obj.obj, &queue->fw_obj.gpu_addr,
&queue->fw_obj.cpu_ptr);
kfree(queue->userq_prop);
amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
}
static int mes_userq_preempt(struct amdgpu_usermode_queue *queue)

View File

@ -2300,6 +2300,11 @@ static int criu_restore_devices(struct kfd_process *p,
ret = -EINVAL;
goto exit;
}
if (pdd->drm_file) {
ret = -EINVAL;
goto exit;
}
pdd->user_gpu_id = device_buckets[i].user_gpu_id;
drm_file = fget(device_buckets[i].drm_fd);
@ -2310,11 +2315,6 @@ static int criu_restore_devices(struct kfd_process *p,
goto exit;
}
if (pdd->drm_file) {
ret = -EINVAL;
goto exit;
}
/* create the vm using render nodes for kfd pdd */
if (kfd_process_device_init_vm(pdd, drm_file)) {
pr_err("could not init vm for given pdd\n");

View File

@ -3308,12 +3308,14 @@ static void copy_context_work_handler(struct work_struct *work)
static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
{
size_t array_size = num_queues * sizeof(uint32_t);
if (!usr_queue_id_array)
return NULL;
return memdup_user(usr_queue_id_array, array_size);
if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
return ERR_PTR(-EINVAL);
return memdup_user(usr_queue_id_array,
array_size(num_queues, sizeof(uint32_t)));
}
int resume_queues(struct kfd_process *p,

View File

@ -3732,6 +3732,9 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
svms = &p->svms;
if (!process_info)
return -EINVAL;
mutex_lock(&process_info->lock);
svm_range_list_lock_and_flush_work(svms, mm);

View File

@ -105,15 +105,26 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppcl
* dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to
* 0x00120264, destroying the marker before it can be read.
*
* Guard the call: if the S0i3 marker is present, skip dccg2_init() so the
* Guard the call: if the S0i3 marker is present, skip init so the
* WA can function correctly. bios_golden_init() will handle init in that case.
*
* DCN21 uses 48MHz refclk, not 100MHz, so we must explicitly set the correct
* values (48MHz is taken from rn_clk_mgr_construct()).
*/
static void dccg21_init(struct dccg *dccg)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (dccg2_is_s0i3_golden_init_wa_done(dccg))
return;
dccg2_init(dccg);
/* 48MHz refclk from rn_clk_mgr_construct() */
REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x00120230);
REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x0010bb80);
REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x0e01003c);
if (REG(REFCLK_CNTL))
REG_WRITE(REFCLK_CNTL, 0);
}
static const struct dccg_funcs dccg21_funcs = {

View File

@ -3076,6 +3076,10 @@ static bool si_dpm_vblank_too_short(void *handle)
/* we never hit the non-gddr5 limit so disable it */
u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0;
/* Disregard vblank time when there are no displays connected */
if (!adev->pm.pm_display_cfg.num_display)
return false;
/* Consider zero vblank time too short and disable MCLK switching.
* Note that the vblank time is set to maximum when no displays are attached,
* so we'll still enable MCLK switching in that case.