Subversion Repositories Kolibri OS

Rev

Rev 1119 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1117 serge 1
/*
2
 * Copyright 2008 Advanced Micro Devices, Inc.
3
 * Copyright 2008 Red Hat Inc.
4
 * Copyright 2009 Jerome Glisse.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors: Dave Airlie
25
 *          Alex Deucher
26
 *          Jerome Glisse
27
 */
28
//#include 
29
//#include "drmP.h"
30
#include "radeon_drm.h"
31
#include "radeon_reg.h"
32
#include "radeon.h"
33
#include "atom.h"
34
 
35
#if 0
36
int radeon_debugfs_ib_init(struct radeon_device *rdev);
37
 
38
/*
39
 * IB.
40
 */
41
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
42
{
43
	struct radeon_fence *fence;
44
	struct radeon_ib *nib;
45
	unsigned long i;
46
	int r = 0;
47
 
48
	*ib = NULL;
49
	r = radeon_fence_create(rdev, &fence);
50
	if (r) {
51
		DRM_ERROR("failed to create fence for new IB\n");
52
		return r;
53
	}
54
    mutex_lock(&rdev->ib_pool.mutex);
55
	i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
56
	if (i < RADEON_IB_POOL_SIZE) {
57
		set_bit(i, rdev->ib_pool.alloc_bm);
58
		rdev->ib_pool.ibs[i].length_dw = 0;
59
		*ib = &rdev->ib_pool.ibs[i];
60
		goto out;
61
	}
62
	if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
63
		/* we go do nothings here */
64
		DRM_ERROR("all IB allocated none scheduled.\n");
65
		r = -EINVAL;
66
		goto out;
67
	}
68
	/* get the first ib on the scheduled list */
69
	nib = list_entry(rdev->ib_pool.scheduled_ibs.next,
70
			 struct radeon_ib, list);
71
	if (nib->fence == NULL) {
72
		/* we go do nothings here */
73
		DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
74
		r = -EINVAL;
75
		goto out;
76
	}
77
	r = radeon_fence_wait(nib->fence, false);
78
	if (r) {
79
		DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
80
			  (unsigned long)nib->gpu_addr, nib->length_dw);
81
		DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n");
82
		goto out;
83
	}
84
	radeon_fence_unref(&nib->fence);
85
	nib->length_dw = 0;
86
	list_del(&nib->list);
87
	INIT_LIST_HEAD(&nib->list);
88
	*ib = nib;
89
out:
90
	mutex_unlock(&rdev->ib_pool.mutex);
91
	if (r) {
92
		radeon_fence_unref(&fence);
93
	} else {
94
		(*ib)->fence = fence;
95
	}
96
	return r;
97
}
98
 
99
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
100
{
101
	struct radeon_ib *tmp = *ib;
102
 
103
	*ib = NULL;
104
	if (tmp == NULL) {
105
		return;
106
	}
107
	mutex_lock(&rdev->ib_pool.mutex);
108
	if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) {
109
		/* IB is scheduled & not signaled don't do anythings */
110
		mutex_unlock(&rdev->ib_pool.mutex);
111
		return;
112
	}
113
	list_del(&tmp->list);
114
	INIT_LIST_HEAD(&tmp->list);
115
	if (tmp->fence) {
116
		radeon_fence_unref(&tmp->fence);
117
	}
118
	tmp->length_dw = 0;
119
	clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
120
	mutex_unlock(&rdev->ib_pool.mutex);
121
}
122
 
123
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
124
{
125
	while ((ib->length_dw & rdev->cp.align_mask)) {
126
		ib->ptr[ib->length_dw++] = PACKET2(0);
127
	}
128
}
129
 
130
static void radeon_ib_cpu_flush(struct radeon_device *rdev,
131
				struct radeon_ib *ib)
132
{
133
	unsigned long tmp;
134
	unsigned i;
135
 
136
	/* To force CPU cache flush ugly but seems reliable */
137
	for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
138
		tmp = readl(&ib->ptr[i]);
139
	}
140
}
141
 
142
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
143
{
144
	int r = 0;
145
 
146
	mutex_lock(&rdev->ib_pool.mutex);
147
	radeon_ib_align(rdev, ib);
148
	radeon_ib_cpu_flush(rdev, ib);
149
	if (!ib->length_dw || !rdev->cp.ready) {
150
		/* TODO: Nothings in the ib we should report. */
151
		mutex_unlock(&rdev->ib_pool.mutex);
152
		DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
153
		return -EINVAL;
154
	}
155
	/* 64 dwords should be enought for fence too */
156
	r = radeon_ring_lock(rdev, 64);
157
	if (r) {
158
		DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
159
		mutex_unlock(&rdev->ib_pool.mutex);
160
		return r;
161
	}
162
	radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1));
163
	radeon_ring_write(rdev, ib->gpu_addr);
164
	radeon_ring_write(rdev, ib->length_dw);
165
	radeon_fence_emit(rdev, ib->fence);
166
	radeon_ring_unlock_commit(rdev);
167
	list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
168
	mutex_unlock(&rdev->ib_pool.mutex);
169
	return 0;
170
}
171
 
172
int radeon_ib_pool_init(struct radeon_device *rdev)
173
{
174
	void *ptr;
175
	uint64_t gpu_addr;
176
	int i;
177
	int r = 0;
178
 
179
	/* Allocate 1M object buffer */
180
	INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
181
	r = radeon_object_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
182
				 true, RADEON_GEM_DOMAIN_GTT,
183
				 false, &rdev->ib_pool.robj);
184
	if (r) {
185
		DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
186
		return r;
187
	}
188
	r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
189
	if (r) {
190
		DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
191
		return r;
192
	}
193
	r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
194
	if (r) {
195
		DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
196
		return r;
197
	}
198
	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
199
		unsigned offset;
200
 
201
		offset = i * 64 * 1024;
202
		rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset;
203
		rdev->ib_pool.ibs[i].ptr = ptr + offset;
204
		rdev->ib_pool.ibs[i].idx = i;
205
		rdev->ib_pool.ibs[i].length_dw = 0;
206
		INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
207
	}
208
	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
209
	rdev->ib_pool.ready = true;
210
	DRM_INFO("radeon: ib pool ready.\n");
211
	if (radeon_debugfs_ib_init(rdev)) {
212
		DRM_ERROR("Failed to register debugfs file for IB !\n");
213
	}
214
	return r;
215
}
216
 
217
void radeon_ib_pool_fini(struct radeon_device *rdev)
218
{
219
	if (!rdev->ib_pool.ready) {
220
		return;
221
	}
222
	mutex_lock(&rdev->ib_pool.mutex);
223
	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
224
	if (rdev->ib_pool.robj) {
225
		radeon_object_kunmap(rdev->ib_pool.robj);
226
		radeon_object_unref(&rdev->ib_pool.robj);
227
		rdev->ib_pool.robj = NULL;
228
	}
229
	mutex_unlock(&rdev->ib_pool.mutex);
230
}
231
 
232
int radeon_ib_test(struct radeon_device *rdev)
233
{
234
	struct radeon_ib *ib;
235
	uint32_t scratch;
236
	uint32_t tmp = 0;
237
	unsigned i;
238
	int r;
239
 
240
	r = radeon_scratch_get(rdev, &scratch);
241
	if (r) {
242
		DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r);
243
		return r;
244
	}
245
	WREG32(scratch, 0xCAFEDEAD);
246
	r = radeon_ib_get(rdev, &ib);
247
	if (r) {
248
		return r;
249
	}
250
	ib->ptr[0] = PACKET0(scratch, 0);
251
	ib->ptr[1] = 0xDEADBEEF;
252
	ib->ptr[2] = PACKET2(0);
253
	ib->ptr[3] = PACKET2(0);
254
	ib->ptr[4] = PACKET2(0);
255
	ib->ptr[5] = PACKET2(0);
256
	ib->ptr[6] = PACKET2(0);
257
	ib->ptr[7] = PACKET2(0);
258
	ib->length_dw = 8;
259
	r = radeon_ib_schedule(rdev, ib);
260
	if (r) {
261
		radeon_scratch_free(rdev, scratch);
262
		radeon_ib_free(rdev, &ib);
263
		return r;
264
	}
265
	r = radeon_fence_wait(ib->fence, false);
266
	if (r) {
267
		return r;
268
	}
269
	for (i = 0; i < rdev->usec_timeout; i++) {
270
		tmp = RREG32(scratch);
271
		if (tmp == 0xDEADBEEF) {
272
			break;
273
		}
274
		DRM_UDELAY(1);
275
	}
276
	if (i < rdev->usec_timeout) {
277
		DRM_INFO("ib test succeeded in %u usecs\n", i);
278
	} else {
279
		DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
280
			  scratch, tmp);
281
		r = -EINVAL;
282
	}
283
	radeon_scratch_free(rdev, scratch);
284
	radeon_ib_free(rdev, &ib);
285
	return r;
286
}
287
 
288
#endif
289
 
290
 
291
/*
292
 * Ring.
293
 */
294
void radeon_ring_free_size(struct radeon_device *rdev)
295
{
296
	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
297
	/* This works because ring_size is a power of 2 */
298
	rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
299
	rdev->cp.ring_free_dw -= rdev->cp.wptr;
300
	rdev->cp.ring_free_dw &= rdev->cp.ptr_mask;
301
	if (!rdev->cp.ring_free_dw) {
302
		rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
303
	}
304
}
305
 
306
int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw)
307
{
308
	int r;
309
 
310
	/* Align requested size with padding so unlock_commit can
311
	 * pad safely */
312
	ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask;
313
//   mutex_lock(&rdev->cp.mutex);
314
	while (ndw > (rdev->cp.ring_free_dw - 1)) {
315
		radeon_ring_free_size(rdev);
316
		if (ndw < rdev->cp.ring_free_dw) {
317
			break;
318
		}
319
        delay(1);
320
 
321
//        r = radeon_fence_wait_next(rdev);
322
//       if (r) {
323
//           mutex_unlock(&rdev->cp.mutex);
324
//           return r;
325
//       }
326
	}
327
	rdev->cp.count_dw = ndw;
328
	rdev->cp.wptr_old = rdev->cp.wptr;
329
	return 0;
330
}
331
 
332
void radeon_ring_unlock_commit(struct radeon_device *rdev)
333
{
334
	unsigned count_dw_pad;
335
	unsigned i;
336
 
337
	/* We pad to match fetch size */
338
	count_dw_pad = (rdev->cp.align_mask + 1) -
339
		       (rdev->cp.wptr & rdev->cp.align_mask);
340
	for (i = 0; i < count_dw_pad; i++) {
341
		radeon_ring_write(rdev, PACKET2(0));
342
	}
343
	DRM_MEMORYBARRIER();
344
	WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
345
	(void)RREG32(RADEON_CP_RB_WPTR);
346
//   mutex_unlock(&rdev->cp.mutex);
347
}
348
 
349
void radeon_ring_unlock_undo(struct radeon_device *rdev)
350
{
351
	rdev->cp.wptr = rdev->cp.wptr_old;
352
 //  mutex_unlock(&rdev->cp.mutex);
353
}
354
 
355
 
356
int radeon_ring_test(struct radeon_device *rdev)
357
{
358
	uint32_t scratch;
359
	uint32_t tmp = 0;
360
	unsigned i;
361
	int r;
362
 
363
    dbgprintf("%s\n\r",__FUNCTION__);
364
 
365
	r = radeon_scratch_get(rdev, &scratch);
366
	if (r) {
367
		DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r);
368
		return r;
369
	}
370
	WREG32(scratch, 0xCAFEDEAD);
371
	r = radeon_ring_lock(rdev, 2);
372
	if (r) {
373
		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
374
		radeon_scratch_free(rdev, scratch);
375
		return r;
376
	}
377
	radeon_ring_write(rdev, PACKET0(scratch, 0));
378
	radeon_ring_write(rdev, 0xDEADBEEF);
379
	radeon_ring_unlock_commit(rdev);
380
	for (i = 0; i < rdev->usec_timeout; i++) {
381
		tmp = RREG32(scratch);
382
		if (tmp == 0xDEADBEEF) {
383
			break;
384
		}
385
		DRM_UDELAY(1);
386
	}
387
	if (i < rdev->usec_timeout) {
388
		DRM_INFO("ring test succeeded in %d usecs\n", i);
389
	} else {
390
		DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
391
			  scratch, tmp);
392
		r = -EINVAL;
393
	}
394
	radeon_scratch_free(rdev, scratch);
395
	return r;
396
}
397
 
398
 
399
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
400
{
401
	int r;
402
 
403
    dbgprintf("%s\n\r",__FUNCTION__);
404
 
405
	rdev->cp.ring_size = ring_size;
406
 
407
#if 0
408
	/* Allocate ring buffer */
409
	if (rdev->cp.ring_obj == NULL) {
410
		r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
411
					 true,
412
					 RADEON_GEM_DOMAIN_GTT,
413
					 false,
414
					 &rdev->cp.ring_obj);
415
		if (r) {
416
			DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
417
      //     mutex_unlock(&rdev->cp.mutex);
418
			return r;
419
		}
420
		r = radeon_object_pin(rdev->cp.ring_obj,
421
				      RADEON_GEM_DOMAIN_GTT,
422
				      &rdev->cp.gpu_addr);
423
		if (r) {
424
			DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
425
      //     mutex_unlock(&rdev->cp.mutex);
426
			return r;
427
		}
428
		r = radeon_object_kmap(rdev->cp.ring_obj,
429
				       (void **)&rdev->cp.ring);
430
		if (r) {
431
			DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
432
      //     mutex_unlock(&rdev->cp.mutex);
433
			return r;
434
		}
435
	}
436
#endif
437
 
438
    rdev->cp.ring     = CreateRingBuffer( ring_size, PG_SW);
439
    rdev->cp.gpu_addr = GetPgAddr(rdev->cp.ring);
440
	rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
441
	rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
442
	return 0;
443
}
444
 
445
void radeon_ring_fini(struct radeon_device *rdev)
446
{
447
 //  mutex_lock(&rdev->cp.mutex);
448
   if (rdev->cp.ring_obj) {
449
 //      radeon_object_kunmap(rdev->cp.ring_obj);
450
 //      radeon_object_unpin(rdev->cp.ring_obj);
451
 //      radeon_object_unref(&rdev->cp.ring_obj);
452
       rdev->cp.ring = NULL;
453
		rdev->cp.ring_obj = NULL;
454
	}
455
 //  mutex_unlock(&rdev->cp.mutex);
456
}
457
 
458
 
459
/*
460
 * Debugfs info
461
 */
462
#if defined(CONFIG_DEBUG_FS)
463
static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
464
{
465
	struct drm_info_node *node = (struct drm_info_node *) m->private;
466
	struct radeon_ib *ib = node->info_ent->data;
467
	unsigned i;
468
 
469
	if (ib == NULL) {
470
		return 0;
471
	}
472
	seq_printf(m, "IB %04lu\n", ib->idx);
473
	seq_printf(m, "IB fence %p\n", ib->fence);
474
	seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
475
	for (i = 0; i < ib->length_dw; i++) {
476
		seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
477
	}
478
	return 0;
479
}
480
 
481
static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
482
static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
483
#endif
484
 
485
int radeon_debugfs_ib_init(struct radeon_device *rdev)
486
{
487
#if defined(CONFIG_DEBUG_FS)
488
	unsigned i;
489
 
490
	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
491
		sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
492
		radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
493
		radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
494
		radeon_debugfs_ib_list[i].driver_features = 0;
495
		radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i];
496
	}
497
	return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
498
					RADEON_IB_POOL_SIZE);
499
#else
500
	return 0;
501
#endif
502
}
503
 
504
 
505
int drm_order(unsigned long size)
506
{
507
    int order;
508
    unsigned long tmp;
509
 
510
    for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
511
 
512
    if (size & (size - 1))
513
        ++order;
514
 
515
    return order;
516
}
517