diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-11-24 12:32:58 +0200 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2012-03-23 17:32:03 -0700 |
commit | dc2056e7a6ad7a1579f645b2dccad6ff42dca82b (patch) | |
tree | 4a980ebfdb85812b5874128dda702d3f45624564 /drivers | |
parent | fbbeba9a4e7ae7020eac36f7738a67367e2b58e9 (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
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/host/dev.c | 43 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 1 |
2 files changed, 36 insertions, 8 deletions
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)); } |