summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/host/bus_client.c39
-rw-r--r--drivers/video/tegra/host/nvhost_job.c54
-rw-r--r--drivers/video/tegra/host/nvhost_job.h3
-rw-r--r--include/trace/events/nvhost.h15
4 files changed, 65 insertions, 46 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 397cd21f555d..9b71542a48aa 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -238,21 +238,28 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
cmdbuf.mem, cmdbuf.words, cmdbuf.offset);
hdr->num_cmdbufs--;
} else if (hdr->num_relocs) {
- consumed = sizeof(struct nvhost_reloc);
- if (remaining < consumed)
+ int numrelocs = remaining / sizeof(struct nvhost_reloc);
+ if (!numrelocs)
break;
- if (copy_from_user(&job->pinarray[job->num_relocs],
+ numrelocs = min_t(int, numrelocs, priv->hdr.num_relocs);
+ consumed = numrelocs * sizeof(struct nvhost_reloc);
+ if (copy_from_user(&job->relocarray[job->num_relocs],
buf, consumed)) {
err = -EFAULT;
break;
}
- trace_nvhost_channel_write_reloc(chname,
- job->pinarray[job->num_relocs].patch_mem,
- job->pinarray[job->num_relocs].patch_offset,
- job->pinarray[job->num_relocs].pin_mem,
- job->pinarray[job->num_relocs].pin_offset);
- job->num_relocs++;
- hdr->num_relocs--;
+ while (numrelocs) {
+ struct nvhost_reloc *reloc =
+ &job->relocarray[job->num_relocs];
+ trace_nvhost_channel_write_reloc(chname,
+ reloc->cmdbuf_mem,
+ reloc->cmdbuf_offset,
+ reloc->target,
+ reloc->target_offset);
+ job->num_relocs++;
+ hdr->num_relocs--;
+ numrelocs--;
+ }
} else if (hdr->num_waitchks) {
int numwaitchks =
(remaining / sizeof(struct nvhost_waitchk));
@@ -274,16 +281,18 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
} else if (priv->num_relocshifts) {
int next_shift =
job->num_relocs - priv->num_relocshifts;
- consumed = sizeof(struct nvhost_reloc_shift);
- if (remaining < consumed)
+ int num =
+ (remaining / sizeof(struct nvhost_reloc_shift));
+ if (!num)
break;
- if (copy_from_user(
- &job->pinarray[next_shift].reloc_shift,
+ num = min_t(int, num, priv->num_relocshifts);
+ consumed = num * sizeof(struct nvhost_reloc_shift);
+ if (copy_from_user(&job->relocshiftarray[next_shift],
buf, consumed)) {
err = -EFAULT;
break;
}
- priv->num_relocshifts--;
+ priv->num_relocshifts -= num;
} else {
err = -EFAULT;
break;
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index 6d8c3bd2bd50..e029449b6184 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -41,7 +41,8 @@ static int job_size(struct nvhost_submit_hdr_ext *hdr)
int num_unpins = num_cmdbufs + num_relocs;
return sizeof(struct nvhost_job)
- + num_relocs * sizeof(struct nvmap_pinarray_elem)
+ + num_relocs * sizeof(struct nvhost_reloc)
+ + num_relocs * sizeof(struct nvhost_reloc_shift)
+ num_unpins * sizeof(struct nvmap_handle_ref *)
+ num_waitchks * sizeof(struct nvhost_waitchk)
+ num_cmdbufs * sizeof(struct nvhost_job_gather);
@@ -63,8 +64,10 @@ static void init_fields(struct nvhost_job *job,
/* Redistribute memory to the structs */
mem += sizeof(struct nvhost_job);
- job->pinarray = num_relocs ? mem : NULL;
- mem += num_relocs * sizeof(struct nvmap_pinarray_elem);
+ job->relocarray = num_relocs ? mem : NULL;
+ mem += num_relocs * sizeof(struct nvhost_reloc);
+ job->relocshiftarray = num_relocs ? mem : NULL;
+ mem += num_relocs * sizeof(struct nvhost_reloc_shift);
job->unpins = num_unpins ? mem : NULL;
mem += num_unpins * sizeof(struct nvmap_handle_ref *);
job->waitchk = num_waitchks ? mem : NULL;
@@ -154,44 +157,46 @@ void nvhost_job_add_gather(struct nvhost_job *job,
job->num_gathers += 1;
}
-static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr)
+static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr)
{
- phys_addr_t pin_phys;
+ phys_addr_t target_phys;
int i;
u32 mem_id = 0;
- struct nvmap_handle_ref *pin_ref = NULL;
+ struct nvmap_handle_ref *target_ref = NULL;
/* pin & patch the relocs for one gather */
for (i = 0; i < job->num_relocs; i++) {
- struct nvmap_pinarray_elem *pin = &job->pinarray[i];
+ struct nvhost_reloc *reloc = &job->relocarray[i];
+ struct nvhost_reloc_shift *shift = &job->relocshiftarray[i];
/* skip all other gathers */
- if (patch_mem != pin->patch_mem)
+ if (cmdbuf_mem != reloc->cmdbuf_mem)
continue;
/* check if pin-mem is same as previous */
- if (pin->pin_mem != mem_id) {
- pin_ref = nvmap_duplicate_handle_id(job->nvmap,
- pin->pin_mem);
- if (IS_ERR(pin_ref))
- return PTR_ERR(pin_ref);
-
- pin_phys = nvmap_pin(job->nvmap, pin_ref);
- if (IS_ERR((void *)pin_phys)) {
- nvmap_free(job->nvmap, pin_ref);
- return pin_phys;
+ if (reloc->target != mem_id) {
+ target_ref = nvmap_duplicate_handle_id(job->nvmap,
+ reloc->target);
+ if (IS_ERR(target_ref))
+ return PTR_ERR(target_ref);
+
+ target_phys = nvmap_pin(job->nvmap, target_ref);
+ if (IS_ERR((void *)target_phys)) {
+ nvmap_free(job->nvmap, target_ref);
+ return target_phys;
}
- mem_id = pin->pin_mem;
- job->unpins[job->num_unpins++] = pin_ref;
+ mem_id = reloc->target;
+ job->unpins[job->num_unpins++] = target_ref;
}
- __raw_writel((pin_phys + pin->pin_offset) >> pin->reloc_shift,
- (patch_addr + pin->patch_offset));
+ __raw_writel(
+ (target_phys + reloc->target_offset) >> shift->shift,
+ (cmdbuf_addr + reloc->cmdbuf_offset));
/* Different gathers might have same mem_id. This ensures we
* perform reloc only once per gather memid. */
- pin->patch_mem = 0;
+ reloc->cmdbuf_mem = 0;
}
return 0;
@@ -216,7 +221,8 @@ static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
continue;
trace_nvhost_syncpt_wait_check(wait->mem, wait->offset,
- wait->syncpt_id, wait->thresh);
+ wait->syncpt_id, wait->thresh,
+ nvhost_syncpt_read(sp, wait->syncpt_id));
if (nvhost_syncpt_is_expired(sp,
wait->syncpt_id, wait->thresh)) {
/*
diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h
index b30f5faf7e8f..ec1366337279 100644
--- a/drivers/video/tegra/host/nvhost_job.h
+++ b/drivers/video/tegra/host/nvhost_job.h
@@ -67,7 +67,8 @@ struct nvhost_job {
u32 waitchk_mask;
/* Array of handles to be pinned & unpinned */
- struct nvmap_pinarray_elem *pinarray;
+ struct nvhost_reloc *relocarray;
+ struct nvhost_reloc_shift *relocshiftarray;
int num_relocs;
struct nvmap_handle_ref **unpins;
int num_unpins;
diff --git a/include/trace/events/nvhost.h b/include/trace/events/nvhost.h
index 6358fedf4482..b4818f55844c 100644
--- a/include/trace/events/nvhost.h
+++ b/include/trace/events/nvhost.h
@@ -482,27 +482,30 @@ TRACE_EVENT(nvhost_syncpt_update_min,
);
TRACE_EVENT(nvhost_syncpt_wait_check,
- TP_PROTO(u32 mem_id, u32 offset, u32 syncpt_id, u32 val),
+ TP_PROTO(u32 mem_id, u32 offset, u32 syncpt_id, u32 thresh, u32 min),
- TP_ARGS(mem_id, offset, syncpt_id, val),
+ TP_ARGS(mem_id, offset, syncpt_id, thresh, min),
TP_STRUCT__entry(
__field(u32, mem_id)
__field(u32, offset)
__field(u32, syncpt_id)
- __field(u32, val)
+ __field(u32, thresh)
+ __field(u32, min)
),
TP_fast_assign(
__entry->mem_id = mem_id;
__entry->offset = offset;
__entry->syncpt_id = syncpt_id;
- __entry->val = val;
+ __entry->thresh = thresh;
+ __entry->min = min;
),
- TP_printk("mem_id=%08x, offset=%05x, id=%d, val=%d",
+ TP_printk("mem_id=%08x, offset=%05x, id=%d, thresh=%d, current=%d",
__entry->mem_id, __entry->offset,
- __entry->syncpt_id, __entry->val)
+ __entry->syncpt_id, __entry->thresh,
+ __entry->min)
);
#endif /* _TRACE_NVHOST_H */