gpu: nvgpu: modify priority of NVS worker thread

In linux threaded interrupts run with a Realtime priority
of 50. This bumps up the priority of bottom-half handlers
over regular kernel/User threads even during process
context.

In the current implementation scheduler thread still
runs in normal kernel thread priority. In order to
allow a seamless scheduling experience, the worker
thread is now created with a Realtime priority of 1.
This allows for the Worker thread to work at a priority
lower than interrupt handlers but higher than the regular
kernel threads.

Linux kernel allows setting priority with the help of
sched_set_fifo() API. Only two modes are supported
i.e. sched_set_fifo() and sched_set_fifo_low().

For more reference, refer to this article
https://lwn.net/Articles/818388/.

Added an implementation of nvgpu_thread_create_priority()
for linux thread using the above two APIs.

Jira NVGPU-860

Signed-off-by: Debarshi Dutta <ddutta@nvidia.com>
Change-Id: I0a5a611bf0e0a5b9bb51354c6ff0a99e42e76e2f
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2751736
Reviewed-by: Prateek Sethi <prsethi@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Debarshi Dutta
2022-07-27 12:44:16 +05:30
committed by mobile promotions
parent 13699c4c15
commit 1d4b7b1c5d
6 changed files with 173 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -15,6 +15,8 @@
*/
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/version.h>
#include <nvgpu/thread.h>
#include <nvgpu/timers.h>
@@ -56,6 +58,47 @@ int nvgpu_thread_create(struct nvgpu_thread *thread,
return 0;
};
int nvgpu_thread_create_priority(struct nvgpu_thread *thread,
void *data, int (*threadfn)(void *data),
int priority, const char *name)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
struct sched_param sparam = {0};
#endif
struct task_struct *task = kthread_create(nvgpu_thread_proxy,
thread, name);
if (IS_ERR(task))
return PTR_ERR(task);
if (priority > 1) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
/* Higher priority tasks are run in threaded interrupt priority level */
sched_set_fifo(task);
#else
sparam.sched_priority = MAX_RT_PRIO / 2;
sched_setscheduler(task, SCHED_FIFO, &sparam);
#endif
} else {
/* Only cares about setting a priority higher than normal,
* Lower than threaded interrupt priority but higher than normal.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
sched_set_fifo_low(task);
#else
sparam.sched_priority = 1;
sched_setscheduler(task, SCHED_FIFO, &sparam);
#endif
}
thread->task = task;
thread->fn = threadfn;
thread->data = data;
nvgpu_atomic_set(&thread->running, true);
wake_up_process(task);
return 0;
}
void nvgpu_thread_stop(struct nvgpu_thread *thread)
{
bool was_running;