aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Kuehling <Felix.Kuehling@amd.com>2018-03-15 17:27:50 -0400
committerOded Gabbay <oded.gabbay@gmail.com>2018-03-15 17:27:50 -0400
commit552764b680a65d6069ad651b356d5465082939d0 (patch)
treec5ccbc25e105cfb9e17daa41873bd1d77b2069c1 /drivers
parentf35751b87034f0c2d11e60cdfb0179c4f1a7e296 (diff)
drm/amdkfd: Add TC flush on VMID deallocation for Hawaii
On GFX7 the CP does not perform a TC flush when queues are unmapped. To avoid TC eviction from accessing an invalid VMID, flush it explicitly before releasing a VMID. v2: Fix unnecessary list_for_each_entry_safe v3: Moved allocation to kfd_process_device_init_vm Signed-off-by: Amber Lin <Amber.Lin@amd.com> 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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c22
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c37
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c34
4 files changed, 95 insertions, 1 deletions
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 b3b6dab71638..c18e048f23c6 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -142,12 +142,31 @@ static int allocate_vmid(struct device_queue_manager *dqm,
142 return 0; 142 return 0;
143} 143}
144 144
145static int flush_texture_cache_nocpsch(struct kfd_dev *kdev,
146 struct qcm_process_device *qpd)
147{
148 uint32_t len;
149
150 if (!qpd->ib_kaddr)
151 return -ENOMEM;
152
153 len = pm_create_release_mem(qpd->ib_base, (uint32_t *)qpd->ib_kaddr);
154
155 return kdev->kfd2kgd->submit_ib(kdev->kgd, KGD_ENGINE_MEC1, qpd->vmid,
156 qpd->ib_base, (uint32_t *)qpd->ib_kaddr, len);
157}
158
145static void deallocate_vmid(struct device_queue_manager *dqm, 159static void deallocate_vmid(struct device_queue_manager *dqm,
146 struct qcm_process_device *qpd, 160 struct qcm_process_device *qpd,
147 struct queue *q) 161 struct queue *q)
148{ 162{
149 int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd; 163 int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd;
150 164
165 /* On GFX v7, CP doesn't flush TC at dequeue */
166 if (q->device->device_info->asic_family == CHIP_HAWAII)
167 if (flush_texture_cache_nocpsch(q->device, qpd))
168 pr_err("Failed to flush TC\n");
169
151 kfd_flush_tlb(qpd_to_pdd(qpd)); 170 kfd_flush_tlb(qpd_to_pdd(qpd));
152 171
153 /* Release the vmid mapping */ 172 /* Release the vmid mapping */
@@ -792,11 +811,12 @@ static void uninitialize(struct device_queue_manager *dqm)
792static int start_nocpsch(struct device_queue_manager *dqm) 811static int start_nocpsch(struct device_queue_manager *dqm)
793{ 812{
794 init_interrupts(dqm); 813 init_interrupts(dqm);
795 return 0; 814 return pm_init(&dqm->packets, dqm);
796} 815}
797 816
798static int stop_nocpsch(struct device_queue_manager *dqm) 817static int stop_nocpsch(struct device_queue_manager *dqm)
799{ 818{
819 pm_uninit(&dqm->packets);
800 return 0; 820 return 0;
801} 821}
802 822
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
index 0ecbd1f9b606..7614375489a4 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
@@ -356,6 +356,43 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
356 return retval; 356 return retval;
357} 357}
358 358
359/* pm_create_release_mem - Create a RELEASE_MEM packet and return the size
360 * of this packet
361 * @gpu_addr - GPU address of the packet. It's a virtual address.
362 * @buffer - buffer to fill up with the packet. It's a CPU kernel pointer
363 * Return - length of the packet
364 */
365uint32_t pm_create_release_mem(uint64_t gpu_addr, uint32_t *buffer)
366{
367 struct pm4_mec_release_mem *packet;
368
369 WARN_ON(!buffer);
370
371 packet = (struct pm4_mec_release_mem *)buffer;
372 memset(buffer, 0, sizeof(*packet));
373
374 packet->header.u32All = build_pm4_header(IT_RELEASE_MEM,
375 sizeof(*packet));
376
377 packet->bitfields2.event_type = CACHE_FLUSH_AND_INV_TS_EVENT;
378 packet->bitfields2.event_index = event_index___release_mem__end_of_pipe;
379 packet->bitfields2.tcl1_action_ena = 1;
380 packet->bitfields2.tc_action_ena = 1;
381 packet->bitfields2.cache_policy = cache_policy___release_mem__lru;
382 packet->bitfields2.atc = 0;
383
384 packet->bitfields3.data_sel = data_sel___release_mem__send_32_bit_low;
385 packet->bitfields3.int_sel =
386 int_sel___release_mem__send_interrupt_after_write_confirm;
387
388 packet->bitfields4.address_lo_32b = (gpu_addr & 0xffffffff) >> 2;
389 packet->address_hi = upper_32_bits(gpu_addr);
390
391 packet->data_lo = 0;
392
393 return sizeof(*packet) / sizeof(unsigned int);
394}
395
359int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm) 396int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
360{ 397{
361 pm->dqm = dqm; 398 pm->dqm = dqm;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index b2b5ef8c4536..aaed005ce1f5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -494,6 +494,7 @@ struct qcm_process_device {
494 494
495 /* IB memory */ 495 /* IB memory */
496 uint64_t ib_base; 496 uint64_t ib_base;
497 void *ib_kaddr;
497}; 498};
498 499
499/* KFD Memory Eviction */ 500/* KFD Memory Eviction */
@@ -834,6 +835,8 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type,
834 835
835void pm_release_ib(struct packet_manager *pm); 836void pm_release_ib(struct packet_manager *pm);
836 837
838uint32_t pm_create_release_mem(uint64_t gpu_addr, uint32_t *buffer);
839
837uint64_t kfd_get_number_elems(struct kfd_dev *kfd); 840uint64_t kfd_get_number_elems(struct kfd_dev *kfd);
838 841
839/* Events */ 842/* Events */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index aeb339db8a90..45ef2d03a975 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -149,6 +149,36 @@ err_alloc_mem:
149 return err; 149 return err;
150} 150}
151 151
152/* kfd_process_device_reserve_ib_mem - Reserve memory inside the
153 * process for IB usage The memory reserved is for KFD to submit
154 * IB to AMDGPU from kernel. If the memory is reserved
155 * successfully, ib_kaddr will have the CPU/kernel
156 * address. Check ib_kaddr before accessing the memory.
157 */
158static int kfd_process_device_reserve_ib_mem(struct kfd_process_device *pdd)
159{
160 struct qcm_process_device *qpd = &pdd->qpd;
161 uint32_t flags = ALLOC_MEM_FLAGS_GTT |
162 ALLOC_MEM_FLAGS_NO_SUBSTITUTE |
163 ALLOC_MEM_FLAGS_WRITABLE |
164 ALLOC_MEM_FLAGS_EXECUTABLE;
165 void *kaddr;
166 int ret;
167
168 if (qpd->ib_kaddr || !qpd->ib_base)
169 return 0;
170
171 /* ib_base is only set for dGPU */
172 ret = kfd_process_alloc_gpuvm(pdd, qpd->ib_base, PAGE_SIZE, flags,
173 &kaddr);
174 if (ret)
175 return ret;
176
177 qpd->ib_kaddr = kaddr;
178
179 return 0;
180}
181
152struct kfd_process *kfd_create_process(struct file *filep) 182struct kfd_process *kfd_create_process(struct file *filep)
153{ 183{
154 struct kfd_process *process; 184 struct kfd_process *process;
@@ -610,6 +640,9 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
610 return ret; 640 return ret;
611 } 641 }
612 642
643 ret = kfd_process_device_reserve_ib_mem(pdd);
644 if (ret)
645 goto err_reserve_ib_mem;
613 ret = kfd_process_device_init_cwsr_dgpu(pdd); 646 ret = kfd_process_device_init_cwsr_dgpu(pdd);
614 if (ret) 647 if (ret)
615 goto err_init_cwsr; 648 goto err_init_cwsr;
@@ -619,6 +652,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
619 return 0; 652 return 0;
620 653
621err_init_cwsr: 654err_init_cwsr:
655err_reserve_ib_mem:
622 kfd_process_device_free_bos(pdd); 656 kfd_process_device_free_bos(pdd);
623 if (!drm_file) 657 if (!drm_file)
624 dev->kfd2kgd->destroy_process_vm(dev->kgd, pdd->vm); 658 dev->kfd2kgd->destroy_process_vm(dev->kgd, pdd->vm);