Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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. */
 21struct pvr_fw_object;
 22
 23enum 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 */
 32struct 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
 93static __always_inline struct pvr_queue *
 94pvr_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 */
120static __always_inline struct pvr_context *
121pvr_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 */
141static __always_inline bool
142pvr_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 */
158static __always_inline struct pvr_context *
159pvr_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 */
182static __always_inline struct pvr_context *
183pvr_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
204static __always_inline u32
205pvr_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
214void pvr_context_put(struct pvr_context *ctx);
215
216int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_context_args *args);
217
218int pvr_context_destroy(struct pvr_file *pvr_file, u32 handle);
219
220void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file);
221
222void pvr_context_device_init(struct pvr_device *pvr_dev);
223
224void pvr_context_device_fini(struct pvr_device *pvr_dev);
225
226#endif /* PVR_CONTEXT_H */