summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2011-11-24 12:32:58 +0200
committerDan Willemsen <dwillemsen@nvidia.com>2012-03-23 17:32:03 -0700
commitdc2056e7a6ad7a1579f645b2dccad6ff42dca82b (patch)
tree4a980ebfdb85812b5874128dda702d3f45624564
parentfbbeba9a4e7ae7020eac36f7738a67367e2b58e9 (diff)
video: tegra: host: Support for right shift on reloc patches
Some hardware architectures require that only select MSB bits be supplied to them for addresses. They do the reverse transformation while accessing the actual memory. Bug 857531 Change-Id: I215f099ff0ee86daff1c1eb1e5b70edf8ae856d9 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/66654 Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Reviewed-by: Shashank Garg <sgarg@nvidia.com> Rebase-Id: R916b93026c73be95f2f8c15f9704f3b5dd53faa7
-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 488e9503755c..389e21faed52 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -58,6 +58,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;
@@ -220,6 +221,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;
}
@@ -227,6 +231,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;
}
@@ -240,6 +245,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);
@@ -271,20 +277,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));
@@ -302,6 +305,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;
@@ -421,6 +436,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);
@@ -688,6 +704,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)
{
@@ -726,6 +750,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 d6fc06079236..de6907f86b71 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,