diff options
Diffstat (limited to 'drivers/accel/rocket/rocket_job.c')
| -rw-r--r-- | drivers/accel/rocket/rocket_job.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c index 4bc4f9c8ee40..c3edb94355a3 100644 --- a/drivers/accel/rocket/rocket_job.c +++ b/drivers/accel/rocket/rocket_job.c @@ -7,6 +7,7 @@ #include <drm/drm_file.h> #include <drm/drm_gem.h> #include <drm/rocket_accel.h> +#include <linux/align.h> #include <linux/interrupt.h> #include <linux/overflow.h> #include <linux/iommu.h> @@ -21,6 +22,15 @@ #define JOB_TIMEOUT_MS 500 +/* + * The PC unit fetches two 64-bit register commands per pc_data_amount unit, + * and the field holds (regcmd_count + 1) / 2 - 1. + */ +#define ROCKET_MAX_REGCMDS ((PC_REGISTER_AMOUNTS_PC_DATA_AMOUNT__MASK + 1) * 2U) + +/* Bits 3:0 of PC_BASE_ADDRESS hold the mode selection bit and reserved bits */ +#define ROCKET_REGCMD_ALIGN 16 + static struct rocket_job * to_rocket_job(struct drm_sched_job *sched_job) { @@ -78,7 +88,7 @@ rocket_copy_tasks(struct drm_device *dev, return -ENOMEM; } - for (int i = 0; i < rjob->task_count; i++) { + for (unsigned int i = 0; i < rjob->task_count; i++) { struct drm_rocket_task task = {0}; if (copy_from_user(&task, @@ -95,6 +105,20 @@ rocket_copy_tasks(struct drm_device *dev, goto fail; } + if (task.regcmd_count > ROCKET_MAX_REGCMDS) { + drm_dbg(dev, "regcmd_count field in drm_rocket_task should be <= %u.\n", + ROCKET_MAX_REGCMDS); + ret = -EINVAL; + goto fail; + } + + if (!IS_ALIGNED(task.regcmd, ROCKET_REGCMD_ALIGN)) { + drm_dbg(dev, "regcmd field in drm_rocket_task should be aligned to %u bytes.\n", + ROCKET_REGCMD_ALIGN); + ret = -EINVAL; + goto fail; + } + rjob->tasks[i].regcmd = task.regcmd; rjob->tasks[i].regcmd_count = task.regcmd_count; } @@ -494,8 +518,6 @@ int rocket_job_init(struct rocket_core *core) return 0; err_sched: - drm_sched_fini(&core->sched); - destroy_workqueue(core->reset.wq); return ret; } |
