diff options
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r-- | drivers/video/tegra/host/bus_client.c | 32 | ||||
-rw-r--r-- | drivers/video/tegra/host/bus_client.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/dev.c | 11 |
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; } } |