Applied to drm-misc-next

On 9/17/2025 5:21 PM, Lizhi Hou wrote:
>
> On 9/17/25 00:24, Karol Wachowski wrote:
>> On 9/16/2025 5:29 PM, Lizhi Hou wrote:
>>> On 9/16/25 01:25, Karol Wachowski wrote:
>>>> On 9/15/2025 10:33 PM, Lizhi Hou wrote:
>>>>> On 9/15/25 03:34, Karol Wachowski wrote:
>>>>>> From: Andrzej Kacprowski <[email protected]>
>>>>>>
>>>>>> Allow user mode drivers to manage preemption buffers, enabling
>>>>>> memory savings by sharing a single buffer across multiple
>>>>>> command queues within the same memory context.
>>>>>>
>>>>>> Introduce DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE to report the required
>>>>>> preemption buffer size as specified by the firmware.
>>>>>>
>>>>>> The preemption buffer is now passed from user space as an entry
>>>>>> in the BO list of DRM_IVPU_CMDQ_SUBMIT. The buffer must be
>>>>>> non-mappable and large enough to hold preemption data.
>>>>>>
>>>>>> For backward compatibility, the kernel will allocate an internal
>>>>>> preemption buffer if user space does not provide one.
>>>>>>
>>>>>> User space can only provide a single preemption buffer,
>>>>>> simplifying the ioctl interface and parameter validation.
>>>>>> A separate secondary preemption buffer is only needed
>>>>>> to save below 4GB address space on 37xx and only if preemption
>>>>>> buffers are not shared.
>>>>>>
>>>>>> Signed-off-by: Andrzej Kacprowski <[email protected]>
>>>>>> Signed-off-by: Karol Wachowski <[email protected]>
>>>>>> ---
>>>>>>     drivers/accel/ivpu/ivpu_drv.c |  3 ++
>>>>>>     drivers/accel/ivpu/ivpu_fw.c  | 57 +++++++++++++++++----
>>>>>>     drivers/accel/ivpu/ivpu_fw.h  |  7 ++-
>>>>>>     drivers/accel/ivpu/ivpu_gem.h |  7 ++-
>>>>>>     drivers/accel/ivpu/ivpu_job.c | 96
>>>>>> ++++++++++++++++++++++++-----------
>>>>>>     drivers/accel/ivpu/ivpu_job.h |  4 +-
>>>>>>     include/uapi/drm/ivpu_accel.h | 11 ++++
>>>>>>     7 files changed, 141 insertions(+), 44 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_drv.c
>>>>>> b/drivers/accel/ivpu/ivpu_drv.c
>>>>>> index 3d6d52492536..61c4f627c7c7 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_drv.c
>>>>>> +++ b/drivers/accel/ivpu/ivpu_drv.c
>>>>>> @@ -200,6 +200,9 @@ static int ivpu_get_param_ioctl(struct
>>>>>> drm_device
>>>>>> *dev, void *data, struct drm_f
>>>>>>         case DRM_IVPU_PARAM_CAPABILITIES:
>>>>>>             args->value = ivpu_is_capable(vdev, args->index);
>>>>>>             break;
>>>>>> +    case DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE:
>>>>>> +        args->value = ivpu_fw_preempt_buf_size(vdev);
>>>>>> +        break;
>>>>>>         default:
>>>>>>             ret = -EINVAL;
>>>>>>             break;
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_fw.c
>>>>>> b/drivers/accel/ivpu/ivpu_fw.c
>>>>>> index 9db741695401..6e0941d324a8 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_fw.c
>>>>>> +++ b/drivers/accel/ivpu/ivpu_fw.c
>>>>>> @@ -26,6 +26,8 @@
>>>>>>     #define FW_RUNTIME_MIN_ADDR    (FW_GLOBAL_MEM_START)
>>>>>>     #define FW_RUNTIME_MAX_ADDR    (FW_GLOBAL_MEM_END -
>>>>>> FW_SHARED_MEM_SIZE)
>>>>>>     #define FW_FILE_IMAGE_OFFSET    (VPU_FW_HEADER_SIZE +
>>>>>> FW_VERSION_HEADER_SIZE)
>>>>>> +#define FW_PREEMPT_BUF_MIN_SIZE SZ_4K
>>>>>> +#define FW_PREEMPT_BUF_MAX_SIZE SZ_32M
>>>>>>       #define WATCHDOG_MSS_REDIRECT    32
>>>>>>     #define WATCHDOG_NCE_REDIRECT    33
>>>>>> @@ -151,6 +153,47 @@ ivpu_fw_sched_mode_select(struct ivpu_device
>>>>>> *vdev, const struct vpu_firmware_he
>>>>>>         return VPU_SCHEDULING_MODE_HW;
>>>>>>     }
>>>>>>     +static void
>>>>>> +ivpu_preemption_config_parse(struct ivpu_device *vdev, const struct
>>>>>> vpu_firmware_header *fw_hdr)
>>>>>> +{
>>>>>> +    struct ivpu_fw_info *fw = vdev->fw;
>>>>>> +    u32 primary_preempt_buf_size, secondary_preempt_buf_size;
>>>>>> +
>>>>>> +    if (fw_hdr->preemption_buffer_1_max_size)
>>>>>> +        primary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_1_max_size;
>>>>>> +    else
>>>>>> +        primary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_1_size;
>>>>>> +
>>>>>> +    if (fw_hdr->preemption_buffer_2_max_size)
>>>>>> +        secondary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_2_max_size;
>>>>>> +    else
>>>>>> +        secondary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_2_size;
>>>>>> +
>>>>>> +    ivpu_dbg(vdev, FW_BOOT, "Preemption buffer size, primary: %u,
>>>>>> secondary: %u\n",
>>>>>> +         primary_preempt_buf_size, secondary_preempt_buf_size);
>>>>>> +
>>>>>> +    if (primary_preempt_buf_size < FW_PREEMPT_BUF_MIN_SIZE ||
>>>>>> +        secondary_preempt_buf_size < FW_PREEMPT_BUF_MIN_SIZE) {
>>>>>> +        ivpu_warn(vdev, "Preemption buffers size too small\n");
>>>>>> +        return;
>>>>>> +    }
>>>>>> +
>>>>>> +    if (primary_preempt_buf_size > FW_PREEMPT_BUF_MAX_SIZE ||
>>>>>> +        secondary_preempt_buf_size > FW_PREEMPT_BUF_MAX_SIZE) {
>>>>>> +        ivpu_warn(vdev, "Preemption buffers size too big\n");
>>>>>> +        return;
>>>>>> +    }
>>>>>> +
>>>>>> +    if (fw->sched_mode != VPU_SCHEDULING_MODE_HW)
>>>>>> +        return;
>>>>>> +
>>>>>> +    if (ivpu_test_mode & IVPU_TEST_MODE_MIP_DISABLE)
>>>>>> +        return;
>>>>>> +
>>>>>> +    vdev->fw->primary_preempt_buf_size =
>>>>>> ALIGN(primary_preempt_buf_size, PAGE_SIZE);
>>>>>> +    vdev->fw->secondary_preempt_buf_size =
>>>>>> ALIGN(secondary_preempt_buf_size, PAGE_SIZE);
>>>>>> +}
>>>>>> +
>>>>>>     static int ivpu_fw_parse(struct ivpu_device *vdev)
>>>>>>     {
>>>>>>         struct ivpu_fw_info *fw = vdev->fw;
>>>>>> @@ -235,17 +278,9 @@ static int ivpu_fw_parse(struct ivpu_device
>>>>>> *vdev)
>>>>>>         fw->sched_mode = ivpu_fw_sched_mode_select(vdev, fw_hdr);
>>>>>>         ivpu_info(vdev, "Scheduler mode: %s\n", fw->sched_mode ?
>>>>>> "HW" :
>>>>>> "OS");
>>>>>>     -    if (fw_hdr->preemption_buffer_1_max_size)
>>>>>> -        fw->primary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_1_max_size;
>>>>>> -    else
>>>>>> -        fw->primary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_1_size;
>>>>>> -
>>>>>> -    if (fw_hdr->preemption_buffer_2_max_size)
>>>>>> -        fw->secondary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_2_max_size;
>>>>>> -    else
>>>>>> -        fw->secondary_preempt_buf_size =
>>>>>> fw_hdr->preemption_buffer_2_size;
>>>>>> -    ivpu_dbg(vdev, FW_BOOT, "Preemption buffer sizes: primary %u,
>>>>>> secondary %u\n",
>>>>>> -         fw->primary_preempt_buf_size,
>>>>>> fw->secondary_preempt_buf_size);
>>>>>> +    ivpu_preemption_config_parse(vdev, fw_hdr);
>>>>>> +    ivpu_dbg(vdev, FW_BOOT, "Mid-inference preemption %s
>>>>>> supported\n",
>>>>>> +         ivpu_fw_preempt_buf_size(vdev) ? "is" : "is not");
>>>>>>           if (fw_hdr->ro_section_start_address &&
>>>>>> !is_within_range(fw_hdr->ro_section_start_address,
>>>>>>                                      fw_hdr->ro_section_size,
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_fw.h
>>>>>> b/drivers/accel/ivpu/ivpu_fw.h
>>>>>> index 7081913fb0dd..6fe2917abda6 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_fw.h
>>>>>> +++ b/drivers/accel/ivpu/ivpu_fw.h
>>>>>> @@ -1,6 +1,6 @@
>>>>>>     /* SPDX-License-Identifier: GPL-2.0-only */
>>>>>>     /*
>>>>>> - * Copyright (C) 2020-2024 Intel Corporation
>>>>>> + * Copyright (C) 2020-2025 Intel Corporation
>>>>>>      */
>>>>>>       #ifndef __IVPU_FW_H__
>>>>>> @@ -52,4 +52,9 @@ static inline bool ivpu_fw_is_cold_boot(struct
>>>>>> ivpu_device *vdev)
>>>>>>         return vdev->fw->entry_point ==
>>>>>> vdev->fw->cold_boot_entry_point;
>>>>>>     }
>>>>>>     +static inline u32 ivpu_fw_preempt_buf_size(struct ivpu_device
>>>>>> *vdev)
>>>>>> +{
>>>>>> +    return vdev->fw->primary_preempt_buf_size +
>>>>>> vdev->fw->secondary_preempt_buf_size;
>>>>>> +}
>>>>>> +
>>>>>>     #endif /* __IVPU_FW_H__ */
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_gem.h
>>>>>> b/drivers/accel/ivpu/ivpu_gem.h
>>>>>> index aa8ff14f7aae..3ee996d503b2 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_gem.h
>>>>>> +++ b/drivers/accel/ivpu/ivpu_gem.h
>>>>>> @@ -1,6 +1,6 @@
>>>>>>     /* SPDX-License-Identifier: GPL-2.0-only */
>>>>>>     /*
>>>>>> - * Copyright (C) 2020-2023 Intel Corporation
>>>>>> + * Copyright (C) 2020-2025 Intel Corporation
>>>>>>      */
>>>>>>     #ifndef __IVPU_GEM_H__
>>>>>>     #define __IVPU_GEM_H__
>>>>>> @@ -96,4 +96,9 @@ static inline u32 cpu_to_vpu_addr(struct ivpu_bo
>>>>>> *bo, void *cpu_addr)
>>>>>>         return bo->vpu_addr + (cpu_addr - ivpu_bo_vaddr(bo));
>>>>>>     }
>>>>>>     +static inline bool ivpu_bo_is_mappable(struct ivpu_bo *bo)
>>>>>> +{
>>>>>> +    return bo->flags & DRM_IVPU_BO_MAPPABLE;
>>>>>> +}
>>>>>> +
>>>>>>     #endif /* __IVPU_GEM_H__ */
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_job.c
>>>>>> b/drivers/accel/ivpu/ivpu_job.c
>>>>>> index fa1720fa06a4..521b7ac6e35e 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_job.c
>>>>>> +++ b/drivers/accel/ivpu/ivpu_job.c
>>>>>> @@ -34,22 +34,20 @@ static void ivpu_cmdq_ring_db(struct ivpu_device
>>>>>> *vdev, struct ivpu_cmdq *cmdq)
>>>>>>     static int ivpu_preemption_buffers_create(struct ivpu_device
>>>>>> *vdev,
>>>>>>                           struct ivpu_file_priv *file_priv, struct
>>>>>> ivpu_cmdq *cmdq)
>>>>>>     {
>>>>>> -    u64 primary_size = ALIGN(vdev->fw->primary_preempt_buf_size,
>>>>>> PAGE_SIZE);
>>>>>> -    u64 secondary_size =
>>>>>> ALIGN(vdev->fw->secondary_preempt_buf_size,
>>>>>> PAGE_SIZE);
>>>>>> -
>>>>>> -    if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW ||
>>>>>> -        ivpu_test_mode & IVPU_TEST_MODE_MIP_DISABLE)
>>>>>> +    if (ivpu_fw_preempt_buf_size(vdev) == 0)
>>>>>>             return 0;
>>>>>>           cmdq->primary_preempt_buf = ivpu_bo_create(vdev,
>>>>>> &file_priv->ctx, &vdev->hw->ranges.user,
>>>>>> -                           primary_size, DRM_IVPU_BO_WC);
>>>>>> +                           vdev->fw->primary_preempt_buf_size,
>>>>>> +                           DRM_IVPU_BO_WC);
>>>>> Could vdev->fw->primary_preempt_buf_size be zero?
>>>> This can be zero and zero is intended to indicate that preemption
>>>> buffers are disabled and should not be allocated by the driver.
>>>>> ivpu_fw_preempt_buf_size(vdev) make sure primary+secondary is not
>>>>> zero.
>>>> Either of them or both can be zero. In case of both of them being zero
>>>> function returns early not allocating any of the buffers.
>>> ivpu_bo_create will generate a warning stack if size is zero. So just
>>> checking if both are zero is not good enough.
>> Thank you for your feedback. I apologize for my earlier inaccurate
>> statement regarding the possibility of zeroing the buffers separately.
>> To clarify, the driver ensures that both preemption buffer sizes are
>> either non-zero or both zero. This is already handled during the
>> firmware header parsing,
>> specifically in the ivpu_preemption_config_parse() function.
>> That function guarantees that both preemption buffer sizes are set to
>> non-zero values together, or both are explicitly set to zero.
>> Therefore, whenever ivpu_preemption_buffers_create() is invoked, both
>> buffers are either allocated with non-zero sizes or not allocated at
>> all.
>> Adding individual checks within this function would reduce readability,
>> as we only ever allocate both buffers together or neither.
>
> Reviewed-by: Lizhi Hou <[email protected]>
>
> Adding some comment might be good. :)
>
>>
>> Thanks,
>> Karol
>>> Lizhi
>>>
>>>> Best regards,
>>>>
>>>> Karol
>>>>
>>>>> Lizhi
>>>>>
>>>>>>         if (!cmdq->primary_preempt_buf) {
>>>>>>             ivpu_err(vdev, "Failed to create primary preemption
>>>>>> buffer\n");
>>>>>>             return -ENOMEM;
>>>>>>         }
>>>>>>           cmdq->secondary_preempt_buf = ivpu_bo_create(vdev,
>>>>>> &file_priv->ctx, &vdev->hw->ranges.dma,
>>>>>> -                             secondary_size, DRM_IVPU_BO_WC);
>>>>>> +                             vdev->fw->secondary_preempt_buf_size,
>>>>>> +                             DRM_IVPU_BO_WC);
>>>>>>         if (!cmdq->secondary_preempt_buf) {
>>>>>>             ivpu_err(vdev, "Failed to create secondary preemption
>>>>>> buffer\n");
>>>>>>             goto err_free_primary;
>>>>>> @@ -66,20 +64,39 @@ static int ivpu_preemption_buffers_create(struct
>>>>>> ivpu_device *vdev,
>>>>>>     static void ivpu_preemption_buffers_free(struct ivpu_device
>>>>>> *vdev,
>>>>>>                          struct ivpu_file_priv *file_priv, struct
>>>>>> ivpu_cmdq *cmdq)
>>>>>>     {
>>>>>> -    if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW)
>>>>>> -        return;
>>>>>> -
>>>>>>         if (cmdq->primary_preempt_buf)
>>>>>>             ivpu_bo_free(cmdq->primary_preempt_buf);
>>>>>>         if (cmdq->secondary_preempt_buf)
>>>>>>             ivpu_bo_free(cmdq->secondary_preempt_buf);
>>>>>>     }
>>>>>>     +static int ivpu_preemption_job_init(struct ivpu_device *vdev,
>>>>>> struct ivpu_file_priv *file_priv,
>>>>>> +                    struct ivpu_cmdq *cmdq, struct ivpu_job *job)
>>>>>> +{
>>>>>> +    int ret;
>>>>>> +
>>>>>> +    /* Use preemption buffer provided by the user space */
>>>>>> +    if (job->primary_preempt_buf)
>>>>>> +        return 0;
>>>>>> +
>>>>>> +    if (!cmdq->primary_preempt_buf) {
>>>>>> +        /* Allocate per command queue preemption buffers */
>>>>>> +        ret = ivpu_preemption_buffers_create(vdev, file_priv,
>>>>>> cmdq);
>>>>>> +        if (ret)
>>>>>> +            return ret;
>>>>>> +    }
>>>>>> +
>>>>>> +    /* Use preemption buffers allocated by the kernel */
>>>>>> +    job->primary_preempt_buf = cmdq->primary_preempt_buf;
>>>>>> +    job->secondary_preempt_buf = cmdq->secondary_preempt_buf;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>>     static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv
>>>>>> *file_priv)
>>>>>>     {
>>>>>>         struct ivpu_device *vdev = file_priv->vdev;
>>>>>>         struct ivpu_cmdq *cmdq;
>>>>>> -    int ret;
>>>>>>           cmdq = kzalloc(sizeof(*cmdq), GFP_KERNEL);
>>>>>>         if (!cmdq)
>>>>>> @@ -89,10 +106,6 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct
>>>>>> ivpu_file_priv *file_priv)
>>>>>>         if (!cmdq->mem)
>>>>>>             goto err_free_cmdq;
>>>>>>     -    ret = ivpu_preemption_buffers_create(vdev, file_priv,
>>>>>> cmdq);
>>>>>> -    if (ret)
>>>>>> -        ivpu_warn(vdev, "Failed to allocate preemption buffers,
>>>>>> preemption limited\n");
>>>>>> -
>>>>>>         return cmdq;
>>>>>>       err_free_cmdq:
>>>>>> @@ -429,17 +442,14 @@ static int ivpu_cmdq_push_job(struct ivpu_cmdq
>>>>>> *cmdq, struct ivpu_job *job)
>>>>>>         if (unlikely(ivpu_test_mode &
>>>>>> IVPU_TEST_MODE_NULL_SUBMISSION))
>>>>>>             entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK;
>>>>>>     -    if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) {
>>>>>> -        if (cmdq->primary_preempt_buf) {
>>>>>> -            entry->primary_preempt_buf_addr =
>>>>>> cmdq->primary_preempt_buf->vpu_addr;
>>>>>> -            entry->primary_preempt_buf_size =
>>>>>> ivpu_bo_size(cmdq->primary_preempt_buf);
>>>>>> -        }
>>>>>> +    if (job->primary_preempt_buf) {
>>>>>> +        entry->primary_preempt_buf_addr =
>>>>>> job->primary_preempt_buf->vpu_addr;
>>>>>> +        entry->primary_preempt_buf_size =
>>>>>> ivpu_bo_size(job->primary_preempt_buf);
>>>>>> +    }
>>>>>>     -        if (cmdq->secondary_preempt_buf) {
>>>>>> -            entry->secondary_preempt_buf_addr =
>>>>>> cmdq->secondary_preempt_buf->vpu_addr;
>>>>>> -            entry->secondary_preempt_buf_size =
>>>>>> -                ivpu_bo_size(cmdq->secondary_preempt_buf);
>>>>>> -        }
>>>>>> +    if (job->secondary_preempt_buf) {
>>>>>> +        entry->secondary_preempt_buf_addr =
>>>>>> job->secondary_preempt_buf->vpu_addr;
>>>>>> +        entry->secondary_preempt_buf_size =
>>>>>> ivpu_bo_size(job->secondary_preempt_buf);
>>>>>>         }
>>>>>>           wmb(); /* Ensure that tail is updated after filling
>>>>>> entry */
>>>>>> @@ -663,6 +673,13 @@ static int ivpu_job_submit(struct ivpu_job
>>>>>> *job,
>>>>>> u8 priority, u32 cmdq_id)
>>>>>>             goto err_unlock;
>>>>>>         }
>>>>>>     +    ret = ivpu_preemption_job_init(vdev, file_priv, cmdq, job);
>>>>>> +    if (ret) {
>>>>>> +        ivpu_err(vdev, "Failed to initialize preemption buffers for
>>>>>> job %d: %d\n",
>>>>>> +             job->job_id, ret);
>>>>>> +        goto err_unlock;
>>>>>> +    }
>>>>>> +
>>>>>>         job->cmdq_id = cmdq->id;
>>>>>>           is_first_job = xa_empty(&vdev->submitted_jobs_xa);
>>>>>> @@ -716,7 +733,7 @@ static int ivpu_job_submit(struct ivpu_job *job,
>>>>>> u8 priority, u32 cmdq_id)
>>>>>>       static int
>>>>>>     ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct
>>>>>> ivpu_job *job, u32 *buf_handles,
>>>>>> -                u32 buf_count, u32 commands_offset)
>>>>>> +                u32 buf_count, u32 commands_offset, u32
>>>>>> preempt_buffer_index)
>>>>>>     {
>>>>>>         struct ivpu_file_priv *file_priv = job->file_priv;
>>>>>>         struct ivpu_device *vdev = file_priv->vdev;
>>>>>> @@ -752,6 +769,20 @@ ivpu_job_prepare_bos_for_submit(struct drm_file
>>>>>> *file, struct ivpu_job *job, u32
>>>>>>           job->cmd_buf_vpu_addr = bo->vpu_addr + commands_offset;
>>>>>>     +    if (preempt_buffer_index) {
>>>>>> +        struct ivpu_bo *preempt_bo =
>>>>>> job->bos[preempt_buffer_index];
>>>>>> +
>>>>>> +        if (ivpu_bo_size(preempt_bo) <
>>>>>> ivpu_fw_preempt_buf_size(vdev)) {
>>>>>> +            ivpu_warn(vdev, "Preemption buffer is too small\n");
>>>>>> +            return -EINVAL;
>>>>>> +        }
>>>>>> +        if (ivpu_bo_is_mappable(preempt_bo)) {
>>>>>> +            ivpu_warn(vdev, "Preemption buffer cannot be
>>>>>> mappable\n");
>>>>>> +            return -EINVAL;
>>>>>> +        }
>>>>>> +        job->primary_preempt_buf = preempt_bo;
>>>>>> +    }
>>>>>> +
>>>>>>         ret = drm_gem_lock_reservations((struct drm_gem_object
>>>>>> **)job->bos, buf_count,
>>>>>>                         &acquire_ctx);
>>>>>>         if (ret) {
>>>>>> @@ -782,7 +813,7 @@ ivpu_job_prepare_bos_for_submit(struct drm_file
>>>>>> *file, struct ivpu_job *job, u32
>>>>>>       static int ivpu_submit(struct drm_file *file, struct
>>>>>> ivpu_file_priv *file_priv, u32 cmdq_id,
>>>>>>                    u32 buffer_count, u32 engine, void __user
>>>>>> *buffers_ptr, u32 cmds_offset,
>>>>>> -               u8 priority)
>>>>>> +               u32 preempt_buffer_index, u8 priority)
>>>>>>     {
>>>>>>         struct ivpu_device *vdev = file_priv->vdev;
>>>>>>         struct ivpu_job *job;
>>>>>> @@ -814,7 +845,8 @@ static int ivpu_submit(struct drm_file *file,
>>>>>> struct ivpu_file_priv *file_priv,
>>>>>>             goto err_exit_dev;
>>>>>>         }
>>>>>>     -    ret = ivpu_job_prepare_bos_for_submit(file, job,
>>>>>> buf_handles,
>>>>>> buffer_count, cmds_offset);
>>>>>> +    ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles,
>>>>>> buffer_count, cmds_offset,
>>>>>> +                          preempt_buffer_index);
>>>>>>         if (ret) {
>>>>>>             ivpu_err(vdev, "Failed to prepare job: %d\n", ret);
>>>>>>             goto err_destroy_job;
>>>>>> @@ -868,7 +900,7 @@ int ivpu_submit_ioctl(struct drm_device *dev,
>>>>>> void *data, struct drm_file *file)
>>>>>>         priority = ivpu_job_to_jsm_priority(args->priority);
>>>>>>           return ivpu_submit(file, file_priv, 0, args->buffer_count,
>>>>>> args->engine,
>>>>>> -               (void __user *)args->buffers_ptr,
>>>>>> args->commands_offset, priority);
>>>>>> +               (void __user *)args->buffers_ptr,
>>>>>> args->commands_offset, 0, priority);
>>>>>>     }
>>>>>>       int ivpu_cmdq_submit_ioctl(struct drm_device *dev, void *data,
>>>>>> struct drm_file *file)
>>>>>> @@ -885,6 +917,9 @@ int ivpu_cmdq_submit_ioctl(struct drm_device
>>>>>> *dev, void *data, struct drm_file *
>>>>>>         if (args->buffer_count == 0 || args->buffer_count >
>>>>>> JOB_MAX_BUFFER_COUNT)
>>>>>>             return -EINVAL;
>>>>>>     +    if (args->preempt_buffer_index >= args->buffer_count)
>>>>>> +        return -EINVAL;
>>>>>> +
>>>>>>         if (!IS_ALIGNED(args->commands_offset, 8))
>>>>>>             return -EINVAL;
>>>>>>     @@ -895,7 +930,8 @@ int ivpu_cmdq_submit_ioctl(struct drm_device
>>>>>> *dev, void *data, struct drm_file *
>>>>>>             return -EBADFD;
>>>>>>           return ivpu_submit(file, file_priv, args->cmdq_id,
>>>>>> args->buffer_count, VPU_ENGINE_COMPUTE,
>>>>>> -               (void __user *)args->buffers_ptr,
>>>>>> args->commands_offset, 0);
>>>>>> +               (void __user *)args->buffers_ptr,
>>>>>> args->commands_offset,
>>>>>> +               args->preempt_buffer_index, 0);
>>>>>>     }
>>>>>>       int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data,
>>>>>> struct drm_file *file)
>>>>>> diff --git a/drivers/accel/ivpu/ivpu_job.h
>>>>>> b/drivers/accel/ivpu/ivpu_job.h
>>>>>> index 2e301c2eea7b..6c8b9c739b51 100644
>>>>>> --- a/drivers/accel/ivpu/ivpu_job.h
>>>>>> +++ b/drivers/accel/ivpu/ivpu_job.h
>>>>>> @@ -1,6 +1,6 @@
>>>>>>     /* SPDX-License-Identifier: GPL-2.0-only */
>>>>>>     /*
>>>>>> - * Copyright (C) 2020-2024 Intel Corporation
>>>>>> + * Copyright (C) 2020-2025 Intel Corporation
>>>>>>      */
>>>>>>       #ifndef __IVPU_JOB_H__
>>>>>> @@ -55,6 +55,8 @@ struct ivpu_job {
>>>>>>         u32 job_id;
>>>>>>         u32 engine_idx;
>>>>>>         size_t bo_count;
>>>>>> +    struct ivpu_bo *primary_preempt_buf;
>>>>>> +    struct ivpu_bo *secondary_preempt_buf;
>>>>>>         struct ivpu_bo *bos[] __counted_by(bo_count);
>>>>>>     };
>>>>>>     diff --git a/include/uapi/drm/ivpu_accel.h
>>>>>> b/include/uapi/drm/ivpu_accel.h
>>>>>> index 160ee1411d4a..e470b0221e02 100644
>>>>>> --- a/include/uapi/drm/ivpu_accel.h
>>>>>> +++ b/include/uapi/drm/ivpu_accel.h
>>>>>> @@ -90,6 +90,7 @@ extern "C" {
>>>>>>     #define DRM_IVPU_PARAM_TILE_CONFIG        11
>>>>>>     #define DRM_IVPU_PARAM_SKU            12
>>>>>>     #define DRM_IVPU_PARAM_CAPABILITIES        13
>>>>>> +#define DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE  14
>>>>>>       #define DRM_IVPU_PLATFORM_TYPE_SILICON        0
>>>>>>     @@ -176,6 +177,9 @@ struct drm_ivpu_param {
>>>>>>          *
>>>>>>          * %DRM_IVPU_PARAM_CAPABILITIES:
>>>>>>          * Supported capabilities (read-only)
>>>>>> +     *
>>>>>> +     * %DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE:
>>>>>> +     * Size of the preemption buffer (read-only)
>>>>>>          */
>>>>>>         __u32 param;
>>>>>>     @@ -371,6 +375,13 @@ struct drm_ivpu_cmdq_submit {
>>>>>>          * to be executed. The offset has to be 8-byte aligned.
>>>>>>          */
>>>>>>         __u32 commands_offset;
>>>>>> +    /**
>>>>>> +     * @preempt_buffer_index:
>>>>>> +     *
>>>>>> +     * Index of the preemption buffer in the buffers_ptr array.
>>>>>> +     */
>>>>>> +    __u32 preempt_buffer_index;
>>>>>> +    __u32 reserved;
>>>>>>     };
>>>>>>       /* drm_ivpu_bo_wait job status codes */

Reply via email to