summaryrefslogtreecommitdiff
path: root/drivers/accel/rocket/rocket_job.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/accel/rocket/rocket_job.c')
-rw-r--r--drivers/accel/rocket/rocket_job.c28
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;
}