summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index 1bea629c49ca..fb3129883a4c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -32,6 +32,7 @@
#include "kfd_device_queue_manager.h"
#include "kfd_pm4_headers.h"
#include "kfd_pm4_opcodes.h"
+#include "amdgpu_reset.h"
#define PM4_COUNT_ZERO (((1 << 15) - 1) << 16)
@@ -45,11 +46,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
int retval;
union PM4_MES_TYPE_3_HEADER nop;
- if (WARN_ON(type != KFD_QUEUE_TYPE_DIQ && type != KFD_QUEUE_TYPE_HIQ))
- return false;
-
- pr_debug("Initializing queue type %d size %d\n", KFD_QUEUE_TYPE_HIQ,
- queue_size);
+ pr_debug("Initializing queue type %d size %d\n", type, queue_size);
memset(&prop, 0, sizeof(prop));
memset(&nop, 0, sizeof(nop));
@@ -68,7 +65,8 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
kq->mqd_mgr = dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
break;
default:
- pr_err("Invalid queue type %d\n", type);
+ WARN(1, "Invalid queue type %d\n", type);
+ dev_err(dev->adev->dev, "Invalid queue type %d\n", type);
return false;
}
@@ -78,13 +76,14 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
prop.doorbell_ptr = kfd_get_kernel_doorbell(dev->kfd, &prop.doorbell_off);
if (!prop.doorbell_ptr) {
- pr_err("Failed to initialize doorbell");
+ dev_err(dev->adev->dev, "Failed to initialize doorbell");
goto err_get_kernel_doorbell;
}
retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq);
if (retval != 0) {
- pr_err("Failed to init pq queues size %d\n", queue_size);
+ dev_err(dev->adev->dev, "Failed to init pq queues size %d\n",
+ queue_size);
goto err_pq_allocate_vidmem;
}
@@ -123,7 +122,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
memset(kq->pq_kernel_addr, 0, queue_size);
memset(kq->rptr_kernel, 0, sizeof(*kq->rptr_kernel));
- memset(kq->wptr_kernel, 0, sizeof(*kq->wptr_kernel));
+ memset(kq->wptr_kernel, 0, dev->kfd->device_info.doorbell_size);
prop.queue_size = queue_size;
prop.is_interop = false;
@@ -196,15 +195,17 @@ err_get_kernel_doorbell:
}
/* Uninitialize a kernel queue and free all its memory usages. */
-static void kq_uninitialize(struct kernel_queue *kq, bool hanging)
+static void kq_uninitialize(struct kernel_queue *kq)
{
- if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && !hanging)
+ if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && down_read_trylock(&kq->dev->adev->reset_domain->sem)) {
kq->mqd_mgr->destroy_mqd(kq->mqd_mgr,
kq->queue->mqd,
KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
KFD_UNMAP_LATENCY_MS,
kq->queue->pipe,
kq->queue->queue);
+ up_read(&kq->dev->adev->reset_domain->sem);
+ }
else if (kq->queue->properties.type == KFD_QUEUE_TYPE_DIQ)
kfd_gtt_sa_free(kq->dev, kq->fence_mem_obj);
@@ -286,7 +287,7 @@ err_no_space:
return -ENOMEM;
}
-void kq_submit_packet(struct kernel_queue *kq)
+int kq_submit_packet(struct kernel_queue *kq)
{
#ifdef DEBUG
int i;
@@ -298,15 +299,26 @@ void kq_submit_packet(struct kernel_queue *kq)
}
pr_debug("\n");
#endif
+ /* Fatal err detected, packet submission won't go through */
+ if (amdgpu_amdkfd_is_fed(kq->dev->adev))
+ return -EIO;
+
+ /* Make sure ring buffer is updated before wptr updated */
+ mb();
+
if (kq->dev->kfd->device_info.doorbell_size == 8) {
*kq->wptr64_kernel = kq->pending_wptr64;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
} else {
*kq->wptr_kernel = kq->pending_wptr;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
+
+ return 0;
}
void kq_rollback_packet(struct kernel_queue *kq)
@@ -332,15 +344,15 @@ struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
if (kq_initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE))
return kq;
- pr_err("Failed to init kernel queue\n");
+ dev_err(dev->adev->dev, "Failed to init kernel queue\n");
kfree(kq);
return NULL;
}
-void kernel_queue_uninit(struct kernel_queue *kq, bool hanging)
+void kernel_queue_uninit(struct kernel_queue *kq)
{
- kq_uninitialize(kq, hanging);
+ kq_uninitialize(kq);
kfree(kq);
}
@@ -351,26 +363,26 @@ static __attribute__((unused)) void test_kq(struct kfd_node *dev)
uint32_t *buffer, i;
int retval;
- pr_err("Starting kernel queue test\n");
+ dev_err(dev->adev->dev, "Starting kernel queue test\n");
kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ);
if (unlikely(!kq)) {
- pr_err(" Failed to initialize HIQ\n");
- pr_err("Kernel queue test failed\n");
+ dev_err(dev->adev->dev, " Failed to initialize HIQ\n");
+ dev_err(dev->adev->dev, "Kernel queue test failed\n");
return;
}
retval = kq_acquire_packet_buffer(kq, 5, &buffer);
if (unlikely(retval != 0)) {
- pr_err(" Failed to acquire packet buffer\n");
- pr_err("Kernel queue test failed\n");
+ dev_err(dev->adev->dev, " Failed to acquire packet buffer\n");
+ dev_err(dev->adev->dev, "Kernel queue test failed\n");
return;
}
for (i = 0; i < 5; i++)
buffer[i] = kq->nop_packet;
kq_submit_packet(kq);
- pr_err("Ending kernel queue test\n");
+ dev_err(dev->adev->dev, "Ending kernel queue test\n");
}