aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Murray <timmurray@google.com>2017-06-14 15:23:55 -0700
committerTim Murray <timmurray@google.com>2017-06-15 23:48:10 +0000
commitdc40906c97ae8c01bd83019ea3d8d22653db846c (patch)
tree58076e872d4b7b7b890ced203ffc5fa822088c87
parent1735e86bf493ea61c90670892374adaf5f2fb61f (diff)
kgsl: convert some workqueues to use kthreadsandroid-o-preview-4_r0.2
adreno_dispatch_work and _kgsl_event_worker are both low-latency low-runtime functions that are in the critical path of GPU rendering. Moving them out of workqueues and into a dedicated FIFO kthread avoids significant jitter. bug 30342017 bug 62616267 Signed-off-by: Tim Murray <timmurray@google.com> Change-Id: I5b071a738948b69c23810a8ea5957bdddc274912
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c6
-rw-r--r--drivers/gpu/msm/adreno_dispatch.h2
-rw-r--r--drivers/gpu/msm/kgsl.c14
-rw-r--r--drivers/gpu/msm/kgsl.h5
-rw-r--r--drivers/gpu/msm/kgsl_events.c8
5 files changed, 26 insertions, 9 deletions
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index f5840ffb268d..c728d9d781d6 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -1911,7 +1911,7 @@ static int adreno_dispatch_process_cmdqueue(struct adreno_device *adreno_dev,
*
* Process expired commands and send new ones.
*/
-static void adreno_dispatcher_work(struct work_struct *work)
+static void adreno_dispatcher_work(struct kthread_work *work)
{
struct adreno_dispatcher *dispatcher =
container_of(work, struct adreno_dispatcher, work);
@@ -1988,7 +1988,7 @@ void adreno_dispatcher_schedule(struct kgsl_device *device)
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
- queue_work(device->work_queue, &dispatcher->work);
+ queue_kthread_work(&kgsl_driver.worker, &dispatcher->work);
}
/**
@@ -2279,7 +2279,7 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev)
setup_timer(&dispatcher->fault_timer, adreno_dispatcher_fault_timer,
(unsigned long) adreno_dev);
- INIT_WORK(&dispatcher->work, adreno_dispatcher_work);
+ init_kthread_work(&dispatcher->work, adreno_dispatcher_work);
init_completion(&dispatcher->idle_gate);
complete_all(&dispatcher->idle_gate);
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index c2721ad0c880..d7637146fe91 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -72,7 +72,7 @@ struct adreno_dispatcher {
atomic_t fault;
struct plist_head pending;
spinlock_t plist_lock;
- struct work_struct work;
+ struct kthread_work work;
struct kobject kobj;
struct completion idle_gate;
};
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 350ad08fb53a..85975052f035 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -4854,6 +4854,8 @@ static void kgsl_core_exit(void)
static int __init kgsl_core_init(void)
{
int result = 0;
+ struct sched_param param = { .sched_priority = 2 };
+
/* alloc major and minor device numbers */
result = alloc_chrdev_region(&kgsl_driver.major, 0, KGSL_DEVICE_MAX,
"kgsl");
@@ -4915,6 +4917,18 @@ static int __init kgsl_core_init(void)
kgsl_mmu_set_mmutype(ksgl_mmu_type);
+ init_kthread_worker(&kgsl_driver.worker);
+
+ kgsl_driver.worker_thread = kthread_run(kthread_worker_fn,
+ &kgsl_driver.worker, "kgsl_worker_thread");
+
+ if (IS_ERR(kgsl_driver.worker_thread)) {
+ pr_err("unable to start kgsl thread\n");
+ goto err;
+ }
+
+ sched_setscheduler(kgsl_driver.worker_thread, SCHED_FIFO, &param);
+
kgsl_events_init();
/* create the memobjs kmem cache */
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index cb8b388e75a8..e4e53e339a18 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -25,6 +25,7 @@
#include <linux/regulator/consumer.h>
#include <linux/mm.h>
#include <linux/dma-attrs.h>
+#include <linux/kthread.h>
/* The number of memstore arrays limits the number of contexts allowed.
* If more contexts are needed, update multiple for MEMSTORE_SIZE
@@ -95,6 +96,8 @@ struct kgsl_driver {
unsigned int mapped_max;
} stats;
unsigned int full_cache_threshold;
+ struct kthread_worker worker;
+ struct task_struct *worker_thread;
};
extern struct kgsl_driver kgsl_driver;
@@ -223,7 +226,7 @@ struct kgsl_event {
void *priv;
struct list_head node;
unsigned int created;
- struct work_struct work;
+ struct kthread_work work;
int result;
struct kgsl_event_group *group;
};
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 81fcbe61e0d4..f4bca88f4b41 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -32,7 +32,7 @@ static inline void signal_event(struct kgsl_device *device,
{
list_del(&event->node);
event->result = result;
- queue_work(device->events_wq, &event->work);
+ queue_kthread_work(&kgsl_driver.worker, &event->work);
}
/**
@@ -42,7 +42,7 @@ static inline void signal_event(struct kgsl_device *device,
* Each event callback has its own work struct and is run on a event specific
* workqeuue. This is the worker that queues up the event callback function.
*/
-static void _kgsl_event_worker(struct work_struct *work)
+static void _kgsl_event_worker(struct kthread_work *work)
{
struct kgsl_event *event = container_of(work, struct kgsl_event, work);
int id = KGSL_CONTEXT_ID(event->context);
@@ -261,7 +261,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group,
event->created = jiffies;
event->group = group;
- INIT_WORK(&event->work, _kgsl_event_worker);
+ init_kthread_work(&event->work, _kgsl_event_worker);
trace_kgsl_register_event(KGSL_CONTEXT_ID(context), timestamp, func);
@@ -276,7 +276,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group,
if (timestamp_cmp(retired, timestamp) >= 0) {
event->result = KGSL_EVENT_RETIRED;
- queue_work(device->events_wq, &event->work);
+ queue_kthread_work(&kgsl_driver.worker, &event->work);
spin_unlock(&group->lock);
return 0;
}