diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2013-03-22 16:34:03 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2013-04-22 12:32:43 +0200 |
commit | 6579324a41cc414009a601738b70a53d6376325c (patch) | |
tree | 61b3491351217d07ff75851c6d989bf02b213383 /drivers/gpu/host1x/intr.c | |
parent | 7ede0b0bf3e2595d40d6195b6fe4c4dcef438830 (diff) | |
download | lwn-6579324a41cc414009a601738b70a53d6376325c.tar.gz lwn-6579324a41cc414009a601738b70a53d6376325c.zip |
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.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c index b1b5a80e3125..2491bf82e30c 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, }; |