summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imagination/pvr_hwrt.h
blob: 676070b20c3ba552319057cfcabe69c890dbc832 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
/* Copyright (c) 2023 Imagination Technologies Ltd. */

#ifndef PVR_HWRT_H
#define PVR_HWRT_H

#include <linux/compiler_attributes.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/xarray.h>
#include <uapi/drm/pvr_drm.h>

#include "pvr_device.h"
#include "pvr_rogue_fwif_shared.h"

/* Forward declaration from pvr_free_list.h. */
struct pvr_free_list;

/* Forward declaration from pvr_gem.h. */
struct pvr_fw_object;

/**
 * struct pvr_hwrt_data - structure representing HWRT data
 */
struct pvr_hwrt_data {
	/** @fw_obj: FW object representing the FW-side structure. */
	struct pvr_fw_object *fw_obj;

	/** @data: Local copy of FW-side structure. */
	struct rogue_fwif_hwrtdata data;

	/** @freelist_node: List node connecting this HWRT to the local freelist. */
	struct list_head freelist_node;

	/**
	 * @srtc_obj: FW object representing shadow render target cache.
	 *
	 * Only valid if @max_rts > 1.
	 */
	struct pvr_fw_object *srtc_obj;

	/**
	 * @raa_obj: FW object representing renders accumulation array.
	 *
	 * Only valid if @max_rts > 1.
	 */
	struct pvr_fw_object *raa_obj;

	/** @hwrt_dataset: Back pointer to owning HWRT dataset. */
	struct pvr_hwrt_dataset *hwrt_dataset;
};

/**
 * struct pvr_hwrt_dataset - structure representing a HWRT data set.
 */
struct pvr_hwrt_dataset {
	/** @ref_count: Reference count of object. */
	struct kref ref_count;

	/** @pvr_dev: Pointer to device that owns this object. */
	struct pvr_device *pvr_dev;

	/** @common_fw_obj: FW object representing common FW-side structure. */
	struct pvr_fw_object *common_fw_obj;

	/** @common: Common HWRT data. */
	struct rogue_fwif_hwrtdata_common common;

	/** @data: HWRT data structures belonging to this set. */
	struct pvr_hwrt_data data[ROGUE_FWIF_NUM_RTDATAS];

	/** @free_lists: Free lists used by HWRT data set. */
	struct pvr_free_list *free_lists[ROGUE_FWIF_NUM_RTDATA_FREELISTS];

	/** @max_rts: Maximum render targets for this HWRT data set. */
	u16 max_rts;
};

struct pvr_hwrt_dataset *
pvr_hwrt_dataset_create(struct pvr_file *pvr_file,
			struct drm_pvr_ioctl_create_hwrt_dataset_args *args);

void
pvr_destroy_hwrt_datasets_for_file(struct pvr_file *pvr_file);

/**
 * pvr_hwrt_dataset_lookup() - Lookup HWRT dataset pointer from handle
 * @pvr_file: Pointer to pvr_file structure.
 * @handle: Object handle.
 *
 * Takes reference on dataset object. Call pvr_hwrt_dataset_put() to release.
 *
 * Returns:
 *  * The requested object on success, or
 *  * %NULL on failure (object does not exist in list, or is not a HWRT
 *    dataset)
 */
static __always_inline struct pvr_hwrt_dataset *
pvr_hwrt_dataset_lookup(struct pvr_file *pvr_file, u32 handle)
{
	struct pvr_hwrt_dataset *hwrt;

	xa_lock(&pvr_file->hwrt_handles);
	hwrt = xa_load(&pvr_file->hwrt_handles, handle);

	if (hwrt)
		kref_get(&hwrt->ref_count);

	xa_unlock(&pvr_file->hwrt_handles);

	return hwrt;
}

void
pvr_hwrt_dataset_put(struct pvr_hwrt_dataset *hwrt);

/**
 * pvr_hwrt_data_lookup() - Lookup HWRT data pointer from handle and index
 * @pvr_file: Pointer to pvr_file structure.
 * @handle: Object handle.
 * @index: Index of RT data within dataset.
 *
 * Takes reference on dataset object. Call pvr_hwrt_data_put() to release.
 *
 * Returns:
 *  * The requested object on success, or
 *  * %NULL on failure (object does not exist in list, or is not a HWRT
 *    dataset, or index is out of range)
 */
static __always_inline struct pvr_hwrt_data *
pvr_hwrt_data_lookup(struct pvr_file *pvr_file, u32 handle, u32 index)
{
	struct pvr_hwrt_dataset *hwrt_dataset = pvr_hwrt_dataset_lookup(pvr_file, handle);

	if (hwrt_dataset) {
		if (index < ARRAY_SIZE(hwrt_dataset->data))
			return &hwrt_dataset->data[index];

		pvr_hwrt_dataset_put(hwrt_dataset);
	}

	return NULL;
}

/**
 * pvr_hwrt_data_put() - Release reference on HWRT data
 * @hwrt: Pointer to HWRT data to release reference on
 */
static __always_inline void
pvr_hwrt_data_put(struct pvr_hwrt_data *hwrt)
{
	if (hwrt)
		pvr_hwrt_dataset_put(hwrt->hwrt_dataset);
}

static __always_inline struct pvr_hwrt_data *
pvr_hwrt_data_get(struct pvr_hwrt_data *hwrt)
{
	if (hwrt)
		kref_get(&hwrt->hwrt_dataset->ref_count);

	return hwrt;
}

#endif /* PVR_HWRT_H */