summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/host/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/host/dev.c')
-rw-r--r--drivers/video/tegra/host/dev.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index 1767e53ca884..fa5cbaeefa2b 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -57,6 +57,7 @@ struct nvhost_channel_userctx {
struct nvhost_channel *ch;
struct nvhost_hwctx *hwctx;
struct nvhost_submit_hdr_ext hdr;
+ int num_relocshifts;
struct nvmap_handle_ref *gather_mem;
u32 *gathers;
u32 *cur_gather;
@@ -219,6 +220,9 @@ static int set_submit(struct nvhost_channel_userctx *ctx)
ctx->cur_waitchk = ctx->waitchks;
ctx->pinarray_size = 0;
+ if (ctx->hdr.submit_version >= NVHOST_SUBMIT_VERSION_V2)
+ ctx->num_relocshifts = ctx->hdr.num_relocs;
+
return 0;
}
@@ -226,6 +230,7 @@ static void reset_submit(struct nvhost_channel_userctx *ctx)
{
ctx->hdr.num_cmdbufs = 0;
ctx->hdr.num_relocs = 0;
+ ctx->num_relocshifts = 0;
ctx->hdr.num_waitchks = 0;
}
@@ -239,6 +244,7 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
while (remaining) {
size_t consumed;
if (!priv->hdr.num_relocs &&
+ !priv->num_relocshifts &&
!priv->hdr.num_cmdbufs &&
!priv->hdr.num_waitchks) {
consumed = sizeof(struct nvhost_submit_hdr);
@@ -270,20 +276,17 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
cmdbuf.mem, cmdbuf.words, cmdbuf.offset);
priv->hdr.num_cmdbufs--;
} else if (priv->hdr.num_relocs) {
- int numrelocs = remaining / sizeof(struct nvhost_reloc);
- if (!numrelocs)
+ consumed = sizeof(struct nvhost_reloc);
+ if (remaining < consumed)
break;
- numrelocs = min_t(int, numrelocs, priv->hdr.num_relocs);
- consumed = numrelocs * sizeof(struct nvhost_reloc);
if (copy_from_user(&priv->pinarray[priv->pinarray_size],
buf, consumed)) {
err = -EFAULT;
break;
}
- trace_nvhost_channel_write_relocs(priv->ch->desc->name,
- numrelocs);
- priv->pinarray_size += numrelocs;
- priv->hdr.num_relocs -= numrelocs;
+ trace_nvhost_channel_write_reloc(priv->ch->desc->name);
+ priv->pinarray_size++;
+ priv->hdr.num_relocs--;
} else if (priv->hdr.num_waitchks) {
int numwaitchks =
(remaining / sizeof(struct nvhost_waitchk));
@@ -301,6 +304,18 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
priv->hdr.waitchk_mask);
priv->cur_waitchk += numwaitchks;
priv->hdr.num_waitchks -= numwaitchks;
+ } else if (priv->num_relocshifts) {
+ int next_shift =
+ priv->pinarray_size - priv->num_relocshifts;
+ consumed = sizeof(struct nvhost_reloc_shift);
+ if (remaining < consumed)
+ break;
+ if (copy_from_user(&priv->pinarray[next_shift].reloc_shift,
+ buf, consumed)) {
+ err = -EFAULT;
+ break;
+ }
+ priv->num_relocshifts--;
} else {
err = -EFAULT;
break;
@@ -420,6 +435,7 @@ static long nvhost_channelctl(struct file *filp,
struct nvhost_submit_hdr_ext *hdr;
if (priv->hdr.num_relocs ||
+ priv->num_relocshifts ||
priv->hdr.num_cmdbufs ||
priv->hdr.num_waitchks) {
reset_submit(priv);
@@ -687,6 +703,14 @@ static int nvhost_ioctl_ctrl_module_regrdwr(
return 0;
}
+static int nvhost_ioctl_ctrl_get_version(
+ struct nvhost_ctrl_userctx *ctx,
+ struct nvhost_get_param_args *args)
+{
+ args->value = NVHOST_SUBMIT_VERSION_MAX_SUPPORTED;
+ return 0;
+}
+
static long nvhost_ctrlctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -725,6 +749,9 @@ static long nvhost_ctrlctl(struct file *filp,
case NVHOST_IOCTL_CTRL_SYNCPT_WAITEX:
err = nvhost_ioctl_ctrl_syncpt_waitex(priv, (void *)buf);
break;
+ case NVHOST_IOCTL_CTRL_GET_VERSION:
+ err = nvhost_ioctl_ctrl_get_version(priv, (void *)buf);
+ break;
default:
err = -ENOTTY;
break;