blob: aa9837a6aa75ffa37788180024cf1d4e81f5aa39 [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
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 <linux/seq_file.h>
29#include "drmP.h"
30#include "radeon_drm.h"
31#include "radeon_reg.h"
32#include "radeon.h"
33#include "atom.h"
34
35int radeon_debugfs_ib_init(struct radeon_device *rdev);
36
37/*
38 * IB.
39 */
40int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
41{
42 struct radeon_fence *fence;
43 struct radeon_ib *nib;
44 unsigned long i;
45 int r = 0;
46
47 *ib = NULL;
48 r = radeon_fence_create(rdev, &fence);
49 if (r) {
50 DRM_ERROR("failed to create fence for new IB\n");
51 return r;
52 }
53 mutex_lock(&rdev->ib_pool.mutex);
54 i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
55 if (i < RADEON_IB_POOL_SIZE) {
56 set_bit(i, rdev->ib_pool.alloc_bm);
57 rdev->ib_pool.ibs[i].length_dw = 0;
58 *ib = &rdev->ib_pool.ibs[i];
59 goto out;
60 }
61 if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
62 /* we go do nothings here */
63 DRM_ERROR("all IB allocated none scheduled.\n");
64 r = -EINVAL;
65 goto out;
66 }
67 /* get the first ib on the scheduled list */
68 nib = list_entry(rdev->ib_pool.scheduled_ibs.next,
69 struct radeon_ib, list);
70 if (nib->fence == NULL) {
71 /* we go do nothings here */
72 DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
73 r = -EINVAL;
74 goto out;
75 }
76 r = radeon_fence_wait(nib->fence, false);
77 if (r) {
78 DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
79 (unsigned long)nib->gpu_addr, nib->length_dw);
80 DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n");
81 goto out;
82 }
83 radeon_fence_unref(&nib->fence);
84 nib->length_dw = 0;
85 list_del(&nib->list);
86 INIT_LIST_HEAD(&nib->list);
87 *ib = nib;
88out:
89 mutex_unlock(&rdev->ib_pool.mutex);
90 if (r) {
91 radeon_fence_unref(&fence);
92 } else {
93 (*ib)->fence = fence;
94 }
95 return r;
96}
97
98void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
99{
100 struct radeon_ib *tmp = *ib;
101
102 *ib = NULL;
103 if (tmp == NULL) {
104 return;
105 }
106 mutex_lock(&rdev->ib_pool.mutex);
107 if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) {
108 /* IB is scheduled & not signaled don't do anythings */
109 mutex_unlock(&rdev->ib_pool.mutex);
110 return;
111 }
112 list_del(&tmp->list);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200113 if (tmp->fence) {
114 radeon_fence_unref(&tmp->fence);
115 }
116 tmp->length_dw = 0;
117 clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
118 mutex_unlock(&rdev->ib_pool.mutex);
119}
120
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200121int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
122{
123 int r = 0;
124
125 mutex_lock(&rdev->ib_pool.mutex);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200126 if (!ib->length_dw || !rdev->cp.ready) {
127 /* TODO: Nothings in the ib we should report. */
128 mutex_unlock(&rdev->ib_pool.mutex);
129 DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
130 return -EINVAL;
131 }
Dave Airlie6cdf6582009-06-29 18:29:13 +1000132 /* 64 dwords should be enough for fence too */
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200133 r = radeon_ring_lock(rdev, 64);
134 if (r) {
135 DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
136 mutex_unlock(&rdev->ib_pool.mutex);
137 return r;
138 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000139 radeon_ring_ib_execute(rdev, ib);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200140 radeon_fence_emit(rdev, ib->fence);
141 radeon_ring_unlock_commit(rdev);
142 list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
143 mutex_unlock(&rdev->ib_pool.mutex);
144 return 0;
145}
146
147int radeon_ib_pool_init(struct radeon_device *rdev)
148{
149 void *ptr;
150 uint64_t gpu_addr;
151 int i;
152 int r = 0;
153
154 /* Allocate 1M object buffer */
155 INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
156 r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
157 true, RADEON_GEM_DOMAIN_GTT,
158 false, &rdev->ib_pool.robj);
159 if (r) {
160 DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
161 return r;
162 }
163 r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
164 if (r) {
165 DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
166 return r;
167 }
168 r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
169 if (r) {
170 DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
171 return r;
172 }
173 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
174 unsigned offset;
175
176 offset = i * 64 * 1024;
177 rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset;
178 rdev->ib_pool.ibs[i].ptr = ptr + offset;
179 rdev->ib_pool.ibs[i].idx = i;
180 rdev->ib_pool.ibs[i].length_dw = 0;
181 INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
182 }
183 bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
184 rdev->ib_pool.ready = true;
185 DRM_INFO("radeon: ib pool ready.\n");
186 if (radeon_debugfs_ib_init(rdev)) {
187 DRM_ERROR("Failed to register debugfs file for IB !\n");
188 }
189 return r;
190}
191
192void radeon_ib_pool_fini(struct radeon_device *rdev)
193{
194 if (!rdev->ib_pool.ready) {
195 return;
196 }
197 mutex_lock(&rdev->ib_pool.mutex);
198 bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
199 if (rdev->ib_pool.robj) {
200 radeon_object_kunmap(rdev->ib_pool.robj);
201 radeon_object_unref(&rdev->ib_pool.robj);
202 rdev->ib_pool.robj = NULL;
203 }
204 mutex_unlock(&rdev->ib_pool.mutex);
205}
206
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200207
208/*
209 * Ring.
210 */
211void radeon_ring_free_size(struct radeon_device *rdev)
212{
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000213 if (rdev->family >= CHIP_R600)
214 rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
215 else
216 rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200217 /* This works because ring_size is a power of 2 */
218 rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
219 rdev->cp.ring_free_dw -= rdev->cp.wptr;
220 rdev->cp.ring_free_dw &= rdev->cp.ptr_mask;
221 if (!rdev->cp.ring_free_dw) {
222 rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
223 }
224}
225
226int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw)
227{
228 int r;
229
230 /* Align requested size with padding so unlock_commit can
231 * pad safely */
232 ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask;
233 mutex_lock(&rdev->cp.mutex);
234 while (ndw > (rdev->cp.ring_free_dw - 1)) {
235 radeon_ring_free_size(rdev);
236 if (ndw < rdev->cp.ring_free_dw) {
237 break;
238 }
239 r = radeon_fence_wait_next(rdev);
240 if (r) {
241 mutex_unlock(&rdev->cp.mutex);
242 return r;
243 }
244 }
245 rdev->cp.count_dw = ndw;
246 rdev->cp.wptr_old = rdev->cp.wptr;
247 return 0;
248}
249
250void radeon_ring_unlock_commit(struct radeon_device *rdev)
251{
252 unsigned count_dw_pad;
253 unsigned i;
254
255 /* We pad to match fetch size */
256 count_dw_pad = (rdev->cp.align_mask + 1) -
257 (rdev->cp.wptr & rdev->cp.align_mask);
258 for (i = 0; i < count_dw_pad; i++) {
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000259 radeon_ring_write(rdev, 2 << 30);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200260 }
261 DRM_MEMORYBARRIER();
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000262 radeon_cp_commit(rdev);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200263 mutex_unlock(&rdev->cp.mutex);
264}
265
266void radeon_ring_unlock_undo(struct radeon_device *rdev)
267{
268 rdev->cp.wptr = rdev->cp.wptr_old;
269 mutex_unlock(&rdev->cp.mutex);
270}
271
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200272int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
273{
274 int r;
275
276 rdev->cp.ring_size = ring_size;
277 /* Allocate ring buffer */
278 if (rdev->cp.ring_obj == NULL) {
279 r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
280 true,
281 RADEON_GEM_DOMAIN_GTT,
282 false,
283 &rdev->cp.ring_obj);
284 if (r) {
285 DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
286 mutex_unlock(&rdev->cp.mutex);
287 return r;
288 }
289 r = radeon_object_pin(rdev->cp.ring_obj,
290 RADEON_GEM_DOMAIN_GTT,
291 &rdev->cp.gpu_addr);
292 if (r) {
293 DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
294 mutex_unlock(&rdev->cp.mutex);
295 return r;
296 }
297 r = radeon_object_kmap(rdev->cp.ring_obj,
298 (void **)&rdev->cp.ring);
299 if (r) {
300 DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
301 mutex_unlock(&rdev->cp.mutex);
302 return r;
303 }
304 }
305 rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
306 rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
307 return 0;
308}
309
310void radeon_ring_fini(struct radeon_device *rdev)
311{
312 mutex_lock(&rdev->cp.mutex);
313 if (rdev->cp.ring_obj) {
314 radeon_object_kunmap(rdev->cp.ring_obj);
315 radeon_object_unpin(rdev->cp.ring_obj);
316 radeon_object_unref(&rdev->cp.ring_obj);
317 rdev->cp.ring = NULL;
318 rdev->cp.ring_obj = NULL;
319 }
320 mutex_unlock(&rdev->cp.mutex);
321}
322
323
324/*
325 * Debugfs info
326 */
327#if defined(CONFIG_DEBUG_FS)
328static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
329{
330 struct drm_info_node *node = (struct drm_info_node *) m->private;
331 struct radeon_ib *ib = node->info_ent->data;
332 unsigned i;
333
334 if (ib == NULL) {
335 return 0;
336 }
337 seq_printf(m, "IB %04lu\n", ib->idx);
338 seq_printf(m, "IB fence %p\n", ib->fence);
339 seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
340 for (i = 0; i < ib->length_dw; i++) {
341 seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
342 }
343 return 0;
344}
345
346static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
347static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
348#endif
349
350int radeon_debugfs_ib_init(struct radeon_device *rdev)
351{
352#if defined(CONFIG_DEBUG_FS)
353 unsigned i;
354
355 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
356 sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
357 radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
358 radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
359 radeon_debugfs_ib_list[i].driver_features = 0;
360 radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i];
361 }
362 return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
363 RADEON_IB_POOL_SIZE);
364#else
365 return 0;
366#endif
367}