diff options
author | Felix Kuehling <Felix.Kuehling@amd.com> | 2018-03-15 17:27:50 -0400 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2018-03-15 17:27:50 -0400 |
commit | 552764b680a65d6069ad651b356d5465082939d0 (patch) | |
tree | c5ccbc25e105cfb9e17daa41873bd1d77b2069c1 /drivers | |
parent | f35751b87034f0c2d11e60cdfb0179c4f1a7e296 (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.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_process.c | 34 |
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 | ||
145 | static 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 | |||
145 | static void deallocate_vmid(struct device_queue_manager *dqm, | 159 | static 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) | |||
792 | static int start_nocpsch(struct device_queue_manager *dqm) | 811 | static 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 | ||
798 | static int stop_nocpsch(struct device_queue_manager *dqm) | 817 | static 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 | */ | ||
365 | uint32_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 | |||
359 | int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm) | 396 | int 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 | ||
835 | void pm_release_ib(struct packet_manager *pm); | 836 | void pm_release_ib(struct packet_manager *pm); |
836 | 837 | ||
838 | uint32_t pm_create_release_mem(uint64_t gpu_addr, uint32_t *buffer); | ||
839 | |||
837 | uint64_t kfd_get_number_elems(struct kfd_dev *kfd); | 840 | uint64_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 | */ | ||
158 | static 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 | |||
152 | struct kfd_process *kfd_create_process(struct file *filep) | 182 | struct 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 | ||
621 | err_init_cwsr: | 654 | err_init_cwsr: |
655 | err_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); |