Kernel dilation increases the input feature-map area accessed by a
kernel operation. Include the x and y dilation settings when
calculating the required IFM bounds.

Without this, a command stream using x2 dilation can access IFM
memory past the range validated by the driver.

Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver")
Cc: [email protected]
Assisted-by: LLM
Signed-off-by: Rob Herring (Arm) <[email protected]>
---
v2:
 - new patch
---
 drivers/accel/ethosu/ethosu_device.h |  2 ++
 drivers/accel/ethosu/ethosu_gem.c    | 10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/accel/ethosu/ethosu_device.h 
b/drivers/accel/ethosu/ethosu_device.h
index d7e1e3c8ca12..8e23fdbf7f8a 100644
--- a/drivers/accel/ethosu/ethosu_device.h
+++ b/drivers/accel/ethosu/ethosu_device.h
@@ -88,6 +88,8 @@ struct gen_pool;
 
 #define NPU_DMA_REGION_INDEX_MODE      BIT(11)
 #define NPU_OP_CONV_WEIGHTS_IFM2       BIT(0)
+#define NPU_KERNEL_DILATION_X          BIT(3)
+#define NPU_KERNEL_DILATION_Y          BIT(4)
 
 enum ethosu_cmds {
        NPU_OP_STOP = 0x0,
diff --git a/drivers/accel/ethosu/ethosu_gem.c 
b/drivers/accel/ethosu/ethosu_gem.c
index 9c86f9062f55..578d1b5b955c 100644
--- a/drivers/accel/ethosu/ethosu_gem.c
+++ b/drivers/accel/ethosu/ethosu_gem.c
@@ -567,10 +567,16 @@ static int calc_sizes(struct drm_device *ddev,
                        ((st->ifm.stride_kernel >> 1) & 0x1) + 1;
                u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) +
                        (st->ifm.stride_kernel & 0x1) + 1;
+               u32 dilation_y = 1 + !!(st->ifm.stride_kernel &
+                                        NPU_KERNEL_DILATION_Y);
+               u32 dilation_x = 1 + !!(st->ifm.stride_kernel &
+                                        NPU_KERNEL_DILATION_X);
                s32 ifm_height = st->ofm.height[2] * stride_y +
-                       st->ifm.height[2] - (st->ifm.pad_top + 
st->ifm.pad_bottom);
+                       st->ifm.height[2] * dilation_y -
+                       (st->ifm.pad_top + st->ifm.pad_bottom);
                s32 ifm_width = st->ofm.width * stride_x +
-                       st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right);
+                       st->ifm.width * dilation_x -
+                       (st->ifm.pad_left + st->ifm.pad_right);
 
                if (ifm_height < 0 || ifm_width < 0)
                        return -EINVAL;

-- 
2.53.0

Reply via email to