Commit 52b29d73 authored by Felix Kuehling's avatar Felix Kuehling Committed by Oded Gabbay

drm/amdkfd: Add per-process IDR for buffer handles

Also used for cleaning up on process termination.

v2: Refactored cleanup on process termination
Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent d01994c2
...@@ -543,6 +543,9 @@ struct kfd_process_device { ...@@ -543,6 +543,9 @@ struct kfd_process_device {
struct file *drm_file; struct file *drm_file;
void *vm; void *vm;
/* GPUVM allocations storage */
struct idr alloc_idr;
/* Flag used to tell the pdd has dequeued from the dqm. /* Flag used to tell the pdd has dequeued from the dqm.
* This is used to prevent dev->dqm->ops.process_termination() from * This is used to prevent dev->dqm->ops.process_termination() from
* being called twice when it is already called in IOMMU callback * being called twice when it is already called in IOMMU callback
...@@ -678,6 +681,14 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, ...@@ -678,6 +681,14 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
int kfd_reserved_mem_mmap(struct kfd_process *process, int kfd_reserved_mem_mmap(struct kfd_process *process,
struct vm_area_struct *vma); struct vm_area_struct *vma);
/* KFD process API for creating and translating handles */
int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
void *mem);
void *kfd_process_device_translate_handle(struct kfd_process_device *p,
int handle);
void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
int handle);
/* Process device data iterator */ /* Process device data iterator */
struct kfd_process_device *kfd_get_first_process_device_data( struct kfd_process_device *kfd_get_first_process_device_data(
struct kfd_process *p); struct kfd_process *p);
......
...@@ -150,6 +150,40 @@ void kfd_unref_process(struct kfd_process *p) ...@@ -150,6 +150,40 @@ void kfd_unref_process(struct kfd_process *p)
kref_put(&p->ref, kfd_process_ref_release); kref_put(&p->ref, kfd_process_ref_release);
} }
static void kfd_process_device_free_bos(struct kfd_process_device *pdd)
{
struct kfd_process *p = pdd->process;
void *mem;
int id;
/*
* Remove all handles from idr and release appropriate
* local memory object
*/
idr_for_each_entry(&pdd->alloc_idr, mem, id) {
struct kfd_process_device *peer_pdd;
list_for_each_entry(peer_pdd, &p->per_device_data,
per_device_list) {
if (!peer_pdd->vm)
continue;
peer_pdd->dev->kfd2kgd->unmap_memory_to_gpu(
peer_pdd->dev->kgd, mem, peer_pdd->vm);
}
pdd->dev->kfd2kgd->free_memory_of_gpu(pdd->dev->kgd, mem);
kfd_process_device_remove_obj_handle(pdd, id);
}
}
static void kfd_process_free_outstanding_kfd_bos(struct kfd_process *p)
{
struct kfd_process_device *pdd;
list_for_each_entry(pdd, &p->per_device_data, per_device_list)
kfd_process_device_free_bos(pdd);
}
static void kfd_process_destroy_pdds(struct kfd_process *p) static void kfd_process_destroy_pdds(struct kfd_process *p)
{ {
struct kfd_process_device *pdd, *temp; struct kfd_process_device *pdd, *temp;
...@@ -171,6 +205,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) ...@@ -171,6 +205,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
free_pages((unsigned long)pdd->qpd.cwsr_kaddr, free_pages((unsigned long)pdd->qpd.cwsr_kaddr,
get_order(KFD_CWSR_TBA_TMA_SIZE)); get_order(KFD_CWSR_TBA_TMA_SIZE));
idr_destroy(&pdd->alloc_idr);
kfree(pdd); kfree(pdd);
} }
} }
...@@ -187,6 +223,8 @@ static void kfd_process_wq_release(struct work_struct *work) ...@@ -187,6 +223,8 @@ static void kfd_process_wq_release(struct work_struct *work)
kfd_iommu_unbind_process(p); kfd_iommu_unbind_process(p);
kfd_process_free_outstanding_kfd_bos(p);
kfd_process_destroy_pdds(p); kfd_process_destroy_pdds(p);
dma_fence_put(p->ef); dma_fence_put(p->ef);
...@@ -371,6 +409,7 @@ static struct kfd_process *create_process(const struct task_struct *thread, ...@@ -371,6 +409,7 @@ static struct kfd_process *create_process(const struct task_struct *thread,
return process; return process;
err_init_cwsr: err_init_cwsr:
kfd_process_free_outstanding_kfd_bos(process);
kfd_process_destroy_pdds(process); kfd_process_destroy_pdds(process);
err_init_apertures: err_init_apertures:
pqm_uninit(&process->pqm); pqm_uninit(&process->pqm);
...@@ -421,6 +460,9 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, ...@@ -421,6 +460,9 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
pdd->already_dequeued = false; pdd->already_dequeued = false;
list_add(&pdd->per_device_list, &p->per_device_data); list_add(&pdd->per_device_list, &p->per_device_data);
/* Init idr used for memory handle translation */
idr_init(&pdd->alloc_idr);
return pdd; return pdd;
} }
...@@ -520,6 +562,37 @@ bool kfd_has_process_device_data(struct kfd_process *p) ...@@ -520,6 +562,37 @@ bool kfd_has_process_device_data(struct kfd_process *p)
return !(list_empty(&p->per_device_data)); return !(list_empty(&p->per_device_data));
} }
/* Create specific handle mapped to mem from process local memory idr
* Assumes that the process lock is held.
*/
int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
void *mem)
{
return idr_alloc(&pdd->alloc_idr, mem, 0, 0, GFP_KERNEL);
}
/* Translate specific handle from process local memory idr
* Assumes that the process lock is held.
*/
void *kfd_process_device_translate_handle(struct kfd_process_device *pdd,
int handle)
{
if (handle < 0)
return NULL;
return idr_find(&pdd->alloc_idr, handle);
}
/* Remove specific handle from process local memory idr
* Assumes that the process lock is held.
*/
void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
int handle)
{
if (handle >= 0)
idr_remove(&pdd->alloc_idr, handle);
}
/* This increments the process->ref counter. */ /* This increments the process->ref counter. */
struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid) struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment