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
This commit is contained in:
commit
f2e295342e
@ -892,6 +892,8 @@ static int kfd_ioctl_get_tile_config(struct file *filep,
|
||||
int err = 0;
|
||||
|
||||
dev = kfd_device_by_id(args->gpu_id);
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
dev->kfd2kgd->get_tile_config(dev->kgd, &config);
|
||||
|
||||
|
@ -292,7 +292,10 @@ static int create_signal_event(struct file *devkfd,
|
||||
struct kfd_event *ev)
|
||||
{
|
||||
if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) {
|
||||
pr_warn("Signal event wasn't created because limit was reached\n");
|
||||
if (!p->signal_event_limit_reached) {
|
||||
pr_warn("Signal event wasn't created because limit was reached\n");
|
||||
p->signal_event_limit_reached = true;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ static void uninitialize(struct kernel_queue *kq)
|
||||
if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ)
|
||||
kq->mqd->destroy_mqd(kq->mqd,
|
||||
kq->queue->mqd,
|
||||
false,
|
||||
KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
|
||||
QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS,
|
||||
kq->queue->pipe,
|
||||
kq->queue->queue);
|
||||
@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
||||
uint32_t wptr, rptr;
|
||||
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;
|
||||
wptr = *kq->wptr_kernel;
|
||||
queue_address = (unsigned int *)kq->pq_kernel_addr;
|
||||
@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
||||
pr_debug("wptr: %d\n", wptr);
|
||||
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;
|
||||
|
||||
if (packet_size_in_dwords >= queue_size_dwords ||
|
||||
packet_size_in_dwords >= available_size) {
|
||||
if (packet_size_in_dwords > available_size) {
|
||||
/*
|
||||
* make sure calling functions know
|
||||
* acquire_packet_buffer() failed
|
||||
@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
|
||||
}
|
||||
|
||||
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) {
|
||||
queue_address[wptr] = kq->nop_packet;
|
||||
wptr = (wptr + 1) % queue_size_dwords;
|
||||
|
@ -521,6 +521,7 @@ struct kfd_process {
|
||||
struct list_head signal_event_pages;
|
||||
u32 next_nonsignal_event_id;
|
||||
size_t signal_event_count;
|
||||
bool signal_event_limit_reached;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user