xref: /aosp_15_r20/external/libdrm/intel/intel_bufmgr_fake.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /**************************************************************************
2*7688df22SAndroid Build Coastguard Worker  *
3*7688df22SAndroid Build Coastguard Worker  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4*7688df22SAndroid Build Coastguard Worker  * All Rights Reserved.
5*7688df22SAndroid Build Coastguard Worker  *
6*7688df22SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*7688df22SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the
8*7688df22SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
9*7688df22SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
10*7688df22SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
11*7688df22SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
12*7688df22SAndroid Build Coastguard Worker  * the following conditions:
13*7688df22SAndroid Build Coastguard Worker  *
14*7688df22SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
15*7688df22SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
16*7688df22SAndroid Build Coastguard Worker  * of the Software.
17*7688df22SAndroid Build Coastguard Worker  *
18*7688df22SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19*7688df22SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*7688df22SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21*7688df22SAndroid Build Coastguard Worker  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22*7688df22SAndroid Build Coastguard Worker  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23*7688df22SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24*7688df22SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25*7688df22SAndroid Build Coastguard Worker  *
26*7688df22SAndroid Build Coastguard Worker  **************************************************************************/
27*7688df22SAndroid Build Coastguard Worker 
28*7688df22SAndroid Build Coastguard Worker /* Originally a fake version of the buffer manager so that we can
29*7688df22SAndroid Build Coastguard Worker  * prototype the changes in a driver fairly quickly, has been fleshed
30*7688df22SAndroid Build Coastguard Worker  * out to a fully functional interim solution.
31*7688df22SAndroid Build Coastguard Worker  *
32*7688df22SAndroid Build Coastguard Worker  * Basically wraps the old style memory management in the new
33*7688df22SAndroid Build Coastguard Worker  * programming interface, but is more expressive and avoids many of
34*7688df22SAndroid Build Coastguard Worker  * the bugs in the old texture manager.
35*7688df22SAndroid Build Coastguard Worker  */
36*7688df22SAndroid Build Coastguard Worker 
37*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
38*7688df22SAndroid Build Coastguard Worker #include <string.h>
39*7688df22SAndroid Build Coastguard Worker #include <assert.h>
40*7688df22SAndroid Build Coastguard Worker #include <errno.h>
41*7688df22SAndroid Build Coastguard Worker #include <strings.h>
42*7688df22SAndroid Build Coastguard Worker #include <xf86drm.h>
43*7688df22SAndroid Build Coastguard Worker #include <pthread.h>
44*7688df22SAndroid Build Coastguard Worker #include "intel_bufmgr.h"
45*7688df22SAndroid Build Coastguard Worker #include "intel_bufmgr_priv.h"
46*7688df22SAndroid Build Coastguard Worker #include "drm.h"
47*7688df22SAndroid Build Coastguard Worker #include "i915_drm.h"
48*7688df22SAndroid Build Coastguard Worker #include "mm.h"
49*7688df22SAndroid Build Coastguard Worker #include "libdrm_macros.h"
50*7688df22SAndroid Build Coastguard Worker #include "libdrm_lists.h"
51*7688df22SAndroid Build Coastguard Worker 
52*7688df22SAndroid Build Coastguard Worker #define DBG(...) do {					\
53*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->bufmgr.debug)			\
54*7688df22SAndroid Build Coastguard Worker 		drmMsg(__VA_ARGS__);			\
55*7688df22SAndroid Build Coastguard Worker } while (0)
56*7688df22SAndroid Build Coastguard Worker 
57*7688df22SAndroid Build Coastguard Worker /* Internal flags:
58*7688df22SAndroid Build Coastguard Worker  */
59*7688df22SAndroid Build Coastguard Worker #define BM_NO_BACKING_STORE			0x00000001
60*7688df22SAndroid Build Coastguard Worker #define BM_NO_FENCE_SUBDATA			0x00000002
61*7688df22SAndroid Build Coastguard Worker #define BM_PINNED				0x00000004
62*7688df22SAndroid Build Coastguard Worker 
63*7688df22SAndroid Build Coastguard Worker /* Wrapper around mm.c's mem_block, which understands that you must
64*7688df22SAndroid Build Coastguard Worker  * wait for fences to expire before memory can be freed.  This is
65*7688df22SAndroid Build Coastguard Worker  * specific to our use of memcpy for uploads - an upload that was
66*7688df22SAndroid Build Coastguard Worker  * processed through the command queue wouldn't need to care about
67*7688df22SAndroid Build Coastguard Worker  * fences.
68*7688df22SAndroid Build Coastguard Worker  */
69*7688df22SAndroid Build Coastguard Worker #define MAX_RELOCS 4096
70*7688df22SAndroid Build Coastguard Worker 
71*7688df22SAndroid Build Coastguard Worker struct fake_buffer_reloc {
72*7688df22SAndroid Build Coastguard Worker 	/** Buffer object that the relocation points at. */
73*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo *target_buf;
74*7688df22SAndroid Build Coastguard Worker 	/** Offset of the relocation entry within reloc_buf. */
75*7688df22SAndroid Build Coastguard Worker 	uint32_t offset;
76*7688df22SAndroid Build Coastguard Worker 	/**
77*7688df22SAndroid Build Coastguard Worker 	 * Cached value of the offset when we last performed this relocation.
78*7688df22SAndroid Build Coastguard Worker 	 */
79*7688df22SAndroid Build Coastguard Worker 	uint32_t last_target_offset;
80*7688df22SAndroid Build Coastguard Worker 	/** Value added to target_buf's offset to get the relocation entry. */
81*7688df22SAndroid Build Coastguard Worker 	uint32_t delta;
82*7688df22SAndroid Build Coastguard Worker 	/** Cache domains the target buffer is read into. */
83*7688df22SAndroid Build Coastguard Worker 	uint32_t read_domains;
84*7688df22SAndroid Build Coastguard Worker 	/** Cache domain the target buffer will have dirty cachelines in. */
85*7688df22SAndroid Build Coastguard Worker 	uint32_t write_domain;
86*7688df22SAndroid Build Coastguard Worker };
87*7688df22SAndroid Build Coastguard Worker 
88*7688df22SAndroid Build Coastguard Worker struct block {
89*7688df22SAndroid Build Coastguard Worker 	struct block *next, *prev;
90*7688df22SAndroid Build Coastguard Worker 	struct mem_block *mem;	/* BM_MEM_AGP */
91*7688df22SAndroid Build Coastguard Worker 
92*7688df22SAndroid Build Coastguard Worker 	/**
93*7688df22SAndroid Build Coastguard Worker 	 * Marks that the block is currently in the aperture and has yet to be
94*7688df22SAndroid Build Coastguard Worker 	 * fenced.
95*7688df22SAndroid Build Coastguard Worker 	 */
96*7688df22SAndroid Build Coastguard Worker 	unsigned on_hardware:1;
97*7688df22SAndroid Build Coastguard Worker 	/**
98*7688df22SAndroid Build Coastguard Worker 	 * Marks that the block is currently fenced (being used by rendering)
99*7688df22SAndroid Build Coastguard Worker 	 * and can't be freed until @fence is passed.
100*7688df22SAndroid Build Coastguard Worker 	 */
101*7688df22SAndroid Build Coastguard Worker 	unsigned fenced:1;
102*7688df22SAndroid Build Coastguard Worker 
103*7688df22SAndroid Build Coastguard Worker 	/** Fence cookie for the block. */
104*7688df22SAndroid Build Coastguard Worker 	unsigned fence;		/* Split to read_fence, write_fence */
105*7688df22SAndroid Build Coastguard Worker 
106*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo *bo;
107*7688df22SAndroid Build Coastguard Worker 	void *virtual;
108*7688df22SAndroid Build Coastguard Worker };
109*7688df22SAndroid Build Coastguard Worker 
110*7688df22SAndroid Build Coastguard Worker typedef struct _bufmgr_fake {
111*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr bufmgr;
112*7688df22SAndroid Build Coastguard Worker 
113*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_t lock;
114*7688df22SAndroid Build Coastguard Worker 
115*7688df22SAndroid Build Coastguard Worker 	unsigned long low_offset;
116*7688df22SAndroid Build Coastguard Worker 	unsigned long size;
117*7688df22SAndroid Build Coastguard Worker 	void *virtual;
118*7688df22SAndroid Build Coastguard Worker 
119*7688df22SAndroid Build Coastguard Worker 	struct mem_block *heap;
120*7688df22SAndroid Build Coastguard Worker 
121*7688df22SAndroid Build Coastguard Worker 	unsigned buf_nr;	/* for generating ids */
122*7688df22SAndroid Build Coastguard Worker 
123*7688df22SAndroid Build Coastguard Worker 	/**
124*7688df22SAndroid Build Coastguard Worker 	 * List of blocks which are currently in the GART but haven't been
125*7688df22SAndroid Build Coastguard Worker 	 * fenced yet.
126*7688df22SAndroid Build Coastguard Worker 	 */
127*7688df22SAndroid Build Coastguard Worker 	struct block on_hardware;
128*7688df22SAndroid Build Coastguard Worker 	/**
129*7688df22SAndroid Build Coastguard Worker 	 * List of blocks which are in the GART and have an active fence on
130*7688df22SAndroid Build Coastguard Worker 	 * them.
131*7688df22SAndroid Build Coastguard Worker 	 */
132*7688df22SAndroid Build Coastguard Worker 	struct block fenced;
133*7688df22SAndroid Build Coastguard Worker 	/**
134*7688df22SAndroid Build Coastguard Worker 	 * List of blocks which have an expired fence and are ready to be
135*7688df22SAndroid Build Coastguard Worker 	 * evicted.
136*7688df22SAndroid Build Coastguard Worker 	 */
137*7688df22SAndroid Build Coastguard Worker 	struct block lru;
138*7688df22SAndroid Build Coastguard Worker 
139*7688df22SAndroid Build Coastguard Worker 	unsigned int last_fence;
140*7688df22SAndroid Build Coastguard Worker 
141*7688df22SAndroid Build Coastguard Worker 	unsigned fail:1;
142*7688df22SAndroid Build Coastguard Worker 	unsigned need_fence:1;
143*7688df22SAndroid Build Coastguard Worker 	int thrashing;
144*7688df22SAndroid Build Coastguard Worker 
145*7688df22SAndroid Build Coastguard Worker 	/**
146*7688df22SAndroid Build Coastguard Worker 	 * Driver callback to emit a fence, returning the cookie.
147*7688df22SAndroid Build Coastguard Worker 	 *
148*7688df22SAndroid Build Coastguard Worker 	 * This allows the driver to hook in a replacement for the DRM usage in
149*7688df22SAndroid Build Coastguard Worker 	 * bufmgr_fake.
150*7688df22SAndroid Build Coastguard Worker 	 *
151*7688df22SAndroid Build Coastguard Worker 	 * Currently, this also requires that a write flush be emitted before
152*7688df22SAndroid Build Coastguard Worker 	 * emitting the fence, but this should change.
153*7688df22SAndroid Build Coastguard Worker 	 */
154*7688df22SAndroid Build Coastguard Worker 	unsigned int (*fence_emit) (void *private);
155*7688df22SAndroid Build Coastguard Worker 	/** Driver callback to wait for a fence cookie to have passed. */
156*7688df22SAndroid Build Coastguard Worker 	void (*fence_wait) (unsigned int fence, void *private);
157*7688df22SAndroid Build Coastguard Worker 	void *fence_priv;
158*7688df22SAndroid Build Coastguard Worker 
159*7688df22SAndroid Build Coastguard Worker 	/**
160*7688df22SAndroid Build Coastguard Worker 	 * Driver callback to execute a buffer.
161*7688df22SAndroid Build Coastguard Worker 	 *
162*7688df22SAndroid Build Coastguard Worker 	 * This allows the driver to hook in a replacement for the DRM usage in
163*7688df22SAndroid Build Coastguard Worker 	 * bufmgr_fake.
164*7688df22SAndroid Build Coastguard Worker 	 */
165*7688df22SAndroid Build Coastguard Worker 	int (*exec) (drm_intel_bo *bo, unsigned int used, void *priv);
166*7688df22SAndroid Build Coastguard Worker 	void *exec_priv;
167*7688df22SAndroid Build Coastguard Worker 
168*7688df22SAndroid Build Coastguard Worker 	/** Driver-supplied argument to driver callbacks */
169*7688df22SAndroid Build Coastguard Worker 	void *driver_priv;
170*7688df22SAndroid Build Coastguard Worker 	/**
171*7688df22SAndroid Build Coastguard Worker 	 * Pointer to kernel-updated sarea data for the last completed user irq
172*7688df22SAndroid Build Coastguard Worker 	 */
173*7688df22SAndroid Build Coastguard Worker 	volatile int *last_dispatch;
174*7688df22SAndroid Build Coastguard Worker 
175*7688df22SAndroid Build Coastguard Worker 	int fd;
176*7688df22SAndroid Build Coastguard Worker 
177*7688df22SAndroid Build Coastguard Worker 	int debug;
178*7688df22SAndroid Build Coastguard Worker 
179*7688df22SAndroid Build Coastguard Worker 	int performed_rendering;
180*7688df22SAndroid Build Coastguard Worker } drm_intel_bufmgr_fake;
181*7688df22SAndroid Build Coastguard Worker 
182*7688df22SAndroid Build Coastguard Worker typedef struct _drm_intel_bo_fake {
183*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo bo;
184*7688df22SAndroid Build Coastguard Worker 
185*7688df22SAndroid Build Coastguard Worker 	unsigned id;		/* debug only */
186*7688df22SAndroid Build Coastguard Worker 	const char *name;
187*7688df22SAndroid Build Coastguard Worker 
188*7688df22SAndroid Build Coastguard Worker 	unsigned dirty:1;
189*7688df22SAndroid Build Coastguard Worker 	/**
190*7688df22SAndroid Build Coastguard Worker 	 * has the card written to this buffer - we make need to copy it back
191*7688df22SAndroid Build Coastguard Worker 	 */
192*7688df22SAndroid Build Coastguard Worker 	unsigned card_dirty:1;
193*7688df22SAndroid Build Coastguard Worker 	unsigned int refcount;
194*7688df22SAndroid Build Coastguard Worker 	/* Flags may consist of any of the DRM_BO flags, plus
195*7688df22SAndroid Build Coastguard Worker 	 * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the
196*7688df22SAndroid Build Coastguard Worker 	 * first two driver private flags.
197*7688df22SAndroid Build Coastguard Worker 	 */
198*7688df22SAndroid Build Coastguard Worker 	uint64_t flags;
199*7688df22SAndroid Build Coastguard Worker 	/** Cache domains the target buffer is read into. */
200*7688df22SAndroid Build Coastguard Worker 	uint32_t read_domains;
201*7688df22SAndroid Build Coastguard Worker 	/** Cache domain the target buffer will have dirty cachelines in. */
202*7688df22SAndroid Build Coastguard Worker 	uint32_t write_domain;
203*7688df22SAndroid Build Coastguard Worker 
204*7688df22SAndroid Build Coastguard Worker 	unsigned int alignment;
205*7688df22SAndroid Build Coastguard Worker 	int is_static, validated;
206*7688df22SAndroid Build Coastguard Worker 	unsigned int map_count;
207*7688df22SAndroid Build Coastguard Worker 
208*7688df22SAndroid Build Coastguard Worker 	/** relocation list */
209*7688df22SAndroid Build Coastguard Worker 	struct fake_buffer_reloc *relocs;
210*7688df22SAndroid Build Coastguard Worker 	int nr_relocs;
211*7688df22SAndroid Build Coastguard Worker 	/**
212*7688df22SAndroid Build Coastguard Worker 	 * Total size of the target_bos of this buffer.
213*7688df22SAndroid Build Coastguard Worker 	 *
214*7688df22SAndroid Build Coastguard Worker 	 * Used for estimation in check_aperture.
215*7688df22SAndroid Build Coastguard Worker 	 */
216*7688df22SAndroid Build Coastguard Worker 	unsigned int child_size;
217*7688df22SAndroid Build Coastguard Worker 
218*7688df22SAndroid Build Coastguard Worker 	struct block *block;
219*7688df22SAndroid Build Coastguard Worker 	void *backing_store;
220*7688df22SAndroid Build Coastguard Worker 	void (*invalidate_cb) (drm_intel_bo *bo, void *ptr);
221*7688df22SAndroid Build Coastguard Worker 	void *invalidate_ptr;
222*7688df22SAndroid Build Coastguard Worker } drm_intel_bo_fake;
223*7688df22SAndroid Build Coastguard Worker 
224*7688df22SAndroid Build Coastguard Worker static int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake,
225*7688df22SAndroid Build Coastguard Worker 			unsigned int fence_cookie);
226*7688df22SAndroid Build Coastguard Worker 
227*7688df22SAndroid Build Coastguard Worker #define MAXFENCE 0x7fffffff
228*7688df22SAndroid Build Coastguard Worker 
229*7688df22SAndroid Build Coastguard Worker static int
FENCE_LTE(unsigned a,unsigned b)230*7688df22SAndroid Build Coastguard Worker FENCE_LTE(unsigned a, unsigned b)
231*7688df22SAndroid Build Coastguard Worker {
232*7688df22SAndroid Build Coastguard Worker 	if (a == b)
233*7688df22SAndroid Build Coastguard Worker 		return 1;
234*7688df22SAndroid Build Coastguard Worker 
235*7688df22SAndroid Build Coastguard Worker 	if (a < b && b - a < (1 << 24))
236*7688df22SAndroid Build Coastguard Worker 		return 1;
237*7688df22SAndroid Build Coastguard Worker 
238*7688df22SAndroid Build Coastguard Worker 	if (a > b && MAXFENCE - a + b < (1 << 24))
239*7688df22SAndroid Build Coastguard Worker 		return 1;
240*7688df22SAndroid Build Coastguard Worker 
241*7688df22SAndroid Build Coastguard Worker 	return 0;
242*7688df22SAndroid Build Coastguard Worker }
243*7688df22SAndroid Build Coastguard Worker 
244*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr * bufmgr,unsigned int (* emit)(void * priv),void (* wait)(unsigned int fence,void * priv),void * priv)245*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr,
246*7688df22SAndroid Build Coastguard Worker 					 unsigned int (*emit) (void *priv),
247*7688df22SAndroid Build Coastguard Worker 					 void (*wait) (unsigned int fence,
248*7688df22SAndroid Build Coastguard Worker 						       void *priv),
249*7688df22SAndroid Build Coastguard Worker 					 void *priv)
250*7688df22SAndroid Build Coastguard Worker {
251*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
252*7688df22SAndroid Build Coastguard Worker 
253*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fence_emit = emit;
254*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fence_wait = wait;
255*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fence_priv = priv;
256*7688df22SAndroid Build Coastguard Worker }
257*7688df22SAndroid Build Coastguard Worker 
258*7688df22SAndroid Build Coastguard Worker static unsigned int
_fence_emit_internal(drm_intel_bufmgr_fake * bufmgr_fake)259*7688df22SAndroid Build Coastguard Worker _fence_emit_internal(drm_intel_bufmgr_fake *bufmgr_fake)
260*7688df22SAndroid Build Coastguard Worker {
261*7688df22SAndroid Build Coastguard Worker 	struct drm_i915_irq_emit ie;
262*7688df22SAndroid Build Coastguard Worker 	int ret, seq = 1;
263*7688df22SAndroid Build Coastguard Worker 
264*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->fence_emit != NULL) {
265*7688df22SAndroid Build Coastguard Worker 		seq = bufmgr_fake->fence_emit(bufmgr_fake->fence_priv);
266*7688df22SAndroid Build Coastguard Worker 		return seq;
267*7688df22SAndroid Build Coastguard Worker 	}
268*7688df22SAndroid Build Coastguard Worker 
269*7688df22SAndroid Build Coastguard Worker 	ie.irq_seq = &seq;
270*7688df22SAndroid Build Coastguard Worker 	ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT,
271*7688df22SAndroid Build Coastguard Worker 				  &ie, sizeof(ie));
272*7688df22SAndroid Build Coastguard Worker 	if (ret) {
273*7688df22SAndroid Build Coastguard Worker 		drmMsg("%s: drm_i915_irq_emit: %d\n", __func__, ret);
274*7688df22SAndroid Build Coastguard Worker 		abort();
275*7688df22SAndroid Build Coastguard Worker 	}
276*7688df22SAndroid Build Coastguard Worker 
277*7688df22SAndroid Build Coastguard Worker 	DBG("emit 0x%08x\n", seq);
278*7688df22SAndroid Build Coastguard Worker 	return seq;
279*7688df22SAndroid Build Coastguard Worker }
280*7688df22SAndroid Build Coastguard Worker 
281*7688df22SAndroid Build Coastguard Worker static void
_fence_wait_internal(drm_intel_bufmgr_fake * bufmgr_fake,int seq)282*7688df22SAndroid Build Coastguard Worker _fence_wait_internal(drm_intel_bufmgr_fake *bufmgr_fake, int seq)
283*7688df22SAndroid Build Coastguard Worker {
284*7688df22SAndroid Build Coastguard Worker 	struct drm_i915_irq_wait iw;
285*7688df22SAndroid Build Coastguard Worker 	int hw_seq, busy_count = 0;
286*7688df22SAndroid Build Coastguard Worker 	int ret;
287*7688df22SAndroid Build Coastguard Worker 	int kernel_lied;
288*7688df22SAndroid Build Coastguard Worker 
289*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->fence_wait != NULL) {
290*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->fence_wait(seq, bufmgr_fake->fence_priv);
291*7688df22SAndroid Build Coastguard Worker 		clear_fenced(bufmgr_fake, seq);
292*7688df22SAndroid Build Coastguard Worker 		return;
293*7688df22SAndroid Build Coastguard Worker 	}
294*7688df22SAndroid Build Coastguard Worker 
295*7688df22SAndroid Build Coastguard Worker 	iw.irq_seq = seq;
296*7688df22SAndroid Build Coastguard Worker 
297*7688df22SAndroid Build Coastguard Worker 	DBG("wait 0x%08x\n", iw.irq_seq);
298*7688df22SAndroid Build Coastguard Worker 
299*7688df22SAndroid Build Coastguard Worker 	/* The kernel IRQ_WAIT implementation is all sorts of broken.
300*7688df22SAndroid Build Coastguard Worker 	 * 1) It returns 1 to 0x7fffffff instead of using the full 32-bit
301*7688df22SAndroid Build Coastguard Worker 	 *    unsigned range.
302*7688df22SAndroid Build Coastguard Worker 	 * 2) It returns 0 if hw_seq >= seq, not seq - hw_seq < 0 on the 32-bit
303*7688df22SAndroid Build Coastguard Worker 	 *    signed range.
304*7688df22SAndroid Build Coastguard Worker 	 * 3) It waits if seq < hw_seq, not seq - hw_seq > 0 on the 32-bit
305*7688df22SAndroid Build Coastguard Worker 	 *    signed range.
306*7688df22SAndroid Build Coastguard Worker 	 * 4) It returns -EBUSY in 3 seconds even if the hardware is still
307*7688df22SAndroid Build Coastguard Worker 	 *    successfully chewing through buffers.
308*7688df22SAndroid Build Coastguard Worker 	 *
309*7688df22SAndroid Build Coastguard Worker 	 * Assume that in userland we treat sequence numbers as ints, which
310*7688df22SAndroid Build Coastguard Worker 	 * makes some of the comparisons convenient, since the sequence
311*7688df22SAndroid Build Coastguard Worker 	 * numbers are all positive signed integers.
312*7688df22SAndroid Build Coastguard Worker 	 *
313*7688df22SAndroid Build Coastguard Worker 	 * From this we get several cases we need to handle.  Here's a timeline.
314*7688df22SAndroid Build Coastguard Worker 	 * 0x2   0x7                                    0x7ffffff8   0x7ffffffd
315*7688df22SAndroid Build Coastguard Worker 	 *   |    |                                             |    |
316*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
317*7688df22SAndroid Build Coastguard Worker 	 *
318*7688df22SAndroid Build Coastguard Worker 	 * A) Normal wait for hw to catch up
319*7688df22SAndroid Build Coastguard Worker 	 * hw_seq seq
320*7688df22SAndroid Build Coastguard Worker 	 *   |    |
321*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
322*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = 5.  If we call IRQ_WAIT, it will wait for hw to
323*7688df22SAndroid Build Coastguard Worker 	 * catch up.
324*7688df22SAndroid Build Coastguard Worker 	 *
325*7688df22SAndroid Build Coastguard Worker 	 * B) Normal wait for a sequence number that's already passed.
326*7688df22SAndroid Build Coastguard Worker 	 * seq    hw_seq
327*7688df22SAndroid Build Coastguard Worker 	 *   |    |
328*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
329*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = -5.  If we call IRQ_WAIT, it returns 0 quickly.
330*7688df22SAndroid Build Coastguard Worker 	 *
331*7688df22SAndroid Build Coastguard Worker 	 * C) Hardware has already wrapped around ahead of us
332*7688df22SAndroid Build Coastguard Worker 	 * hw_seq                                                    seq
333*7688df22SAndroid Build Coastguard Worker 	 *   |                                                       |
334*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
335*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = 0x80000000 - 5.  If we called IRQ_WAIT, it would wait
336*7688df22SAndroid Build Coastguard Worker 	 * for hw_seq >= seq, which may never occur.  Thus, we want to catch
337*7688df22SAndroid Build Coastguard Worker 	 * this in userland and return 0.
338*7688df22SAndroid Build Coastguard Worker 	 *
339*7688df22SAndroid Build Coastguard Worker 	 * D) We've wrapped around ahead of the hardware.
340*7688df22SAndroid Build Coastguard Worker 	 * seq                                                      hw_seq
341*7688df22SAndroid Build Coastguard Worker 	 *   |                                                       |
342*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
343*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = -(0x80000000 - 5).  If we called IRQ_WAIT, it would
344*7688df22SAndroid Build Coastguard Worker 	 * return 0 quickly because hw_seq >= seq, even though the hardware
345*7688df22SAndroid Build Coastguard Worker 	 * isn't caught up. Thus, we need to catch this early return in
346*7688df22SAndroid Build Coastguard Worker 	 * userland and bother the kernel until the hardware really does
347*7688df22SAndroid Build Coastguard Worker 	 * catch up.
348*7688df22SAndroid Build Coastguard Worker 	 *
349*7688df22SAndroid Build Coastguard Worker 	 * E) Hardware might wrap after we test in userland.
350*7688df22SAndroid Build Coastguard Worker 	 *                                                  hw_seq  seq
351*7688df22SAndroid Build Coastguard Worker 	 *                                                      |    |
352*7688df22SAndroid Build Coastguard Worker 	 * ------------------------------------------------------------
353*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = 5.  If we call IRQ_WAIT, it will likely see seq >=
354*7688df22SAndroid Build Coastguard Worker 	 * hw_seq and wait.  However, suppose hw_seq wraps before we make it
355*7688df22SAndroid Build Coastguard Worker 	 * into the kernel.  The kernel sees hw_seq >= seq and waits for 3
356*7688df22SAndroid Build Coastguard Worker 	 * seconds then returns -EBUSY.  This is case C).  We should catch
357*7688df22SAndroid Build Coastguard Worker 	 * this and then return successfully.
358*7688df22SAndroid Build Coastguard Worker 	 *
359*7688df22SAndroid Build Coastguard Worker 	 * F) Hardware might take a long time on a buffer.
360*7688df22SAndroid Build Coastguard Worker 	 * hw_seq seq
361*7688df22SAndroid Build Coastguard Worker 	 *   |    |
362*7688df22SAndroid Build Coastguard Worker 	 * -------------------------------------------------------------------
363*7688df22SAndroid Build Coastguard Worker 	 * seq - hw_seq = 5.  If we call IRQ_WAIT, if sequence 2 through 5
364*7688df22SAndroid Build Coastguard Worker 	 * take too long, it will return -EBUSY.  Batchbuffers in the
365*7688df22SAndroid Build Coastguard Worker 	 * gltestperf demo were seen to take up to 7 seconds.  We should
366*7688df22SAndroid Build Coastguard Worker 	 * catch early -EBUSY return and keep trying.
367*7688df22SAndroid Build Coastguard Worker 	 */
368*7688df22SAndroid Build Coastguard Worker 
369*7688df22SAndroid Build Coastguard Worker 	do {
370*7688df22SAndroid Build Coastguard Worker 		/* Keep a copy of last_dispatch so that if the wait -EBUSYs
371*7688df22SAndroid Build Coastguard Worker 		 * because the hardware didn't catch up in 3 seconds, we can
372*7688df22SAndroid Build Coastguard Worker 		 * see if it at least made progress and retry.
373*7688df22SAndroid Build Coastguard Worker 		 */
374*7688df22SAndroid Build Coastguard Worker 		hw_seq = *bufmgr_fake->last_dispatch;
375*7688df22SAndroid Build Coastguard Worker 
376*7688df22SAndroid Build Coastguard Worker 		/* Catch case C */
377*7688df22SAndroid Build Coastguard Worker 		if (seq - hw_seq > 0x40000000)
378*7688df22SAndroid Build Coastguard Worker 			return;
379*7688df22SAndroid Build Coastguard Worker 
380*7688df22SAndroid Build Coastguard Worker 		ret = drmCommandWrite(bufmgr_fake->fd, DRM_I915_IRQ_WAIT,
381*7688df22SAndroid Build Coastguard Worker 				      &iw, sizeof(iw));
382*7688df22SAndroid Build Coastguard Worker 		/* Catch case D */
383*7688df22SAndroid Build Coastguard Worker 		kernel_lied = (ret == 0) && (seq - *bufmgr_fake->last_dispatch <
384*7688df22SAndroid Build Coastguard Worker 					     -0x40000000);
385*7688df22SAndroid Build Coastguard Worker 
386*7688df22SAndroid Build Coastguard Worker 		/* Catch case E */
387*7688df22SAndroid Build Coastguard Worker 		if (ret == -EBUSY
388*7688df22SAndroid Build Coastguard Worker 		    && (seq - *bufmgr_fake->last_dispatch > 0x40000000))
389*7688df22SAndroid Build Coastguard Worker 			ret = 0;
390*7688df22SAndroid Build Coastguard Worker 
391*7688df22SAndroid Build Coastguard Worker 		/* Catch case F: Allow up to 15 seconds chewing on one buffer. */
392*7688df22SAndroid Build Coastguard Worker 		if ((ret == -EBUSY) && (hw_seq != *bufmgr_fake->last_dispatch))
393*7688df22SAndroid Build Coastguard Worker 			busy_count = 0;
394*7688df22SAndroid Build Coastguard Worker 		else
395*7688df22SAndroid Build Coastguard Worker 			busy_count++;
396*7688df22SAndroid Build Coastguard Worker 	} while (kernel_lied || ret == -EAGAIN || ret == -EINTR ||
397*7688df22SAndroid Build Coastguard Worker 		 (ret == -EBUSY && busy_count < 5));
398*7688df22SAndroid Build Coastguard Worker 
399*7688df22SAndroid Build Coastguard Worker 	if (ret != 0) {
400*7688df22SAndroid Build Coastguard Worker 		drmMsg("%s:%d: Error waiting for fence: %s.\n", __FILE__,
401*7688df22SAndroid Build Coastguard Worker 		       __LINE__, strerror(-ret));
402*7688df22SAndroid Build Coastguard Worker 		abort();
403*7688df22SAndroid Build Coastguard Worker 	}
404*7688df22SAndroid Build Coastguard Worker 	clear_fenced(bufmgr_fake, seq);
405*7688df22SAndroid Build Coastguard Worker }
406*7688df22SAndroid Build Coastguard Worker 
407*7688df22SAndroid Build Coastguard Worker static int
_fence_test(drm_intel_bufmgr_fake * bufmgr_fake,unsigned fence)408*7688df22SAndroid Build Coastguard Worker _fence_test(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)
409*7688df22SAndroid Build Coastguard Worker {
410*7688df22SAndroid Build Coastguard Worker 	/* Slight problem with wrap-around:
411*7688df22SAndroid Build Coastguard Worker 	 */
412*7688df22SAndroid Build Coastguard Worker 	return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence);
413*7688df22SAndroid Build Coastguard Worker }
414*7688df22SAndroid Build Coastguard Worker 
415*7688df22SAndroid Build Coastguard Worker /**
416*7688df22SAndroid Build Coastguard Worker  * Allocate a memory manager block for the buffer.
417*7688df22SAndroid Build Coastguard Worker  */
418*7688df22SAndroid Build Coastguard Worker static int
alloc_block(drm_intel_bo * bo)419*7688df22SAndroid Build Coastguard Worker alloc_block(drm_intel_bo *bo)
420*7688df22SAndroid Build Coastguard Worker {
421*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
422*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
423*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
424*7688df22SAndroid Build Coastguard Worker 	struct block *block = (struct block *)calloc(sizeof *block, 1);
425*7688df22SAndroid Build Coastguard Worker 	unsigned int align_log2 = ffs(bo_fake->alignment) - 1;
426*7688df22SAndroid Build Coastguard Worker 	unsigned int sz;
427*7688df22SAndroid Build Coastguard Worker 
428*7688df22SAndroid Build Coastguard Worker 	if (!block)
429*7688df22SAndroid Build Coastguard Worker 		return 1;
430*7688df22SAndroid Build Coastguard Worker 
431*7688df22SAndroid Build Coastguard Worker 	sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1);
432*7688df22SAndroid Build Coastguard Worker 
433*7688df22SAndroid Build Coastguard Worker 	block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0);
434*7688df22SAndroid Build Coastguard Worker 	if (!block->mem) {
435*7688df22SAndroid Build Coastguard Worker 		free(block);
436*7688df22SAndroid Build Coastguard Worker 		return 0;
437*7688df22SAndroid Build Coastguard Worker 	}
438*7688df22SAndroid Build Coastguard Worker 
439*7688df22SAndroid Build Coastguard Worker 	DRMINITLISTHEAD(block);
440*7688df22SAndroid Build Coastguard Worker 
441*7688df22SAndroid Build Coastguard Worker 	/* Insert at head or at tail??? */
442*7688df22SAndroid Build Coastguard Worker 	DRMLISTADDTAIL(block, &bufmgr_fake->lru);
443*7688df22SAndroid Build Coastguard Worker 
444*7688df22SAndroid Build Coastguard Worker 	block->virtual = (uint8_t *) bufmgr_fake->virtual +
445*7688df22SAndroid Build Coastguard Worker 	    block->mem->ofs - bufmgr_fake->low_offset;
446*7688df22SAndroid Build Coastguard Worker 	block->bo = bo;
447*7688df22SAndroid Build Coastguard Worker 
448*7688df22SAndroid Build Coastguard Worker 	bo_fake->block = block;
449*7688df22SAndroid Build Coastguard Worker 
450*7688df22SAndroid Build Coastguard Worker 	return 1;
451*7688df22SAndroid Build Coastguard Worker }
452*7688df22SAndroid Build Coastguard Worker 
453*7688df22SAndroid Build Coastguard Worker /* Release the card storage associated with buf:
454*7688df22SAndroid Build Coastguard Worker  */
455*7688df22SAndroid Build Coastguard Worker static void
free_block(drm_intel_bufmgr_fake * bufmgr_fake,struct block * block,int skip_dirty_copy)456*7688df22SAndroid Build Coastguard Worker free_block(drm_intel_bufmgr_fake *bufmgr_fake, struct block *block,
457*7688df22SAndroid Build Coastguard Worker 	   int skip_dirty_copy)
458*7688df22SAndroid Build Coastguard Worker {
459*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake;
460*7688df22SAndroid Build Coastguard Worker 	DBG("free block %p %08x %d %d\n", block, block->mem->ofs,
461*7688df22SAndroid Build Coastguard Worker 	    block->on_hardware, block->fenced);
462*7688df22SAndroid Build Coastguard Worker 
463*7688df22SAndroid Build Coastguard Worker 	if (!block)
464*7688df22SAndroid Build Coastguard Worker 		return;
465*7688df22SAndroid Build Coastguard Worker 
466*7688df22SAndroid Build Coastguard Worker 	bo_fake = (drm_intel_bo_fake *) block->bo;
467*7688df22SAndroid Build Coastguard Worker 
468*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))
469*7688df22SAndroid Build Coastguard Worker 		skip_dirty_copy = 1;
470*7688df22SAndroid Build Coastguard Worker 
471*7688df22SAndroid Build Coastguard Worker 	if (!skip_dirty_copy && (bo_fake->card_dirty == 1)) {
472*7688df22SAndroid Build Coastguard Worker 		memcpy(bo_fake->backing_store, block->virtual, block->bo->size);
473*7688df22SAndroid Build Coastguard Worker 		bo_fake->card_dirty = 0;
474*7688df22SAndroid Build Coastguard Worker 		bo_fake->dirty = 1;
475*7688df22SAndroid Build Coastguard Worker 	}
476*7688df22SAndroid Build Coastguard Worker 
477*7688df22SAndroid Build Coastguard Worker 	if (block->on_hardware) {
478*7688df22SAndroid Build Coastguard Worker 		block->bo = NULL;
479*7688df22SAndroid Build Coastguard Worker 	} else if (block->fenced) {
480*7688df22SAndroid Build Coastguard Worker 		block->bo = NULL;
481*7688df22SAndroid Build Coastguard Worker 	} else {
482*7688df22SAndroid Build Coastguard Worker 		DBG("    - free immediately\n");
483*7688df22SAndroid Build Coastguard Worker 		DRMLISTDEL(block);
484*7688df22SAndroid Build Coastguard Worker 
485*7688df22SAndroid Build Coastguard Worker 		mmFreeMem(block->mem);
486*7688df22SAndroid Build Coastguard Worker 		free(block);
487*7688df22SAndroid Build Coastguard Worker 	}
488*7688df22SAndroid Build Coastguard Worker }
489*7688df22SAndroid Build Coastguard Worker 
490*7688df22SAndroid Build Coastguard Worker static void
alloc_backing_store(drm_intel_bo * bo)491*7688df22SAndroid Build Coastguard Worker alloc_backing_store(drm_intel_bo *bo)
492*7688df22SAndroid Build Coastguard Worker {
493*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
494*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
495*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
496*7688df22SAndroid Build Coastguard Worker 	assert(!bo_fake->backing_store);
497*7688df22SAndroid Build Coastguard Worker 	assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)));
498*7688df22SAndroid Build Coastguard Worker 
499*7688df22SAndroid Build Coastguard Worker 	bo_fake->backing_store = malloc(bo->size);
500*7688df22SAndroid Build Coastguard Worker 
501*7688df22SAndroid Build Coastguard Worker 	DBG("alloc_backing - buf %d %p %lu\n", bo_fake->id,
502*7688df22SAndroid Build Coastguard Worker 	    bo_fake->backing_store, bo->size);
503*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->backing_store);
504*7688df22SAndroid Build Coastguard Worker }
505*7688df22SAndroid Build Coastguard Worker 
506*7688df22SAndroid Build Coastguard Worker static void
free_backing_store(drm_intel_bo * bo)507*7688df22SAndroid Build Coastguard Worker free_backing_store(drm_intel_bo *bo)
508*7688df22SAndroid Build Coastguard Worker {
509*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
510*7688df22SAndroid Build Coastguard Worker 
511*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->backing_store) {
512*7688df22SAndroid Build Coastguard Worker 		assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)));
513*7688df22SAndroid Build Coastguard Worker 		free(bo_fake->backing_store);
514*7688df22SAndroid Build Coastguard Worker 		bo_fake->backing_store = NULL;
515*7688df22SAndroid Build Coastguard Worker 	}
516*7688df22SAndroid Build Coastguard Worker }
517*7688df22SAndroid Build Coastguard Worker 
518*7688df22SAndroid Build Coastguard Worker static void
set_dirty(drm_intel_bo * bo)519*7688df22SAndroid Build Coastguard Worker set_dirty(drm_intel_bo *bo)
520*7688df22SAndroid Build Coastguard Worker {
521*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
522*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
523*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
524*7688df22SAndroid Build Coastguard Worker 
525*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->flags & BM_NO_BACKING_STORE
526*7688df22SAndroid Build Coastguard Worker 	    && bo_fake->invalidate_cb != NULL)
527*7688df22SAndroid Build Coastguard Worker 		bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr);
528*7688df22SAndroid Build Coastguard Worker 
529*7688df22SAndroid Build Coastguard Worker 	assert(!(bo_fake->flags & BM_PINNED));
530*7688df22SAndroid Build Coastguard Worker 
531*7688df22SAndroid Build Coastguard Worker 	DBG("set_dirty - buf %d\n", bo_fake->id);
532*7688df22SAndroid Build Coastguard Worker 	bo_fake->dirty = 1;
533*7688df22SAndroid Build Coastguard Worker }
534*7688df22SAndroid Build Coastguard Worker 
535*7688df22SAndroid Build Coastguard Worker static int
evict_lru(drm_intel_bufmgr_fake * bufmgr_fake,unsigned int max_fence)536*7688df22SAndroid Build Coastguard Worker evict_lru(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int max_fence)
537*7688df22SAndroid Build Coastguard Worker {
538*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
539*7688df22SAndroid Build Coastguard Worker 
540*7688df22SAndroid Build Coastguard Worker 	DBG("%s\n", __func__);
541*7688df22SAndroid Build Coastguard Worker 
542*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
543*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
544*7688df22SAndroid Build Coastguard Worker 
545*7688df22SAndroid Build Coastguard Worker 		if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
546*7688df22SAndroid Build Coastguard Worker 			continue;
547*7688df22SAndroid Build Coastguard Worker 
548*7688df22SAndroid Build Coastguard Worker 		if (block->fence && max_fence && !FENCE_LTE(block->fence,
549*7688df22SAndroid Build Coastguard Worker 							    max_fence))
550*7688df22SAndroid Build Coastguard Worker 			return 0;
551*7688df22SAndroid Build Coastguard Worker 
552*7688df22SAndroid Build Coastguard Worker 		set_dirty(&bo_fake->bo);
553*7688df22SAndroid Build Coastguard Worker 		bo_fake->block = NULL;
554*7688df22SAndroid Build Coastguard Worker 
555*7688df22SAndroid Build Coastguard Worker 		free_block(bufmgr_fake, block, 0);
556*7688df22SAndroid Build Coastguard Worker 		return 1;
557*7688df22SAndroid Build Coastguard Worker 	}
558*7688df22SAndroid Build Coastguard Worker 
559*7688df22SAndroid Build Coastguard Worker 	return 0;
560*7688df22SAndroid Build Coastguard Worker }
561*7688df22SAndroid Build Coastguard Worker 
562*7688df22SAndroid Build Coastguard Worker static int
evict_mru(drm_intel_bufmgr_fake * bufmgr_fake)563*7688df22SAndroid Build Coastguard Worker evict_mru(drm_intel_bufmgr_fake *bufmgr_fake)
564*7688df22SAndroid Build Coastguard Worker {
565*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
566*7688df22SAndroid Build Coastguard Worker 
567*7688df22SAndroid Build Coastguard Worker 	DBG("%s\n", __func__);
568*7688df22SAndroid Build Coastguard Worker 
569*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFEREVERSE(block, tmp, &bufmgr_fake->lru) {
570*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
571*7688df22SAndroid Build Coastguard Worker 
572*7688df22SAndroid Build Coastguard Worker 		if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
573*7688df22SAndroid Build Coastguard Worker 			continue;
574*7688df22SAndroid Build Coastguard Worker 
575*7688df22SAndroid Build Coastguard Worker 		set_dirty(&bo_fake->bo);
576*7688df22SAndroid Build Coastguard Worker 		bo_fake->block = NULL;
577*7688df22SAndroid Build Coastguard Worker 
578*7688df22SAndroid Build Coastguard Worker 		free_block(bufmgr_fake, block, 0);
579*7688df22SAndroid Build Coastguard Worker 		return 1;
580*7688df22SAndroid Build Coastguard Worker 	}
581*7688df22SAndroid Build Coastguard Worker 
582*7688df22SAndroid Build Coastguard Worker 	return 0;
583*7688df22SAndroid Build Coastguard Worker }
584*7688df22SAndroid Build Coastguard Worker 
585*7688df22SAndroid Build Coastguard Worker /**
586*7688df22SAndroid Build Coastguard Worker  * Removes all objects from the fenced list older than the given fence.
587*7688df22SAndroid Build Coastguard Worker  */
588*7688df22SAndroid Build Coastguard Worker static int
clear_fenced(drm_intel_bufmgr_fake * bufmgr_fake,unsigned int fence_cookie)589*7688df22SAndroid Build Coastguard Worker clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int fence_cookie)
590*7688df22SAndroid Build Coastguard Worker {
591*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
592*7688df22SAndroid Build Coastguard Worker 	int ret = 0;
593*7688df22SAndroid Build Coastguard Worker 
594*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->last_fence = fence_cookie;
595*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->fenced) {
596*7688df22SAndroid Build Coastguard Worker 		assert(block->fenced);
597*7688df22SAndroid Build Coastguard Worker 
598*7688df22SAndroid Build Coastguard Worker 		if (_fence_test(bufmgr_fake, block->fence)) {
599*7688df22SAndroid Build Coastguard Worker 
600*7688df22SAndroid Build Coastguard Worker 			block->fenced = 0;
601*7688df22SAndroid Build Coastguard Worker 
602*7688df22SAndroid Build Coastguard Worker 			if (!block->bo) {
603*7688df22SAndroid Build Coastguard Worker 				DBG("delayed free: offset %x sz %x\n",
604*7688df22SAndroid Build Coastguard Worker 				    block->mem->ofs, block->mem->size);
605*7688df22SAndroid Build Coastguard Worker 				DRMLISTDEL(block);
606*7688df22SAndroid Build Coastguard Worker 				mmFreeMem(block->mem);
607*7688df22SAndroid Build Coastguard Worker 				free(block);
608*7688df22SAndroid Build Coastguard Worker 			} else {
609*7688df22SAndroid Build Coastguard Worker 				DBG("return to lru: offset %x sz %x\n",
610*7688df22SAndroid Build Coastguard Worker 				    block->mem->ofs, block->mem->size);
611*7688df22SAndroid Build Coastguard Worker 				DRMLISTDEL(block);
612*7688df22SAndroid Build Coastguard Worker 				DRMLISTADDTAIL(block, &bufmgr_fake->lru);
613*7688df22SAndroid Build Coastguard Worker 			}
614*7688df22SAndroid Build Coastguard Worker 
615*7688df22SAndroid Build Coastguard Worker 			ret = 1;
616*7688df22SAndroid Build Coastguard Worker 		} else {
617*7688df22SAndroid Build Coastguard Worker 			/* Blocks are ordered by fence, so if one fails, all
618*7688df22SAndroid Build Coastguard Worker 			 * from here will fail also:
619*7688df22SAndroid Build Coastguard Worker 			 */
620*7688df22SAndroid Build Coastguard Worker 			DBG("fence not passed: offset %x sz %x %d %d \n",
621*7688df22SAndroid Build Coastguard Worker 			    block->mem->ofs, block->mem->size, block->fence,
622*7688df22SAndroid Build Coastguard Worker 			    bufmgr_fake->last_fence);
623*7688df22SAndroid Build Coastguard Worker 			break;
624*7688df22SAndroid Build Coastguard Worker 		}
625*7688df22SAndroid Build Coastguard Worker 	}
626*7688df22SAndroid Build Coastguard Worker 
627*7688df22SAndroid Build Coastguard Worker 	DBG("%s: %d\n", __func__, ret);
628*7688df22SAndroid Build Coastguard Worker 	return ret;
629*7688df22SAndroid Build Coastguard Worker }
630*7688df22SAndroid Build Coastguard Worker 
631*7688df22SAndroid Build Coastguard Worker static void
fence_blocks(drm_intel_bufmgr_fake * bufmgr_fake,unsigned fence)632*7688df22SAndroid Build Coastguard Worker fence_blocks(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)
633*7688df22SAndroid Build Coastguard Worker {
634*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
635*7688df22SAndroid Build Coastguard Worker 
636*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) {
637*7688df22SAndroid Build Coastguard Worker 		DBG("Fence block %p (sz 0x%x ofs %x buf %p) with fence %d\n",
638*7688df22SAndroid Build Coastguard Worker 		    block, block->mem->size, block->mem->ofs, block->bo, fence);
639*7688df22SAndroid Build Coastguard Worker 		block->fence = fence;
640*7688df22SAndroid Build Coastguard Worker 
641*7688df22SAndroid Build Coastguard Worker 		block->on_hardware = 0;
642*7688df22SAndroid Build Coastguard Worker 		block->fenced = 1;
643*7688df22SAndroid Build Coastguard Worker 
644*7688df22SAndroid Build Coastguard Worker 		/* Move to tail of pending list here
645*7688df22SAndroid Build Coastguard Worker 		 */
646*7688df22SAndroid Build Coastguard Worker 		DRMLISTDEL(block);
647*7688df22SAndroid Build Coastguard Worker 		DRMLISTADDTAIL(block, &bufmgr_fake->fenced);
648*7688df22SAndroid Build Coastguard Worker 	}
649*7688df22SAndroid Build Coastguard Worker 
650*7688df22SAndroid Build Coastguard Worker 	assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
651*7688df22SAndroid Build Coastguard Worker }
652*7688df22SAndroid Build Coastguard Worker 
653*7688df22SAndroid Build Coastguard Worker static int
evict_and_alloc_block(drm_intel_bo * bo)654*7688df22SAndroid Build Coastguard Worker evict_and_alloc_block(drm_intel_bo *bo)
655*7688df22SAndroid Build Coastguard Worker {
656*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
657*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
658*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
659*7688df22SAndroid Build Coastguard Worker 
660*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->block == NULL);
661*7688df22SAndroid Build Coastguard Worker 
662*7688df22SAndroid Build Coastguard Worker 	/* Search for already free memory:
663*7688df22SAndroid Build Coastguard Worker 	 */
664*7688df22SAndroid Build Coastguard Worker 	if (alloc_block(bo))
665*7688df22SAndroid Build Coastguard Worker 		return 1;
666*7688df22SAndroid Build Coastguard Worker 
667*7688df22SAndroid Build Coastguard Worker 	/* If we're not thrashing, allow lru eviction to dig deeper into
668*7688df22SAndroid Build Coastguard Worker 	 * recently used textures.  We'll probably be thrashing soon:
669*7688df22SAndroid Build Coastguard Worker 	 */
670*7688df22SAndroid Build Coastguard Worker 	if (!bufmgr_fake->thrashing) {
671*7688df22SAndroid Build Coastguard Worker 		while (evict_lru(bufmgr_fake, 0))
672*7688df22SAndroid Build Coastguard Worker 			if (alloc_block(bo))
673*7688df22SAndroid Build Coastguard Worker 				return 1;
674*7688df22SAndroid Build Coastguard Worker 	}
675*7688df22SAndroid Build Coastguard Worker 
676*7688df22SAndroid Build Coastguard Worker 	/* Keep thrashing counter alive?
677*7688df22SAndroid Build Coastguard Worker 	 */
678*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->thrashing)
679*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->thrashing = 20;
680*7688df22SAndroid Build Coastguard Worker 
681*7688df22SAndroid Build Coastguard Worker 	/* Wait on any already pending fences - here we are waiting for any
682*7688df22SAndroid Build Coastguard Worker 	 * freed memory that has been submitted to hardware and fenced to
683*7688df22SAndroid Build Coastguard Worker 	 * become available:
684*7688df22SAndroid Build Coastguard Worker 	 */
685*7688df22SAndroid Build Coastguard Worker 	while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) {
686*7688df22SAndroid Build Coastguard Worker 		uint32_t fence = bufmgr_fake->fenced.next->fence;
687*7688df22SAndroid Build Coastguard Worker 		_fence_wait_internal(bufmgr_fake, fence);
688*7688df22SAndroid Build Coastguard Worker 
689*7688df22SAndroid Build Coastguard Worker 		if (alloc_block(bo))
690*7688df22SAndroid Build Coastguard Worker 			return 1;
691*7688df22SAndroid Build Coastguard Worker 	}
692*7688df22SAndroid Build Coastguard Worker 
693*7688df22SAndroid Build Coastguard Worker 	if (!DRMLISTEMPTY(&bufmgr_fake->on_hardware)) {
694*7688df22SAndroid Build Coastguard Worker 		while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) {
695*7688df22SAndroid Build Coastguard Worker 			uint32_t fence = bufmgr_fake->fenced.next->fence;
696*7688df22SAndroid Build Coastguard Worker 			_fence_wait_internal(bufmgr_fake, fence);
697*7688df22SAndroid Build Coastguard Worker 		}
698*7688df22SAndroid Build Coastguard Worker 
699*7688df22SAndroid Build Coastguard Worker 		if (!bufmgr_fake->thrashing) {
700*7688df22SAndroid Build Coastguard Worker 			DBG("thrashing\n");
701*7688df22SAndroid Build Coastguard Worker 		}
702*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->thrashing = 20;
703*7688df22SAndroid Build Coastguard Worker 
704*7688df22SAndroid Build Coastguard Worker 		if (alloc_block(bo))
705*7688df22SAndroid Build Coastguard Worker 			return 1;
706*7688df22SAndroid Build Coastguard Worker 	}
707*7688df22SAndroid Build Coastguard Worker 
708*7688df22SAndroid Build Coastguard Worker 	while (evict_mru(bufmgr_fake))
709*7688df22SAndroid Build Coastguard Worker 		if (alloc_block(bo))
710*7688df22SAndroid Build Coastguard Worker 			return 1;
711*7688df22SAndroid Build Coastguard Worker 
712*7688df22SAndroid Build Coastguard Worker 	DBG("%s 0x%lx bytes failed\n", __func__, bo->size);
713*7688df22SAndroid Build Coastguard Worker 
714*7688df22SAndroid Build Coastguard Worker 	return 0;
715*7688df22SAndroid Build Coastguard Worker }
716*7688df22SAndroid Build Coastguard Worker 
717*7688df22SAndroid Build Coastguard Worker /***********************************************************************
718*7688df22SAndroid Build Coastguard Worker  * Public functions
719*7688df22SAndroid Build Coastguard Worker  */
720*7688df22SAndroid Build Coastguard Worker 
721*7688df22SAndroid Build Coastguard Worker /**
722*7688df22SAndroid Build Coastguard Worker  * Wait for hardware idle by emitting a fence and waiting for it.
723*7688df22SAndroid Build Coastguard Worker  */
724*7688df22SAndroid Build Coastguard Worker static void
drm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake * bufmgr_fake)725*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake *bufmgr_fake)
726*7688df22SAndroid Build Coastguard Worker {
727*7688df22SAndroid Build Coastguard Worker 	unsigned int cookie;
728*7688df22SAndroid Build Coastguard Worker 
729*7688df22SAndroid Build Coastguard Worker 	cookie = _fence_emit_internal(bufmgr_fake);
730*7688df22SAndroid Build Coastguard Worker 	_fence_wait_internal(bufmgr_fake, cookie);
731*7688df22SAndroid Build Coastguard Worker }
732*7688df22SAndroid Build Coastguard Worker 
733*7688df22SAndroid Build Coastguard Worker /**
734*7688df22SAndroid Build Coastguard Worker  * Wait for rendering to a buffer to complete.
735*7688df22SAndroid Build Coastguard Worker  *
736*7688df22SAndroid Build Coastguard Worker  * It is assumed that the batchbuffer which performed the rendering included
737*7688df22SAndroid Build Coastguard Worker  * the necessary flushing.
738*7688df22SAndroid Build Coastguard Worker  */
739*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_wait_rendering_locked(drm_intel_bo * bo)740*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_wait_rendering_locked(drm_intel_bo *bo)
741*7688df22SAndroid Build Coastguard Worker {
742*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
743*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
744*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
745*7688df22SAndroid Build Coastguard Worker 
746*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->block == NULL || !bo_fake->block->fenced)
747*7688df22SAndroid Build Coastguard Worker 		return;
748*7688df22SAndroid Build Coastguard Worker 
749*7688df22SAndroid Build Coastguard Worker 	_fence_wait_internal(bufmgr_fake, bo_fake->block->fence);
750*7688df22SAndroid Build Coastguard Worker }
751*7688df22SAndroid Build Coastguard Worker 
752*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_wait_rendering(drm_intel_bo * bo)753*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_wait_rendering(drm_intel_bo *bo)
754*7688df22SAndroid Build Coastguard Worker {
755*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
756*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
757*7688df22SAndroid Build Coastguard Worker 
758*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
759*7688df22SAndroid Build Coastguard Worker 	drm_intel_fake_bo_wait_rendering_locked(bo);
760*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
761*7688df22SAndroid Build Coastguard Worker }
762*7688df22SAndroid Build Coastguard Worker 
763*7688df22SAndroid Build Coastguard Worker /* Specifically ignore texture memory sharing.
764*7688df22SAndroid Build Coastguard Worker  *  -- just evict everything
765*7688df22SAndroid Build Coastguard Worker  *  -- and wait for idle
766*7688df22SAndroid Build Coastguard Worker  */
767*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr * bufmgr)768*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr)
769*7688df22SAndroid Build Coastguard Worker {
770*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
771*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
772*7688df22SAndroid Build Coastguard Worker 
773*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
774*7688df22SAndroid Build Coastguard Worker 
775*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->need_fence = 1;
776*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fail = 0;
777*7688df22SAndroid Build Coastguard Worker 
778*7688df22SAndroid Build Coastguard Worker 	/* Wait for hardware idle.  We don't know where acceleration has been
779*7688df22SAndroid Build Coastguard Worker 	 * happening, so we'll need to wait anyway before letting anything get
780*7688df22SAndroid Build Coastguard Worker 	 * put on the card again.
781*7688df22SAndroid Build Coastguard Worker 	 */
782*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
783*7688df22SAndroid Build Coastguard Worker 
784*7688df22SAndroid Build Coastguard Worker 	/* Check that we hadn't released the lock without having fenced the last
785*7688df22SAndroid Build Coastguard Worker 	 * set of buffers.
786*7688df22SAndroid Build Coastguard Worker 	 */
787*7688df22SAndroid Build Coastguard Worker 	assert(DRMLISTEMPTY(&bufmgr_fake->fenced));
788*7688df22SAndroid Build Coastguard Worker 	assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
789*7688df22SAndroid Build Coastguard Worker 
790*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
791*7688df22SAndroid Build Coastguard Worker 		assert(_fence_test(bufmgr_fake, block->fence));
792*7688df22SAndroid Build Coastguard Worker 		set_dirty(block->bo);
793*7688df22SAndroid Build Coastguard Worker 	}
794*7688df22SAndroid Build Coastguard Worker 
795*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
796*7688df22SAndroid Build Coastguard Worker }
797*7688df22SAndroid Build Coastguard Worker 
798*7688df22SAndroid Build Coastguard Worker static drm_intel_bo *
drm_intel_fake_bo_alloc(drm_intel_bufmgr * bufmgr,const char * name,unsigned long size,unsigned int alignment)799*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_alloc(drm_intel_bufmgr *bufmgr,
800*7688df22SAndroid Build Coastguard Worker 			const char *name,
801*7688df22SAndroid Build Coastguard Worker 			unsigned long size,
802*7688df22SAndroid Build Coastguard Worker 			unsigned int alignment)
803*7688df22SAndroid Build Coastguard Worker {
804*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake;
805*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake;
806*7688df22SAndroid Build Coastguard Worker 
807*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
808*7688df22SAndroid Build Coastguard Worker 
809*7688df22SAndroid Build Coastguard Worker 	assert(size != 0);
810*7688df22SAndroid Build Coastguard Worker 
811*7688df22SAndroid Build Coastguard Worker 	bo_fake = calloc(1, sizeof(*bo_fake));
812*7688df22SAndroid Build Coastguard Worker 	if (!bo_fake)
813*7688df22SAndroid Build Coastguard Worker 		return NULL;
814*7688df22SAndroid Build Coastguard Worker 
815*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.size = size;
816*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.offset = -1;
817*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.virtual = NULL;
818*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.bufmgr = bufmgr;
819*7688df22SAndroid Build Coastguard Worker 	bo_fake->refcount = 1;
820*7688df22SAndroid Build Coastguard Worker 
821*7688df22SAndroid Build Coastguard Worker 	/* Alignment must be a power of two */
822*7688df22SAndroid Build Coastguard Worker 	assert((alignment & (alignment - 1)) == 0);
823*7688df22SAndroid Build Coastguard Worker 	if (alignment == 0)
824*7688df22SAndroid Build Coastguard Worker 		alignment = 1;
825*7688df22SAndroid Build Coastguard Worker 	bo_fake->alignment = alignment;
826*7688df22SAndroid Build Coastguard Worker 	bo_fake->id = ++bufmgr_fake->buf_nr;
827*7688df22SAndroid Build Coastguard Worker 	bo_fake->name = name;
828*7688df22SAndroid Build Coastguard Worker 	bo_fake->flags = 0;
829*7688df22SAndroid Build Coastguard Worker 	bo_fake->is_static = 0;
830*7688df22SAndroid Build Coastguard Worker 
831*7688df22SAndroid Build Coastguard Worker 	DBG("drm_bo_alloc: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name,
832*7688df22SAndroid Build Coastguard Worker 	    bo_fake->bo.size / 1024);
833*7688df22SAndroid Build Coastguard Worker 
834*7688df22SAndroid Build Coastguard Worker 	return &bo_fake->bo;
835*7688df22SAndroid Build Coastguard Worker }
836*7688df22SAndroid Build Coastguard Worker 
837*7688df22SAndroid Build Coastguard Worker static drm_intel_bo *
drm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr,const char * name,int x,int y,int cpp,uint32_t * tiling_mode,unsigned long * pitch,unsigned long flags)838*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr,
839*7688df22SAndroid Build Coastguard Worker 			      const char *name,
840*7688df22SAndroid Build Coastguard Worker 			      int x, int y, int cpp,
841*7688df22SAndroid Build Coastguard Worker 			      uint32_t *tiling_mode,
842*7688df22SAndroid Build Coastguard Worker 			      unsigned long *pitch,
843*7688df22SAndroid Build Coastguard Worker 			      unsigned long flags)
844*7688df22SAndroid Build Coastguard Worker {
845*7688df22SAndroid Build Coastguard Worker 	unsigned long stride, aligned_y;
846*7688df22SAndroid Build Coastguard Worker 
847*7688df22SAndroid Build Coastguard Worker 	/* No runtime tiling support for fake. */
848*7688df22SAndroid Build Coastguard Worker 	*tiling_mode = I915_TILING_NONE;
849*7688df22SAndroid Build Coastguard Worker 
850*7688df22SAndroid Build Coastguard Worker 	/* Align it for being a render target.  Shouldn't need anything else. */
851*7688df22SAndroid Build Coastguard Worker 	stride = x * cpp;
852*7688df22SAndroid Build Coastguard Worker 	stride = ROUND_UP_TO(stride, 64);
853*7688df22SAndroid Build Coastguard Worker 
854*7688df22SAndroid Build Coastguard Worker 	/* 965 subspan loading alignment */
855*7688df22SAndroid Build Coastguard Worker 	aligned_y = ALIGN(y, 2);
856*7688df22SAndroid Build Coastguard Worker 
857*7688df22SAndroid Build Coastguard Worker 	*pitch = stride;
858*7688df22SAndroid Build Coastguard Worker 
859*7688df22SAndroid Build Coastguard Worker 	return drm_intel_fake_bo_alloc(bufmgr, name, stride * aligned_y,
860*7688df22SAndroid Build Coastguard Worker 				       4096);
861*7688df22SAndroid Build Coastguard Worker }
862*7688df22SAndroid Build Coastguard Worker 
863*7688df22SAndroid Build Coastguard Worker drm_public drm_intel_bo *
drm_intel_bo_fake_alloc_static(drm_intel_bufmgr * bufmgr,const char * name,unsigned long offset,unsigned long size,void * virtual)864*7688df22SAndroid Build Coastguard Worker drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr,
865*7688df22SAndroid Build Coastguard Worker 			       const char *name,
866*7688df22SAndroid Build Coastguard Worker 			       unsigned long offset,
867*7688df22SAndroid Build Coastguard Worker 			       unsigned long size, void *virtual)
868*7688df22SAndroid Build Coastguard Worker {
869*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake;
870*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake;
871*7688df22SAndroid Build Coastguard Worker 
872*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
873*7688df22SAndroid Build Coastguard Worker 
874*7688df22SAndroid Build Coastguard Worker 	assert(size != 0);
875*7688df22SAndroid Build Coastguard Worker 
876*7688df22SAndroid Build Coastguard Worker 	bo_fake = calloc(1, sizeof(*bo_fake));
877*7688df22SAndroid Build Coastguard Worker 	if (!bo_fake)
878*7688df22SAndroid Build Coastguard Worker 		return NULL;
879*7688df22SAndroid Build Coastguard Worker 
880*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.size = size;
881*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.offset = offset;
882*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.virtual = virtual;
883*7688df22SAndroid Build Coastguard Worker 	bo_fake->bo.bufmgr = bufmgr;
884*7688df22SAndroid Build Coastguard Worker 	bo_fake->refcount = 1;
885*7688df22SAndroid Build Coastguard Worker 	bo_fake->id = ++bufmgr_fake->buf_nr;
886*7688df22SAndroid Build Coastguard Worker 	bo_fake->name = name;
887*7688df22SAndroid Build Coastguard Worker 	bo_fake->flags = BM_PINNED;
888*7688df22SAndroid Build Coastguard Worker 	bo_fake->is_static = 1;
889*7688df22SAndroid Build Coastguard Worker 
890*7688df22SAndroid Build Coastguard Worker 	DBG("drm_bo_alloc_static: (buf %d: %s, %lu kb)\n", bo_fake->id,
891*7688df22SAndroid Build Coastguard Worker 	    bo_fake->name, bo_fake->bo.size / 1024);
892*7688df22SAndroid Build Coastguard Worker 
893*7688df22SAndroid Build Coastguard Worker 	return &bo_fake->bo;
894*7688df22SAndroid Build Coastguard Worker }
895*7688df22SAndroid Build Coastguard Worker 
896*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_reference(drm_intel_bo * bo)897*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_reference(drm_intel_bo *bo)
898*7688df22SAndroid Build Coastguard Worker {
899*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
900*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
901*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
902*7688df22SAndroid Build Coastguard Worker 
903*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
904*7688df22SAndroid Build Coastguard Worker 	bo_fake->refcount++;
905*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
906*7688df22SAndroid Build Coastguard Worker }
907*7688df22SAndroid Build Coastguard Worker 
908*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_reference_locked(drm_intel_bo * bo)909*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_reference_locked(drm_intel_bo *bo)
910*7688df22SAndroid Build Coastguard Worker {
911*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
912*7688df22SAndroid Build Coastguard Worker 
913*7688df22SAndroid Build Coastguard Worker 	bo_fake->refcount++;
914*7688df22SAndroid Build Coastguard Worker }
915*7688df22SAndroid Build Coastguard Worker 
916*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_unreference_locked(drm_intel_bo * bo)917*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_unreference_locked(drm_intel_bo *bo)
918*7688df22SAndroid Build Coastguard Worker {
919*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
920*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
921*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
922*7688df22SAndroid Build Coastguard Worker 	int i;
923*7688df22SAndroid Build Coastguard Worker 
924*7688df22SAndroid Build Coastguard Worker 	if (--bo_fake->refcount == 0) {
925*7688df22SAndroid Build Coastguard Worker 		assert(bo_fake->map_count == 0);
926*7688df22SAndroid Build Coastguard Worker 		/* No remaining references, so free it */
927*7688df22SAndroid Build Coastguard Worker 		if (bo_fake->block)
928*7688df22SAndroid Build Coastguard Worker 			free_block(bufmgr_fake, bo_fake->block, 1);
929*7688df22SAndroid Build Coastguard Worker 		free_backing_store(bo);
930*7688df22SAndroid Build Coastguard Worker 
931*7688df22SAndroid Build Coastguard Worker 		for (i = 0; i < bo_fake->nr_relocs; i++)
932*7688df22SAndroid Build Coastguard Worker 			drm_intel_fake_bo_unreference_locked(bo_fake->relocs[i].
933*7688df22SAndroid Build Coastguard Worker 							     target_buf);
934*7688df22SAndroid Build Coastguard Worker 
935*7688df22SAndroid Build Coastguard Worker 		DBG("drm_bo_unreference: free buf %d %s\n", bo_fake->id,
936*7688df22SAndroid Build Coastguard Worker 		    bo_fake->name);
937*7688df22SAndroid Build Coastguard Worker 
938*7688df22SAndroid Build Coastguard Worker 		free(bo_fake->relocs);
939*7688df22SAndroid Build Coastguard Worker 		free(bo);
940*7688df22SAndroid Build Coastguard Worker 	}
941*7688df22SAndroid Build Coastguard Worker }
942*7688df22SAndroid Build Coastguard Worker 
943*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_bo_unreference(drm_intel_bo * bo)944*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_unreference(drm_intel_bo *bo)
945*7688df22SAndroid Build Coastguard Worker {
946*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
947*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
948*7688df22SAndroid Build Coastguard Worker 
949*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
950*7688df22SAndroid Build Coastguard Worker 	drm_intel_fake_bo_unreference_locked(bo);
951*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
952*7688df22SAndroid Build Coastguard Worker }
953*7688df22SAndroid Build Coastguard Worker 
954*7688df22SAndroid Build Coastguard Worker /**
955*7688df22SAndroid Build Coastguard Worker  * Set the buffer as not requiring backing store, and instead get the callback
956*7688df22SAndroid Build Coastguard Worker  * invoked whenever it would be set dirty.
957*7688df22SAndroid Build Coastguard Worker  */
958*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bo_fake_disable_backing_store(drm_intel_bo * bo,void (* invalidate_cb)(drm_intel_bo * bo,void * ptr),void * ptr)959*7688df22SAndroid Build Coastguard Worker drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo,
960*7688df22SAndroid Build Coastguard Worker 					void (*invalidate_cb) (drm_intel_bo *bo,
961*7688df22SAndroid Build Coastguard Worker 							       void *ptr),
962*7688df22SAndroid Build Coastguard Worker 					void *ptr)
963*7688df22SAndroid Build Coastguard Worker {
964*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
965*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
966*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
967*7688df22SAndroid Build Coastguard Worker 
968*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
969*7688df22SAndroid Build Coastguard Worker 
970*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->backing_store)
971*7688df22SAndroid Build Coastguard Worker 		free_backing_store(bo);
972*7688df22SAndroid Build Coastguard Worker 
973*7688df22SAndroid Build Coastguard Worker 	bo_fake->flags |= BM_NO_BACKING_STORE;
974*7688df22SAndroid Build Coastguard Worker 
975*7688df22SAndroid Build Coastguard Worker 	DBG("disable_backing_store set buf %d dirty\n", bo_fake->id);
976*7688df22SAndroid Build Coastguard Worker 	bo_fake->dirty = 1;
977*7688df22SAndroid Build Coastguard Worker 	bo_fake->invalidate_cb = invalidate_cb;
978*7688df22SAndroid Build Coastguard Worker 	bo_fake->invalidate_ptr = ptr;
979*7688df22SAndroid Build Coastguard Worker 
980*7688df22SAndroid Build Coastguard Worker 	/* Note that it is invalid right from the start.  Also note
981*7688df22SAndroid Build Coastguard Worker 	 * invalidate_cb is called with the bufmgr locked, so cannot
982*7688df22SAndroid Build Coastguard Worker 	 * itself make bufmgr calls.
983*7688df22SAndroid Build Coastguard Worker 	 */
984*7688df22SAndroid Build Coastguard Worker 	if (invalidate_cb != NULL)
985*7688df22SAndroid Build Coastguard Worker 		invalidate_cb(bo, ptr);
986*7688df22SAndroid Build Coastguard Worker 
987*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
988*7688df22SAndroid Build Coastguard Worker }
989*7688df22SAndroid Build Coastguard Worker 
990*7688df22SAndroid Build Coastguard Worker /**
991*7688df22SAndroid Build Coastguard Worker  * Map a buffer into bo->virtual, allocating either card memory space (If
992*7688df22SAndroid Build Coastguard Worker  * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary.
993*7688df22SAndroid Build Coastguard Worker  */
994*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_map_locked(drm_intel_bo * bo,int write_enable)995*7688df22SAndroid Build Coastguard Worker  drm_intel_fake_bo_map_locked(drm_intel_bo *bo, int write_enable)
996*7688df22SAndroid Build Coastguard Worker {
997*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
998*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
999*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1000*7688df22SAndroid Build Coastguard Worker 
1001*7688df22SAndroid Build Coastguard Worker 	/* Static buffers are always mapped. */
1002*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->is_static) {
1003*7688df22SAndroid Build Coastguard Worker 		if (bo_fake->card_dirty) {
1004*7688df22SAndroid Build Coastguard Worker 			drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1005*7688df22SAndroid Build Coastguard Worker 			bo_fake->card_dirty = 0;
1006*7688df22SAndroid Build Coastguard Worker 		}
1007*7688df22SAndroid Build Coastguard Worker 		return 0;
1008*7688df22SAndroid Build Coastguard Worker 	}
1009*7688df22SAndroid Build Coastguard Worker 
1010*7688df22SAndroid Build Coastguard Worker 	/* Allow recursive mapping.  Mesa may recursively map buffers with
1011*7688df22SAndroid Build Coastguard Worker 	 * nested display loops, and it is used internally in bufmgr_fake
1012*7688df22SAndroid Build Coastguard Worker 	 * for relocation.
1013*7688df22SAndroid Build Coastguard Worker 	 */
1014*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->map_count++ != 0)
1015*7688df22SAndroid Build Coastguard Worker 		return 0;
1016*7688df22SAndroid Build Coastguard Worker 
1017*7688df22SAndroid Build Coastguard Worker 	{
1018*7688df22SAndroid Build Coastguard Worker 		DBG("drm_bo_map: (buf %d: %s, %lu kb)\n", bo_fake->id,
1019*7688df22SAndroid Build Coastguard Worker 		    bo_fake->name, bo_fake->bo.size / 1024);
1020*7688df22SAndroid Build Coastguard Worker 
1021*7688df22SAndroid Build Coastguard Worker 		if (bo->virtual != NULL) {
1022*7688df22SAndroid Build Coastguard Worker 			drmMsg("%s: already mapped\n", __func__);
1023*7688df22SAndroid Build Coastguard Worker 			abort();
1024*7688df22SAndroid Build Coastguard Worker 		} else if (bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)) {
1025*7688df22SAndroid Build Coastguard Worker 
1026*7688df22SAndroid Build Coastguard Worker 			if (!bo_fake->block && !evict_and_alloc_block(bo)) {
1027*7688df22SAndroid Build Coastguard Worker 				DBG("%s: alloc failed\n", __func__);
1028*7688df22SAndroid Build Coastguard Worker 				bufmgr_fake->fail = 1;
1029*7688df22SAndroid Build Coastguard Worker 				return 1;
1030*7688df22SAndroid Build Coastguard Worker 			} else {
1031*7688df22SAndroid Build Coastguard Worker 				assert(bo_fake->block);
1032*7688df22SAndroid Build Coastguard Worker 				bo_fake->dirty = 0;
1033*7688df22SAndroid Build Coastguard Worker 
1034*7688df22SAndroid Build Coastguard Worker 				if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA) &&
1035*7688df22SAndroid Build Coastguard Worker 				    bo_fake->block->fenced) {
1036*7688df22SAndroid Build Coastguard Worker 					drm_intel_fake_bo_wait_rendering_locked
1037*7688df22SAndroid Build Coastguard Worker 					    (bo);
1038*7688df22SAndroid Build Coastguard Worker 				}
1039*7688df22SAndroid Build Coastguard Worker 
1040*7688df22SAndroid Build Coastguard Worker 				bo->virtual = bo_fake->block->virtual;
1041*7688df22SAndroid Build Coastguard Worker 			}
1042*7688df22SAndroid Build Coastguard Worker 		} else {
1043*7688df22SAndroid Build Coastguard Worker 			if (write_enable)
1044*7688df22SAndroid Build Coastguard Worker 				set_dirty(bo);
1045*7688df22SAndroid Build Coastguard Worker 
1046*7688df22SAndroid Build Coastguard Worker 			if (bo_fake->backing_store == 0)
1047*7688df22SAndroid Build Coastguard Worker 				alloc_backing_store(bo);
1048*7688df22SAndroid Build Coastguard Worker 
1049*7688df22SAndroid Build Coastguard Worker 			if ((bo_fake->card_dirty == 1) && bo_fake->block) {
1050*7688df22SAndroid Build Coastguard Worker 				if (bo_fake->block->fenced)
1051*7688df22SAndroid Build Coastguard Worker 					drm_intel_fake_bo_wait_rendering_locked
1052*7688df22SAndroid Build Coastguard Worker 					    (bo);
1053*7688df22SAndroid Build Coastguard Worker 
1054*7688df22SAndroid Build Coastguard Worker 				memcpy(bo_fake->backing_store,
1055*7688df22SAndroid Build Coastguard Worker 				       bo_fake->block->virtual,
1056*7688df22SAndroid Build Coastguard Worker 				       bo_fake->block->bo->size);
1057*7688df22SAndroid Build Coastguard Worker 				bo_fake->card_dirty = 0;
1058*7688df22SAndroid Build Coastguard Worker 			}
1059*7688df22SAndroid Build Coastguard Worker 
1060*7688df22SAndroid Build Coastguard Worker 			bo->virtual = bo_fake->backing_store;
1061*7688df22SAndroid Build Coastguard Worker 		}
1062*7688df22SAndroid Build Coastguard Worker 	}
1063*7688df22SAndroid Build Coastguard Worker 
1064*7688df22SAndroid Build Coastguard Worker 	return 0;
1065*7688df22SAndroid Build Coastguard Worker }
1066*7688df22SAndroid Build Coastguard Worker 
1067*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_map(drm_intel_bo * bo,int write_enable)1068*7688df22SAndroid Build Coastguard Worker  drm_intel_fake_bo_map(drm_intel_bo *bo, int write_enable)
1069*7688df22SAndroid Build Coastguard Worker {
1070*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1071*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1072*7688df22SAndroid Build Coastguard Worker 	int ret;
1073*7688df22SAndroid Build Coastguard Worker 
1074*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
1075*7688df22SAndroid Build Coastguard Worker 	ret = drm_intel_fake_bo_map_locked(bo, write_enable);
1076*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
1077*7688df22SAndroid Build Coastguard Worker 
1078*7688df22SAndroid Build Coastguard Worker 	return ret;
1079*7688df22SAndroid Build Coastguard Worker }
1080*7688df22SAndroid Build Coastguard Worker 
1081*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_unmap_locked(drm_intel_bo * bo)1082*7688df22SAndroid Build Coastguard Worker  drm_intel_fake_bo_unmap_locked(drm_intel_bo *bo)
1083*7688df22SAndroid Build Coastguard Worker {
1084*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1085*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1086*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1087*7688df22SAndroid Build Coastguard Worker 
1088*7688df22SAndroid Build Coastguard Worker 	/* Static buffers are always mapped. */
1089*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->is_static)
1090*7688df22SAndroid Build Coastguard Worker 		return 0;
1091*7688df22SAndroid Build Coastguard Worker 
1092*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->map_count != 0);
1093*7688df22SAndroid Build Coastguard Worker 	if (--bo_fake->map_count != 0)
1094*7688df22SAndroid Build Coastguard Worker 		return 0;
1095*7688df22SAndroid Build Coastguard Worker 
1096*7688df22SAndroid Build Coastguard Worker 	DBG("drm_bo_unmap: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name,
1097*7688df22SAndroid Build Coastguard Worker 	    bo_fake->bo.size / 1024);
1098*7688df22SAndroid Build Coastguard Worker 
1099*7688df22SAndroid Build Coastguard Worker 	bo->virtual = NULL;
1100*7688df22SAndroid Build Coastguard Worker 
1101*7688df22SAndroid Build Coastguard Worker 	return 0;
1102*7688df22SAndroid Build Coastguard Worker }
1103*7688df22SAndroid Build Coastguard Worker 
drm_intel_fake_bo_unmap(drm_intel_bo * bo)1104*7688df22SAndroid Build Coastguard Worker static int drm_intel_fake_bo_unmap(drm_intel_bo *bo)
1105*7688df22SAndroid Build Coastguard Worker {
1106*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1107*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1108*7688df22SAndroid Build Coastguard Worker 	int ret;
1109*7688df22SAndroid Build Coastguard Worker 
1110*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
1111*7688df22SAndroid Build Coastguard Worker 	ret = drm_intel_fake_bo_unmap_locked(bo);
1112*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
1113*7688df22SAndroid Build Coastguard Worker 
1114*7688df22SAndroid Build Coastguard Worker 	return ret;
1115*7688df22SAndroid Build Coastguard Worker }
1116*7688df22SAndroid Build Coastguard Worker 
1117*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_subdata(drm_intel_bo * bo,unsigned long offset,unsigned long size,const void * data)1118*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_subdata(drm_intel_bo *bo, unsigned long offset,
1119*7688df22SAndroid Build Coastguard Worker 			  unsigned long size, const void *data)
1120*7688df22SAndroid Build Coastguard Worker {
1121*7688df22SAndroid Build Coastguard Worker 	int ret;
1122*7688df22SAndroid Build Coastguard Worker 
1123*7688df22SAndroid Build Coastguard Worker 	if (size == 0 || data == NULL)
1124*7688df22SAndroid Build Coastguard Worker 		return 0;
1125*7688df22SAndroid Build Coastguard Worker 
1126*7688df22SAndroid Build Coastguard Worker 	ret = drm_intel_bo_map(bo, 1);
1127*7688df22SAndroid Build Coastguard Worker 	if (ret)
1128*7688df22SAndroid Build Coastguard Worker 		return ret;
1129*7688df22SAndroid Build Coastguard Worker 	memcpy((unsigned char *)bo->virtual + offset, data, size);
1130*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_unmap(bo);
1131*7688df22SAndroid Build Coastguard Worker 	return 0;
1132*7688df22SAndroid Build Coastguard Worker }
1133*7688df22SAndroid Build Coastguard Worker 
1134*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake * bufmgr_fake)1135*7688df22SAndroid Build Coastguard Worker  drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake)
1136*7688df22SAndroid Build Coastguard Worker {
1137*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
1138*7688df22SAndroid Build Coastguard Worker 
1139*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->performed_rendering = 0;
1140*7688df22SAndroid Build Coastguard Worker 	/* okay for ever BO that is on the HW kick it off.
1141*7688df22SAndroid Build Coastguard Worker 	   seriously not afraid of the POLICE right now */
1142*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) {
1143*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
1144*7688df22SAndroid Build Coastguard Worker 
1145*7688df22SAndroid Build Coastguard Worker 		block->on_hardware = 0;
1146*7688df22SAndroid Build Coastguard Worker 		free_block(bufmgr_fake, block, 0);
1147*7688df22SAndroid Build Coastguard Worker 		bo_fake->block = NULL;
1148*7688df22SAndroid Build Coastguard Worker 		bo_fake->validated = 0;
1149*7688df22SAndroid Build Coastguard Worker 		if (!(bo_fake->flags & BM_NO_BACKING_STORE))
1150*7688df22SAndroid Build Coastguard Worker 			bo_fake->dirty = 1;
1151*7688df22SAndroid Build Coastguard Worker 	}
1152*7688df22SAndroid Build Coastguard Worker 
1153*7688df22SAndroid Build Coastguard Worker }
1154*7688df22SAndroid Build Coastguard Worker 
1155*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_validate(drm_intel_bo * bo)1156*7688df22SAndroid Build Coastguard Worker  drm_intel_fake_bo_validate(drm_intel_bo *bo)
1157*7688df22SAndroid Build Coastguard Worker {
1158*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake;
1159*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1160*7688df22SAndroid Build Coastguard Worker 
1161*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake = (drm_intel_bufmgr_fake *) bo->bufmgr;
1162*7688df22SAndroid Build Coastguard Worker 
1163*7688df22SAndroid Build Coastguard Worker 	DBG("drm_bo_validate: (buf %d: %s, %lu kb)\n", bo_fake->id,
1164*7688df22SAndroid Build Coastguard Worker 	    bo_fake->name, bo_fake->bo.size / 1024);
1165*7688df22SAndroid Build Coastguard Worker 
1166*7688df22SAndroid Build Coastguard Worker 	/* Sanity check: Buffers should be unmapped before being validated.
1167*7688df22SAndroid Build Coastguard Worker 	 * This is not so much of a problem for bufmgr_fake, but TTM refuses,
1168*7688df22SAndroid Build Coastguard Worker 	 * and the problem is harder to debug there.
1169*7688df22SAndroid Build Coastguard Worker 	 */
1170*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->map_count == 0);
1171*7688df22SAndroid Build Coastguard Worker 
1172*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->is_static) {
1173*7688df22SAndroid Build Coastguard Worker 		/* Add it to the needs-fence list */
1174*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->need_fence = 1;
1175*7688df22SAndroid Build Coastguard Worker 		return 0;
1176*7688df22SAndroid Build Coastguard Worker 	}
1177*7688df22SAndroid Build Coastguard Worker 
1178*7688df22SAndroid Build Coastguard Worker 	/* Allocate the card memory */
1179*7688df22SAndroid Build Coastguard Worker 	if (!bo_fake->block && !evict_and_alloc_block(bo)) {
1180*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->fail = 1;
1181*7688df22SAndroid Build Coastguard Worker 		DBG("Failed to validate buf %d:%s\n", bo_fake->id,
1182*7688df22SAndroid Build Coastguard Worker 		    bo_fake->name);
1183*7688df22SAndroid Build Coastguard Worker 		return -1;
1184*7688df22SAndroid Build Coastguard Worker 	}
1185*7688df22SAndroid Build Coastguard Worker 
1186*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->block);
1187*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->block->bo == &bo_fake->bo);
1188*7688df22SAndroid Build Coastguard Worker 
1189*7688df22SAndroid Build Coastguard Worker 	bo->offset = bo_fake->block->mem->ofs;
1190*7688df22SAndroid Build Coastguard Worker 
1191*7688df22SAndroid Build Coastguard Worker 	/* Upload the buffer contents if necessary */
1192*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->dirty) {
1193*7688df22SAndroid Build Coastguard Worker 		DBG("Upload dirty buf %d:%s, sz %lu offset 0x%x\n", bo_fake->id,
1194*7688df22SAndroid Build Coastguard Worker 		    bo_fake->name, bo->size, bo_fake->block->mem->ofs);
1195*7688df22SAndroid Build Coastguard Worker 
1196*7688df22SAndroid Build Coastguard Worker 		assert(!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)));
1197*7688df22SAndroid Build Coastguard Worker 
1198*7688df22SAndroid Build Coastguard Worker 		/* Actually, should be able to just wait for a fence on the
1199*7688df22SAndroid Build Coastguard Worker 		 * memory, which we would be tracking when we free it. Waiting
1200*7688df22SAndroid Build Coastguard Worker 		 * for idle is a sufficiently large hammer for now.
1201*7688df22SAndroid Build Coastguard Worker 		 */
1202*7688df22SAndroid Build Coastguard Worker 		drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1203*7688df22SAndroid Build Coastguard Worker 
1204*7688df22SAndroid Build Coastguard Worker 		/* we may never have mapped this BO so it might not have any
1205*7688df22SAndroid Build Coastguard Worker 		 * backing store if this happens it should be rare, but 0 the
1206*7688df22SAndroid Build Coastguard Worker 		 * card memory in any case */
1207*7688df22SAndroid Build Coastguard Worker 		if (bo_fake->backing_store)
1208*7688df22SAndroid Build Coastguard Worker 			memcpy(bo_fake->block->virtual, bo_fake->backing_store,
1209*7688df22SAndroid Build Coastguard Worker 			       bo->size);
1210*7688df22SAndroid Build Coastguard Worker 		else
1211*7688df22SAndroid Build Coastguard Worker 			memset(bo_fake->block->virtual, 0, bo->size);
1212*7688df22SAndroid Build Coastguard Worker 
1213*7688df22SAndroid Build Coastguard Worker 		bo_fake->dirty = 0;
1214*7688df22SAndroid Build Coastguard Worker 	}
1215*7688df22SAndroid Build Coastguard Worker 
1216*7688df22SAndroid Build Coastguard Worker 	bo_fake->block->fenced = 0;
1217*7688df22SAndroid Build Coastguard Worker 	bo_fake->block->on_hardware = 1;
1218*7688df22SAndroid Build Coastguard Worker 	DRMLISTDEL(bo_fake->block);
1219*7688df22SAndroid Build Coastguard Worker 	DRMLISTADDTAIL(bo_fake->block, &bufmgr_fake->on_hardware);
1220*7688df22SAndroid Build Coastguard Worker 
1221*7688df22SAndroid Build Coastguard Worker 	bo_fake->validated = 1;
1222*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->need_fence = 1;
1223*7688df22SAndroid Build Coastguard Worker 
1224*7688df22SAndroid Build Coastguard Worker 	return 0;
1225*7688df22SAndroid Build Coastguard Worker }
1226*7688df22SAndroid Build Coastguard Worker 
1227*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_fence_validated(drm_intel_bufmgr * bufmgr)1228*7688df22SAndroid Build Coastguard Worker drm_intel_fake_fence_validated(drm_intel_bufmgr *bufmgr)
1229*7688df22SAndroid Build Coastguard Worker {
1230*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1231*7688df22SAndroid Build Coastguard Worker 	unsigned int cookie;
1232*7688df22SAndroid Build Coastguard Worker 
1233*7688df22SAndroid Build Coastguard Worker 	cookie = _fence_emit_internal(bufmgr_fake);
1234*7688df22SAndroid Build Coastguard Worker 	fence_blocks(bufmgr_fake, cookie);
1235*7688df22SAndroid Build Coastguard Worker 
1236*7688df22SAndroid Build Coastguard Worker 	DBG("drm_fence_validated: 0x%08x cookie\n", cookie);
1237*7688df22SAndroid Build Coastguard Worker }
1238*7688df22SAndroid Build Coastguard Worker 
1239*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_destroy(drm_intel_bufmgr * bufmgr)1240*7688df22SAndroid Build Coastguard Worker drm_intel_fake_destroy(drm_intel_bufmgr *bufmgr)
1241*7688df22SAndroid Build Coastguard Worker {
1242*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1243*7688df22SAndroid Build Coastguard Worker 
1244*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_destroy(&bufmgr_fake->lock);
1245*7688df22SAndroid Build Coastguard Worker 	mmDestroy(bufmgr_fake->heap);
1246*7688df22SAndroid Build Coastguard Worker 	free(bufmgr);
1247*7688df22SAndroid Build Coastguard Worker }
1248*7688df22SAndroid Build Coastguard Worker 
1249*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_emit_reloc(drm_intel_bo * bo,uint32_t offset,drm_intel_bo * target_bo,uint32_t target_offset,uint32_t read_domains,uint32_t write_domain)1250*7688df22SAndroid Build Coastguard Worker drm_intel_fake_emit_reloc(drm_intel_bo *bo, uint32_t offset,
1251*7688df22SAndroid Build Coastguard Worker 			  drm_intel_bo *target_bo, uint32_t target_offset,
1252*7688df22SAndroid Build Coastguard Worker 			  uint32_t read_domains, uint32_t write_domain)
1253*7688df22SAndroid Build Coastguard Worker {
1254*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1255*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1256*7688df22SAndroid Build Coastguard Worker 	struct fake_buffer_reloc *r;
1257*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1258*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *) target_bo;
1259*7688df22SAndroid Build Coastguard Worker 	int i;
1260*7688df22SAndroid Build Coastguard Worker 
1261*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
1262*7688df22SAndroid Build Coastguard Worker 
1263*7688df22SAndroid Build Coastguard Worker 	assert(bo);
1264*7688df22SAndroid Build Coastguard Worker 	assert(target_bo);
1265*7688df22SAndroid Build Coastguard Worker 
1266*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->relocs == NULL) {
1267*7688df22SAndroid Build Coastguard Worker 		bo_fake->relocs =
1268*7688df22SAndroid Build Coastguard Worker 		    malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS);
1269*7688df22SAndroid Build Coastguard Worker 	}
1270*7688df22SAndroid Build Coastguard Worker 
1271*7688df22SAndroid Build Coastguard Worker 	r = &bo_fake->relocs[bo_fake->nr_relocs++];
1272*7688df22SAndroid Build Coastguard Worker 
1273*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->nr_relocs <= MAX_RELOCS);
1274*7688df22SAndroid Build Coastguard Worker 
1275*7688df22SAndroid Build Coastguard Worker 	drm_intel_fake_bo_reference_locked(target_bo);
1276*7688df22SAndroid Build Coastguard Worker 
1277*7688df22SAndroid Build Coastguard Worker 	if (!target_fake->is_static) {
1278*7688df22SAndroid Build Coastguard Worker 		bo_fake->child_size +=
1279*7688df22SAndroid Build Coastguard Worker 		    ALIGN(target_bo->size, target_fake->alignment);
1280*7688df22SAndroid Build Coastguard Worker 		bo_fake->child_size += target_fake->child_size;
1281*7688df22SAndroid Build Coastguard Worker 	}
1282*7688df22SAndroid Build Coastguard Worker 	r->target_buf = target_bo;
1283*7688df22SAndroid Build Coastguard Worker 	r->offset = offset;
1284*7688df22SAndroid Build Coastguard Worker 	r->last_target_offset = target_bo->offset;
1285*7688df22SAndroid Build Coastguard Worker 	r->delta = target_offset;
1286*7688df22SAndroid Build Coastguard Worker 	r->read_domains = read_domains;
1287*7688df22SAndroid Build Coastguard Worker 	r->write_domain = write_domain;
1288*7688df22SAndroid Build Coastguard Worker 
1289*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->debug) {
1290*7688df22SAndroid Build Coastguard Worker 		/* Check that a conflicting relocation hasn't already been
1291*7688df22SAndroid Build Coastguard Worker 		 * emitted.
1292*7688df22SAndroid Build Coastguard Worker 		 */
1293*7688df22SAndroid Build Coastguard Worker 		for (i = 0; i < bo_fake->nr_relocs - 1; i++) {
1294*7688df22SAndroid Build Coastguard Worker 			struct fake_buffer_reloc *r2 = &bo_fake->relocs[i];
1295*7688df22SAndroid Build Coastguard Worker 
1296*7688df22SAndroid Build Coastguard Worker 			assert(r->offset != r2->offset);
1297*7688df22SAndroid Build Coastguard Worker 		}
1298*7688df22SAndroid Build Coastguard Worker 	}
1299*7688df22SAndroid Build Coastguard Worker 
1300*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
1301*7688df22SAndroid Build Coastguard Worker 
1302*7688df22SAndroid Build Coastguard Worker 	return 0;
1303*7688df22SAndroid Build Coastguard Worker }
1304*7688df22SAndroid Build Coastguard Worker 
1305*7688df22SAndroid Build Coastguard Worker /**
1306*7688df22SAndroid Build Coastguard Worker  * Incorporates the validation flags associated with each relocation into
1307*7688df22SAndroid Build Coastguard Worker  * the combined validation flags for the buffer on this batchbuffer submission.
1308*7688df22SAndroid Build Coastguard Worker  */
1309*7688df22SAndroid Build Coastguard Worker static void
drm_intel_fake_calculate_domains(drm_intel_bo * bo)1310*7688df22SAndroid Build Coastguard Worker drm_intel_fake_calculate_domains(drm_intel_bo *bo)
1311*7688df22SAndroid Build Coastguard Worker {
1312*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1313*7688df22SAndroid Build Coastguard Worker 	int i;
1314*7688df22SAndroid Build Coastguard Worker 
1315*7688df22SAndroid Build Coastguard Worker 	for (i = 0; i < bo_fake->nr_relocs; i++) {
1316*7688df22SAndroid Build Coastguard Worker 		struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1317*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *target_fake =
1318*7688df22SAndroid Build Coastguard Worker 		    (drm_intel_bo_fake *) r->target_buf;
1319*7688df22SAndroid Build Coastguard Worker 
1320*7688df22SAndroid Build Coastguard Worker 		/* Do the same for the tree of buffers we depend on */
1321*7688df22SAndroid Build Coastguard Worker 		drm_intel_fake_calculate_domains(r->target_buf);
1322*7688df22SAndroid Build Coastguard Worker 
1323*7688df22SAndroid Build Coastguard Worker 		target_fake->read_domains |= r->read_domains;
1324*7688df22SAndroid Build Coastguard Worker 		target_fake->write_domain |= r->write_domain;
1325*7688df22SAndroid Build Coastguard Worker 	}
1326*7688df22SAndroid Build Coastguard Worker }
1327*7688df22SAndroid Build Coastguard Worker 
1328*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_reloc_and_validate_buffer(drm_intel_bo * bo)1329*7688df22SAndroid Build Coastguard Worker drm_intel_fake_reloc_and_validate_buffer(drm_intel_bo *bo)
1330*7688df22SAndroid Build Coastguard Worker {
1331*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1332*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1333*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1334*7688df22SAndroid Build Coastguard Worker 	int i, ret;
1335*7688df22SAndroid Build Coastguard Worker 
1336*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->map_count == 0);
1337*7688df22SAndroid Build Coastguard Worker 
1338*7688df22SAndroid Build Coastguard Worker 	for (i = 0; i < bo_fake->nr_relocs; i++) {
1339*7688df22SAndroid Build Coastguard Worker 		struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1340*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *target_fake =
1341*7688df22SAndroid Build Coastguard Worker 		    (drm_intel_bo_fake *) r->target_buf;
1342*7688df22SAndroid Build Coastguard Worker 		uint32_t reloc_data;
1343*7688df22SAndroid Build Coastguard Worker 
1344*7688df22SAndroid Build Coastguard Worker 		/* Validate the target buffer if that hasn't been done. */
1345*7688df22SAndroid Build Coastguard Worker 		if (!target_fake->validated) {
1346*7688df22SAndroid Build Coastguard Worker 			ret =
1347*7688df22SAndroid Build Coastguard Worker 			    drm_intel_fake_reloc_and_validate_buffer(r->target_buf);
1348*7688df22SAndroid Build Coastguard Worker 			if (ret != 0) {
1349*7688df22SAndroid Build Coastguard Worker 				if (bo->virtual != NULL)
1350*7688df22SAndroid Build Coastguard Worker 					drm_intel_fake_bo_unmap_locked(bo);
1351*7688df22SAndroid Build Coastguard Worker 				return ret;
1352*7688df22SAndroid Build Coastguard Worker 			}
1353*7688df22SAndroid Build Coastguard Worker 		}
1354*7688df22SAndroid Build Coastguard Worker 
1355*7688df22SAndroid Build Coastguard Worker 		/* Calculate the value of the relocation entry. */
1356*7688df22SAndroid Build Coastguard Worker 		if (r->target_buf->offset != r->last_target_offset) {
1357*7688df22SAndroid Build Coastguard Worker 			reloc_data = r->target_buf->offset + r->delta;
1358*7688df22SAndroid Build Coastguard Worker 
1359*7688df22SAndroid Build Coastguard Worker 			if (bo->virtual == NULL)
1360*7688df22SAndroid Build Coastguard Worker 				drm_intel_fake_bo_map_locked(bo, 1);
1361*7688df22SAndroid Build Coastguard Worker 
1362*7688df22SAndroid Build Coastguard Worker 			*(uint32_t *) ((uint8_t *) bo->virtual + r->offset) =
1363*7688df22SAndroid Build Coastguard Worker 			    reloc_data;
1364*7688df22SAndroid Build Coastguard Worker 
1365*7688df22SAndroid Build Coastguard Worker 			r->last_target_offset = r->target_buf->offset;
1366*7688df22SAndroid Build Coastguard Worker 		}
1367*7688df22SAndroid Build Coastguard Worker 	}
1368*7688df22SAndroid Build Coastguard Worker 
1369*7688df22SAndroid Build Coastguard Worker 	if (bo->virtual != NULL)
1370*7688df22SAndroid Build Coastguard Worker 		drm_intel_fake_bo_unmap_locked(bo);
1371*7688df22SAndroid Build Coastguard Worker 
1372*7688df22SAndroid Build Coastguard Worker 	if (bo_fake->write_domain != 0) {
1373*7688df22SAndroid Build Coastguard Worker 		if (!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))) {
1374*7688df22SAndroid Build Coastguard Worker 			if (bo_fake->backing_store == 0)
1375*7688df22SAndroid Build Coastguard Worker 				alloc_backing_store(bo);
1376*7688df22SAndroid Build Coastguard Worker 		}
1377*7688df22SAndroid Build Coastguard Worker 		bo_fake->card_dirty = 1;
1378*7688df22SAndroid Build Coastguard Worker 		bufmgr_fake->performed_rendering = 1;
1379*7688df22SAndroid Build Coastguard Worker 	}
1380*7688df22SAndroid Build Coastguard Worker 
1381*7688df22SAndroid Build Coastguard Worker 	return drm_intel_fake_bo_validate(bo);
1382*7688df22SAndroid Build Coastguard Worker }
1383*7688df22SAndroid Build Coastguard Worker 
1384*7688df22SAndroid Build Coastguard Worker static void
drm_intel_bo_fake_post_submit(drm_intel_bo * bo)1385*7688df22SAndroid Build Coastguard Worker drm_intel_bo_fake_post_submit(drm_intel_bo *bo)
1386*7688df22SAndroid Build Coastguard Worker {
1387*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1388*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1389*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1390*7688df22SAndroid Build Coastguard Worker 	int i;
1391*7688df22SAndroid Build Coastguard Worker 
1392*7688df22SAndroid Build Coastguard Worker 	for (i = 0; i < bo_fake->nr_relocs; i++) {
1393*7688df22SAndroid Build Coastguard Worker 		struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1394*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *target_fake =
1395*7688df22SAndroid Build Coastguard Worker 		    (drm_intel_bo_fake *) r->target_buf;
1396*7688df22SAndroid Build Coastguard Worker 
1397*7688df22SAndroid Build Coastguard Worker 		if (target_fake->validated)
1398*7688df22SAndroid Build Coastguard Worker 			drm_intel_bo_fake_post_submit(r->target_buf);
1399*7688df22SAndroid Build Coastguard Worker 
1400*7688df22SAndroid Build Coastguard Worker 		DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n",
1401*7688df22SAndroid Build Coastguard Worker 		    bo_fake->name, (uint32_t) bo->offset, r->offset,
1402*7688df22SAndroid Build Coastguard Worker 		    target_fake->name, (uint32_t) r->target_buf->offset,
1403*7688df22SAndroid Build Coastguard Worker 		    r->delta);
1404*7688df22SAndroid Build Coastguard Worker 	}
1405*7688df22SAndroid Build Coastguard Worker 
1406*7688df22SAndroid Build Coastguard Worker 	assert(bo_fake->map_count == 0);
1407*7688df22SAndroid Build Coastguard Worker 	bo_fake->validated = 0;
1408*7688df22SAndroid Build Coastguard Worker 	bo_fake->read_domains = 0;
1409*7688df22SAndroid Build Coastguard Worker 	bo_fake->write_domain = 0;
1410*7688df22SAndroid Build Coastguard Worker }
1411*7688df22SAndroid Build Coastguard Worker 
1412*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr * bufmgr,int (* exec)(drm_intel_bo * bo,unsigned int used,void * priv),void * priv)1413*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr,
1414*7688df22SAndroid Build Coastguard Worker 					     int (*exec) (drm_intel_bo *bo,
1415*7688df22SAndroid Build Coastguard Worker 							  unsigned int used,
1416*7688df22SAndroid Build Coastguard Worker 							  void *priv),
1417*7688df22SAndroid Build Coastguard Worker 					     void *priv)
1418*7688df22SAndroid Build Coastguard Worker {
1419*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1420*7688df22SAndroid Build Coastguard Worker 
1421*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->exec = exec;
1422*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->exec_priv = priv;
1423*7688df22SAndroid Build Coastguard Worker }
1424*7688df22SAndroid Build Coastguard Worker 
1425*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_bo_exec(drm_intel_bo * bo,int used,drm_clip_rect_t * cliprects,int num_cliprects,int DR4)1426*7688df22SAndroid Build Coastguard Worker drm_intel_fake_bo_exec(drm_intel_bo *bo, int used,
1427*7688df22SAndroid Build Coastguard Worker 		       drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
1428*7688df22SAndroid Build Coastguard Worker {
1429*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1430*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo->bufmgr;
1431*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake *batch_fake = (drm_intel_bo_fake *) bo;
1432*7688df22SAndroid Build Coastguard Worker 	struct drm_i915_batchbuffer batch;
1433*7688df22SAndroid Build Coastguard Worker 	int ret;
1434*7688df22SAndroid Build Coastguard Worker 	int retry_count = 0;
1435*7688df22SAndroid Build Coastguard Worker 
1436*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
1437*7688df22SAndroid Build Coastguard Worker 
1438*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->performed_rendering = 0;
1439*7688df22SAndroid Build Coastguard Worker 
1440*7688df22SAndroid Build Coastguard Worker 	drm_intel_fake_calculate_domains(bo);
1441*7688df22SAndroid Build Coastguard Worker 
1442*7688df22SAndroid Build Coastguard Worker 	batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND;
1443*7688df22SAndroid Build Coastguard Worker 
1444*7688df22SAndroid Build Coastguard Worker 	/* we've ran out of RAM so blow the whole lot away and retry */
1445*7688df22SAndroid Build Coastguard Worker restart:
1446*7688df22SAndroid Build Coastguard Worker 	ret = drm_intel_fake_reloc_and_validate_buffer(bo);
1447*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->fail == 1) {
1448*7688df22SAndroid Build Coastguard Worker 		if (retry_count == 0) {
1449*7688df22SAndroid Build Coastguard Worker 			retry_count++;
1450*7688df22SAndroid Build Coastguard Worker 			drm_intel_fake_kick_all_locked(bufmgr_fake);
1451*7688df22SAndroid Build Coastguard Worker 			bufmgr_fake->fail = 0;
1452*7688df22SAndroid Build Coastguard Worker 			goto restart;
1453*7688df22SAndroid Build Coastguard Worker 		} else		/* dump out the memory here */
1454*7688df22SAndroid Build Coastguard Worker 			mmDumpMemInfo(bufmgr_fake->heap);
1455*7688df22SAndroid Build Coastguard Worker 	}
1456*7688df22SAndroid Build Coastguard Worker 
1457*7688df22SAndroid Build Coastguard Worker 	assert(ret == 0);
1458*7688df22SAndroid Build Coastguard Worker 
1459*7688df22SAndroid Build Coastguard Worker 	if (bufmgr_fake->exec != NULL) {
1460*7688df22SAndroid Build Coastguard Worker 		ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv);
1461*7688df22SAndroid Build Coastguard Worker 		if (ret != 0) {
1462*7688df22SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&bufmgr_fake->lock);
1463*7688df22SAndroid Build Coastguard Worker 			return ret;
1464*7688df22SAndroid Build Coastguard Worker 		}
1465*7688df22SAndroid Build Coastguard Worker 	} else {
1466*7688df22SAndroid Build Coastguard Worker 		batch.start = bo->offset;
1467*7688df22SAndroid Build Coastguard Worker 		batch.used = used;
1468*7688df22SAndroid Build Coastguard Worker 		batch.cliprects = cliprects;
1469*7688df22SAndroid Build Coastguard Worker 		batch.num_cliprects = num_cliprects;
1470*7688df22SAndroid Build Coastguard Worker 		batch.DR1 = 0;
1471*7688df22SAndroid Build Coastguard Worker 		batch.DR4 = DR4;
1472*7688df22SAndroid Build Coastguard Worker 
1473*7688df22SAndroid Build Coastguard Worker 		if (drmCommandWrite
1474*7688df22SAndroid Build Coastguard Worker 		    (bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch,
1475*7688df22SAndroid Build Coastguard Worker 		     sizeof(batch))) {
1476*7688df22SAndroid Build Coastguard Worker 			drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno);
1477*7688df22SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&bufmgr_fake->lock);
1478*7688df22SAndroid Build Coastguard Worker 			return -errno;
1479*7688df22SAndroid Build Coastguard Worker 		}
1480*7688df22SAndroid Build Coastguard Worker 	}
1481*7688df22SAndroid Build Coastguard Worker 
1482*7688df22SAndroid Build Coastguard Worker 	drm_intel_fake_fence_validated(bo->bufmgr);
1483*7688df22SAndroid Build Coastguard Worker 
1484*7688df22SAndroid Build Coastguard Worker 	drm_intel_bo_fake_post_submit(bo);
1485*7688df22SAndroid Build Coastguard Worker 
1486*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
1487*7688df22SAndroid Build Coastguard Worker 
1488*7688df22SAndroid Build Coastguard Worker 	return 0;
1489*7688df22SAndroid Build Coastguard Worker }
1490*7688df22SAndroid Build Coastguard Worker 
1491*7688df22SAndroid Build Coastguard Worker /**
1492*7688df22SAndroid Build Coastguard Worker  * Return an error if the list of BOs will exceed the aperture size.
1493*7688df22SAndroid Build Coastguard Worker  *
1494*7688df22SAndroid Build Coastguard Worker  * This is a rough guess and likely to fail, as during the validate sequence we
1495*7688df22SAndroid Build Coastguard Worker  * may place a buffer in an inopportune spot early on and then fail to fit
1496*7688df22SAndroid Build Coastguard Worker  * a set smaller than the aperture.
1497*7688df22SAndroid Build Coastguard Worker  */
1498*7688df22SAndroid Build Coastguard Worker static int
drm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array,int count)1499*7688df22SAndroid Build Coastguard Worker drm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array, int count)
1500*7688df22SAndroid Build Coastguard Worker {
1501*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake =
1502*7688df22SAndroid Build Coastguard Worker 	    (drm_intel_bufmgr_fake *) bo_array[0]->bufmgr;
1503*7688df22SAndroid Build Coastguard Worker 	unsigned int sz = 0;
1504*7688df22SAndroid Build Coastguard Worker 	int i;
1505*7688df22SAndroid Build Coastguard Worker 
1506*7688df22SAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
1507*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo_array[i];
1508*7688df22SAndroid Build Coastguard Worker 
1509*7688df22SAndroid Build Coastguard Worker 		if (bo_fake == NULL)
1510*7688df22SAndroid Build Coastguard Worker 			continue;
1511*7688df22SAndroid Build Coastguard Worker 
1512*7688df22SAndroid Build Coastguard Worker 		if (!bo_fake->is_static)
1513*7688df22SAndroid Build Coastguard Worker 			sz += ALIGN(bo_array[i]->size, bo_fake->alignment);
1514*7688df22SAndroid Build Coastguard Worker 		sz += bo_fake->child_size;
1515*7688df22SAndroid Build Coastguard Worker 	}
1516*7688df22SAndroid Build Coastguard Worker 
1517*7688df22SAndroid Build Coastguard Worker 	if (sz > bufmgr_fake->size) {
1518*7688df22SAndroid Build Coastguard Worker 		DBG("check_space: overflowed bufmgr size, %ukb vs %lukb\n",
1519*7688df22SAndroid Build Coastguard Worker 		    sz / 1024, bufmgr_fake->size / 1024);
1520*7688df22SAndroid Build Coastguard Worker 		return -1;
1521*7688df22SAndroid Build Coastguard Worker 	}
1522*7688df22SAndroid Build Coastguard Worker 
1523*7688df22SAndroid Build Coastguard Worker 	DBG("drm_check_space: sz %ukb vs bufgr %lukb\n", sz / 1024,
1524*7688df22SAndroid Build Coastguard Worker 	    bufmgr_fake->size / 1024);
1525*7688df22SAndroid Build Coastguard Worker 	return 0;
1526*7688df22SAndroid Build Coastguard Worker }
1527*7688df22SAndroid Build Coastguard Worker 
1528*7688df22SAndroid Build Coastguard Worker /**
1529*7688df22SAndroid Build Coastguard Worker  * Evicts all buffers, waiting for fences to pass and copying contents out
1530*7688df22SAndroid Build Coastguard Worker  * as necessary.
1531*7688df22SAndroid Build Coastguard Worker  *
1532*7688df22SAndroid Build Coastguard Worker  * Used by the X Server on LeaveVT, when the card memory is no longer our
1533*7688df22SAndroid Build Coastguard Worker  * own.
1534*7688df22SAndroid Build Coastguard Worker  */
1535*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr * bufmgr)1536*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr)
1537*7688df22SAndroid Build Coastguard Worker {
1538*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1539*7688df22SAndroid Build Coastguard Worker 	struct block *block, *tmp;
1540*7688df22SAndroid Build Coastguard Worker 
1541*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_lock(&bufmgr_fake->lock);
1542*7688df22SAndroid Build Coastguard Worker 
1543*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->need_fence = 1;
1544*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fail = 0;
1545*7688df22SAndroid Build Coastguard Worker 
1546*7688df22SAndroid Build Coastguard Worker 	/* Wait for hardware idle.  We don't know where acceleration has been
1547*7688df22SAndroid Build Coastguard Worker 	 * happening, so we'll need to wait anyway before letting anything get
1548*7688df22SAndroid Build Coastguard Worker 	 * put on the card again.
1549*7688df22SAndroid Build Coastguard Worker 	 */
1550*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1551*7688df22SAndroid Build Coastguard Worker 
1552*7688df22SAndroid Build Coastguard Worker 	/* Check that we hadn't released the lock without having fenced the last
1553*7688df22SAndroid Build Coastguard Worker 	 * set of buffers.
1554*7688df22SAndroid Build Coastguard Worker 	 */
1555*7688df22SAndroid Build Coastguard Worker 	assert(DRMLISTEMPTY(&bufmgr_fake->fenced));
1556*7688df22SAndroid Build Coastguard Worker 	assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
1557*7688df22SAndroid Build Coastguard Worker 
1558*7688df22SAndroid Build Coastguard Worker 	DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
1559*7688df22SAndroid Build Coastguard Worker 		drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
1560*7688df22SAndroid Build Coastguard Worker 		/* Releases the memory, and memcpys dirty contents out if
1561*7688df22SAndroid Build Coastguard Worker 		 * necessary.
1562*7688df22SAndroid Build Coastguard Worker 		 */
1563*7688df22SAndroid Build Coastguard Worker 		free_block(bufmgr_fake, block, 0);
1564*7688df22SAndroid Build Coastguard Worker 		bo_fake->block = NULL;
1565*7688df22SAndroid Build Coastguard Worker 	}
1566*7688df22SAndroid Build Coastguard Worker 
1567*7688df22SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&bufmgr_fake->lock);
1568*7688df22SAndroid Build Coastguard Worker }
1569*7688df22SAndroid Build Coastguard Worker 
1570*7688df22SAndroid Build Coastguard Worker drm_public void
drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr * bufmgr,volatile unsigned int * last_dispatch)1571*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr,
1572*7688df22SAndroid Build Coastguard Worker 					volatile unsigned int
1573*7688df22SAndroid Build Coastguard Worker 					*last_dispatch)
1574*7688df22SAndroid Build Coastguard Worker {
1575*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1576*7688df22SAndroid Build Coastguard Worker 
1577*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->last_dispatch = (volatile int *)last_dispatch;
1578*7688df22SAndroid Build Coastguard Worker }
1579*7688df22SAndroid Build Coastguard Worker 
1580*7688df22SAndroid Build Coastguard Worker drm_public drm_intel_bufmgr *
drm_intel_bufmgr_fake_init(int fd,unsigned long low_offset,void * low_virtual,unsigned long size,volatile unsigned int * last_dispatch)1581*7688df22SAndroid Build Coastguard Worker drm_intel_bufmgr_fake_init(int fd, unsigned long low_offset,
1582*7688df22SAndroid Build Coastguard Worker 			   void *low_virtual, unsigned long size,
1583*7688df22SAndroid Build Coastguard Worker 			   volatile unsigned int *last_dispatch)
1584*7688df22SAndroid Build Coastguard Worker {
1585*7688df22SAndroid Build Coastguard Worker 	drm_intel_bufmgr_fake *bufmgr_fake;
1586*7688df22SAndroid Build Coastguard Worker 
1587*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake = calloc(1, sizeof(*bufmgr_fake));
1588*7688df22SAndroid Build Coastguard Worker 
1589*7688df22SAndroid Build Coastguard Worker 	if (pthread_mutex_init(&bufmgr_fake->lock, NULL) != 0) {
1590*7688df22SAndroid Build Coastguard Worker 		free(bufmgr_fake);
1591*7688df22SAndroid Build Coastguard Worker 		return NULL;
1592*7688df22SAndroid Build Coastguard Worker 	}
1593*7688df22SAndroid Build Coastguard Worker 
1594*7688df22SAndroid Build Coastguard Worker 	/* Initialize allocator */
1595*7688df22SAndroid Build Coastguard Worker 	DRMINITLISTHEAD(&bufmgr_fake->fenced);
1596*7688df22SAndroid Build Coastguard Worker 	DRMINITLISTHEAD(&bufmgr_fake->on_hardware);
1597*7688df22SAndroid Build Coastguard Worker 	DRMINITLISTHEAD(&bufmgr_fake->lru);
1598*7688df22SAndroid Build Coastguard Worker 
1599*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->low_offset = low_offset;
1600*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->virtual = low_virtual;
1601*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->size = size;
1602*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->heap = mmInit(low_offset, size);
1603*7688df22SAndroid Build Coastguard Worker 
1604*7688df22SAndroid Build Coastguard Worker 	/* Hook in methods */
1605*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_alloc = drm_intel_fake_bo_alloc;
1606*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_alloc_for_render = drm_intel_fake_bo_alloc;
1607*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_alloc_tiled = drm_intel_fake_bo_alloc_tiled;
1608*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_reference = drm_intel_fake_bo_reference;
1609*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_unreference = drm_intel_fake_bo_unreference;
1610*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_map = drm_intel_fake_bo_map;
1611*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_unmap = drm_intel_fake_bo_unmap;
1612*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_subdata = drm_intel_fake_bo_subdata;
1613*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_wait_rendering =
1614*7688df22SAndroid Build Coastguard Worker 	    drm_intel_fake_bo_wait_rendering;
1615*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_emit_reloc = drm_intel_fake_emit_reloc;
1616*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.destroy = drm_intel_fake_destroy;
1617*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.bo_exec = drm_intel_fake_bo_exec;
1618*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.check_aperture_space =
1619*7688df22SAndroid Build Coastguard Worker 	    drm_intel_fake_check_aperture_space;
1620*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->bufmgr.debug = 0;
1621*7688df22SAndroid Build Coastguard Worker 
1622*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->fd = fd;
1623*7688df22SAndroid Build Coastguard Worker 	bufmgr_fake->last_dispatch = (volatile int *)last_dispatch;
1624*7688df22SAndroid Build Coastguard Worker 
1625*7688df22SAndroid Build Coastguard Worker 	return &bufmgr_fake->bufmgr;
1626*7688df22SAndroid Build Coastguard Worker }
1627