Commit f2e29534 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-amdkfd-fixes-2017-09-24' of...

Merge tag 'drm-amdkfd-fixes-2017-09-24' of git://people.freedesktop.org/~gabbayo/linux into drm-fixes

It contains the following fixes:
- correct checking of return value
- send correct parameter to function (According to the parameter type)
- avoid spamming of dmesg log
- fix queue wrapping calculations

* tag 'drm-amdkfd-fixes-2017-09-24' of git://people.freedesktop.org/~gabbayo/linux:
  drm/amdkfd: Print event limit messages only once per process
  drm/amdkfd: Fix kernel-queue wrapping bugs
  drm/amdkfd: Fix incorrect destroy_mqd parameter
  drm/amdkfd: check for null dev to avoid a null pointer dereference
parents e19b205b c986169f
...@@ -892,6 +892,8 @@ static int kfd_ioctl_get_tile_config(struct file *filep, ...@@ -892,6 +892,8 @@ static int kfd_ioctl_get_tile_config(struct file *filep,
int err = 0; int err = 0;
dev = kfd_device_by_id(args->gpu_id); dev = kfd_device_by_id(args->gpu_id);
if (!dev)
return -EINVAL;
dev->kfd2kgd->get_tile_config(dev->kgd, &config); dev->kfd2kgd->get_tile_config(dev->kgd, &config);
......
...@@ -292,7 +292,10 @@ static int create_signal_event(struct file *devkfd, ...@@ -292,7 +292,10 @@ static int create_signal_event(struct file *devkfd,
struct kfd_event *ev) struct kfd_event *ev)
{ {
if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) { if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) {
if (!p->signal_event_limit_reached) {
pr_warn("Signal event wasn't created because limit was reached\n"); pr_warn("Signal event wasn't created because limit was reached\n");
p->signal_event_limit_reached = true;
}
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -184,7 +184,7 @@ static void uninitialize(struct kernel_queue *kq) ...@@ -184,7 +184,7 @@ static void uninitialize(struct kernel_queue *kq)
if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ) if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ)
kq->mqd->destroy_mqd(kq->mqd, kq->mqd->destroy_mqd(kq->mqd,
kq->queue->mqd, kq->queue->mqd,
false, KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS, QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS,
kq->queue->pipe, kq->queue->pipe,
kq->queue->queue); kq->queue->queue);
...@@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
uint32_t wptr, rptr; uint32_t wptr, rptr;
unsigned int *queue_address; unsigned int *queue_address;
/* When rptr == wptr, the buffer is empty.
* When rptr == wptr + 1, the buffer is full.
* It is always rptr that advances to the position of wptr, rather than
* the opposite. So we can only use up to queue_size_dwords - 1 dwords.
*/
rptr = *kq->rptr_kernel; rptr = *kq->rptr_kernel;
wptr = *kq->wptr_kernel; wptr = *kq->wptr_kernel;
queue_address = (unsigned int *)kq->pq_kernel_addr; queue_address = (unsigned int *)kq->pq_kernel_addr;
...@@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
pr_debug("wptr: %d\n", wptr); pr_debug("wptr: %d\n", wptr);
pr_debug("queue_address 0x%p\n", queue_address); pr_debug("queue_address 0x%p\n", queue_address);
available_size = (rptr - 1 - wptr + queue_size_dwords) % available_size = (rptr + queue_size_dwords - 1 - wptr) %
queue_size_dwords; queue_size_dwords;
if (packet_size_in_dwords >= queue_size_dwords || if (packet_size_in_dwords > available_size) {
packet_size_in_dwords >= available_size) {
/* /*
* make sure calling functions know * make sure calling functions know
* acquire_packet_buffer() failed * acquire_packet_buffer() failed
...@@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq, ...@@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
} }
if (wptr + packet_size_in_dwords >= queue_size_dwords) { if (wptr + packet_size_in_dwords >= queue_size_dwords) {
/* make sure after rolling back to position 0, there is
* still enough space.
*/
if (packet_size_in_dwords >= rptr) {
*buffer_ptr = NULL;
return -ENOMEM;
}
/* fill nops, roll back and start at position 0 */
while (wptr > 0) { while (wptr > 0) {
queue_address[wptr] = kq->nop_packet; queue_address[wptr] = kq->nop_packet;
wptr = (wptr + 1) % queue_size_dwords; wptr = (wptr + 1) % queue_size_dwords;
......
...@@ -521,6 +521,7 @@ struct kfd_process { ...@@ -521,6 +521,7 @@ struct kfd_process {
struct list_head signal_event_pages; struct list_head signal_event_pages;
u32 next_nonsignal_event_id; u32 next_nonsignal_event_id;
size_t signal_event_count; size_t signal_event_count;
bool signal_event_limit_reached;
}; };
/** /**
......
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