xref: /linux/drivers/gpu/drm/imagination/pvr_hwrt.h (revision ab779466166348eecf17d20f620aa9a47965c934)
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. */
18 struct pvr_free_list;
19 
20 /* Forward declaration from pvr_gem.h. */
21 struct pvr_fw_object;
22 
23 /**
24  * struct pvr_hwrt_data - structure representing HWRT data
25  */
26 struct 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  */
57 struct 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 	struct rogue_fwif_hwrtdata_common common;
68 
69 	/** @data: HWRT data structures belonging to this set. */
70 	struct pvr_hwrt_data data[ROGUE_FWIF_NUM_RTDATAS];
71 
72 	/** @free_lists: Free lists used by HWRT data set. */
73 	struct pvr_free_list *free_lists[ROGUE_FWIF_NUM_RTDATA_FREELISTS];
74 
75 	/** @max_rts: Maximum render targets for this HWRT data set. */
76 	u16 max_rts;
77 };
78 
79 struct pvr_hwrt_dataset *
80 pvr_hwrt_dataset_create(struct pvr_file *pvr_file,
81 			struct drm_pvr_ioctl_create_hwrt_dataset_args *args);
82 
83 void
84 pvr_destroy_hwrt_datasets_for_file(struct pvr_file *pvr_file);
85 
86 /**
87  * pvr_hwrt_dataset_lookup() - Lookup HWRT dataset pointer from handle
88  * @pvr_file: Pointer to pvr_file structure.
89  * @handle: Object handle.
90  *
91  * Takes reference on dataset object. Call pvr_hwrt_dataset_put() to release.
92  *
93  * Returns:
94  *  * The requested object on success, or
95  *  * %NULL on failure (object does not exist in list, or is not a HWRT
96  *    dataset)
97  */
98 static __always_inline struct pvr_hwrt_dataset *
99 pvr_hwrt_dataset_lookup(struct pvr_file *pvr_file, u32 handle)
100 {
101 	struct pvr_hwrt_dataset *hwrt;
102 
103 	xa_lock(&pvr_file->hwrt_handles);
104 	hwrt = xa_load(&pvr_file->hwrt_handles, handle);
105 
106 	if (hwrt)
107 		kref_get(&hwrt->ref_count);
108 
109 	xa_unlock(&pvr_file->hwrt_handles);
110 
111 	return hwrt;
112 }
113 
114 void
115 pvr_hwrt_dataset_put(struct pvr_hwrt_dataset *hwrt);
116 
117 /**
118  * pvr_hwrt_data_lookup() - Lookup HWRT data pointer from handle and index
119  * @pvr_file: Pointer to pvr_file structure.
120  * @handle: Object handle.
121  * @index: Index of RT data within dataset.
122  *
123  * Takes reference on dataset object. Call pvr_hwrt_data_put() to release.
124  *
125  * Returns:
126  *  * The requested object on success, or
127  *  * %NULL on failure (object does not exist in list, or is not a HWRT
128  *    dataset, or index is out of range)
129  */
130 static __always_inline struct pvr_hwrt_data *
131 pvr_hwrt_data_lookup(struct pvr_file *pvr_file, u32 handle, u32 index)
132 {
133 	struct pvr_hwrt_dataset *hwrt_dataset = pvr_hwrt_dataset_lookup(pvr_file, handle);
134 
135 	if (hwrt_dataset) {
136 		if (index < ARRAY_SIZE(hwrt_dataset->data))
137 			return &hwrt_dataset->data[index];
138 
139 		pvr_hwrt_dataset_put(hwrt_dataset);
140 	}
141 
142 	return NULL;
143 }
144 
145 /**
146  * pvr_hwrt_data_put() - Release reference on HWRT data
147  * @hwrt: Pointer to HWRT data to release reference on
148  */
149 static __always_inline void
150 pvr_hwrt_data_put(struct pvr_hwrt_data *hwrt)
151 {
152 	if (hwrt)
153 		pvr_hwrt_dataset_put(hwrt->hwrt_dataset);
154 }
155 
156 static __always_inline struct pvr_hwrt_data *
157 pvr_hwrt_data_get(struct pvr_hwrt_data *hwrt)
158 {
159 	if (hwrt)
160 		kref_get(&hwrt->hwrt_dataset->ref_count);
161 
162 	return hwrt;
163 }
164 
165 #endif /* PVR_HWRT_H */
166