summaryrefslogtreecommitdiff
path: root/linux-core/ttm/ttm_fence_driver.h
blob: 2eca4944348d1a963ac8fbac7f68eba54893ce1e (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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/**************************************************************************
 *
 * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
 * All Rights Reserved.
 * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/
/*
 * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
 */
#ifndef _TTM_FENCE_DRIVER_H_
#define _TTM_FENCE_DRIVER_H_

#include <linux/kref.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include "ttm_fence_api.h"
#include "ttm_memory.h"

/** @file ttm_fence_driver.h
 *
 * Definitions needed for a driver implementing the
 * ttm_fence subsystem.
 */

/**
 * struct ttm_fence_class_manager:
 *
 * @wrap_diff: Sequence difference to catch 32-bit wrapping.
 * if (seqa - seqb) > @wrap_diff, then seqa < seqb.
 * @flush_diff: Sequence difference to trigger fence flush.
 * if (cur_seq - seqa) > @flush_diff, then consider fence object with
 * seqa as old an needing a flush.
 * @sequence_mask: Mask of valid bits in a fence sequence.
 * @lock: Lock protecting this struct as well as fence objects
 * associated with this struct.
 * @ring: Circular sequence-ordered list of fence objects.
 * @pending_flush: Fence types currently needing a flush.
 * @waiting_types: Fence types that are currently waited for.
 * @fence_queue: Queue of waiters on fences belonging to this fence class.
 * @highest_waiting_sequence: Sequence number of the fence with highest sequence
 * number and that is waited for.
 * @latest_queued_sequence: Sequence number of the fence latest queued on the ring.
 */

struct ttm_fence_class_manager {

	/*
	 * Unprotected constant members.
	 */

	uint32_t wrap_diff;
	uint32_t flush_diff;
	uint32_t sequence_mask;

	/*
	 * The rwlock protects this structure as well as
	 * the data in all fence objects belonging to this
	 * class. This should be OK as most fence objects are
	 * only read from once they're created.
	 */

	rwlock_t lock;
	struct list_head ring;
	uint32_t pending_flush;
	uint32_t waiting_types;
	wait_queue_head_t fence_queue;
	uint32_t highest_waiting_sequence;
	uint32_t latest_queued_sequence;
};

/**
 * struct ttm_fence_device
 *
 * @fence_class:  Array of fence class managers.
 * @num_classes:  Array dimension of @fence_class.
 * @count:        Current number of fence objects for statistics.
 * @driver:       Driver struct.
 *
 * Provided in the driver interface so that the driver can derive
 * from this struct for its driver_private, and accordingly
 * access the driver_private from the fence driver callbacks.
 *
 * All members except "count" are initialized at creation and
 * never touched after that. No protection needed.
 *
 * This struct is private to the fence implementation and to the fence
 * driver callbacks, and may otherwise be used by drivers only to
 * obtain the derived device_private object using container_of().
 */

struct ttm_fence_device {
	struct ttm_mem_global *mem_glob;
	struct ttm_fence_class_manager *fence_class;
	uint32_t num_classes;
	atomic_t count;
	const struct ttm_fence_driver *driver;
};

/**
 * struct ttm_fence_class_init
 *
 * @wrap_diff:    Fence sequence number wrap indicator. If
 * (sequence1 - sequence2) > @wrap_diff, then sequence1 is
 * considered to be older than sequence2.
 * @flush_diff:   Fence sequence number flush indicator.
 * If a non-completely-signaled fence has a fence sequence number
 * sequence1 and (sequence1 - current_emit_sequence) > @flush_diff,
 * the fence is considered too old and it will be flushed upon the
 * next call of ttm_fence_flush_old(), to make sure no fences with
 * stale sequence numbers remains unsignaled. @flush_diff should
 * be sufficiently less than @wrap_diff.
 * @sequence_mask: Mask with valid bits of the fence sequence
 * number set to 1.
 *
 * This struct is used as input to ttm_fence_device_init.
 */

struct ttm_fence_class_init {
	uint32_t wrap_diff;
	uint32_t flush_diff;
	uint32_t sequence_mask;
};

/**
 * struct ttm_fence_driver
 *
 * @has_irq: Called by a potential waiter. Should return 1 if a
 * fence object with indicated parameters is expected to signal
 * automatically, and 0 if the fence implementation needs to
 * repeatedly call @poll to make it signal.
 * @emit:    Make sure a fence with the given parameters is
 * present in the indicated command stream. Return its sequence number
 * in "breadcrumb".
 * @poll:    Check and report sequences of the given "fence_class"
 *           that have signaled "types"
 * @flush:   Make sure that the types indicated by the bitfield
 *           ttm_fence_class_manager::pending_flush will eventually
 *           signal. These bits have been put together using the
 *           result from the needed_flush function described below.
 * @needed_flush: Given the fence_class and fence_types indicated by
 *           "fence", and the last received fence sequence of this
 *           fence class, indicate what types need a fence flush to
 *           signal. Return as a bitfield.
 * @wait:    Set to non-NULL if the driver wants to override the fence
 *           wait implementation. Return 0 on success, -EBUSY on failure,
 *           and -ERESTART if interruptible and a signal is pending.
 * @signaled:  Driver callback that is called whenever a
 *           ttm_fence_object::signaled_types has changed status.
 *           This function is called from atomic context,
 *           with the ttm_fence_class_manager::lock held in write mode.
 * @lockup:  Driver callback that is called whenever a wait has exceeded
 *           the lifetime of a fence object.
 *           If there is a GPU lockup,
 *           this function should, if possible, reset the GPU,
 *           call the ttm_fence_handler with an error status, and
 *           return. If no lockup was detected, simply extend the
 *           fence timeout_jiffies and return. The driver might
 *           want to protect the lockup check with a mutex and cache a
 *           non-locked-up status for a while to avoid an excessive
 *           amount of lockup checks from every waiting thread.
 */

struct ttm_fence_driver {
	bool (*has_irq) (struct ttm_fence_device * fdev,
			uint32_t fence_class, uint32_t flags);
	int (*emit) (struct ttm_fence_device * fdev,
		     uint32_t fence_class,
		     uint32_t flags,
		     uint32_t * breadcrumb, unsigned long *timeout_jiffies);
	void (*flush) (struct ttm_fence_device * fdev, uint32_t fence_class);
	void (*poll) (struct ttm_fence_device * fdev,
		      uint32_t fence_class, uint32_t types);
	 uint32_t(*needed_flush)
	 (struct ttm_fence_object * fence);
	int (*wait) (struct ttm_fence_object * fence, bool lazy,
		     bool interruptible, uint32_t mask);
	void (*signaled) (struct ttm_fence_object * fence);
	void (*lockup) (struct ttm_fence_object * fence, uint32_t fence_types);
};

/**
 * function ttm_fence_device_init
 *
 * @num_classes:      Number of fence classes for this fence implementation.
 * @mem_global:       Pointer to the global memory accounting info.
 * @fdev:             Pointer to an uninitialised struct ttm_fence_device.
 * @init:             Array of initialization info for each fence class.
 * @replicate_init:   Use the first @init initialization info for all classes.
 * @driver:           Driver callbacks.
 *
 * Initialize a struct ttm_fence_driver structure. Returns -ENOMEM if
 * out-of-memory. Otherwise returns 0.
 */
extern int
ttm_fence_device_init(int num_classes,
		      struct ttm_mem_global *mem_glob,
		      struct ttm_fence_device *fdev,
		      const struct ttm_fence_class_init *init,
		      bool replicate_init,
		      const struct ttm_fence_driver *driver);

/**
 * function ttm_fence_device_release
 *
 * @fdev:             Pointer to the fence device.
 *
 * Release all resources held by a fence device. Note that before
 * this function is called, the caller must have made sure all fence
 * objects belonging to this fence device are completely signaled.
 */

extern void ttm_fence_device_release(struct ttm_fence_device *fdev);

/**
 * ttm_fence_handler - the fence handler.
 *
 * @fdev:        Pointer to the fence device.
 * @fence_class: Fence class that signals.
 * @sequence:    Signaled sequence.
 * @type:        Types that signal.
 * @error:       Error from the engine.
 *
 * This function signals all fences with a sequence previous to the
 * @sequence argument, and belonging to @fence_class. The signaled fence
 * types are provided in @type. If error is non-zero, the error member
 * of the fence with sequence = @sequence is set to @error. This value
 * may be reported back to user-space, indicating, for example an illegal
 * 3D command or illegal mpeg data.
 *
 * This function is typically called from the driver::poll method when the
 * command sequence preceding the fence marker has executed. It should be
 * called with the ttm_fence_class_manager::lock held in write mode and
 * may be called from interrupt context.
 */

extern void
ttm_fence_handler(struct ttm_fence_device *fdev,
		  uint32_t fence_class,
		  uint32_t sequence, uint32_t type, uint32_t error);

/**
 * ttm_fence_driver_from_dev
 *
 * @fdev:        The ttm fence device.
 *
 * Returns a pointer to the fence driver struct.
 */

static inline const struct ttm_fence_driver *ttm_fence_driver_from_dev(struct
								       ttm_fence_device
								       *fdev)
{
	return fdev->driver;
}

/**
 * ttm_fence_driver
 *
 * @fence:        Pointer to a ttm fence object.
 *
 * Returns a pointer to the fence driver struct.
 */

static inline const struct ttm_fence_driver *ttm_fence_driver(struct
							      ttm_fence_object
							      *fence)
{
	return ttm_fence_driver_from_dev(fence->fdev);
}

/**
 * ttm_fence_fc
 *
 * @fence:        Pointer to a ttm fence object.
 *
 * Returns a pointer to the struct ttm_fence_class_manager for the
 * fence class of @fence.
 */

static inline struct ttm_fence_class_manager *ttm_fence_fc(struct
							   ttm_fence_object
							   *fence)
{
	return &fence->fdev->fence_class[fence->fence_class];
}

#endif