Subversion Repositories Kolibri OS

Rev

Rev 1117 | Rev 1120 | Go to most recent revision | Details | Compare with Previous | 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
 
1119 serge 35
extern void * ring_buffer;
36
 
1117 serge 37
#if 0
38
int radeon_debugfs_ib_init(struct radeon_device *rdev);
39
 
40
/*
41
 * IB.
42
 */
43
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
44
{
45
	struct radeon_fence *fence;
46
	struct radeon_ib *nib;
47
	unsigned long i;
48
	int r = 0;
49
 
50
	*ib = NULL;
51
	r = radeon_fence_create(rdev, &fence);
52
	if (r) {
53
		DRM_ERROR("failed to create fence for new IB\n");
54
		return r;
55
	}
56
    mutex_lock(&rdev->ib_pool.mutex);
57
	i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
58
	if (i < RADEON_IB_POOL_SIZE) {
59
		set_bit(i, rdev->ib_pool.alloc_bm);
60
		rdev->ib_pool.ibs[i].length_dw = 0;
61
		*ib = &rdev->ib_pool.ibs[i];
62
		goto out;
63
	}
64
	if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
65
		/* we go do nothings here */
66
		DRM_ERROR("all IB allocated none scheduled.\n");
67
		r = -EINVAL;
68
		goto out;
69
	}
70
	/* get the first ib on the scheduled list */
71
	nib = list_entry(rdev->ib_pool.scheduled_ibs.next,
72
			 struct radeon_ib, list);
73
	if (nib->fence == NULL) {
74
		/* we go do nothings here */
75
		DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
76
		r = -EINVAL;
77
		goto out;
78
	}
79
	r = radeon_fence_wait(nib->fence, false);
80
	if (r) {
81
		DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
82
			  (unsigned long)nib->gpu_addr, nib->length_dw);
83
		DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n");
84
		goto out;
85
	}
86
	radeon_fence_unref(&nib->fence);
87
	nib->length_dw = 0;
88
	list_del(&nib->list);
89
	INIT_LIST_HEAD(&nib->list);
90
	*ib = nib;
91
out:
92
	mutex_unlock(&rdev->ib_pool.mutex);
93
	if (r) {
94
		radeon_fence_unref(&fence);
95
	} else {
96
		(*ib)->fence = fence;
97
	}
98
	return r;
99
}
100
 
101
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
102
{
103
	struct radeon_ib *tmp = *ib;
104
 
105
	*ib = NULL;
106
	if (tmp == NULL) {
107
		return;
108
	}
109
	mutex_lock(&rdev->ib_pool.mutex);
110
	if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) {
111
		/* IB is scheduled & not signaled don't do anythings */
112
		mutex_unlock(&rdev->ib_pool.mutex);
113
		return;
114
	}
115
	list_del(&tmp->list);
116
	INIT_LIST_HEAD(&tmp->list);
117
	if (tmp->fence) {
118
		radeon_fence_unref(&tmp->fence);
119
	}
120
	tmp->length_dw = 0;
121
	clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
122
	mutex_unlock(&rdev->ib_pool.mutex);
123
}
124
 
125
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
126
{
127
	while ((ib->length_dw & rdev->cp.align_mask)) {
128
		ib->ptr[ib->length_dw++] = PACKET2(0);
129
	}
130
}
131
 
132
static void radeon_ib_cpu_flush(struct radeon_device *rdev,
133
				struct radeon_ib *ib)
134
{
135
	unsigned long tmp;
136
	unsigned i;
137
 
138
	/* To force CPU cache flush ugly but seems reliable */
139
	for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
140
		tmp = readl(&ib->ptr[i]);
141
	}
142
}
143
 
144
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
145
{
146
	int r = 0;
147
 
148
	mutex_lock(&rdev->ib_pool.mutex);
149
	radeon_ib_align(rdev, ib);
150
	radeon_ib_cpu_flush(rdev, ib);
151
	if (!ib->length_dw || !rdev->cp.ready) {
152
		/* TODO: Nothings in the ib we should report. */
153
		mutex_unlock(&rdev->ib_pool.mutex);
154
		DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
155
		return -EINVAL;
156
	}
157
	/* 64 dwords should be enought for fence too */
158
	r = radeon_ring_lock(rdev, 64);
159
	if (r) {
160
		DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
161
		mutex_unlock(&rdev->ib_pool.mutex);
162
		return r;
163
	}
164
	radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1));
165
	radeon_ring_write(rdev, ib->gpu_addr);
166
	radeon_ring_write(rdev, ib->length_dw);
167
	radeon_fence_emit(rdev, ib->fence);
168
	radeon_ring_unlock_commit(rdev);
169
	list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
170
	mutex_unlock(&rdev->ib_pool.mutex);
171
	return 0;
172
}
173
 
174
int radeon_ib_pool_init(struct radeon_device *rdev)
175
{
176
	void *ptr;
177
	uint64_t gpu_addr;
178
	int i;
179
	int r = 0;
180
 
181
	/* Allocate 1M object buffer */
182
	INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
183
	r = radeon_object_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
184
				 true, RADEON_GEM_DOMAIN_GTT,
185
				 false, &rdev->ib_pool.robj);
186
	if (r) {
187
		DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
188
		return r;
189
	}
190
	r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
191
	if (r) {
192
		DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
193
		return r;
194
	}
195
	r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
196
	if (r) {
197
		DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
198
		return r;
199
	}
200
	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
201
		unsigned offset;
202
 
203
		offset = i * 64 * 1024;
204
		rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset;
205
		rdev->ib_pool.ibs[i].ptr = ptr + offset;
206
		rdev->ib_pool.ibs[i].idx = i;
207
		rdev->ib_pool.ibs[i].length_dw = 0;
208
		INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
209
	}
210
	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
211
	rdev->ib_pool.ready = true;
212
	DRM_INFO("radeon: ib pool ready.\n");
213
	if (radeon_debugfs_ib_init(rdev)) {
214
		DRM_ERROR("Failed to register debugfs file for IB !\n");
215
	}
216
	return r;
217
}
218
 
219
void radeon_ib_pool_fini(struct radeon_device *rdev)
220
{
221
	if (!rdev->ib_pool.ready) {
222
		return;
223
	}
224
	mutex_lock(&rdev->ib_pool.mutex);
225
	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
226
	if (rdev->ib_pool.robj) {
227
		radeon_object_kunmap(rdev->ib_pool.robj);
228
		radeon_object_unref(&rdev->ib_pool.robj);
229
		rdev->ib_pool.robj = NULL;
230
	}
231
	mutex_unlock(&rdev->ib_pool.mutex);
232
}
233
 
234
int radeon_ib_test(struct radeon_device *rdev)
235
{
236
	struct radeon_ib *ib;
237
	uint32_t scratch;
238
	uint32_t tmp = 0;
239
	unsigned i;
240
	int r;
241
 
242
	r = radeon_scratch_get(rdev, &scratch);
243
	if (r) {
244
		DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r);
245
		return r;
246
	}
247
	WREG32(scratch, 0xCAFEDEAD);
248
	r = radeon_ib_get(rdev, &ib);
249
	if (r) {
250
		return r;
251
	}
252
	ib->ptr[0] = PACKET0(scratch, 0);
253
	ib->ptr[1] = 0xDEADBEEF;
254
	ib->ptr[2] = PACKET2(0);
255
	ib->ptr[3] = PACKET2(0);
256
	ib->ptr[4] = PACKET2(0);
257
	ib->ptr[5] = PACKET2(0);
258
	ib->ptr[6] = PACKET2(0);
259
	ib->ptr[7] = PACKET2(0);
260
	ib->length_dw = 8;
261
	r = radeon_ib_schedule(rdev, ib);
262
	if (r) {
263
		radeon_scratch_free(rdev, scratch);
264
		radeon_ib_free(rdev, &ib);
265
		return r;
266
	}
267
	r = radeon_fence_wait(ib->fence, false);
268
	if (r) {
269
		return r;
270
	}
271
	for (i = 0; i < rdev->usec_timeout; i++) {
272
		tmp = RREG32(scratch);
273
		if (tmp == 0xDEADBEEF) {
274
			break;
275
		}
276
		DRM_UDELAY(1);
277
	}
278
	if (i < rdev->usec_timeout) {
279
		DRM_INFO("ib test succeeded in %u usecs\n", i);
280
	} else {
281
		DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
282
			  scratch, tmp);
283
		r = -EINVAL;
284
	}
285
	radeon_scratch_free(rdev, scratch);
286
	radeon_ib_free(rdev, &ib);
287
	return r;
288
}
289
 
290
#endif
291
 
292
/*
293
 * Ring.
294
 */
295
void radeon_ring_free_size(struct radeon_device *rdev)
296
{
297
	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
298
	/* This works because ring_size is a power of 2 */
299
	rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
300
	rdev->cp.ring_free_dw -= rdev->cp.wptr;
301
	rdev->cp.ring_free_dw &= rdev->cp.ptr_mask;
302
	if (!rdev->cp.ring_free_dw) {
303
		rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
304
	}
305
}
306
 
307
int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw)
308
{
309
	int r;
310
 
311
	/* Align requested size with padding so unlock_commit can
312
	 * pad safely */
313
	ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask;
314
//   mutex_lock(&rdev->cp.mutex);
315
	while (ndw > (rdev->cp.ring_free_dw - 1)) {
316
		radeon_ring_free_size(rdev);
317
		if (ndw < rdev->cp.ring_free_dw) {
318
			break;
319
		}
320
        delay(1);
321
 
322
//        r = radeon_fence_wait_next(rdev);
323
//       if (r) {
324
//           mutex_unlock(&rdev->cp.mutex);
325
//           return r;
326
//       }
327
	}
328
	rdev->cp.count_dw = ndw;
329
	rdev->cp.wptr_old = rdev->cp.wptr;
330
	return 0;
331
}
332
 
333
void radeon_ring_unlock_commit(struct radeon_device *rdev)
334
{
335
	unsigned count_dw_pad;
336
	unsigned i;
337
 
338
	/* We pad to match fetch size */
339
	count_dw_pad = (rdev->cp.align_mask + 1) -
340
		       (rdev->cp.wptr & rdev->cp.align_mask);
341
	for (i = 0; i < count_dw_pad; i++) {
342
		radeon_ring_write(rdev, PACKET2(0));
343
	}
344
	DRM_MEMORYBARRIER();
345
	WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
346
	(void)RREG32(RADEON_CP_RB_WPTR);
347
//   mutex_unlock(&rdev->cp.mutex);
348
}
349
 
350
void radeon_ring_unlock_undo(struct radeon_device *rdev)
351
{
352
	rdev->cp.wptr = rdev->cp.wptr_old;
353
 //  mutex_unlock(&rdev->cp.mutex);
354
}
355
 
356
 
357
int radeon_ring_test(struct radeon_device *rdev)
358
{
359
	uint32_t scratch;
360
	uint32_t tmp = 0;
361
	unsigned i;
362
	int r;
363
 
1119 serge 364
    dbgprintf("%s\n",__FUNCTION__);
1117 serge 365
 
366
	r = radeon_scratch_get(rdev, &scratch);
367
	if (r) {
368
		DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r);
369
		return r;
370
	}
371
	WREG32(scratch, 0xCAFEDEAD);
372
	r = radeon_ring_lock(rdev, 2);
373
	if (r) {
374
		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
375
		radeon_scratch_free(rdev, scratch);
376
		return r;
377
	}
378
	radeon_ring_write(rdev, PACKET0(scratch, 0));
379
	radeon_ring_write(rdev, 0xDEADBEEF);
380
	radeon_ring_unlock_commit(rdev);
1119 serge 381
    for (i = 0; i < 100000; i++) {
1117 serge 382
		tmp = RREG32(scratch);
383
		if (tmp == 0xDEADBEEF) {
384
			break;
385
		}
1119 serge 386
        DRM_UDELAY(1);
1117 serge 387
	}
1119 serge 388
    if (i < 100000) {
1117 serge 389
		DRM_INFO("ring test succeeded in %d usecs\n", i);
390
	} else {
391
		DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
392
			  scratch, tmp);
393
		r = -EINVAL;
394
	}
395
	radeon_scratch_free(rdev, scratch);
1119 serge 396
 
397
    dbgprintf("done %s\n",__FUNCTION__);
1117 serge 398
	return r;
399
}
400
 
401
 
1119 serge 402
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
403
             int pages, u32_t *pagelist);
404
 
405
#define page_tabs  0xFDC00000
406
 
407
 
1117 serge 408
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
409
{
410
	int r;
411
 
1119 serge 412
    dbgprintf("%s\n",__FUNCTION__);
1117 serge 413
 
414
	rdev->cp.ring_size = ring_size;
415
 
416
#if 0
417
	/* Allocate ring buffer */
418
	if (rdev->cp.ring_obj == NULL) {
419
		r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
420
					 true,
421
					 RADEON_GEM_DOMAIN_GTT,
422
					 false,
423
					 &rdev->cp.ring_obj);
424
		if (r) {
425
			DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
426
      //     mutex_unlock(&rdev->cp.mutex);
427
			return r;
428
		}
429
		r = radeon_object_pin(rdev->cp.ring_obj,
430
				      RADEON_GEM_DOMAIN_GTT,
431
				      &rdev->cp.gpu_addr);
432
		if (r) {
433
			DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
434
      //     mutex_unlock(&rdev->cp.mutex);
435
			return r;
436
		}
437
		r = radeon_object_kmap(rdev->cp.ring_obj,
438
				       (void **)&rdev->cp.ring);
439
		if (r) {
440
			DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
441
      //     mutex_unlock(&rdev->cp.mutex);
442
			return r;
443
		}
444
	}
445
#endif
446
 
1119 serge 447
    dbgprintf("ring size %x\n", ring_size);
448
 
449
    dbgprintf("ring buffer %x\n", rdev->cp.ring );
450
 
451
    rdev->cp.ring  = ring_buffer; //CreateRingBuffer( ring_size, PG_SW );
452
 
453
    dbgprintf("ring buffer %x\n", rdev->cp.ring );
454
 
455
    rdev->cp.gpu_addr = rdev->mc.gtt_location;
456
 
457
    u32_t *pagelist =  &((u32_t*)page_tabs)[(u32_t)rdev->cp.ring >> 12];
458
 
459
    dbgprintf("pagelist %x\n", pagelist);
460
 
461
    radeon_gart_bind(rdev, 0, ring_size / 4096, pagelist);
462
 
1117 serge 463
	rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
464
	rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
1119 serge 465
 
466
    dbgprintf("done %s\n",__FUNCTION__);
467
 
1117 serge 468
	return 0;
469
}
470
 
471
void radeon_ring_fini(struct radeon_device *rdev)
472
{
473
 //  mutex_lock(&rdev->cp.mutex);
474
   if (rdev->cp.ring_obj) {
475
 //      radeon_object_kunmap(rdev->cp.ring_obj);
476
 //      radeon_object_unpin(rdev->cp.ring_obj);
477
 //      radeon_object_unref(&rdev->cp.ring_obj);
478
       rdev->cp.ring = NULL;
479
		rdev->cp.ring_obj = NULL;
480
	}
481
 //  mutex_unlock(&rdev->cp.mutex);
482
}
483
 
484
 
485
/*
486
 * Debugfs info
487
 */
488
#if defined(CONFIG_DEBUG_FS)
489
static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
490
{
491
	struct drm_info_node *node = (struct drm_info_node *) m->private;
492
	struct radeon_ib *ib = node->info_ent->data;
493
	unsigned i;
494
 
495
	if (ib == NULL) {
496
		return 0;
497
	}
498
	seq_printf(m, "IB %04lu\n", ib->idx);
499
	seq_printf(m, "IB fence %p\n", ib->fence);
500
	seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
501
	for (i = 0; i < ib->length_dw; i++) {
502
		seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
503
	}
504
	return 0;
505
}
506
 
507
static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
508
static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
509
#endif
510
 
511
int radeon_debugfs_ib_init(struct radeon_device *rdev)
512
{
513
#if defined(CONFIG_DEBUG_FS)
514
	unsigned i;
515
 
516
	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
517
		sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
518
		radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
519
		radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
520
		radeon_debugfs_ib_list[i].driver_features = 0;
521
		radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i];
522
	}
523
	return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
524
					RADEON_IB_POOL_SIZE);
525
#else
526
	return 0;
527
#endif
528
}
529
 
530
 
531
int drm_order(unsigned long size)
532
{
533
    int order;
534
    unsigned long tmp;
535
 
536
    for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
537
 
538
    if (size & (size - 1))
539
        ++order;
540
 
541
    return order;
542
}
543