summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring (Arm) <robh@kernel.org>2026-08-27 15:33:02 -0500
committerRob Herring (Arm) <robh@kernel.org>2026-09-03 12:06:45 -0500
commiteb3a41fd35e352fba387c4320a1fa0352f3e551c (patch)
treec13397c37d0b66e279ecff2e594e6151f87c13de
parent2cbd3691565f7c86c0eaca305f5beb3435b4ba70 (diff)
downloadlinux-eb3a41fd35e352fba387c4320a1fa0352f3e551c.tar.gz
linux-eb3a41fd35e352fba387c4320a1fa0352f3e551c.zip
accel: ethosu: Ensure cmd stream ends with a stop op
While the QSIZE register setting should prevent an out of bounds access of the command stream, it is not clear whether the h/w generates an interrupt in this case as is required (to prevent a timeout). As a stop op is expected end of the command stream, let's just ensure it is present. A stop op in the middle of the command stream also makes no sense. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20260827-ethosu-fixes-v1-3-346f9ea8791c@kernel.org Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
-rw-r--r--drivers/accel/ethosu/ethosu_device.h1
-rw-r--r--drivers/accel/ethosu/ethosu_gem.c9
2 files changed, 10 insertions, 0 deletions
diff --git a/drivers/accel/ethosu/ethosu_device.h b/drivers/accel/ethosu/ethosu_device.h
index d4458eac8447..1eca8590e68d 100644
--- a/drivers/accel/ethosu/ethosu_device.h
+++ b/drivers/accel/ethosu/ethosu_device.h
@@ -87,6 +87,7 @@ struct gen_pool;
#define PMU_EV_TYPE_IDLE 0x20
enum ethosu_cmds {
+ NPU_OP_STOP = 0x0,
NPU_OP_CONV = 0x2,
NPU_OP_DEPTHWISE = 0x3,
NPU_OP_POOL = 0x5,
diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c
index fa37a190e9ff..9afe2549ec84 100644
--- a/drivers/accel/ethosu/ethosu_gem.c
+++ b/drivers/accel/ethosu/ethosu_gem.c
@@ -390,6 +390,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
struct ethosu_validated_cmdstream_info __free(kfree) *info = kzalloc_obj(*info);
struct ethosu_device *edev = to_ethosu_device(ddev);
u32 *bocmds = bo->base.vaddr;
+ bool ends_with_stop = false;
struct cmd_state st;
int i, ret;
@@ -426,6 +427,11 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
}
switch (cmd) {
+ case NPU_OP_STOP:
+ if (i != size / 4 - 1)
+ return -EINVAL;
+ ends_with_stop = true;
+ break;
case NPU_OP_DMA_START:
srclen = dma_length(info, &st.dma, &st.dma.src);
dstlen = dma_length(info, &st.dma, &st.dma.dst);
@@ -688,6 +694,9 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
}
}
+ if (!ends_with_stop)
+ return -EINVAL;
+
for (i = 0; i < NPU_BASEP_REGION_MAX; i++) {
if (!info->region_size[i])
continue;