summaryrefslogtreecommitdiff
path: root/drivers/video/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/host/bus_client.c32
-rw-r--r--drivers/video/tegra/host/bus_client.h4
-rw-r--r--drivers/video/tegra/host/dev.c11
3 files changed, 40 insertions, 7 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 962de32f359f..651a8dec738c 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -50,10 +50,28 @@
#include "nvhost_job.h"
#include "nvhost_hwctx.h"
-void nvhost_read_module_regs(struct nvhost_device *ndev,
+static int validate_reg(struct nvhost_device *ndev, u32 offset, int count)
+{
+ struct resource *r = nvhost_get_resource(ndev, IORESOURCE_MEM, 0);
+ int err = 0;
+
+ if (offset + 4 * count > resource_size(r)
+ || (offset + 4 * count < offset))
+ err = -EPERM;
+
+ return err;
+}
+
+int nvhost_read_module_regs(struct nvhost_device *ndev,
u32 offset, int count, u32 *values)
{
void __iomem *p = ndev->aperture + offset;
+ int err;
+
+ /* verify offset */
+ err = validate_reg(ndev, offset, count);
+ if (err)
+ return err;
nvhost_module_busy(ndev);
while (count--) {
@@ -62,12 +80,20 @@ void nvhost_read_module_regs(struct nvhost_device *ndev,
}
rmb();
nvhost_module_idle(ndev);
+
+ return 0;
}
-void nvhost_write_module_regs(struct nvhost_device *ndev,
+int nvhost_write_module_regs(struct nvhost_device *ndev,
u32 offset, int count, const u32 *values)
{
void __iomem *p = ndev->aperture + offset;
+ int err;
+
+ /* verify offset */
+ err = validate_reg(ndev, offset, count);
+ if (err)
+ return err;
nvhost_module_busy(ndev);
while (count--) {
@@ -76,6 +102,8 @@ void nvhost_write_module_regs(struct nvhost_device *ndev,
}
wmb();
nvhost_module_idle(ndev);
+
+ return 0;
}
struct nvhost_channel_userctx {
diff --git a/drivers/video/tegra/host/bus_client.h b/drivers/video/tegra/host/bus_client.h
index adc3a704ea5d..e95ea0bc3401 100644
--- a/drivers/video/tegra/host/bus_client.h
+++ b/drivers/video/tegra/host/bus_client.h
@@ -24,10 +24,10 @@
#include <linux/types.h>
struct nvhost_device;
-void nvhost_read_module_regs(struct nvhost_device *ndev,
+int nvhost_read_module_regs(struct nvhost_device *ndev,
u32 offset, int count, u32 *values);
-void nvhost_write_module_regs(struct nvhost_device *ndev,
+int nvhost_write_module_regs(struct nvhost_device *ndev,
u32 offset, int count, const u32 *values);
int nvhost_client_user_init(struct nvhost_device *dev);
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index ca73528fbeeb..67520a884d3e 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -205,6 +205,7 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx,
return -EINVAL;
while (num_offsets--) {
+ int err;
int remaining = args->block_size >> 2;
u32 offs;
if (get_user(offs, offsets))
@@ -216,17 +217,21 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx,
if (copy_from_user(vals, values,
batch*sizeof(u32)))
return -EFAULT;
- nvhost_write_module_regs(ndev,
+ err = nvhost_write_module_regs(ndev,
offs, batch, vals);
+ if (err)
+ return err;
} else {
- nvhost_read_module_regs(ndev,
+ err = nvhost_read_module_regs(ndev,
offs, batch, vals);
+ if (err)
+ return err;
if (copy_to_user(values, vals,
batch*sizeof(u32)))
return -EFAULT;
}
remaining -= batch;
- offs += batch;
+ offs += batch*sizeof(u32);
values += batch;
}
}