Subversion Repositories Kolibri OS

Rev

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