xref: /linux/drivers/gpu/drm/imagination/pvr_job.h (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
1 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
2 /* Copyright (c) 2023 Imagination Technologies Ltd. */
3 
4 #ifndef PVR_JOB_H
5 #define PVR_JOB_H
6 
7 #include <uapi/drm/pvr_drm.h>
8 
9 #include <linux/kref.h>
10 #include <linux/types.h>
11 
12 #include <drm/drm_gem.h>
13 #include <drm/gpu_scheduler.h>
14 
15 #include "pvr_power.h"
16 
17 /* Forward declaration from "pvr_context.h". */
18 struct pvr_context;
19 
20 /* Forward declarations from "pvr_device.h". */
21 struct pvr_device;
22 struct pvr_file;
23 
24 /* Forward declarations from "pvr_hwrt.h". */
25 struct pvr_hwrt_data;
26 
27 /* Forward declaration from "pvr_queue.h". */
28 struct pvr_queue;
29 
30 struct pvr_job {
31 	/** @base: drm_sched_job object. */
32 	struct drm_sched_job base;
33 
34 	/** @ref_count: Refcount for job. */
35 	struct kref ref_count;
36 
37 	/** @type: Type of job. */
38 	enum drm_pvr_job_type type;
39 
40 	/** @id: Job ID number. */
41 	u32 id;
42 
43 	/**
44 	 * @paired_job: Job paired to this job.
45 	 *
46 	 * This field is only meaningful for geometry and fragment jobs.
47 	 *
48 	 * Paired jobs are executed on the same context, and need to be submitted
49 	 * atomically to the FW, to make sure the partial render logic has a
50 	 * fragment job to execute when the Parameter Manager runs out of memory.
51 	 *
52 	 * The geometry job should point to the fragment job it's paired with,
53 	 * and the fragment job should point to the geometry job it's paired with.
54 	 */
55 	struct pvr_job *paired_job;
56 
57 	/** @cccb_fence: Fence used to wait for CCCB space. */
58 	struct dma_fence *cccb_fence;
59 
60 	/** @kccb_fence: Fence used to wait for KCCB space. */
61 	struct dma_fence *kccb_fence;
62 
63 	/** @done_fence: Fence to signal when the job is done. */
64 	struct dma_fence *done_fence;
65 
66 	/** @pvr_dev: Device pointer. */
67 	struct pvr_device *pvr_dev;
68 
69 	/** @ctx: Pointer to owning context. */
70 	struct pvr_context *ctx;
71 
72 	/** @cmd: Command data. Format depends on @type. */
73 	void *cmd;
74 
75 	/** @cmd_len: Length of command data, in bytes. */
76 	u32 cmd_len;
77 
78 	/**
79 	 * @fw_ccb_cmd_type: Firmware CCB command type. Must be one of %ROGUE_FWIF_CCB_CMD_TYPE_*.
80 	 */
81 	u32 fw_ccb_cmd_type;
82 
83 	/** @hwrt: HWRT object. Will be NULL for compute and transfer jobs. */
84 	struct pvr_hwrt_data *hwrt;
85 
86 	/**
87 	 * @has_pm_ref: True if the job has a power ref, thus forcing the GPU to stay on until
88 	 * the job is done.
89 	 */
90 	bool has_pm_ref;
91 };
92 
93 /**
94  * pvr_job_get() - Take additional reference on job.
95  * @job: Job pointer.
96  *
97  * Call pvr_job_put() to release.
98  *
99  * Returns:
100  *  * The requested job on success, or
101  *  * %NULL if no job pointer passed.
102  */
103 static __always_inline struct pvr_job *
104 pvr_job_get(struct pvr_job *job)
105 {
106 	if (job)
107 		kref_get(&job->ref_count);
108 
109 	return job;
110 }
111 
112 void pvr_job_put(struct pvr_job *job);
113 
114 /**
115  * pvr_job_release_pm_ref() - Release the PM ref if the job acquired it.
116  * @job: The job to release the PM ref on.
117  */
118 static __always_inline void
119 pvr_job_release_pm_ref(struct pvr_job *job)
120 {
121 	if (job->has_pm_ref) {
122 		pvr_power_put(job->pvr_dev);
123 		job->has_pm_ref = false;
124 	}
125 }
126 
127 /**
128  * pvr_job_get_pm_ref() - Get a PM ref and attach it to the job.
129  * @job: The job to attach the PM ref to.
130  *
131  * Return:
132  *  * 0 on success, or
133  *  * Any error returned by pvr_power_get() otherwise.
134  */
135 static __always_inline int
136 pvr_job_get_pm_ref(struct pvr_job *job)
137 {
138 	int err;
139 
140 	if (job->has_pm_ref)
141 		return 0;
142 
143 	err = pvr_power_get(job->pvr_dev);
144 	if (!err)
145 		job->has_pm_ref = true;
146 
147 	return err;
148 }
149 
150 int pvr_job_wait_first_non_signaled_native_dep(struct pvr_job *job);
151 
152 bool pvr_job_non_native_deps_done(struct pvr_job *job);
153 
154 int pvr_job_fits_in_cccb(struct pvr_job *job, unsigned long native_dep_count);
155 
156 void pvr_job_submit(struct pvr_job *job);
157 
158 int pvr_submit_jobs(struct pvr_device *pvr_dev, struct pvr_file *pvr_file,
159 		    struct drm_pvr_ioctl_submit_jobs_args *args);
160 
161 #endif /* PVR_JOB_H */
162