[PATCH 3/9] drm/amdkfd: Refactor queue wptr_bo GART mapping

Felix Kuehling felix.kuehling at amd.com
Thu Jul 18 20:48:44 UTC 2024



On 2024-07-18 15:57, Philip Yang wrote:
> 
> On 2024-07-17 16:16, Felix Kuehling wrote:
>> Sorry, I see that this patch still doesn't propagate errors returned from kfd_queue_releasre_buffers correctly. And the later patches in the series don't seem to fix it either. See inline.
> kfd_queue_release_buffers return value is handled in queue destroy path, to return -ERESTARTSYS if fail to hold vm lock to release buffers because signal is received. See inline.

Sorry, I thought I had searched all the places that call kfd_queue_release_buffers, but I missed the one where the error handling matters most, that does it correctly. More inline.

>>
>> On 2024-07-15 08:34, Philip Yang wrote:
>>> Add helper function kfd_queue_acquire_buffers to get queue wptr_bo
>>> reference from queue write_ptr if it is mapped to the KFD node with
>>> expected size.
>>>
>>> Move wptr_bo to structure queue_properties from struct queue as queue is
>>> allocated after queue buffers are validated, then we can remove wptr_bo
>>> parameter from pqm_create_queue.
>>>
>>> Because amdgpu_bo_unref clear the pointer, queue_properties wptr_bo is
>>> used to acquire and release wptr_bo for validation, add wptr_bo_gart to
>>> queue_propertes, to hold wptr_bo reference for GART mapping and
>>> umapping.
>>>
>>> Move MES wptr_bo GART mapping to init_user_queue, the same location with
>>> queue ctx_bo GART mapping.
>>>
>>> Signed-off-by: Philip Yang <Philip.Yang at amd.com>
>>> ---
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h    |  2 +-
>>>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |  5 +-
>>>   drivers/gpu/drm/amd/amdkfd/kfd_chardev.c      | 56 +++---------------
>>>   .../drm/amd/amdkfd/kfd_device_queue_manager.c |  6 +-
>>>   drivers/gpu/drm/amd/amdkfd/kfd_priv.h         | 14 +++--
>>>   .../amd/amdkfd/kfd_process_queue_manager.c    | 45 +++++++++++----
>>>   drivers/gpu/drm/amd/amdkfd/kfd_queue.c        | 57 +++++++++++++++++++
>>>   7 files changed, 116 insertions(+), 69 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
>>> index 6e591280774b..4ed49265c764 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
>>> @@ -322,7 +322,7 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
>>>                            void **kptr, uint64_t *size);
>>>   void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_mem *mem);
>>>   -int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo);
>>> +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo, struct amdgpu_bo **bo_gart);
>>>     int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
>>>                           struct dma_fence __rcu **ef);
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> index 199e387d35f4..0ab37e7aec26 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> @@ -2226,11 +2226,12 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
>>>   /**
>>>    * amdgpu_amdkfd_map_gtt_bo_to_gart - Map BO to GART and increment reference count
>>>    * @bo: Buffer object to be mapped
>>> + * @bo_gart: Return bo reference
>>>    *
>>>    * Before return, bo reference count is incremented. To release the reference and unpin/
>>>    * unmap the BO, call amdgpu_amdkfd_free_gtt_mem.
>>>    */
>>> -int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
>>> +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo, struct amdgpu_bo **bo_gart)
>>>   {
>>>       int ret;
>>>   @@ -2257,7 +2258,7 @@ int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
>>>         amdgpu_bo_unreserve(bo);
>>>   -    bo = amdgpu_bo_ref(bo);
>>> +    *bo_gart = amdgpu_bo_ref(bo);
>>>         return 0;
>>>   diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
>>> index 823f245dc7d0..202f24ee4bd7 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
>>> @@ -247,8 +247,8 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
>>>       q_properties->priority = args->queue_priority;
>>>       q_properties->queue_address = args->ring_base_address;
>>>       q_properties->queue_size = args->ring_size;
>>> -    q_properties->read_ptr = (uint32_t *) args->read_pointer_address;
>>> -    q_properties->write_ptr = (uint32_t *) args->write_pointer_address;
>>> +    q_properties->read_ptr = (void __user *)args->read_pointer_address;
>>> +    q_properties->write_ptr = (void __user *)args->write_pointer_address;
>>>       q_properties->eop_ring_buffer_address = args->eop_buffer_address;
>>>       q_properties->eop_ring_buffer_size = args->eop_buffer_size;
>>>       q_properties->ctx_save_restore_area_address =
>>> @@ -306,7 +306,6 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
>>>       struct kfd_process_device *pdd;
>>>       struct queue_properties q_properties;
>>>       uint32_t doorbell_offset_in_process = 0;
>>> -    struct amdgpu_bo *wptr_bo = NULL;
>>>         memset(&q_properties, 0, sizeof(struct queue_properties));
>>>   @@ -342,53 +341,17 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
>>>           }
>>>       }
>>>   -    /* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work
>>> -     * on unmapped queues for usermode queue oversubscription (no aggregated doorbell)
>>> -     */
>>> -    if (dev->kfd->shared_resources.enable_mes &&
>>> -            ((dev->adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK)
>>> -            >> AMDGPU_MES_API_VERSION_SHIFT) >= 2) {
>>> -        struct amdgpu_bo_va_mapping *wptr_mapping;
>>> -        struct amdgpu_vm *wptr_vm;
>>> -
>>> -        wptr_vm = drm_priv_to_vm(pdd->drm_priv);
>>> -        err = amdgpu_bo_reserve(wptr_vm->root.bo, false);
>>> -        if (err)
>>> -            goto err_wptr_map_gart;
>>> -
>>> -        wptr_mapping = amdgpu_vm_bo_lookup_mapping(
>>> -                wptr_vm, args->write_pointer_address >> PAGE_SHIFT);
>>> -        amdgpu_bo_unreserve(wptr_vm->root.bo);
>>> -        if (!wptr_mapping) {
>>> -            pr_err("Failed to lookup wptr bo\n");
>>> -            err = -EINVAL;
>>> -            goto err_wptr_map_gart;
>>> -        }
>>> -
>>> -        wptr_bo = wptr_mapping->bo_va->base.bo;
>>> -        if (wptr_bo->tbo.base.size > PAGE_SIZE) {
>>> -            pr_err("Requested GART mapping for wptr bo larger than one page\n");
>>> -            err = -EINVAL;
>>> -            goto err_wptr_map_gart;
>>> -        }
>>> -        if (dev->adev != amdgpu_ttm_adev(wptr_bo->tbo.bdev)) {
>>> -            pr_err("Queue memory allocated to wrong device\n");
>>> -            err = -EINVAL;
>>> -            goto err_wptr_map_gart;
>>> -        }
>>> -
>>> -        err = amdgpu_amdkfd_map_gtt_bo_to_gart(wptr_bo);
>>> -        if (err) {
>>> -            pr_err("Failed to map wptr bo to GART\n");
>>> -            goto err_wptr_map_gart;
>>> -        }
>>> +    err = kfd_queue_acquire_buffers(pdd, &q_properties);
>>> +    if (err) {
>>> +        pr_debug("failed to acquire user queue buffers\n");
>>> +        goto err_acquire_queue_buf;
>>>       }
>>>         pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n",
>>>               p->pasid,
>>>               dev->id);
>>>   -    err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, wptr_bo,
>>> +    err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id,
>>>               NULL, NULL, NULL, &doorbell_offset_in_process);
>>>       if (err != 0)
>>>           goto err_create_queue;
>>> @@ -422,9 +385,8 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
>>>       return 0;
>>>     err_create_queue:
>>> -    if (wptr_bo)
>>> -        amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&wptr_bo);
>>> -err_wptr_map_gart:
>>> +    kfd_queue_release_buffers(pdd, &q_properties);
>>
>> You're ignoring the return value here. In this patch, the function always returns 0, but in later patches it can return -ERESTARTSYS and you never fix up the error handling here. This patch should lay the groundwork for proper error handling.
> This is error handling path after acquiring queue buffers, but fail to alloc queue, or fail GART mapping queue wptr or F/W return failure to create queue, 

Right. We're still potentially leaking bo_va->queue_refcounts here. I don't have a good solution, and it probably doesn't matter. If queue creation failed, the application is going to be broken anyway, and the cleanup at process teardown will still clean it up.


>>
>>
>>> +err_acquire_queue_buf:
>>>   err_bind_process:
>>>   err_pdd:
>>>       mutex_unlock(&p->mutex);
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
>>> index 420444eb8e98..fdc76c24b2e7 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
>>> @@ -208,10 +208,8 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
>>>       queue_input.mqd_addr = q->gart_mqd_addr;
>>>       queue_input.wptr_addr = (uint64_t)q->properties.write_ptr;
>>>   -    if (q->wptr_bo) {
>>> -        wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1);
>>> -        queue_input.wptr_mc_addr = amdgpu_bo_gpu_offset(q->wptr_bo) + wptr_addr_off;
>>> -    }
>>> +    wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1);
>>> +    queue_input.wptr_mc_addr = amdgpu_bo_gpu_offset(q->properties.wptr_bo) + wptr_addr_off;
>>>         queue_input.is_kfd_process = 1;
>>>       queue_input.is_aql_queue = (q->properties.format == KFD_QUEUE_FORMAT_AQL);
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> index 2b3ec92981e8..c98ff548313c 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> @@ -494,8 +494,8 @@ struct queue_properties {
>>>       uint64_t  queue_size;
>>>       uint32_t priority;
>>>       uint32_t queue_percent;
>>> -    uint32_t *read_ptr;
>>> -    uint32_t *write_ptr;
>>> +    void __user *read_ptr;
>>> +    void __user *write_ptr;
>>>       void __iomem *doorbell_ptr;
>>>       uint32_t doorbell_off;
>>>       bool is_interop;
>>> @@ -522,6 +522,9 @@ struct queue_properties {
>>>       uint64_t tba_addr;
>>>       uint64_t tma_addr;
>>>       uint64_t exception_status;
>>> +
>>> +    struct amdgpu_bo *wptr_bo_gart;
>>> +    struct amdgpu_bo *wptr_bo;
>>>   };
>>>     #define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 &&    \
>>> @@ -603,8 +606,6 @@ struct queue {
>>>       void *gang_ctx_bo;
>>>       uint64_t gang_ctx_gpu_addr;
>>>       void *gang_ctx_cpu_ptr;
>>> -
>>> -    struct amdgpu_bo *wptr_bo;
>>>   };
>>>     enum KFD_MQD_TYPE {
>>> @@ -1284,6 +1285,10 @@ int init_queue(struct queue **q, const struct queue_properties *properties);
>>>   void uninit_queue(struct queue *q);
>>>   void print_queue_properties(struct queue_properties *q);
>>>   void print_queue(struct queue *q);
>>> +int kfd_queue_buffer_get(struct amdgpu_vm *vm, void __user *addr, struct amdgpu_bo **pbo,
>>> +             u64 expected_size);
>>> +int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_properties *properties);
>>> +int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_properties *properties);
>>>     struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
>>>           struct kfd_node *dev);
>>> @@ -1320,7 +1325,6 @@ int pqm_create_queue(struct process_queue_manager *pqm,
>>>                   struct file *f,
>>>                   struct queue_properties *properties,
>>>                   unsigned int *qid,
>>> -                struct amdgpu_bo *wptr_bo,
>>>                   const struct kfd_criu_queue_priv_data *q_data,
>>>                   const void *restore_mqd,
>>>                   const void *restore_ctl_stack,
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
>>> index 36f0460cbffe..8552400d6d47 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
>>> @@ -205,18 +205,21 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
>>>         if (dev->kfd->shared_resources.enable_mes) {
>>>           amdgpu_amdkfd_free_gtt_mem(dev->adev, &pqn->q->gang_ctx_bo);
>>> -        if (pqn->q->wptr_bo)
>>> -            amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&pqn->q->wptr_bo);
>>> +        amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&pqn->q->properties.wptr_bo_gart);
>>>       }
>>>   }
>>>     void pqm_uninit(struct process_queue_manager *pqm)
>>>   {
>>>       struct process_queue_node *pqn, *next;
>>> +    struct kfd_process_device *pdd;
>>>         list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
>>> -        if (pqn->q)
>>> +        if (pqn->q) {
>>> +            pdd = kfd_get_process_device_data(pqn->q->device, pqm->process);
>>> +            kfd_queue_release_buffers(pdd, &pqn->q->properties);
>> You're ignoring the return value here. In this patch, the function always returns 0, but in later patches it can return -ERESTARTSYS and you never fix up the error handling here. This patch should lay the groundwork for proper error handling.
> This is called from kfd_process_wq_release kernel worker, to cleanup outstanding user queues after process exit, it is impossible to be interrupted by user signal, I think it is safe to ignore the return value here.

I agree. The memory is about to be freed anyway.

>>
>> Regards,
>>   Felix
>>
>>
>>>               pqm_clean_queue_resource(pqm, pqn);
>>> +        }
>>>             kfd_procfs_del_queue(pqn->q);
>>>           uninit_queue(pqn->q);
>>> @@ -231,8 +234,7 @@ void pqm_uninit(struct process_queue_manager *pqm)
>>>   static int init_user_queue(struct process_queue_manager *pqm,
>>>                   struct kfd_node *dev, struct queue **q,
>>>                   struct queue_properties *q_properties,
>>> -                struct file *f, struct amdgpu_bo *wptr_bo,
>>> -                unsigned int qid)
>>> +                struct file *f, unsigned int qid)
>>>   {
>>>       int retval;
>>>   @@ -263,12 +265,32 @@ static int init_user_queue(struct process_queue_manager *pqm,
>>>               goto cleanup;
>>>           }
>>>           memset((*q)->gang_ctx_cpu_ptr, 0, AMDGPU_MES_GANG_CTX_SIZE);
>>> -        (*q)->wptr_bo = wptr_bo;
>>> +
>>> +        /* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work
>>> +         * on unmapped queues for usermode queue oversubscription (no aggregated doorbell)
>>> +         */
>>> +        if (((dev->adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK)
>>> +            >> AMDGPU_MES_API_VERSION_SHIFT) >= 2) {
>>> +            if (dev->adev != amdgpu_ttm_adev(q_properties->wptr_bo->tbo.bdev)) {
>>> +                pr_err("Queue memory allocated to wrong device\n");
>>> +                retval = -EINVAL;
>>> +                goto free_gang_ctx_bo;
>>> +            }
>>> +
>>> +            retval = amdgpu_amdkfd_map_gtt_bo_to_gart(q_properties->wptr_bo,
>>> +                                  &(*q)->properties.wptr_bo_gart);
>>> +            if (retval) {
>>> +                pr_err("Failed to map wptr bo to GART\n");
>>> +                goto free_gang_ctx_bo;
>>> +            }
>>> +        }
>>>       }
>>>         pr_debug("PQM After init queue");
>>>       return 0;
>>>   +free_gang_ctx_bo:
>>> +    amdgpu_amdkfd_free_gtt_mem(dev->adev, (*q)->gang_ctx_bo);
>>>   cleanup:
>>>       uninit_queue(*q);
>>>       *q = NULL;
>>> @@ -280,7 +302,6 @@ int pqm_create_queue(struct process_queue_manager *pqm,
>>>                   struct file *f,
>>>                   struct queue_properties *properties,
>>>                   unsigned int *qid,
>>> -                struct amdgpu_bo *wptr_bo,
>>>                   const struct kfd_criu_queue_priv_data *q_data,
>>>                   const void *restore_mqd,
>>>                   const void *restore_ctl_stack,
>>> @@ -351,7 +372,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
>>>            * allocate_sdma_queue() in create_queue() has the
>>>            * corresponding check logic.
>>>            */
>>> -        retval = init_user_queue(pqm, dev, &q, properties, f, wptr_bo, *qid);
>>> +        retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
>>>           if (retval != 0)
>>>               goto err_create_queue;
>>>           pqn->q = q;
>>> @@ -372,7 +393,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
>>>               goto err_create_queue;
>>>           }
>>>   -        retval = init_user_queue(pqm, dev, &q, properties, f, wptr_bo, *qid);
>>> +        retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
>>>           if (retval != 0)
>>>               goto err_create_queue;
>>>           pqn->q = q;
>>> @@ -490,6 +511,10 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
>>>       }
>>>         if (pqn->q) {
>>> +        retval = kfd_queue_release_buffers(pdd, &pqn->q->properties);
>>> +        if (retval)
>>> +            goto err_destroy_queue;
> 
> if destroy queue wait for vm lock is interrupted return by a signal, here return -ERESTARTSYS, then user process could retry or exit.

Thanks for pointing this out, for some reason I missed this call-site in my review.

Regards,
  Felix

> 
> Regards,
> 
> Philip
> 
>>> +
>>>           kfd_procfs_del_queue(pqn->q);
>>>           dqm = pqn->q->device->dqm;
>>>           retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q);
>>> @@ -971,7 +996,7 @@ int kfd_criu_restore_queue(struct kfd_process *p,
>>>         print_queue_properties(&qp);
>>>   -    ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, NULL, q_data, mqd, ctl_stack,
>>> +    ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, mqd, ctl_stack,
>>>                   NULL);
>>>       if (ret) {
>>>           pr_err("Failed to create new queue err:%d\n", ret);
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
>>> index 0f6992b1895c..b4529ec298a9 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
>>> @@ -82,3 +82,60 @@ void uninit_queue(struct queue *q)
>>>   {
>>>       kfree(q);
>>>   }
>>> +
>>> +int kfd_queue_buffer_get(struct amdgpu_vm *vm, void __user *addr, struct amdgpu_bo **pbo,
>>> +             u64 expected_size)
>>> +{
>>> +    struct amdgpu_bo_va_mapping *mapping;
>>> +    u64 user_addr;
>>> +    u64 size;
>>> +
>>> +    user_addr = (u64)addr >> AMDGPU_GPU_PAGE_SHIFT;
>>> +    size = expected_size >> AMDGPU_GPU_PAGE_SHIFT;
>>> +
>>> +    mapping = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
>>> +    if (!mapping)
>>> +        goto out_err;
>>> +
>>> +    if (user_addr != mapping->start || user_addr + size - 1 != mapping->last) {
>>> +        pr_debug("expected size 0x%llx not equal to mapping addr 0x%llx size 0x%llx\n",
>>> +            expected_size, mapping->start << AMDGPU_GPU_PAGE_SHIFT,
>>> +            (mapping->last - mapping->start + 1) << AMDGPU_GPU_PAGE_SHIFT);
>>> +        goto out_err;
>>> +    }
>>> +
>>> +    *pbo = amdgpu_bo_ref(mapping->bo_va->base.bo);
>>> +    return 0;
>>> +
>>> +out_err:
>>> +    *pbo = NULL;
>>> +    return -EINVAL;
>>> +}
>>> +
>>> +int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_properties *properties)
>>> +{
>>> +    struct amdgpu_vm *vm;
>>> +    int err;
>>> +
>>> +    vm = drm_priv_to_vm(pdd->drm_priv);
>>> +    err = amdgpu_bo_reserve(vm->root.bo, false);
>>> +    if (err)
>>> +        return err;
>>> +
>>> +    err = kfd_queue_buffer_get(vm, properties->write_ptr, &properties->wptr_bo, PAGE_SIZE);
>>> +    if (err)
>>> +        goto out_unreserve;
>>> +
>>> +    amdgpu_bo_unreserve(vm->root.bo);
>>> +    return 0;
>>> +
>>> +out_unreserve:
>>> +    amdgpu_bo_unreserve(vm->root.bo);
>>> +    return err;
>>> +}
>>> +
>>> +int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_properties *properties)
>>> +{
>>> +    amdgpu_bo_unref(&properties->wptr_bo);
>>> +    return 0;
>>> +}


More information about the amd-gfx mailing list