diff options
Diffstat (limited to 'drivers/gpu/host1x/job.c')
-rw-r--r-- | drivers/gpu/host1x/job.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index c4e1050f2252..de5ec333ce1a 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -18,6 +18,7 @@ #include <linux/dma-mapping.h> #include <linux/err.h> +#include <linux/host1x.h> #include <linux/kref.h> #include <linux/module.h> #include <linux/scatterlist.h> @@ -27,7 +28,6 @@ #include "channel.h" #include "dev.h" -#include "host1x_bo.h" #include "job.h" #include "syncpt.h" @@ -264,7 +264,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) } static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, - unsigned int offset) + unsigned int offset) { offset *= sizeof(u32); @@ -281,7 +281,7 @@ struct host1x_firewall { unsigned int num_relocs; struct host1x_reloc *reloc; - struct host1x_bo *cmdbuf_id; + struct host1x_bo *cmdbuf; unsigned int offset; u32 words; @@ -291,25 +291,37 @@ struct host1x_firewall { u32 count; }; +static int check_register(struct host1x_firewall *fw, unsigned long offset) +{ + if (fw->job->is_addr_reg(fw->dev, fw->class, offset)) { + if (!fw->num_relocs) + return -EINVAL; + + if (!check_reloc(fw->reloc, fw->cmdbuf, fw->offset)) + return -EINVAL; + + fw->num_relocs--; + fw->reloc++; + } + + return 0; +} + static int check_mask(struct host1x_firewall *fw) { u32 mask = fw->mask; u32 reg = fw->reg; + int ret; while (mask) { if (fw->words == 0) return -EINVAL; if (mask & 1) { - if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { - if (!fw->num_relocs) - return -EINVAL; - if (!check_reloc(fw->reloc, fw->cmdbuf_id, - fw->offset)) - return -EINVAL; - fw->reloc++; - fw->num_relocs--; - } + ret = check_register(fw, reg); + if (ret < 0) + return ret; + fw->words--; fw->offset++; } @@ -324,19 +336,16 @@ static int check_incr(struct host1x_firewall *fw) { u32 count = fw->count; u32 reg = fw->reg; + int ret; while (count) { if (fw->words == 0) return -EINVAL; - if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { - if (!fw->num_relocs) - return -EINVAL; - if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) - return -EINVAL; - fw->reloc++; - fw->num_relocs--; - } + ret = check_register(fw, reg); + if (ret < 0) + return ret; + reg++; fw->words--; fw->offset++; @@ -348,21 +357,17 @@ static int check_incr(struct host1x_firewall *fw) static int check_nonincr(struct host1x_firewall *fw) { - int is_addr_reg = fw->job->is_addr_reg(fw->dev, fw->class, fw->reg); u32 count = fw->count; + int ret; while (count) { if (fw->words == 0) return -EINVAL; - if (is_addr_reg) { - if (!fw->num_relocs) - return -EINVAL; - if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) - return -EINVAL; - fw->reloc++; - fw->num_relocs--; - } + ret = check_register(fw, fw->reg); + if (ret < 0) + return ret; + fw->words--; fw->offset++; count--; @@ -381,7 +386,7 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g) return 0; fw->words = g->words; - fw->cmdbuf_id = g->bo; + fw->cmdbuf = g->bo; fw->offset = 0; while (fw->words && !err) { @@ -436,10 +441,6 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g) } } - /* No relocs should remain at this point */ - if (fw->num_relocs) - err = -EINVAL; - out: return err; } @@ -493,6 +494,10 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev) offset += g->words * sizeof(u32); } + /* No relocs should remain at this point */ + if (fw.num_relocs) + return -EINVAL; + return 0; } |