summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/host/bus_client.c6
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c33
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h3
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c24
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c10
-rw-r--r--include/trace/events/nvhost.h62
6 files changed, 121 insertions, 17 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 9b71542a48aa..87aa9c64d363 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -141,12 +141,6 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp)
priv->clientid = atomic_add_return(1,
&nvhost_get_host(ch->dev)->clientid);
priv->timeout = MAX_STUCK_CHECK_COUNT * SYNCPT_CHECK_PERIOD;
-
- priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr,
- NULL, priv->priority, priv->clientid);
- if (!priv->job)
- goto fail;
-
return 0;
fail:
nvhost_channelrelease(inode, filp);
diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c
index b1f138317cc1..c87415bf5ac2 100644
--- a/drivers/video/tegra/host/nvhost_cdma.c
+++ b/drivers/video/tegra/host/nvhost_cdma.c
@@ -53,6 +53,18 @@ static void add_to_sync_queue(struct nvhost_cdma *cdma,
job->num_slots = nr_slots;
nvhost_job_get(job);
list_add_tail(&job->list, &cdma->sync_queue);
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ cdma->high_prio_count++;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ cdma->med_prio_count++;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ cdma->low_prio_count++;
+ break;
+ }
}
/**
@@ -200,6 +212,19 @@ static void update_cdma_locked(struct nvhost_cdma *cdma)
}
list_del(&job->list);
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ cdma->high_prio_count--;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ cdma->med_prio_count--;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ cdma->low_prio_count--;
+ break;
+ }
+
nvhost_job_put(job);
}
@@ -466,6 +491,12 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma,
if (job->timeout && was_idle)
cdma_start_timer_locked(cdma, job);
+ trace_nvhost_cdma_end(job->ch->dev->name,
+ job->priority,
+ job->ch->cdma.high_prio_count,
+ job->ch->cdma.med_prio_count,
+ job->ch->cdma.low_prio_count);
+
mutex_unlock(&cdma->lock);
}
@@ -490,6 +521,8 @@ int nvhost_cdma_flush(struct nvhost_cdma *cdma, int timeout)
unsigned int space, err = 0;
unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout);
+ trace_nvhost_cdma_flush(cdma_to_channel(cdma)->dev->name, timeout);
+
/*
* Wait for at most timeout ms. Recalculate timeout at each iteration
* to better keep within given timeout.
diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h
index 98393f0cc765..2056774a7bc7 100644
--- a/drivers/video/tegra/host/nvhost_cdma.h
+++ b/drivers/video/tegra/host/nvhost_cdma.h
@@ -99,6 +99,9 @@ struct nvhost_cdma {
struct buffer_timeout timeout; /* channel's timeout state/wq */
bool running;
bool torndown;
+ int high_prio_count;
+ int med_prio_count;
+ int low_prio_count;
};
#define cdma_to_channel(cdma) container_of(cdma, struct nvhost_channel, cdma)
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index ef8886fe4652..ad303cf0a22d 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -51,10 +51,26 @@ int nvhost_channel_init(struct nvhost_channel *ch,
int nvhost_channel_submit(struct nvhost_job *job)
{
- /* Low priority submits wait until sync queue is empty. Ignores result
- * from nvhost_cdma_flush, as we submit either when push buffer is
- * empty or when we reach the timeout. */
- if (job->priority < NVHOST_PRIORITY_MEDIUM)
+ /*
+ * Check if queue has higher priority jobs running. If so, wait until
+ * queue is empty. Ignores result from nvhost_cdma_flush, as we submit
+ * either when push buffer is empty or when we reach the timeout.
+ */
+ int higher_count = 0;
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ higher_count = 0;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ higher_count = job->ch->cdma.high_prio_count;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ higher_count = job->ch->cdma.high_prio_count
+ + job->ch->cdma.med_prio_count;
+ break;
+ }
+ if (higher_count > 0)
(void)nvhost_cdma_flush(&job->ch->cdma,
NVHOST_CHANNEL_LOW_PRIO_MAX_WAIT);
diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c
index ba821f694cb4..af2e3ad1bdb5 100644
--- a/drivers/video/tegra/host/nvhost_intr.c
+++ b/drivers/video/tegra/host/nvhost_intr.c
@@ -128,12 +128,16 @@ static void action_submit_complete(struct nvhost_waitlist *waiter)
struct nvhost_channel *channel = waiter->data;
int nr_completed = waiter->count;
+ nvhost_cdma_update(&channel->cdma);
+ nvhost_module_idle_mult(channel->dev, nr_completed);
+
/* Add nr_completed to trace */
trace_nvhost_channel_submit_complete(channel->dev->name,
- nr_completed, waiter->thresh);
+ nr_completed, waiter->thresh,
+ channel->cdma.high_prio_count,
+ channel->cdma.med_prio_count,
+ channel->cdma.low_prio_count);
- nvhost_cdma_update(&channel->cdma);
- nvhost_module_idle_mult(channel->dev, nr_completed);
}
static void action_ctxsave(struct nvhost_waitlist *waiter)
diff --git a/include/trace/events/nvhost.h b/include/trace/events/nvhost.h
index b4818f55844c..6506af44e576 100644
--- a/include/trace/events/nvhost.h
+++ b/include/trace/events/nvhost.h
@@ -138,6 +138,52 @@ TRACE_EVENT(nvhost_channel_write_cmdbuf,
__entry->words, __entry->offset)
);
+TRACE_EVENT(nvhost_cdma_end,
+ TP_PROTO(const char *name, int prio,
+ int hi_count, int med_count, int low_count),
+
+ TP_ARGS(name, prio, hi_count, med_count, low_count),
+
+ TP_STRUCT__entry(
+ __field(const char *, name)
+ __field(int, prio)
+ __field(int, hi_count)
+ __field(int, med_count)
+ __field(int, low_count)
+ ),
+
+ TP_fast_assign(
+ __entry->name = name;
+ __entry->prio = prio;
+ __entry->hi_count = hi_count;
+ __entry->med_count = med_count;
+ __entry->low_count = low_count;
+ ),
+
+ TP_printk("name=%s, prio=%d, hi=%d, med=%d, low=%d",
+ __entry->name, __entry->prio,
+ __entry->hi_count, __entry->med_count, __entry->low_count)
+);
+
+TRACE_EVENT(nvhost_cdma_flush,
+ TP_PROTO(const char *name, int timeout),
+
+ TP_ARGS(name, timeout),
+
+ TP_STRUCT__entry(
+ __field(const char *, name)
+ __field(int, timeout)
+ ),
+
+ TP_fast_assign(
+ __entry->name = name;
+ __entry->timeout = timeout;
+ ),
+
+ TP_printk("name=%s, timeout=%d",
+ __entry->name, __entry->timeout)
+);
+
TRACE_EVENT(nvhost_cdma_push,
TP_PROTO(const char *name, u32 op1, u32 op2),
@@ -425,24 +471,32 @@ TRACE_EVENT(nvhost_channel_submitted,
);
TRACE_EVENT(nvhost_channel_submit_complete,
- TP_PROTO(const char *name, int count, u32 thresh),
+ TP_PROTO(const char *name, int count, u32 thresh,
+ int hi_count, int med_count, int low_count),
- TP_ARGS(name, count, thresh),
+ TP_ARGS(name, count, thresh, hi_count, med_count, low_count),
TP_STRUCT__entry(
__field(const char *, name)
__field(int, count)
__field(u32, thresh)
+ __field(int, hi_count)
+ __field(int, med_count)
+ __field(int, low_count)
),
TP_fast_assign(
__entry->name = name;
__entry->count = count;
__entry->thresh = thresh;
+ __entry->hi_count = hi_count;
+ __entry->med_count = med_count;
+ __entry->low_count = low_count;
),
- TP_printk("name=%s, count=%d, thresh=%d",
- __entry->name, __entry->count, __entry->thresh)
+ TP_printk("name=%s, count=%d, thresh=%d, hi=%d, med=%d, low=%d",
+ __entry->name, __entry->count, __entry->thresh,
+ __entry->hi_count, __entry->med_count, __entry->low_count)
);
TRACE_EVENT(nvhost_wait_cdma,