On Mon, 12 Oct 2026 14:59:39 +0200
Ketil Johnsen <[email protected]> wrote:

> From: Boris Brezillon <[email protected]>
> 
> Extends struct drm_panthor_group_create to allow user provided protm
> suspend buffer. This is needed for protm execution with this group.
> 
> Make use of the user supplied suspend buffer (import).
> 
> Allow PROT_REGION instruction for groups which provided protm
> suspend buffer.
> 
> Store the suspend buffer sizes (normal and protected) provided by FW
> after FW start. Unsafe to read directly from FW as these will return
> zero between FW load and FW start.
> 
> Signed-off-by: Boris Brezillon <[email protected]>
> Co-developed-by: Ketil Johnsen <[email protected]>
> Signed-off-by: Ketil Johnsen <[email protected]>
> 
> ---
> 
> v4:
> - First version of this change as a separate commit
> ---
>  drivers/gpu/drm/panthor/panthor_fw.c    | 24 ++++++++++
>  drivers/gpu/drm/panthor/panthor_fw.h    |  2 +
>  drivers/gpu/drm/panthor/panthor_sched.c | 59 ++++++++++++++++++++-----
>  include/uapi/drm/panthor_drm.h          | 10 ++++-
>  4 files changed, 83 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.c 
> b/drivers/gpu/drm/panthor/panthor_fw.c
> index 0af6addfd55a5..11c370ef86aad 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.c
> +++ b/drivers/gpu/drm/panthor/panthor_fw.c
> @@ -269,6 +269,12 @@ struct panthor_fw {
>       /** @protm_init_lock: Used to serialize protm initialization. */
>       struct mutex protm_init_lock;
>  
> +     /** @suspend_size: Size of regular suspend buffer */
> +     u32 suspend_size;
> +
> +     /** @protm_suspend_size: Size of protected suspend buffer size */
> +     u32 protm_suspend_size;
> +
>       /**
>        * @req_waitqueue: FW request waitqueue.
>        *
> @@ -1006,6 +1012,14 @@ static int panthor_init_csg_iface(struct 
> panthor_device *ptdev,
>       }
>  
>       if (!csg_idx) {
> +             /* We make a copy of these sizes, as csg_iface can read these
> +              * as zero during full GPU reset, between FW sections being
> +              * reloaded and FW fully booted.
> +              */
> +             ptdev->fw->suspend_size = csg_iface->control->suspend_size;
> +             ptdev->fw->protm_suspend_size =
> +                     csg_iface->control->protm_suspend_size;
> +
>               ptdev->protm.info.group_protected_suspend_buf_size =
>                       csg_iface->control->protm_suspend_size;
>       }
> @@ -1523,6 +1537,16 @@ static void panthor_fw_ping_work(struct work_struct 
> *work)
>       }
>  }
>  
> +u32 panthor_fw_suspend_size(struct panthor_device *ptdev)
> +{
> +     return ptdev->fw->suspend_size;
> +}
> +
> +u32 panthor_fw_protm_suspend_size(struct panthor_device *ptdev)
> +{
> +     return ptdev->fw->protm_suspend_size;
> +}
> +
>  static bool wait_protm_enter(struct panthor_device *ptdev,
>                            s64 protm_session_seqno)
>  {
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.h 
> b/drivers/gpu/drm/panthor/panthor_fw.h
> index 34bc9dc82314c..98576114cc803 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.h
> +++ b/drivers/gpu/drm/panthor/panthor_fw.h
> @@ -531,6 +531,8 @@ void panthor_fw_unplug(struct panthor_device *ptdev);
>  
>  int panthor_fw_protm_init(struct drm_file *file,
>                         struct drm_panthor_protm_init *args);
> +u32 panthor_fw_suspend_size(struct panthor_device *ptdev);
> +u32 panthor_fw_protm_suspend_size(struct panthor_device *ptdev);
>  int panthor_fw_protm_enter(struct panthor_device *ptdev);
>  int panthor_fw_protm_exit(struct panthor_device *ptdev, u32 timeout_ms);
>  int panthor_fw_protm_exit_wait(struct panthor_device *ptdev, u32 timeout_ms);
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c 
> b/drivers/gpu/drm/panthor/panthor_sched.c
> index fff805fd794a5..d1178be178a48 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -1462,10 +1462,15 @@ cs_slot_process_protm_pending_event_locked(struct 
> panthor_device *ptdev,
>       if (!group)
>               return;
>  
> -     /* Do not allow user space work to switch into protected mode, as we
> -      * do not fully support this quite yet.
> +     /* Do not allow user space work to switch into protected mode if we
> +      * do not support protected mode on this device.
> +      * User space should query (and init) this support before attempting
> +      * to use such GPU instructions.
>        */
> -     atomic_or(BIT(cs_id), &group->fatal_queues);
> +     if (group->protm_suspend_buf)
> +             atomic_or(BIT(cs_id), &group->protm_pending_queues);
> +     else
> +             atomic_or(BIT(cs_id), &group->fatal_queues);
>  
>       sched_queue_delayed_work(sched, tick, 0);
>  }
> @@ -4074,6 +4079,7 @@ static void add_group_kbo_sizes(struct panthor_device 
> *ptdev,
>  }
>  
>  #define MAX_GROUPS_PER_POOL          128
> +#define GROUP_CREATE_FLAGS DRM_PANTHOR_GROUP_CREATE_PROTECTED
>  
>  int panthor_group_create(struct drm_file *file,
>                        const struct drm_panthor_group_create *group_args,
> @@ -4083,14 +4089,10 @@ int panthor_group_create(struct drm_file *file,
>       struct panthor_device *ptdev = pfile->ptdev;
>       struct panthor_group_pool *gpool = pfile->groups;
>       struct panthor_scheduler *sched = ptdev->scheduler;
> -     struct panthor_fw_csg_iface *csg_iface = 
> panthor_fw_get_csg_iface(ptdev, 0);
>       struct panthor_group *group = NULL;
> -     u32 gid, i, suspend_size;
> +     u32 gid, i;
>       int ret;
>  
> -     if (group_args->pad)
> -             return -EINVAL;
> -
>       if (group_args->priority >= PANTHOR_CSG_PRIORITY_COUNT)
>               return -EINVAL;
>  
> @@ -4136,14 +4138,51 @@ int panthor_group_create(struct drm_file *file,
>               goto err_put_group;
>       }
>  
> -     suspend_size = csg_iface->control->suspend_size;
> -     group->suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, 
> suspend_size);
> +     group->suspend_buf = panthor_fw_alloc_suspend_buf_mem(
> +             ptdev, panthor_fw_suspend_size(ptdev));
>       if (IS_ERR(group->suspend_buf)) {
>               ret = PTR_ERR(group->suspend_buf);
>               group->suspend_buf = NULL;
>               goto err_put_group;
>       }
>  
> +     if (group_args->protected_suspend_bo_handle) {
> +             struct drm_gem_object *obj;
> +
> +             /* Read a correct snapshot of the state */
> +             if (!(smp_load_acquire(&ptdev->protm.info.state) &
> +                   DRM_PANTHOR_PROTM_INITIALIZED)) {

Same comment I made in previous patch: let's use a regular lock to
access this state.

> +                     ret = -EINVAL;
> +                     goto err_put_group;
> +             }
> +
> +             obj = drm_gem_object_lookup(
> +                     file, group_args->protected_suspend_bo_handle);

                obj = drm_gem_object_lookup(file,
                                            
group_args->protected_suspend_bo_handle);

> +             if (!obj) {
> +                     ret = -ENOENT;
> +                     goto err_put_group;
> +             }
> +
> +             if (obj->size <
> +                 ptdev->protm.info.group_protected_suspend_buf_size) {

                if (obj->size < 
ptdev->protm.info.group_protected_suspend_buf_size) {

> +                     drm_gem_object_put(obj);
> +                     ret = -EINVAL;
> +                     goto err_put_group;
> +             }
> +
> +             group->protm_suspend_buf = panthor_kernel_bo_create_from_gem(
> +                     ptdev, panthor_fw_vm(ptdev), to_panthor_bo(obj),
> +                     DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
> +                     PANTHOR_VM_KERNEL_AUTO_VA,
> +                     panthor_fw_protm_suspend_size(ptdev));

                group->protm_suspend_buf =
                        panthor_kernel_bo_create_from_gem(ptdev, 
panthor_fw_vm(ptdev),
                                                          to_panthor_bo(obj),
                                                          
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
                                                          
PANTHOR_VM_KERNEL_AUTO_VA,
                                                          
panthor_fw_protm_suspend_size(ptdev));

> +             drm_gem_object_put(obj);
> +             if (IS_ERR(group->protm_suspend_buf)) {
> +                     ret = PTR_ERR(group->protm_suspend_buf);
> +                     group->protm_suspend_buf = NULL;
> +                     goto err_put_group;
> +             }
> +     }
> +
>       group->syncobjs = panthor_kernel_bo_create(ptdev, group->vm,
>                                                  group_args->queues.count *
>                                                  sizeof(struct 
> panthor_syncobj_64b),
> diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
> index d2d21e3e6bb39..a0ed16041e178 100644
> --- a/include/uapi/drm/panthor_drm.h
> +++ b/include/uapi/drm/panthor_drm.h
> @@ -956,8 +956,14 @@ struct drm_panthor_group_create {
>       /** @priority: Group priority (see enum drm_panthor_group_priority). */
>       __u8 priority;
>  
> -     /** @pad: Padding field, MBZ. */
> -     __u32 pad;
> +     /**
> +      * @protected_suspend_bo_handle: BO to use as a protected suspend 
> buffer.
> +      *
> +      * This BO must have been allocated from a protected DMA-BUF heap and
> +      * imported in panthor. It's size must be at least
> +      * drm_panthor_protm_info::group_protected_suspend_buf_size.
> +      */
> +     __u32 protected_suspend_bo_handle;
>  
>       /**
>        * @compute_core_mask: Mask encoding cores that can be used for compute 
> jobs.

Reply via email to