summaryrefslogtreecommitdiff
path: root/drivers/gpu/host1x/intr.c
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2013-03-22 14:34:03 (GMT)
committerThierry Reding <thierry.reding@avionic-design.de>2013-04-22 10:32:43 (GMT)
commit6579324a41cc414009a601738b70a53d6376325c (patch)
tree61b3491351217d07ff75851c6d989bf02b213383 /drivers/gpu/host1x/intr.c
parent7ede0b0bf3e2595d40d6195b6fe4c4dcef438830 (diff)
downloadlinux-6579324a41cc414009a601738b70a53d6376325c.tar.xz
gpu: host1x: Add channel support
Add support for host1x client modules, and host1x channels to submit work to the clients. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/gpu/host1x/intr.c')
-rw-r--r--drivers/gpu/host1x/intr.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c
index b1b5a80..2491bf8 100644
--- a/drivers/gpu/host1x/intr.c
+++ b/drivers/gpu/host1x/intr.c
@@ -21,6 +21,8 @@
#include <linux/slab.h>
#include <linux/irq.h>
+#include <trace/events/host1x.h>
+#include "channel.h"
#include "dev.h"
#include "intr.h"
@@ -66,7 +68,7 @@ static void remove_completed_waiters(struct list_head *head, u32 sync,
struct list_head completed[HOST1X_INTR_ACTION_COUNT])
{
struct list_head *dest;
- struct host1x_waitlist *waiter, *next;
+ struct host1x_waitlist *waiter, *next, *prev;
list_for_each_entry_safe(waiter, next, head, list) {
if ((s32)(waiter->thresh - sync) > 0)
@@ -74,6 +76,17 @@ static void remove_completed_waiters(struct list_head *head, u32 sync,
dest = completed + waiter->action;
+ /* consolidate submit cleanups */
+ if (waiter->action == HOST1X_INTR_ACTION_SUBMIT_COMPLETE &&
+ !list_empty(dest)) {
+ prev = list_entry(dest->prev,
+ struct host1x_waitlist, list);
+ if (prev->data == waiter->data) {
+ prev->count++;
+ dest = NULL;
+ }
+ }
+
/* PENDING->REMOVED or CANCELLED->HANDLED */
if (atomic_inc_return(&waiter->state) == WLS_HANDLED || !dest) {
list_del(&waiter->list);
@@ -94,6 +107,18 @@ static void reset_threshold_interrupt(struct host1x *host,
host1x_hw_intr_enable_syncpt_intr(host, id);
}
+static void action_submit_complete(struct host1x_waitlist *waiter)
+{
+ struct host1x_channel *channel = waiter->data;
+
+ host1x_cdma_update(&channel->cdma);
+
+ /* Add nr_completed to trace */
+ trace_host1x_channel_submit_complete(dev_name(channel->dev),
+ waiter->count, waiter->thresh);
+
+}
+
static void action_wakeup(struct host1x_waitlist *waiter)
{
wait_queue_head_t *wq = waiter->data;
@@ -109,6 +134,7 @@ static void action_wakeup_interruptible(struct host1x_waitlist *waiter)
typedef void (*action_handler)(struct host1x_waitlist *waiter);
static action_handler action_handlers[HOST1X_INTR_ACTION_COUNT] = {
+ action_submit_complete,
action_wakeup,
action_wakeup_interruptible,
};