]> Git Repo - linux.git/blob - drivers/gpu/drm/imagination/pvr_context.h
Merge tag 'for-linus-6.14-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / gpu / drm / imagination / pvr_context.h
1 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
2 /* Copyright (c) 2023 Imagination Technologies Ltd. */
3
4 #ifndef PVR_CONTEXT_H
5 #define PVR_CONTEXT_H
6
7 #include <drm/gpu_scheduler.h>
8
9 #include <linux/compiler_attributes.h>
10 #include <linux/dma-fence.h>
11 #include <linux/kref.h>
12 #include <linux/types.h>
13 #include <linux/xarray.h>
14 #include <uapi/drm/pvr_drm.h>
15
16 #include "pvr_cccb.h"
17 #include "pvr_device.h"
18 #include "pvr_queue.h"
19
20 /* Forward declaration from pvr_gem.h. */
21 struct pvr_fw_object;
22
23 enum pvr_context_priority {
24         PVR_CTX_PRIORITY_LOW = 0,
25         PVR_CTX_PRIORITY_MEDIUM,
26         PVR_CTX_PRIORITY_HIGH,
27 };
28
29 /**
30  * struct pvr_context - Context data
31  */
32 struct pvr_context {
33         /** @ref_count: Refcount for context. */
34         struct kref ref_count;
35
36         /** @pvr_dev: Pointer to owning device. */
37         struct pvr_device *pvr_dev;
38
39         /** @vm_ctx: Pointer to associated VM context. */
40         struct pvr_vm_context *vm_ctx;
41
42         /** @type: Type of context. */
43         enum drm_pvr_ctx_type type;
44
45         /** @flags: Context flags. */
46         u32 flags;
47
48         /** @priority: Context priority*/
49         enum pvr_context_priority priority;
50
51         /** @fw_obj: FW object representing FW-side context data. */
52         struct pvr_fw_object *fw_obj;
53
54         /** @data: Pointer to local copy of FW context data. */
55         void *data;
56
57         /** @data_size: Size of FW context data, in bytes. */
58         u32 data_size;
59
60         /** @ctx_id: FW context ID. */
61         u32 ctx_id;
62
63         /**
64          * @faulty: Set to 1 when the context queues had unfinished job when
65          * a GPU reset happened.
66          *
67          * In that case, the context is in an inconsistent state and can't be
68          * used anymore.
69          */
70         atomic_t faulty;
71
72         /** @queues: Union containing all kind of queues. */
73         union {
74                 struct {
75                         /** @geometry: Geometry queue. */
76                         struct pvr_queue *geometry;
77
78                         /** @fragment: Fragment queue. */
79                         struct pvr_queue *fragment;
80                 };
81
82                 /** @compute: Compute queue. */
83                 struct pvr_queue *compute;
84
85                 /** @compute: Transfer queue. */
86                 struct pvr_queue *transfer;
87         } queues;
88
89         /** @file_link: pvr_file PVR context list link. */
90         struct list_head file_link;
91 };
92
93 static __always_inline struct pvr_queue *
94 pvr_context_get_queue_for_job(struct pvr_context *ctx, enum drm_pvr_job_type type)
95 {
96         switch (type) {
97         case DRM_PVR_JOB_TYPE_GEOMETRY:
98                 return ctx->type == DRM_PVR_CTX_TYPE_RENDER ? ctx->queues.geometry : NULL;
99         case DRM_PVR_JOB_TYPE_FRAGMENT:
100                 return ctx->type == DRM_PVR_CTX_TYPE_RENDER ? ctx->queues.fragment : NULL;
101         case DRM_PVR_JOB_TYPE_COMPUTE:
102                 return ctx->type == DRM_PVR_CTX_TYPE_COMPUTE ? ctx->queues.compute : NULL;
103         case DRM_PVR_JOB_TYPE_TRANSFER_FRAG:
104                 return ctx->type == DRM_PVR_CTX_TYPE_TRANSFER_FRAG ? ctx->queues.transfer : NULL;
105         }
106
107         return NULL;
108 }
109
110 /**
111  * pvr_context_get() - Take additional reference on context.
112  * @ctx: Context pointer.
113  *
114  * Call pvr_context_put() to release.
115  *
116  * Returns:
117  *  * The requested context on success, or
118  *  * %NULL if no context pointer passed.
119  */
120 static __always_inline struct pvr_context *
121 pvr_context_get(struct pvr_context *ctx)
122 {
123         if (ctx)
124                 kref_get(&ctx->ref_count);
125
126         return ctx;
127 }
128
129 /**
130  * pvr_context_get_if_referenced() - Take an additional reference on a still
131  * referenced context.
132  * @ctx: Context pointer.
133  *
134  * Call pvr_context_put() to release.
135  *
136  * Returns:
137  *  * True on success, or
138  *  * false if no context pointer passed, or the context wasn't still
139  *  * referenced.
140  */
141 static __always_inline bool
142 pvr_context_get_if_referenced(struct pvr_context *ctx)
143 {
144         return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
145 }
146
147 /**
148  * pvr_context_lookup() - Lookup context pointer from handle and file.
149  * @pvr_file: Pointer to pvr_file structure.
150  * @handle: Context handle.
151  *
152  * Takes reference on context. Call pvr_context_put() to release.
153  *
154  * Return:
155  *  * The requested context on success, or
156  *  * %NULL on failure (context does not exist, or does not belong to @pvr_file).
157  */
158 static __always_inline struct pvr_context *
159 pvr_context_lookup(struct pvr_file *pvr_file, u32 handle)
160 {
161         struct pvr_context *ctx;
162
163         /* Take the array lock to protect against context removal.  */
164         xa_lock(&pvr_file->ctx_handles);
165         ctx = pvr_context_get(xa_load(&pvr_file->ctx_handles, handle));
166         xa_unlock(&pvr_file->ctx_handles);
167
168         return ctx;
169 }
170
171 /**
172  * pvr_context_lookup_id() - Lookup context pointer from ID.
173  * @pvr_dev: Device pointer.
174  * @id: FW context ID.
175  *
176  * Takes reference on context. Call pvr_context_put() to release.
177  *
178  * Return:
179  *  * The requested context on success, or
180  *  * %NULL on failure (context does not exist).
181  */
182 static __always_inline struct pvr_context *
183 pvr_context_lookup_id(struct pvr_device *pvr_dev, u32 id)
184 {
185         struct pvr_context *ctx;
186
187         /* Take the array lock to protect against context removal.  */
188         xa_lock(&pvr_dev->ctx_ids);
189
190         /* Contexts are removed from the ctx_ids set in the context release path,
191          * meaning the ref_count reached zero before they get removed. We need
192          * to make sure we're not trying to acquire a context that's being
193          * destroyed.
194          */
195         ctx = xa_load(&pvr_dev->ctx_ids, id);
196         if (!kref_get_unless_zero(&ctx->ref_count))
197                 ctx = NULL;
198
199         xa_unlock(&pvr_dev->ctx_ids);
200
201         return ctx;
202 }
203
204 static __always_inline u32
205 pvr_context_get_fw_addr(struct pvr_context *ctx)
206 {
207         u32 ctx_fw_addr = 0;
208
209         pvr_fw_object_get_fw_addr(ctx->fw_obj, &ctx_fw_addr);
210
211         return ctx_fw_addr;
212 }
213
214 void pvr_context_put(struct pvr_context *ctx);
215
216 int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_context_args *args);
217
218 int pvr_context_destroy(struct pvr_file *pvr_file, u32 handle);
219
220 void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file);
221
222 void pvr_context_device_init(struct pvr_device *pvr_dev);
223
224 void pvr_context_device_fini(struct pvr_device *pvr_dev);
225
226 #endif /* PVR_CONTEXT_H */
This page took 0.041111 seconds and 4 git commands to generate.