aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/job.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/job.c')
-rw-r--r--drivers/gpu/host1x/job.c73
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 @@
18 18
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/host1x.h>
21#include <linux/kref.h> 22#include <linux/kref.h>
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/scatterlist.h> 24#include <linux/scatterlist.h>
@@ -27,7 +28,6 @@
27 28
28#include "channel.h" 29#include "channel.h"
29#include "dev.h" 30#include "dev.h"
30#include "host1x_bo.h"
31#include "job.h" 31#include "job.h"
32#include "syncpt.h" 32#include "syncpt.h"
33 33
@@ -264,7 +264,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
264} 264}
265 265
266static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, 266static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
267 unsigned int offset) 267 unsigned int offset)
268{ 268{
269 offset *= sizeof(u32); 269 offset *= sizeof(u32);
270 270
@@ -281,7 +281,7 @@ struct host1x_firewall {
281 unsigned int num_relocs; 281 unsigned int num_relocs;
282 struct host1x_reloc *reloc; 282 struct host1x_reloc *reloc;
283 283
284 struct host1x_bo *cmdbuf_id; 284 struct host1x_bo *cmdbuf;
285 unsigned int offset; 285 unsigned int offset;
286 286
287 u32 words; 287 u32 words;
@@ -291,25 +291,37 @@ struct host1x_firewall {
291 u32 count; 291 u32 count;
292}; 292};
293 293
294static int check_register(struct host1x_firewall *fw, unsigned long offset)
295{
296 if (fw->job->is_addr_reg(fw->dev, fw->class, offset)) {
297 if (!fw->num_relocs)
298 return -EINVAL;
299
300 if (!check_reloc(fw->reloc, fw->cmdbuf, fw->offset))
301 return -EINVAL;
302
303 fw->num_relocs--;
304 fw->reloc++;
305 }
306
307 return 0;
308}
309
294static int check_mask(struct host1x_firewall *fw) 310static int check_mask(struct host1x_firewall *fw)
295{ 311{
296 u32 mask = fw->mask; 312 u32 mask = fw->mask;
297 u32 reg = fw->reg; 313 u32 reg = fw->reg;
314 int ret;
298 315
299 while (mask) { 316 while (mask) {
300 if (fw->words == 0) 317 if (fw->words == 0)
301 return -EINVAL; 318 return -EINVAL;
302 319
303 if (mask & 1) { 320 if (mask & 1) {
304 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 321 ret = check_register(fw, reg);
305 if (!fw->num_relocs) 322 if (ret < 0)
306 return -EINVAL; 323 return ret;
307 if (!check_reloc(fw->reloc, fw->cmdbuf_id, 324
308 fw->offset))
309 return -EINVAL;
310 fw->reloc++;
311 fw->num_relocs--;
312 }
313 fw->words--; 325 fw->words--;
314 fw->offset++; 326 fw->offset++;
315 } 327 }
@@ -324,19 +336,16 @@ static int check_incr(struct host1x_firewall *fw)
324{ 336{
325 u32 count = fw->count; 337 u32 count = fw->count;
326 u32 reg = fw->reg; 338 u32 reg = fw->reg;
339 int ret;
327 340
328 while (count) { 341 while (count) {
329 if (fw->words == 0) 342 if (fw->words == 0)
330 return -EINVAL; 343 return -EINVAL;
331 344
332 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 345 ret = check_register(fw, reg);
333 if (!fw->num_relocs) 346 if (ret < 0)
334 return -EINVAL; 347 return ret;
335 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) 348
336 return -EINVAL;
337 fw->reloc++;
338 fw->num_relocs--;
339 }
340 reg++; 349 reg++;
341 fw->words--; 350 fw->words--;
342 fw->offset++; 351 fw->offset++;
@@ -348,21 +357,17 @@ static int check_incr(struct host1x_firewall *fw)
348 357
349static int check_nonincr(struct host1x_firewall *fw) 358static int check_nonincr(struct host1x_firewall *fw)
350{ 359{
351 int is_addr_reg = fw->job->is_addr_reg(fw->dev, fw->class, fw->reg);
352 u32 count = fw->count; 360 u32 count = fw->count;
361 int ret;
353 362
354 while (count) { 363 while (count) {
355 if (fw->words == 0) 364 if (fw->words == 0)
356 return -EINVAL; 365 return -EINVAL;
357 366
358 if (is_addr_reg) { 367 ret = check_register(fw, fw->reg);
359 if (!fw->num_relocs) 368 if (ret < 0)
360 return -EINVAL; 369 return ret;
361 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) 370
362 return -EINVAL;
363 fw->reloc++;
364 fw->num_relocs--;
365 }
366 fw->words--; 371 fw->words--;
367 fw->offset++; 372 fw->offset++;
368 count--; 373 count--;
@@ -381,7 +386,7 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)
381 return 0; 386 return 0;
382 387
383 fw->words = g->words; 388 fw->words = g->words;
384 fw->cmdbuf_id = g->bo; 389 fw->cmdbuf = g->bo;
385 fw->offset = 0; 390 fw->offset = 0;
386 391
387 while (fw->words && !err) { 392 while (fw->words && !err) {
@@ -436,10 +441,6 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)
436 } 441 }
437 } 442 }
438 443
439 /* No relocs should remain at this point */
440 if (fw->num_relocs)
441 err = -EINVAL;
442
443out: 444out:
444 return err; 445 return err;
445} 446}
@@ -493,6 +494,10 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
493 offset += g->words * sizeof(u32); 494 offset += g->words * sizeof(u32);
494 } 495 }
495 496
497 /* No relocs should remain at this point */
498 if (fw.num_relocs)
499 return -EINVAL;
500
496 return 0; 501 return 0;
497} 502}
498 503