aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Kuehling <Felix.Kuehling@amd.com>2018-03-15 17:27:48 -0400
committerOded Gabbay <oded.gabbay@gmail.com>2018-03-15 17:27:48 -0400
commit52b29d73340da6cbb10ba42b0a28e7fb795afe9c (patch)
treeba1d240c9bf1591c098c72fa8c327a7ba5f944eb
parentd01994c24cb28b6f200138d98cbfc17b6bd967c5 (diff)
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: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h11
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c73
2 files changed, 84 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index 0d5d924b31ef..b2b5ef8c4536 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -543,6 +543,9 @@ struct kfd_process_device {
543 struct file *drm_file; 543 struct file *drm_file;
544 void *vm; 544 void *vm;
545 545
546 /* GPUVM allocations storage */
547 struct idr alloc_idr;
548
546 /* Flag used to tell the pdd has dequeued from the dqm. 549 /* Flag used to tell the pdd has dequeued from the dqm.
547 * This is used to prevent dev->dqm->ops.process_termination() from 550 * This is used to prevent dev->dqm->ops.process_termination() from
548 * being called twice when it is already called in IOMMU callback 551 * 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,
678int kfd_reserved_mem_mmap(struct kfd_process *process, 681int kfd_reserved_mem_mmap(struct kfd_process *process,
679 struct vm_area_struct *vma); 682 struct vm_area_struct *vma);
680 683
684/* KFD process API for creating and translating handles */
685int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
686 void *mem);
687void *kfd_process_device_translate_handle(struct kfd_process_device *p,
688 int handle);
689void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
690 int handle);
691
681/* Process device data iterator */ 692/* Process device data iterator */
682struct kfd_process_device *kfd_get_first_process_device_data( 693struct kfd_process_device *kfd_get_first_process_device_data(
683 struct kfd_process *p); 694 struct kfd_process *p);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 6618aaa6b84f..a2ae0236a3ea 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -150,6 +150,40 @@ void kfd_unref_process(struct kfd_process *p)
150 kref_put(&p->ref, kfd_process_ref_release); 150 kref_put(&p->ref, kfd_process_ref_release);
151} 151}
152 152
153static void kfd_process_device_free_bos(struct kfd_process_device *pdd)
154{
155 struct kfd_process *p = pdd->process;
156 void *mem;
157 int id;
158
159 /*
160 * Remove all handles from idr and release appropriate
161 * local memory object
162 */
163 idr_for_each_entry(&pdd->alloc_idr, mem, id) {
164 struct kfd_process_device *peer_pdd;
165
166 list_for_each_entry(peer_pdd, &p->per_device_data,
167 per_device_list) {
168 if (!peer_pdd->vm)
169 continue;
170 peer_pdd->dev->kfd2kgd->unmap_memory_to_gpu(
171 peer_pdd->dev->kgd, mem, peer_pdd->vm);
172 }
173
174 pdd->dev->kfd2kgd->free_memory_of_gpu(pdd->dev->kgd, mem);
175 kfd_process_device_remove_obj_handle(pdd, id);
176 }
177}
178
179static void kfd_process_free_outstanding_kfd_bos(struct kfd_process *p)
180{
181 struct kfd_process_device *pdd;
182
183 list_for_each_entry(pdd, &p->per_device_data, per_device_list)
184 kfd_process_device_free_bos(pdd);
185}
186
153static void kfd_process_destroy_pdds(struct kfd_process *p) 187static void kfd_process_destroy_pdds(struct kfd_process *p)
154{ 188{
155 struct kfd_process_device *pdd, *temp; 189 struct kfd_process_device *pdd, *temp;
@@ -171,6 +205,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
171 free_pages((unsigned long)pdd->qpd.cwsr_kaddr, 205 free_pages((unsigned long)pdd->qpd.cwsr_kaddr,
172 get_order(KFD_CWSR_TBA_TMA_SIZE)); 206 get_order(KFD_CWSR_TBA_TMA_SIZE));
173 207
208 idr_destroy(&pdd->alloc_idr);
209
174 kfree(pdd); 210 kfree(pdd);
175 } 211 }
176} 212}
@@ -187,6 +223,8 @@ static void kfd_process_wq_release(struct work_struct *work)
187 223
188 kfd_iommu_unbind_process(p); 224 kfd_iommu_unbind_process(p);
189 225
226 kfd_process_free_outstanding_kfd_bos(p);
227
190 kfd_process_destroy_pdds(p); 228 kfd_process_destroy_pdds(p);
191 dma_fence_put(p->ef); 229 dma_fence_put(p->ef);
192 230
@@ -371,6 +409,7 @@ static struct kfd_process *create_process(const struct task_struct *thread,
371 return process; 409 return process;
372 410
373err_init_cwsr: 411err_init_cwsr:
412 kfd_process_free_outstanding_kfd_bos(process);
374 kfd_process_destroy_pdds(process); 413 kfd_process_destroy_pdds(process);
375err_init_apertures: 414err_init_apertures:
376 pqm_uninit(&process->pqm); 415 pqm_uninit(&process->pqm);
@@ -421,6 +460,9 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
421 pdd->already_dequeued = false; 460 pdd->already_dequeued = false;
422 list_add(&pdd->per_device_list, &p->per_device_data); 461 list_add(&pdd->per_device_list, &p->per_device_data);
423 462
463 /* Init idr used for memory handle translation */
464 idr_init(&pdd->alloc_idr);
465
424 return pdd; 466 return pdd;
425} 467}
426 468
@@ -520,6 +562,37 @@ bool kfd_has_process_device_data(struct kfd_process *p)
520 return !(list_empty(&p->per_device_data)); 562 return !(list_empty(&p->per_device_data));
521} 563}
522 564
565/* Create specific handle mapped to mem from process local memory idr
566 * Assumes that the process lock is held.
567 */
568int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
569 void *mem)
570{
571 return idr_alloc(&pdd->alloc_idr, mem, 0, 0, GFP_KERNEL);
572}
573
574/* Translate specific handle from process local memory idr
575 * Assumes that the process lock is held.
576 */
577void *kfd_process_device_translate_handle(struct kfd_process_device *pdd,
578 int handle)
579{
580 if (handle < 0)
581 return NULL;
582
583 return idr_find(&pdd->alloc_idr, handle);
584}
585
586/* Remove specific handle from process local memory idr
587 * Assumes that the process lock is held.
588 */
589void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
590 int handle)
591{
592 if (handle >= 0)
593 idr_remove(&pdd->alloc_idr, handle);
594}
595
523/* This increments the process->ref counter. */ 596/* This increments the process->ref counter. */
524struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid) 597struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid)
525{ 598{