Subversion Repositories Kolibri OS

Rev

Rev 2004 | Rev 2997 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1125 serge 1
/*
2
 * Copyright 2009 Jerome Glisse.
3
 * All Rights Reserved.
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the
7
 * "Software"), to deal in the Software without restriction, including
8
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * distribute, sub license, and/or sell copies of the Software, and to
10
 * permit persons to whom the Software is furnished to do so, subject to
11
 * the following conditions:
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20
 *
21
 * The above copyright notice and this permission notice (including the
22
 * next paragraph) shall be included in all copies or substantial portions
23
 * of the Software.
24
 *
25
 */
26
/*
27
 * Authors:
28
 *    Jerome Glisse 
29
 *    Dave Airlie
30
 */
31
#include 
32
#include 
2004 serge 33
//#include 
1125 serge 34
#include 
35
#include 
1986 serge 36
#include 
1125 serge 37
#include "drmP.h"
38
#include "drm.h"
39
#include "radeon_reg.h"
40
#include "radeon.h"
41
 
2004 serge 42
static void radeon_fence_write(struct radeon_device *rdev, u32 seq)
43
{
44
	if (rdev->wb.enabled) {
45
		u32 scratch_index;
46
		if (rdev->wb.use_event)
47
			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
48
		else
49
			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
50
		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
51
	} else
52
		WREG32(rdev->fence_drv.scratch_reg, seq);
53
}
54
 
55
static u32 radeon_fence_read(struct radeon_device *rdev)
56
{
57
	u32 seq;
58
 
59
	if (rdev->wb.enabled) {
60
		u32 scratch_index;
61
		if (rdev->wb.use_event)
62
			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
63
		else
64
			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
65
		seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
66
	} else
67
		seq = RREG32(rdev->fence_drv.scratch_reg);
68
	return seq;
69
}
70
 
1125 serge 71
int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
72
{
73
	unsigned long irq_flags;
74
 
75
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
76
	if (fence->emited) {
77
		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
78
		return 0;
79
	}
80
	fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
2004 serge 81
	if (!rdev->cp.ready)
1125 serge 82
		/* FIXME: cp is not running assume everythings is done right
83
		 * away
84
		 */
2004 serge 85
		radeon_fence_write(rdev, fence->seq);
86
	else
1125 serge 87
		radeon_fence_ring_emit(rdev, fence);
1179 serge 88
 
2004 serge 89
//   trace_radeon_fence_emit(rdev->ddev, fence->seq);
1125 serge 90
	fence->emited = true;
1986 serge 91
	list_move_tail(&fence->list, &rdev->fence_drv.emited);
1125 serge 92
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
93
	return 0;
94
}
95
 
96
static bool radeon_fence_poll_locked(struct radeon_device *rdev)
97
{
98
	struct radeon_fence *fence;
99
	struct list_head *i, *n;
100
	uint32_t seq;
101
	bool wake = false;
1963 serge 102
	unsigned long cjiffies;
1125 serge 103
 
2004 serge 104
	seq = radeon_fence_read(rdev);
1963 serge 105
	if (seq != rdev->fence_drv.last_seq) {
106
		rdev->fence_drv.last_seq = seq;
2005 serge 107
        rdev->fence_drv.last_jiffies = GetTimerTicks();
108
        rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
1963 serge 109
	} else {
2005 serge 110
        cjiffies = GetTimerTicks();
1963 serge 111
		if (time_after(cjiffies, rdev->fence_drv.last_jiffies)) {
112
			cjiffies -= rdev->fence_drv.last_jiffies;
113
			if (time_after(rdev->fence_drv.last_timeout, cjiffies)) {
114
				/* update the timeout */
115
				rdev->fence_drv.last_timeout -= cjiffies;
116
			} else {
117
				/* the 500ms timeout is elapsed we should test
118
				 * for GPU lockup
119
				 */
120
				rdev->fence_drv.last_timeout = 1;
121
			}
122
		} else {
123
			/* wrap around update last jiffies, we will just wait
124
			 * a little longer
125
			 */
126
			rdev->fence_drv.last_jiffies = cjiffies;
1125 serge 127
	}
1963 serge 128
		return false;
1125 serge 129
	}
130
	n = NULL;
131
	list_for_each(i, &rdev->fence_drv.emited) {
132
		fence = list_entry(i, struct radeon_fence, list);
133
		if (fence->seq == seq) {
134
			n = i;
135
			break;
136
		}
137
	}
138
	/* all fence previous to this one are considered as signaled */
139
	if (n) {
2005 serge 140
        kevent_t event;
141
        event.code = -1;
1125 serge 142
		i = n;
143
		do {
144
			n = i->prev;
1986 serge 145
			list_move_tail(i, &rdev->fence_drv.signaled);
1125 serge 146
			fence = list_entry(i, struct radeon_fence, list);
147
			fence->signaled = true;
2005 serge 148
//            dbgprintf("fence %x done\n", fence);
149
            RaiseEvent(fence->evnt, 0, &event);
1125 serge 150
			i = n;
151
		} while (i != &rdev->fence_drv.emited);
152
		wake = true;
153
	}
154
	return wake;
155
}
156
 
157
 
158
int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence)
159
{
160
	unsigned long irq_flags;
161
 
162
	*fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL);
163
	if ((*fence) == NULL) {
164
		return -ENOMEM;
165
	}
2005 serge 166
 
167
    (*fence)->evnt = CreateEvent(NULL, MANUAL_DESTROY);
2004 serge 168
//	kref_init(&((*fence)->kref));
1125 serge 169
	(*fence)->rdev = rdev;
170
	(*fence)->emited = false;
171
	(*fence)->signaled = false;
172
	(*fence)->seq = 0;
173
	INIT_LIST_HEAD(&(*fence)->list);
174
 
175
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
176
	list_add_tail(&(*fence)->list, &rdev->fence_drv.created);
177
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
178
	return 0;
179
}
180
 
181
 
182
bool radeon_fence_signaled(struct radeon_fence *fence)
183
{
184
	unsigned long irq_flags;
185
	bool signaled = false;
186
 
1404 serge 187
	if (!fence)
1125 serge 188
		return true;
1404 serge 189
 
190
	if (fence->rdev->gpu_lockup)
1125 serge 191
		return true;
1404 serge 192
 
1125 serge 193
	write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags);
194
	signaled = fence->signaled;
195
	/* if we are shuting down report all fence as signaled */
196
	if (fence->rdev->shutdown) {
197
		signaled = true;
198
	}
199
	if (!fence->emited) {
200
		WARN(1, "Querying an unemited fence : %p !\n", fence);
201
		signaled = true;
202
	}
203
	if (!signaled) {
204
		radeon_fence_poll_locked(fence->rdev);
205
		signaled = fence->signaled;
206
	}
207
	write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags);
208
	return signaled;
209
}
210
 
1179 serge 211
int radeon_fence_wait(struct radeon_fence *fence, bool intr)
212
{
213
	struct radeon_device *rdev;
1963 serge 214
	unsigned long irq_flags, timeout;
215
	u32 seq;
1125 serge 216
	int r;
217
 
218
	if (fence == NULL) {
219
		WARN(1, "Querying an invalid fence : %p !\n", fence);
220
		return 0;
221
	}
222
	rdev = fence->rdev;
223
	if (radeon_fence_signaled(fence)) {
224
		return 0;
225
	}
1963 serge 226
	timeout = rdev->fence_drv.last_timeout;
1125 serge 227
retry:
1963 serge 228
	/* save current sequence used to check for GPU lockup */
229
	seq = rdev->fence_drv.last_seq;
2004 serge 230
//   trace_radeon_fence_wait_begin(rdev->ddev, seq);
1179 serge 231
	if (intr) {
1321 serge 232
		radeon_irq_kms_sw_irq_get(rdev);
2005 serge 233
//       r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
234
//               radeon_fence_signaled(fence), timeout);
235
 
236
        WaitEvent(fence->evnt);
237
 
1321 serge 238
		radeon_irq_kms_sw_irq_put(rdev);
1963 serge 239
		if (unlikely(r < 0)) {
1321 serge 240
			return r;
1963 serge 241
		}
1125 serge 242
	} else {
1321 serge 243
		radeon_irq_kms_sw_irq_get(rdev);
2005 serge 244
//       r = wait_event_timeout(rdev->fence_drv.queue,
245
//            radeon_fence_signaled(fence), timeout);
246
 
247
        WaitEvent(fence->evnt);
248
 
1321 serge 249
		radeon_irq_kms_sw_irq_put(rdev);
1125 serge 250
	}
2004 serge 251
//   trace_radeon_fence_wait_end(rdev->ddev, seq);
1125 serge 252
	if (unlikely(!radeon_fence_signaled(fence))) {
1963 serge 253
		/* we were interrupted for some reason and fence isn't
254
		 * isn't signaled yet, resume wait
255
		 */
256
		if (r) {
257
			timeout = r;
258
			goto retry;
1125 serge 259
		}
1963 serge 260
		/* don't protect read access to rdev->fence_drv.last_seq
261
		 * if we experiencing a lockup the value doesn't change
262
		 */
263
		if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) {
264
			/* good news we believe it's a lockup */
265
			WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
266
			     fence->seq, seq);
267
			/* FIXME: what should we do ? marking everyone
268
			 * as signaled for now
269
			 */
270
			rdev->gpu_lockup = true;
2005 serge 271
//           r = radeon_gpu_reset(rdev);
272
//           if (r)
273
//               return r;
274
            return true;
275
 
276
//           radeon_fence_write(rdev, fence->seq);
277
//           rdev->gpu_lockup = false;
1125 serge 278
			}
2005 serge 279
        timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
1963 serge 280
		write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
2005 serge 281
        rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
282
        rdev->fence_drv.last_jiffies = GetTimerTicks();
1963 serge 283
		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
1125 serge 284
		goto retry;
285
	}
286
	return 0;
287
}
288
 
2004 serge 289
#if 0
1125 serge 290
int radeon_fence_wait_next(struct radeon_device *rdev)
291
{
292
	unsigned long irq_flags;
293
	struct radeon_fence *fence;
294
	int r;
295
 
296
	if (rdev->gpu_lockup) {
297
		return 0;
298
	}
299
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
300
	if (list_empty(&rdev->fence_drv.emited)) {
301
		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
302
		return 0;
303
	}
304
	fence = list_entry(rdev->fence_drv.emited.next,
305
			   struct radeon_fence, list);
306
	radeon_fence_ref(fence);
307
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
308
	r = radeon_fence_wait(fence, false);
309
	radeon_fence_unref(&fence);
310
	return r;
311
}
312
 
313
int radeon_fence_wait_last(struct radeon_device *rdev)
314
{
315
	unsigned long irq_flags;
316
	struct radeon_fence *fence;
317
	int r;
318
 
319
	if (rdev->gpu_lockup) {
320
		return 0;
321
	}
322
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
323
	if (list_empty(&rdev->fence_drv.emited)) {
324
		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
325
		return 0;
326
	}
327
	fence = list_entry(rdev->fence_drv.emited.prev,
328
			   struct radeon_fence, list);
329
	radeon_fence_ref(fence);
330
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
331
	r = radeon_fence_wait(fence, false);
332
	radeon_fence_unref(&fence);
333
	return r;
334
}
335
 
336
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
337
{
338
	kref_get(&fence->kref);
339
	return fence;
340
}
341
 
2004 serge 342
#endif
343
 
1125 serge 344
void radeon_fence_unref(struct radeon_fence **fence)
345
{
2005 serge 346
    unsigned long irq_flags;
1125 serge 347
	struct radeon_fence *tmp = *fence;
348
 
349
	*fence = NULL;
2005 serge 350
 
351
    if(tmp)
352
    {
353
        write_lock_irqsave(&tmp->rdev->fence_drv.lock, irq_flags);
354
        list_del(&tmp->list);
355
        tmp->emited = false;
356
        write_unlock_irqrestore(&tmp->rdev->fence_drv.lock, irq_flags);
357
    };
1125 serge 358
}
359
 
360
void radeon_fence_process(struct radeon_device *rdev)
361
{
362
	unsigned long irq_flags;
363
	bool wake;
364
 
365
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
366
	wake = radeon_fence_poll_locked(rdev);
367
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
368
}
369
 
370
int radeon_fence_driver_init(struct radeon_device *rdev)
371
{
372
	unsigned long irq_flags;
373
	int r;
374
 
375
	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
376
	r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg);
377
	if (r) {
1404 serge 378
		dev_err(rdev->dev, "fence failed to get scratch register\n");
1125 serge 379
		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
380
		return r;
381
	}
2004 serge 382
	radeon_fence_write(rdev, 0);
1125 serge 383
	atomic_set(&rdev->fence_drv.seq, 0);
384
	INIT_LIST_HEAD(&rdev->fence_drv.created);
385
	INIT_LIST_HEAD(&rdev->fence_drv.emited);
386
	INIT_LIST_HEAD(&rdev->fence_drv.signaled);
2004 serge 387
//   init_waitqueue_head(&rdev->fence_drv.queue);
1404 serge 388
	rdev->fence_drv.initialized = true;
1125 serge 389
	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
2004 serge 390
    return 0;
1125 serge 391
}
392
 
393
 
394
/*
395
 * Fence debugfs
396
 */
397
#if defined(CONFIG_DEBUG_FS)
398
static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
399
{
400
	struct drm_info_node *node = (struct drm_info_node *)m->private;
401
	struct drm_device *dev = node->minor->dev;
402
	struct radeon_device *rdev = dev->dev_private;
403
	struct radeon_fence *fence;
404
 
405
	seq_printf(m, "Last signaled fence 0x%08X\n",
2004 serge 406
		   radeon_fence_read(rdev));
1125 serge 407
	if (!list_empty(&rdev->fence_drv.emited)) {
408
		   fence = list_entry(rdev->fence_drv.emited.prev,
409
				      struct radeon_fence, list);
410
		   seq_printf(m, "Last emited fence %p with 0x%08X\n",
411
			      fence,  fence->seq);
412
	}
413
	return 0;
414
}
415
 
416
static struct drm_info_list radeon_debugfs_fence_list[] = {
417
	{"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL},
418
};
419
#endif
420
 
421
int radeon_debugfs_fence_init(struct radeon_device *rdev)
422
{
423
#if defined(CONFIG_DEBUG_FS)
424
	return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1);
425
#else
426
	return 0;
427
#endif
428
}