1/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
2/* Copyright (c) 2023 Imagination Technologies Ltd. */
3
4#ifndef PVR_HWRT_H
5#define PVR_HWRT_H
6
7#include <linux/compiler_attributes.h>
8#include <linux/kref.h>
9#include <linux/list.h>
10#include <linux/types.h>
11#include <linux/xarray.h>
12#include <uapi/drm/pvr_drm.h>
13
14#include "pvr_device.h"
15#include "pvr_rogue_fwif_shared.h"
16
17/* Forward declaration from pvr_free_list.h. */
18struct pvr_free_list;
19
20/* Forward declaration from pvr_gem.h. */
21struct pvr_fw_object;
22
23/**
24 * struct pvr_hwrt_data - structure representing HWRT data
25 */
26struct pvr_hwrt_data {
27	/** @fw_obj: FW object representing the FW-side structure. */
28	struct pvr_fw_object *fw_obj;
29
30	/** @data: Local copy of FW-side structure. */
31	struct rogue_fwif_hwrtdata data;
32
33	/** @freelist_node: List node connecting this HWRT to the local freelist. */
34	struct list_head freelist_node;
35
36	/**
37	 * @srtc_obj: FW object representing shadow render target cache.
38	 *
39	 * Only valid if @max_rts > 1.
40	 */
41	struct pvr_fw_object *srtc_obj;
42
43	/**
44	 * @raa_obj: FW object representing renders accumulation array.
45	 *
46	 * Only valid if @max_rts > 1.
47	 */
48	struct pvr_fw_object *raa_obj;
49
50	/** @hwrt_dataset: Back pointer to owning HWRT dataset. */
51	struct pvr_hwrt_dataset *hwrt_dataset;
52};
53
54/**
55 * struct pvr_hwrt_dataset - structure representing a HWRT data set.
56 */
57struct pvr_hwrt_dataset {
58	/** @ref_count: Reference count of object. */
59	struct kref ref_count;
60
61	/** @pvr_dev: Pointer to device that owns this object. */
62	struct pvr_device *pvr_dev;
63
64	/** @common_fw_obj: FW object representing common FW-side structure. */
65	struct pvr_fw_object *common_fw_obj;
66
67	/** @common: Common HWRT data. */
68	struct rogue_fwif_hwrtdata_common common;
69
70	/** @data: HWRT data structures belonging to this set. */
71	struct pvr_hwrt_data data[ROGUE_FWIF_NUM_RTDATAS];
72
73	/** @free_lists: Free lists used by HWRT data set. */
74	struct pvr_free_list *free_lists[ROGUE_FWIF_NUM_RTDATA_FREELISTS];
75
76	/** @max_rts: Maximum render targets for this HWRT data set. */
77	u16 max_rts;
78};
79
80struct pvr_hwrt_dataset *
81pvr_hwrt_dataset_create(struct pvr_file *pvr_file,
82			struct drm_pvr_ioctl_create_hwrt_dataset_args *args);
83
84void
85pvr_destroy_hwrt_datasets_for_file(struct pvr_file *pvr_file);
86
87/**
88 * pvr_hwrt_dataset_lookup() - Lookup HWRT dataset pointer from handle
89 * @pvr_file: Pointer to pvr_file structure.
90 * @handle: Object handle.
91 *
92 * Takes reference on dataset object. Call pvr_hwrt_dataset_put() to release.
93 *
94 * Returns:
95 *  * The requested object on success, or
96 *  * %NULL on failure (object does not exist in list, or is not a HWRT
97 *    dataset)
98 */
99static __always_inline struct pvr_hwrt_dataset *
100pvr_hwrt_dataset_lookup(struct pvr_file *pvr_file, u32 handle)
101{
102	struct pvr_hwrt_dataset *hwrt;
103
104	xa_lock(&pvr_file->hwrt_handles);
105	hwrt = xa_load(&pvr_file->hwrt_handles, handle);
106
107	if (hwrt)
108		kref_get(&hwrt->ref_count);
109
110	xa_unlock(&pvr_file->hwrt_handles);
111
112	return hwrt;
113}
114
115void
116pvr_hwrt_dataset_put(struct pvr_hwrt_dataset *hwrt);
117
118/**
119 * pvr_hwrt_data_lookup() - Lookup HWRT data pointer from handle and index
120 * @pvr_file: Pointer to pvr_file structure.
121 * @handle: Object handle.
122 * @index: Index of RT data within dataset.
123 *
124 * Takes reference on dataset object. Call pvr_hwrt_data_put() to release.
125 *
126 * Returns:
127 *  * The requested object on success, or
128 *  * %NULL on failure (object does not exist in list, or is not a HWRT
129 *    dataset, or index is out of range)
130 */
131static __always_inline struct pvr_hwrt_data *
132pvr_hwrt_data_lookup(struct pvr_file *pvr_file, u32 handle, u32 index)
133{
134	struct pvr_hwrt_dataset *hwrt_dataset = pvr_hwrt_dataset_lookup(pvr_file, handle);
135
136	if (hwrt_dataset) {
137		if (index < ARRAY_SIZE(hwrt_dataset->data))
138			return &hwrt_dataset->data[index];
139
140		pvr_hwrt_dataset_put(hwrt_dataset);
141	}
142
143	return NULL;
144}
145
146/**
147 * pvr_hwrt_data_put() - Release reference on HWRT data
148 * @hwrt: Pointer to HWRT data to release reference on
149 */
150static __always_inline void
151pvr_hwrt_data_put(struct pvr_hwrt_data *hwrt)
152{
153	if (hwrt)
154		pvr_hwrt_dataset_put(hwrt->hwrt_dataset);
155}
156
157static __always_inline struct pvr_hwrt_data *
158pvr_hwrt_data_get(struct pvr_hwrt_data *hwrt)
159{
160	if (hwrt)
161		kref_get(&hwrt->hwrt_dataset->ref_count);
162
163	return hwrt;
164}
165
166#endif /* PVR_HWRT_H */
167