162 lines
3.7 KiB
C
162 lines
3.7 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
||
|
/* Copyright (c) 2023 Imagination Technologies Ltd. */
|
||
|
|
||
|
#ifndef PVR_JOB_H
|
||
|
#define PVR_JOB_H
|
||
|
|
||
|
#include <uapi/drm/pvr_drm.h>
|
||
|
|
||
|
#include <linux/kref.h>
|
||
|
#include <linux/types.h>
|
||
|
|
||
|
#include <drm/drm_gem.h>
|
||
|
#include <drm/gpu_scheduler.h>
|
||
|
|
||
|
#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 */
|