Subversion Repositories Kolibri OS

Rev

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