/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ /* Copyright (c) 2023 Imagination Technologies Ltd. */ #ifndef PVR_JOB_H #define PVR_JOB_H #include #include #include #include #include #include "pvr_power.h" /* Forward declaration from "pvr_context.h". */ struct pvr_context; /* Forward declarations from "pvr_device.h". */ struct pvr_device; struct pvr_file; /* Forward declarations from "pvr_hwrt.h". */ struct pvr_hwrt_data; /* Forward declaration from "pvr_queue.h". */ struct pvr_queue; struct pvr_job { /** @base: drm_sched_job object. */ struct drm_sched_job base; /** @ref_count: Refcount for job. */ struct kref ref_count; /** @type: Type of job. */ enum drm_pvr_job_type type; /** @id: Job ID number. */ u32 id; /** * @paired_job: Job paired to this job. * * This field is only meaningful for geometry and fragment jobs. * * Paired jobs are executed on the same context, and need to be submitted * atomically to the FW, to make sure the partial render logic has a * fragment job to execute when the Parameter Manager runs out of memory. * * The geometry job should point to the fragment job it's paired with, * and the fragment job should point to the geometry job it's paired with. */ struct pvr_job *paired_job; /** @cccb_fence: Fence used to wait for CCCB space. */ struct dma_fence *cccb_fence; /** @kccb_fence: Fence used to wait for KCCB space. */ struct dma_fence *kccb_fence; /** @done_fence: Fence to signal when the job is done. */ struct dma_fence *done_fence; /** @pvr_dev: Device pointer. */ struct pvr_device *pvr_dev; /** @ctx: Pointer to owning context. */ struct pvr_context *ctx; /** @cmd: Command data. Format depends on @type. */ void *cmd; /** @cmd_len: Length of command data, in bytes. */ u32 cmd_len; /** * @fw_ccb_cmd_type: Firmware CCB command type. Must be one of %ROGUE_FWIF_CCB_CMD_TYPE_*. */ u32 fw_ccb_cmd_type; /** @hwrt: HWRT object. Will be NULL for compute and transfer jobs. */ struct pvr_hwrt_data *hwrt; /** * @has_pm_ref: True if the job has a power ref, thus forcing the GPU to stay on until * the job is done. */ bool has_pm_ref; }; /** * pvr_job_get() - Take additional reference on job. * @job: Job pointer. * * Call pvr_job_put() to release. * * Returns: * * The requested job on success, or * * %NULL if no job pointer passed. */ static __always_inline struct pvr_job * pvr_job_get(struct pvr_job *job) { if (job) kref_get(&job->ref_count); return job; } void pvr_job_put(struct pvr_job *job); /** * pvr_job_release_pm_ref() - Release the PM ref if the job acquired it. * @job: The job to release the PM ref on. */ static __always_inline void pvr_job_release_pm_ref(struct pvr_job *job) { if (job->has_pm_ref) { pvr_power_put(job->pvr_dev); job->has_pm_ref = false; } } /** * pvr_job_get_pm_ref() - Get a PM ref and attach it to the job. * @job: The job to attach the PM ref to. * * Return: * * 0 on success, or * * Any error returned by pvr_power_get() otherwise. */ static __always_inline int pvr_job_get_pm_ref(struct pvr_job *job) { int err; if (job->has_pm_ref) return 0; err = pvr_power_get(job->pvr_dev); if (!err) job->has_pm_ref = true; return err; } int pvr_job_wait_first_non_signaled_native_dep(struct pvr_job *job); bool pvr_job_non_native_deps_done(struct pvr_job *job); int pvr_job_fits_in_cccb(struct pvr_job *job, unsigned long native_dep_count); void pvr_job_submit(struct pvr_job *job); int pvr_submit_jobs(struct pvr_device *pvr_dev, struct pvr_file *pvr_file, struct drm_pvr_ioctl_submit_jobs_args *args); #endif /* PVR_JOB_H */