root/drivers/gpu/drm/nouveau/nouveau_sched.h
/* SPDX-License-Identifier: MIT */

#ifndef NOUVEAU_SCHED_H
#define NOUVEAU_SCHED_H

#include <linux/types.h>

#include <drm/drm_gpuvm.h>
#include <drm/gpu_scheduler.h>

#include "nouveau_drv.h"

#define to_nouveau_job(sched_job)               \
                container_of((sched_job), struct nouveau_job, base)

struct nouveau_job_ops;

enum nouveau_job_state {
        NOUVEAU_JOB_UNINITIALIZED = 0,
        NOUVEAU_JOB_INITIALIZED,
        NOUVEAU_JOB_SUBMIT_SUCCESS,
        NOUVEAU_JOB_SUBMIT_FAILED,
        NOUVEAU_JOB_RUN_SUCCESS,
        NOUVEAU_JOB_RUN_FAILED,
};

struct nouveau_job_args {
        struct drm_file *file_priv;
        struct nouveau_sched *sched;
        u32 credits;

        enum dma_resv_usage resv_usage;
        bool sync;

        struct {
                struct drm_nouveau_sync *s;
                u32 count;
        } in_sync;

        struct {
                struct drm_nouveau_sync *s;
                u32 count;
        } out_sync;

        const struct nouveau_job_ops *ops;
};

struct nouveau_job {
        struct drm_sched_job base;

        enum nouveau_job_state state;

        struct nouveau_sched *sched;
        struct list_head entry;

        struct drm_file *file_priv;
        struct nouveau_cli *cli;

        enum dma_resv_usage resv_usage;
        struct dma_fence *done_fence;

        bool sync;

        struct {
                struct drm_nouveau_sync *data;
                u32 count;
        } in_sync;

        struct {
                struct drm_nouveau_sync *data;
                struct drm_syncobj **objs;
                struct dma_fence_chain **chains;
                u32 count;
        } out_sync;

        const struct nouveau_job_ops {
                /* If .submit() returns without any error, it is guaranteed that
                 * armed_submit() is called.
                 */
                int (*submit)(struct nouveau_job *, struct drm_gpuvm_exec *);
                void (*armed_submit)(struct nouveau_job *, struct drm_gpuvm_exec *);
                struct dma_fence *(*run)(struct nouveau_job *);
                void (*free)(struct nouveau_job *);
                enum drm_gpu_sched_stat (*timeout)(struct nouveau_job *);
        } *ops;
};

int nouveau_job_ucopy_syncs(struct nouveau_job_args *args,
                            u32 inc, u64 ins,
                            u32 outc, u64 outs);

int nouveau_job_init(struct nouveau_job *job,
                     struct nouveau_job_args *args);
void nouveau_job_fini(struct nouveau_job *job);
int nouveau_job_submit(struct nouveau_job *job);
void nouveau_job_done(struct nouveau_job *job);
void nouveau_job_free(struct nouveau_job *job);

struct nouveau_sched {
        struct drm_gpu_scheduler base;
        struct drm_sched_entity entity;
        struct workqueue_struct *wq;
        struct mutex mutex;

        struct {
                struct {
                        struct list_head head;
                        spinlock_t lock;
                } list;
                struct wait_queue_head wq;
        } job;
};

int nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm,
                         struct workqueue_struct *wq, u32 credit_limit);
void nouveau_sched_destroy(struct nouveau_sched **psched);

#endif