brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · 07afa17 Raw
227 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only OR MIT */2/* Copyright (c) 2023 Imagination Technologies Ltd. */3 4#ifndef PVR_CONTEXT_H5#define PVR_CONTEXT_H6 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 data31 */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 when65	 * a GPU reset happened.66	 *67	 * In that case, the context is in an inconsistent state and can't be68	 * 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, or118 *  * %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 still131 * referenced context.132 * @ctx: Context pointer.133 *134 * Call pvr_context_put() to release.135 *136 * Returns:137 *  * True on success, or138 *  * false if no context pointer passed, or the context wasn't still139 *  * referenced.140 */141static __always_inline bool142pvr_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, or156 *  * %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, or180 *  * %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 need192	 * to make sure we're not trying to acquire a context that's being193	 * 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 u32205pvr_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 */227