summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/include/mach/nvmap.h1
-rw-r--r--drivers/video/tegra/host/dev.c43
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c1
-rw-r--r--include/linux/nvhost_ioctl.h12
-rw-r--r--include/trace/events/nvhost.h12
5 files changed, 52 insertions, 17 deletions
diff --git a/arch/arm/mach-tegra/include/mach/nvmap.h b/arch/arm/mach-tegra/include/mach/nvmap.h
index ad23caa45cfb..cb5375226bc8 100644
--- a/arch/arm/mach-tegra/include/mach/nvmap.h
+++ b/arch/arm/mach-tegra/include/mach/nvmap.h
@@ -65,6 +65,7 @@ struct nvmap_pinarray_elem {
__u32 patch_offset;
__u32 pin_mem;
__u32 pin_offset;
+ __u32 reloc_shift;
};
/* handle_ref objects are client-local references to an nvmap_handle;
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;
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 0bf4d884aa81..5fcdee61b71c 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -423,6 +423,7 @@ static int nvmap_reloc_pin_array(struct nvmap_client *client,
}
reloc_addr = handle_phys(pin) + arr[i].pin_offset;
+ reloc_addr >>= arr[i].reloc_shift;
__raw_writel(reloc_addr, addr + (phys & ~PAGE_MASK));
}
diff --git a/include/linux/nvhost_ioctl.h b/include/linux/nvhost_ioctl.h
index 31ff22f45fb9..a1fc0b7cd247 100644
--- a/include/linux/nvhost_ioctl.h
+++ b/include/linux/nvhost_ioctl.h
@@ -48,7 +48,8 @@ struct nvhost_submit_hdr {
#define NVHOST_SUBMIT_VERSION_V0 0x0
#define NVHOST_SUBMIT_VERSION_V1 0x1
-#define NVHOST_SUBMIT_VERSION_MAX_SUPPORTED NVHOST_SUBMIT_VERSION_V1
+#define NVHOST_SUBMIT_VERSION_V2 0x2
+#define NVHOST_SUBMIT_VERSION_MAX_SUPPORTED NVHOST_SUBMIT_VERSION_V2
/* version 1 header (used with ioctl() submit interface) */
struct nvhost_submit_hdr_ext {
@@ -75,6 +76,10 @@ struct nvhost_reloc {
__u32 target_offset;
};
+struct nvhost_reloc_shift {
+ __u32 shift;
+};
+
struct nvhost_waitchk {
__u32 mem;
__u32 offset;
@@ -188,8 +193,11 @@ struct nvhost_ctrl_module_regrdwr_args {
#define NVHOST_IOCTL_CTRL_SYNCPT_WAITEX \
_IOWR(NVHOST_IOCTL_MAGIC, 6, struct nvhost_ctrl_syncpt_waitex_args)
+#define NVHOST_IOCTL_CTRL_GET_VERSION \
+ _IOR(NVHOST_IOCTL_MAGIC, 7, struct nvhost_get_param_args)
+
#define NVHOST_IOCTL_CTRL_LAST \
- _IOC_NR(NVHOST_IOCTL_CTRL_SYNCPT_WAITEX)
+ _IOC_NR(NVHOST_IOCTL_CTRL_GET_VERSION)
#define NVHOST_IOCTL_CTRL_MAX_ARG_SIZE \
sizeof(struct nvhost_ctrl_module_regrdwr_args)
diff --git a/include/trace/events/nvhost.h b/include/trace/events/nvhost.h
index a0184440a09c..6c266b9f2ea4 100644
--- a/include/trace/events/nvhost.h
+++ b/include/trace/events/nvhost.h
@@ -172,23 +172,21 @@ TRACE_EVENT(nvhost_channel_write_cmdbuf_data,
__entry->cmdbuf ? __entry->words * 4 : 0))
);
-TRACE_EVENT(nvhost_channel_write_relocs,
- TP_PROTO(const char *name, u32 relocs),
+TRACE_EVENT(nvhost_channel_write_reloc,
+ TP_PROTO(const char *name),
- TP_ARGS(name, relocs),
+ TP_ARGS(name),
TP_STRUCT__entry(
__field(const char *, name)
- __field(u32, relocs)
),
TP_fast_assign(
__entry->name = name;
- __entry->relocs = relocs;
),
- TP_printk("name=%s, relocs=%u",
- __entry->name, __entry->relocs)
+ TP_printk("name=%s",
+ __entry->name)
);
TRACE_EVENT(nvhost_channel_write_waitchks,