Rev 2005 | Rev 3764 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2005 | Rev 2997 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: Dave Airlie |
24 | * Authors: Dave Airlie |
25 | * Alex Deucher |
25 | * Alex Deucher |
26 | * Jerome Glisse |
26 | * Jerome Glisse |
- | 27 | * Christian Konig |
|
27 | */ |
28 | */ |
28 | #include |
29 | #include |
29 | #include |
30 | #include |
30 | #include "drmP.h" |
31 | #include |
31 | #include "radeon_drm.h" |
32 | #include |
32 | #include "radeon_reg.h" |
33 | #include "radeon_reg.h" |
33 | #include "radeon.h" |
34 | #include "radeon.h" |
34 | #include "atom.h" |
35 | #include "atom.h" |
Line 35... | Line -... | ||
35 | - | ||
36 | int radeon_debugfs_ib_init(struct radeon_device *rdev); |
- | |
37 | 36 | ||
38 | /* |
37 | /* |
- | 38 | * IB |
|
- | 39 | * IBs (Indirect Buffers) and areas of GPU accessible memory where |
|
- | 40 | * commands are stored. You can put a pointer to the IB in the |
|
- | 41 | * command ring and the hw will fetch the commands from the IB |
|
- | 42 | * and execute them. Generally userspace acceleration drivers |
|
- | 43 | * produce command buffers which are send to the kernel and |
|
39 | * IB. |
44 | * put in IBs for execution by the requested ring. |
- | 45 | */ |
|
- | 46 | static int radeon_debugfs_sa_init(struct radeon_device *rdev); |
|
- | 47 | ||
- | 48 | /** |
|
- | 49 | * radeon_ib_get - request an IB (Indirect Buffer) |
|
- | 50 | * |
|
- | 51 | * @rdev: radeon_device pointer |
|
- | 52 | * @ring: ring index the IB is associated with |
|
- | 53 | * @ib: IB object returned |
|
- | 54 | * @size: requested IB size |
|
- | 55 | * |
|
- | 56 | * Request an IB (all asics). IBs are allocated using the |
|
- | 57 | * suballocator. |
|
- | 58 | * Returns 0 on success, error on failure. |
|
40 | */ |
59 | */ |
- | 60 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
|
- | 61 | struct radeon_ib *ib, struct radeon_vm *vm, |
|
41 | int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) |
62 | unsigned size) |
42 | { |
- | |
43 | struct radeon_fence *fence; |
- | |
44 | struct radeon_ib *nib; |
63 | { |
Line 45... | Line -... | ||
45 | int r = 0, i, c; |
- | |
46 | 64 | int i, r; |
|
47 | *ib = NULL; |
65 | |
48 | r = radeon_fence_create(rdev, &fence); |
66 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); |
49 | if (r) { |
67 | if (r) { |
50 | dev_err(rdev->dev, "failed to create fence for new IB\n"); |
68 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
51 | return r; |
- | |
52 | } |
- | |
53 | mutex_lock(&rdev->ib_pool.mutex); |
- | |
54 | for (i = rdev->ib_pool.head_id, c = 0, nib = NULL; c < RADEON_IB_POOL_SIZE; c++, i++) { |
- | |
55 | i &= (RADEON_IB_POOL_SIZE - 1); |
- | |
56 | if (rdev->ib_pool.ibs[i].free) { |
- | |
57 | nib = &rdev->ib_pool.ibs[i]; |
- | |
58 | break; |
69 | return r; |
59 | } |
- | |
60 | } |
- | |
61 | if (nib == NULL) { |
- | |
62 | /* This should never happen, it means we allocated all |
- | |
63 | * IB and haven't scheduled one yet, return EBUSY to |
- | |
64 | * userspace hoping that on ioctl recall we get better |
- | |
65 | * luck |
- | |
66 | */ |
- | |
67 | dev_err(rdev->dev, "no free indirect buffer !\n"); |
- | |
68 | mutex_unlock(&rdev->ib_pool.mutex); |
- | |
69 | radeon_fence_unref(&fence); |
- | |
70 | return -EBUSY; |
- | |
71 | } |
- | |
72 | rdev->ib_pool.head_id = (nib->idx + 1) & (RADEON_IB_POOL_SIZE - 1); |
- | |
73 | nib->free = false; |
- | |
74 | if (nib->fence) { |
70 | } |
75 | mutex_unlock(&rdev->ib_pool.mutex); |
71 | |
76 | r = radeon_fence_wait(nib->fence, false); |
- | |
77 | if (r) { |
- | |
78 | dev_err(rdev->dev, "error waiting fence of IB(%u:0x%016lX:%u)\n", |
- | |
79 | nib->idx, (unsigned long)nib->gpu_addr, nib->length_dw); |
- | |
80 | mutex_lock(&rdev->ib_pool.mutex); |
- | |
81 | nib->free = true; |
- | |
82 | mutex_unlock(&rdev->ib_pool.mutex); |
72 | r = radeon_semaphore_create(rdev, &ib->semaphore); |
83 | radeon_fence_unref(&fence); |
73 | if (r) { |
- | 74 | return r; |
|
- | 75 | } |
|
- | 76 | ||
- | 77 | ib->ring = ring; |
|
- | 78 | ib->fence = NULL; |
|
- | 79 | ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); |
|
- | 80 | ib->vm = vm; |
|
- | 81 | if (vm) { |
|
- | 82 | /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address |
|
- | 83 | * space and soffset is the offset inside the pool bo |
|
- | 84 | */ |
|
84 | return r; |
85 | ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET; |
85 | } |
86 | } else { |
86 | mutex_lock(&rdev->ib_pool.mutex); |
- | |
87 | } |
87 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); |
88 | radeon_fence_unref(&nib->fence); |
- | |
89 | nib->fence = fence; |
88 | } |
90 | nib->length_dw = 0; |
89 | ib->is_const_ib = false; |
- | 90 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
|
91 | mutex_unlock(&rdev->ib_pool.mutex); |
91 | ib->sync_to[i] = NULL; |
92 | *ib = nib; |
92 | |
Line -... | Line 93... | ||
- | 93 | return 0; |
|
- | 94 | } |
|
- | 95 | ||
- | 96 | /** |
|
- | 97 | * radeon_ib_free - free an IB (Indirect Buffer) |
|
- | 98 | * |
|
- | 99 | * @rdev: radeon_device pointer |
|
- | 100 | * @ib: IB object to free |
|
93 | return 0; |
101 | * |
94 | } |
102 | * Free an IB (all asics). |
95 | 103 | */ |
|
96 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) |
- | |
97 | { |
- | |
98 | struct radeon_ib *tmp = *ib; |
- | |
99 | - | ||
100 | *ib = NULL; |
- | |
101 | if (tmp == NULL) { |
104 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
102 | return; |
105 | { |
103 | } |
- | |
104 | if (!tmp->fence->emited) |
- | |
105 | radeon_fence_unref(&tmp->fence); |
- | |
106 | mutex_lock(&rdev->ib_pool.mutex); |
106 | radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); |
Line -... | Line 107... | ||
- | 107 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); |
|
- | 108 | radeon_fence_unref(&ib->fence); |
|
- | 109 | } |
|
- | 110 | ||
- | 111 | /** |
|
- | 112 | * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring |
|
- | 113 | * |
|
- | 114 | * @rdev: radeon_device pointer |
|
- | 115 | * @ib: IB object to schedule |
|
- | 116 | * @const_ib: Const IB to schedule (SI only) |
|
- | 117 | * |
|
- | 118 | * Schedule an IB on the associated ring (all asics). |
|
- | 119 | * Returns 0 on success, error on failure. |
|
- | 120 | * |
|
- | 121 | * On SI, there are two parallel engines fed from the primary ring, |
|
- | 122 | * the CE (Constant Engine) and the DE (Drawing Engine). Since |
|
- | 123 | * resource descriptors have moved to memory, the CE allows you to |
|
- | 124 | * prime the caches while the DE is updating register state so that |
|
- | 125 | * the resource descriptors will be already in cache when the draw is |
|
- | 126 | * processed. To accomplish this, the userspace driver submits two |
|
107 | tmp->free = true; |
127 | * IBs, one for the CE and one for the DE. If there is a CE IB (called |
- | 128 | * a CONST_IB), it will be put on the ring prior to the DE IB. Prior |
|
108 | mutex_unlock(&rdev->ib_pool.mutex); |
129 | * to SI there was just a DE IB. |
- | 130 | */ |
|
- | 131 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, |
|
109 | } |
132 | struct radeon_ib *const_ib) |
Line 110... | Line 133... | ||
110 | 133 | { |
|
111 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) |
134 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
112 | { |
135 | bool need_sync = false; |
113 | int r = 0; |
136 | int i, r = 0; |
114 | 137 | ||
Line 115... | Line 138... | ||
115 | if (!ib->length_dw || !rdev->cp.ready) { |
138 | if (!ib->length_dw || !ring->ready) { |
116 | /* TODO: Nothings in the ib we should report. */ |
139 | /* TODO: Nothings in the ib we should report. */ |
- | 140 | dev_err(rdev->dev, "couldn't schedule ib\n"); |
|
- | 141 | return -EINVAL; |
|
- | 142 | } |
|
- | 143 | ||
- | 144 | /* 64 dwords should be enough for fence too */ |
|
- | 145 | r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); |
|
- | 146 | if (r) { |
|
- | 147 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); |
|
- | 148 | return r; |
|
- | 149 | } |
|
- | 150 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
|
- | 151 | struct radeon_fence *fence = ib->sync_to[i]; |
|
- | 152 | if (radeon_fence_need_sync(fence, ib->ring)) { |
|
- | 153 | need_sync = true; |
|
- | 154 | radeon_semaphore_sync_rings(rdev, ib->semaphore, |
|
- | 155 | fence->ring, ib->ring); |
|
- | 156 | radeon_fence_note_sync(fence, ib->ring); |
|
- | 157 | } |
|
- | 158 | } |
|
- | 159 | /* immediately free semaphore when we don't need to sync */ |
|
- | 160 | if (!need_sync) { |
|
- | 161 | radeon_semaphore_free(rdev, &ib->semaphore, NULL); |
|
- | 162 | } |
|
- | 163 | /* if we can't remember our last VM flush then flush now! */ |
|
- | 164 | if (ib->vm && !ib->vm->last_flush) { |
|
- | 165 | radeon_ring_vm_flush(rdev, ib->ring, ib->vm); |
|
- | 166 | } |
|
117 | DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx); |
167 | if (const_ib) { |
118 | return -EINVAL; |
168 | radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); |
- | 169 | radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); |
|
119 | } |
170 | } |
120 | 171 | radeon_ring_ib_execute(rdev, ib->ring, ib); |
|
121 | /* 64 dwords should be enough for fence too */ |
172 | r = radeon_fence_emit(rdev, &ib->fence, ib->ring); |
122 | r = radeon_ring_lock(rdev, 64); |
173 | if (r) { |
123 | if (r) { |
- | |
- | 174 | dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r); |
|
124 | DRM_ERROR("radeon: scheduling IB failed (%d).\n", r); |
175 | radeon_ring_unlock_undo(rdev, ring); |
125 | return r; |
176 | return r; |
126 | } |
177 | } |
- | 178 | if (const_ib) { |
|
127 | radeon_ring_ib_execute(rdev, ib); |
179 | const_ib->fence = radeon_fence_ref(ib->fence); |
128 | radeon_fence_emit(rdev, ib->fence); |
180 | } |
129 | mutex_lock(&rdev->ib_pool.mutex); |
181 | /* we just flushed the VM, remember that */ |
Line -... | Line 182... | ||
- | 182 | if (ib->vm && !ib->vm->last_flush) { |
|
- | 183 | ib->vm->last_flush = radeon_fence_ref(ib->fence); |
|
- | 184 | } |
|
- | 185 | radeon_ring_unlock_commit(rdev, ring); |
|
- | 186 | return 0; |
|
- | 187 | } |
|
- | 188 | ||
- | 189 | /** |
|
- | 190 | * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool |
|
130 | /* once scheduled IB is considered free and protected by the fence */ |
191 | * |
131 | ib->free = true; |
192 | * @rdev: radeon_device pointer |
132 | mutex_unlock(&rdev->ib_pool.mutex); |
- | |
133 | radeon_ring_unlock_commit(rdev); |
- | |
134 | return 0; |
193 | * |
135 | } |
- | |
Line 136... | Line 194... | ||
136 | 194 | * Initialize the suballocator to manage a pool of memory |
|
137 | int radeon_ib_pool_init(struct radeon_device *rdev) |
195 | * for use as IBs (all asics). |
138 | { |
- | |
139 | void *ptr; |
- | |
140 | uint64_t gpu_addr; |
- | |
141 | int i; |
- | |
142 | int r = 0; |
- | |
143 | - | ||
144 | if (rdev->ib_pool.robj) |
- | |
145 | return 0; |
- | |
146 | INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib); |
196 | * Returns 0 on success, error on failure. |
147 | /* Allocate 1M object buffer */ |
197 | */ |
148 | r = radeon_bo_create(rdev, RADEON_IB_POOL_SIZE*64*1024, |
198 | int radeon_ib_pool_init(struct radeon_device *rdev) |
149 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, |
- | |
150 | &rdev->ib_pool.robj); |
199 | { |
151 | if (r) { |
200 | int r; |
152 | DRM_ERROR("radeon: failed to ib pool (%d).\n", r); |
- | |
153 | return r; |
- | |
154 | } |
201 | |
155 | r = radeon_bo_reserve(rdev->ib_pool.robj, false); |
202 | if (rdev->ib_pool_ready) { |
- | 203 | return 0; |
|
156 | if (unlikely(r != 0)) |
204 | } |
157 | return r; |
- | |
158 | r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr); |
205 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, |
159 | if (r) { |
- | |
160 | radeon_bo_unreserve(rdev->ib_pool.robj); |
206 | RADEON_IB_POOL_SIZE*64*1024, |
161 | DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r); |
207 | RADEON_GEM_DOMAIN_GTT); |
162 | return r; |
- | |
163 | } |
- | |
Line 164... | Line -... | ||
164 | r = radeon_bo_kmap(rdev->ib_pool.robj, &ptr); |
- | |
165 | radeon_bo_unreserve(rdev->ib_pool.robj); |
- | |
166 | if (r) { |
- | |
167 | DRM_ERROR("radeon: failed to map ib pool (%d).\n", r); |
- | |
168 | return r; |
- | |
169 | } |
- | |
170 | for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { |
- | |
171 | unsigned offset; |
- | |
172 | 208 | if (r) { |
|
173 | offset = i * 64 * 1024; |
- | |
174 | rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset; |
209 | return r; |
175 | rdev->ib_pool.ibs[i].ptr = ptr + offset; |
210 | } |
176 | rdev->ib_pool.ibs[i].idx = i; |
211 | |
177 | rdev->ib_pool.ibs[i].length_dw = 0; |
212 | r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); |
178 | rdev->ib_pool.ibs[i].free = true; |
213 | if (r) { |
Line -... | Line 214... | ||
- | 214 | return r; |
|
- | 215 | } |
|
- | 216 | ||
- | 217 | rdev->ib_pool_ready = true; |
|
- | 218 | if (radeon_debugfs_sa_init(rdev)) { |
|
- | 219 | dev_err(rdev->dev, "failed to register debugfs file for SA\n"); |
|
- | 220 | } |
|
- | 221 | return 0; |
|
179 | } |
222 | } |
180 | rdev->ib_pool.head_id = 0; |
223 | |
- | 224 | /** |
|
- | 225 | * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool |
|
- | 226 | * |
|
- | 227 | * @rdev: radeon_device pointer |
|
- | 228 | * |
|
- | 229 | * Tear down the suballocator managing the pool of memory |
|
- | 230 | * for use as IBs (all asics). |
|
- | 231 | */ |
|
- | 232 | void radeon_ib_pool_fini(struct radeon_device *rdev) |
|
- | 233 | { |
|
- | 234 | if (rdev->ib_pool_ready) { |
|
- | 235 | radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); |
|
- | 236 | radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); |
|
- | 237 | rdev->ib_pool_ready = false; |
|
- | 238 | } |
|
- | 239 | } |
|
- | 240 | ||
- | 241 | /** |
|
- | 242 | * radeon_ib_ring_tests - test IBs on the rings |
|
- | 243 | * |
|
181 | rdev->ib_pool.ready = true; |
244 | * @rdev: radeon_device pointer |
182 | DRM_INFO("radeon: ib pool ready.\n"); |
- | |
Line 183... | Line 245... | ||
183 | if (radeon_debugfs_ib_init(rdev)) { |
245 | * |
184 | DRM_ERROR("Failed to register debugfs file for IB !\n"); |
- | |
185 | } |
- | |
186 | return r; |
- | |
187 | } |
246 | * Test an IB (Indirect Buffer) on each ring. |
188 | - | ||
189 | void radeon_ib_pool_fini(struct radeon_device *rdev) |
- | |
190 | { |
- | |
Line 191... | Line 247... | ||
191 | int r; |
247 | * If the test fails, disable the ring. |
- | 248 | * Returns 0 on success, error if the primary GFX ring |
|
- | 249 | * IB test fails. |
|
192 | struct radeon_bo *robj; |
250 | */ |
193 | 251 | int radeon_ib_ring_tests(struct radeon_device *rdev) |
|
194 | if (!rdev->ib_pool.ready) { |
252 | { |
- | 253 | unsigned i; |
|
- | 254 | int r; |
|
- | 255 | ||
- | 256 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
|
- | 257 | struct radeon_ring *ring = &rdev->ring[i]; |
|
195 | return; |
258 | |
- | 259 | if (!ring->ready) |
|
- | 260 | continue; |
|
196 | } |
261 | |
- | 262 | r = radeon_ib_test(rdev, i, ring); |
|
197 | mutex_lock(&rdev->ib_pool.mutex); |
263 | if (r) { |
198 | // radeon_ib_bogus_cleanup(rdev); |
- | |
199 | robj = rdev->ib_pool.robj; |
264 | ring->ready = false; |
200 | rdev->ib_pool.robj = NULL; |
265 | |
- | 266 | if (i == RADEON_RING_TYPE_GFX_INDEX) { |
|
201 | mutex_unlock(&rdev->ib_pool.mutex); |
267 | /* oh, oh, that's really bad */ |
Line 202... | Line 268... | ||
202 | 268 | DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r); |
|
203 | if (robj) { |
269 | rdev->accel_working = false; |
- | 270 | return r; |
|
- | 271 | ||
- | 272 | } else { |
|
- | 273 | /* still not good, but we can live with it */ |
|
- | 274 | DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r); |
|
- | 275 | } |
|
- | 276 | } |
|
- | 277 | } |
|
- | 278 | return 0; |
|
- | 279 | } |
|
- | 280 | ||
- | 281 | /* |
|
- | 282 | * Rings |
|
- | 283 | * Most engines on the GPU are fed via ring buffers. Ring |
|
- | 284 | * buffers are areas of GPU accessible memory that the host |
|
- | 285 | * writes commands into and the GPU reads commands out of. |
|
- | 286 | * There is a rptr (read pointer) that determines where the |
|
- | 287 | * GPU is currently reading, and a wptr (write pointer) |
|
- | 288 | * which determines where the host has written. When the |
|
- | 289 | * pointers are equal, the ring is idle. When the host |
|
- | 290 | * writes commands to the ring buffer, it increments the |
|
- | 291 | * wptr. The GPU then starts fetching commands and executes |
|
- | 292 | * them until the pointers are equal again. |
|
- | 293 | */ |
|
- | 294 | static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); |
|
- | 295 | ||
- | 296 | /** |
|
- | 297 | * radeon_ring_write - write a value to the ring |
|
- | 298 | * |
|
- | 299 | * @ring: radeon_ring structure holding ring information |
|
- | 300 | * @v: dword (dw) value to write |
|
- | 301 | * |
|
- | 302 | * Write a value to the requested ring buffer (all asics). |
|
- | 303 | */ |
|
- | 304 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) |
|
- | 305 | { |
|
- | 306 | #if DRM_DEBUG_CODE |
|
- | 307 | if (ring->count_dw <= 0) { |
|
- | 308 | DRM_ERROR("radeon: writing more dwords to the ring than expected!\n"); |
|
- | 309 | } |
|
- | 310 | #endif |
|
- | 311 | ring->ring[ring->wptr++] = v; |
|
- | 312 | ring->wptr &= ring->ptr_mask; |
|
204 | r = radeon_bo_reserve(robj, false); |
313 | ring->count_dw--; |
205 | if (likely(r == 0)) { |
314 | ring->ring_free_dw--; |
- | 315 | } |
|
206 | radeon_bo_kunmap(robj); |
316 | |
- | 317 | /** |
|
- | 318 | * radeon_ring_supports_scratch_reg - check if the ring supports |
|
- | 319 | * writing to scratch registers |
|
- | 320 | * |
|
- | 321 | * @rdev: radeon_device pointer |
|
- | 322 | * @ring: radeon_ring structure holding ring information |
|
- | 323 | * |
|
- | 324 | * Check if a specific ring supports writing to scratch registers (all asics). |
|
- | 325 | * Returns true if the ring supports writing to scratch regs, false if not. |
|
- | 326 | */ |
|
- | 327 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, |
|
- | 328 | struct radeon_ring *ring) |
|
- | 329 | { |
|
- | 330 | switch (ring->idx) { |
|
- | 331 | case RADEON_RING_TYPE_GFX_INDEX: |
|
- | 332 | case CAYMAN_RING_TYPE_CP1_INDEX: |
|
- | 333 | case CAYMAN_RING_TYPE_CP2_INDEX: |
|
- | 334 | return true; |
|
- | 335 | default: |
|
- | 336 | return false; |
|
- | 337 | } |
|
- | 338 | } |
|
207 | radeon_bo_unpin(robj); |
339 | |
208 | radeon_bo_unreserve(robj); |
340 | /** |
209 | } |
- | |
210 | radeon_bo_unref(&robj); |
- | |
211 | } |
- | |
212 | } |
341 | * radeon_ring_free_size - update the free size |
213 | 342 | * |
|
214 | - | ||
- | 343 | * @rdev: radeon_device pointer |
|
215 | /* |
344 | * @ring: radeon_ring structure holding ring information |
216 | * Ring. |
345 | * |
217 | */ |
346 | * Update the free dw slots in the ring buffer (all asics). |
218 | void radeon_ring_free_size(struct radeon_device *rdev) |
347 | */ |
219 | { |
348 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
220 | if (rdev->wb.enabled) |
349 | { |
221 | rdev->cp.rptr = le32_to_cpu(rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4]); |
350 | u32 rptr; |
222 | else { |
351 | |
Line -... | Line 352... | ||
- | 352 | if (rdev->wb.enabled) |
|
- | 353 | rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); |
|
- | 354 | else |
|
- | 355 | rptr = RREG32(ring->rptr_reg); |
|
- | 356 | ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; |
|
- | 357 | /* This works because ring_size is a power of 2 */ |
|
- | 358 | ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4)); |
|
- | 359 | ring->ring_free_dw -= ring->wptr; |
|
- | 360 | ring->ring_free_dw &= ring->ptr_mask; |
|
- | 361 | if (!ring->ring_free_dw) { |
|
223 | if (rdev->family >= CHIP_R600) |
362 | ring->ring_free_dw = ring->ring_size / 4; |
224 | rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); |
363 | } |
225 | else |
364 | } |
Line 226... | Line 365... | ||
226 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); |
365 | |
227 | } |
366 | /** |
228 | /* This works because ring_size is a power of 2 */ |
367 | * radeon_ring_alloc - allocate space on the ring buffer |
229 | rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); |
368 | * |
230 | rdev->cp.ring_free_dw -= rdev->cp.wptr; |
369 | * @rdev: radeon_device pointer |
231 | rdev->cp.ring_free_dw &= rdev->cp.ptr_mask; |
370 | * @ring: radeon_ring structure holding ring information |
232 | if (!rdev->cp.ring_free_dw) { |
371 | * @ndw: number of dwords to allocate in the ring buffer |
233 | rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; |
372 | * |
234 | } |
373 | * Allocate @ndw dwords in the ring buffer (all asics). |
235 | } |
374 | * Returns 0 on success, error on failure. |
236 | 375 | */ |
|
237 | int radeon_ring_alloc(struct radeon_device *rdev, unsigned ndw) |
376 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
238 | { |
377 | { |
239 | int r; |
378 | int r; |
240 | 379 | ||
241 | /* Align requested size with padding so unlock_commit can |
380 | /* Align requested size with padding so unlock_commit can |
242 | * pad safely */ |
381 | * pad safely */ |
243 | ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask; |
382 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; |
Line -... | Line 383... | ||
- | 383 | while (ndw > (ring->ring_free_dw - 1)) { |
|
- | 384 | radeon_ring_free_size(rdev, ring); |
|
- | 385 | if (ndw < ring->ring_free_dw) { |
|
- | 386 | break; |
|
- | 387 | } |
|
- | 388 | // r = radeon_fence_wait_next(rdev); |
|
- | 389 | // if (r) { |
|
- | 390 | // mutex_unlock(&rdev->cp.mutex); |
|
- | 391 | // return r; |
|
- | 392 | // } |
|
- | 393 | } |
|
244 | while (ndw > (rdev->cp.ring_free_dw - 1)) { |
394 | ring->count_dw = ndw; |
245 | radeon_ring_free_size(rdev); |
395 | ring->wptr_old = ring->wptr; |
246 | if (ndw < rdev->cp.ring_free_dw) { |
396 | return 0; |
Line 247... | Line 397... | ||
247 | break; |
397 | } |
248 | } |
398 | |
249 | // r = radeon_fence_wait_next(rdev); |
399 | /** |
250 | // if (r) { |
400 | * radeon_ring_lock - lock the ring and allocate space on it |
251 | // mutex_unlock(&rdev->cp.mutex); |
401 | * |
252 | // return r; |
402 | * @rdev: radeon_device pointer |
253 | // } |
403 | * @ring: radeon_ring structure holding ring information |
254 | } |
404 | * @ndw: number of dwords to allocate in the ring buffer |
Line -... | Line 405... | ||
- | 405 | * |
|
- | 406 | * Lock the ring and allocate @ndw dwords in the ring buffer |
|
- | 407 | * (all asics). |
|
- | 408 | * Returns 0 on success, error on failure. |
|
- | 409 | */ |
|
- | 410 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
|
- | 411 | { |
|
- | 412 | int r; |
|
- | 413 | ||
- | 414 | mutex_lock(&rdev->ring_lock); |
|
255 | rdev->cp.count_dw = ndw; |
415 | r = radeon_ring_alloc(rdev, ring, ndw); |
256 | rdev->cp.wptr_old = rdev->cp.wptr; |
416 | if (r) { |
257 | return 0; |
- | |
258 | } |
- | |
259 | - | ||
260 | int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw) |
417 | mutex_unlock(&rdev->ring_lock); |
261 | { |
- | |
262 | int r; |
418 | return r; |
263 | - | ||
264 | mutex_lock(&rdev->cp.mutex); |
419 | } |
265 | r = radeon_ring_alloc(rdev, ndw); |
420 | return 0; |
266 | if (r) { |
421 | } |
- | 422 | ||
- | 423 | /** |
|
- | 424 | * radeon_ring_commit - tell the GPU to execute the new |
|
- | 425 | * commands on the ring buffer |
|
- | 426 | * |
|
- | 427 | * @rdev: radeon_device pointer |
|
- | 428 | * @ring: radeon_ring structure holding ring information |
|
- | 429 | * |
|
- | 430 | * Update the wptr (write pointer) to tell the GPU to |
|
- | 431 | * execute new commands on the ring buffer (all asics). |
|
- | 432 | */ |
|
- | 433 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
|
- | 434 | { |
|
- | 435 | /* We pad to match fetch size */ |
|
- | 436 | while (ring->wptr & ring->align_mask) { |
|
267 | mutex_unlock(&rdev->cp.mutex); |
437 | radeon_ring_write(ring, ring->nop); |
- | 438 | } |
|
- | 439 | DRM_MEMORYBARRIER(); |
|
- | 440 | WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask); |
|
- | 441 | (void)RREG32(ring->wptr_reg); |
|
- | 442 | } |
|
- | 443 | ||
- | 444 | /** |
|
- | 445 | * radeon_ring_unlock_commit - tell the GPU to execute the new |
|
- | 446 | * commands on the ring buffer and unlock it |
|
- | 447 | * |
|
- | 448 | * @rdev: radeon_device pointer |
|
- | 449 | * @ring: radeon_ring structure holding ring information |
|
- | 450 | * |
|
- | 451 | * Call radeon_ring_commit() then unlock the ring (all asics). |
|
- | 452 | */ |
|
- | 453 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
|
- | 454 | { |
|
- | 455 | radeon_ring_commit(rdev, ring); |
|
- | 456 | mutex_unlock(&rdev->ring_lock); |
|
- | 457 | } |
|
- | 458 | ||
- | 459 | /** |
|
- | 460 | * radeon_ring_undo - reset the wptr |
|
- | 461 | * |
|
- | 462 | * @ring: radeon_ring structure holding ring information |
|
- | 463 | * |
|
- | 464 | * Reset the driver's copy of the wtpr (all asics). |
|
- | 465 | */ |
|
- | 466 | void radeon_ring_undo(struct radeon_ring *ring) |
|
- | 467 | { |
|
- | 468 | ring->wptr = ring->wptr_old; |
|
- | 469 | } |
|
- | 470 | ||
- | 471 | /** |
|
- | 472 | * radeon_ring_unlock_undo - reset the wptr and unlock the ring |
|
- | 473 | * |
|
- | 474 | * @ring: radeon_ring structure holding ring information |
|
- | 475 | * |
|
- | 476 | * Call radeon_ring_undo() then unlock the ring (all asics). |
|
- | 477 | */ |
|
- | 478 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) |
|
- | 479 | { |
|
- | 480 | radeon_ring_undo(ring); |
|
- | 481 | mutex_unlock(&rdev->ring_lock); |
|
- | 482 | } |
|
- | 483 | ||
- | 484 | /** |
|
- | 485 | * radeon_ring_force_activity - add some nop packets to the ring |
|
- | 486 | * |
|
- | 487 | * @rdev: radeon_device pointer |
|
- | 488 | * @ring: radeon_ring structure holding ring information |
|
- | 489 | * |
|
- | 490 | * Add some nop packets to the ring to force activity (all asics). |
|
- | 491 | * Used for lockup detection to see if the rptr is advancing. |
|
- | 492 | */ |
|
- | 493 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) |
|
- | 494 | { |
|
- | 495 | int r; |
|
- | 496 | ||
- | 497 | radeon_ring_free_size(rdev, ring); |
|
- | 498 | if (ring->rptr == ring->wptr) { |
|
- | 499 | r = radeon_ring_alloc(rdev, ring, 1); |
|
268 | return r; |
500 | if (!r) { |
Line -... | Line 501... | ||
- | 501 | radeon_ring_write(ring, ring->nop); |
|
- | 502 | radeon_ring_commit(rdev, ring); |
|
- | 503 | } |
|
- | 504 | } |
|
- | 505 | } |
|
- | 506 | ||
- | 507 | /** |
|
- | 508 | * radeon_ring_force_activity - update lockup variables |
|
- | 509 | * |
|
- | 510 | * @ring: radeon_ring structure holding ring information |
|
- | 511 | * |
|
- | 512 | * Update the last rptr value and timestamp (all asics). |
|
- | 513 | */ |
|
- | 514 | void radeon_ring_lockup_update(struct radeon_ring *ring) |
|
- | 515 | { |
|
- | 516 | ring->last_rptr = ring->rptr; |
|
- | 517 | ring->last_activity = GetTimerTicks(); |
|
- | 518 | } |
|
- | 519 | ||
- | 520 | /** |
|
269 | } |
521 | * radeon_ring_test_lockup() - check if ring is lockedup by recording information |
- | 522 | * @rdev: radeon device structure |
|
- | 523 | * @ring: radeon_ring structure holding ring information |
|
- | 524 | * |
|
- | 525 | * We don't need to initialize the lockup tracking information as we will either |
|
- | 526 | * have CP rptr to a different value of jiffies wrap around which will force |
|
- | 527 | * initialization of the lockup tracking informations. |
|
- | 528 | * |
|
- | 529 | * A possible false positivie is if we get call after while and last_cp_rptr == |
|
- | 530 | * the current CP rptr, even if it's unlikely it might happen. To avoid this |
|
- | 531 | * if the elapsed time since last call is bigger than 2 second than we return |
|
- | 532 | * false and update the tracking information. Due to this the caller must call |
|
- | 533 | * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported |
|
- | 534 | * the fencing code should be cautious about that. |
|
- | 535 | * |
|
- | 536 | * Caller should write to the ring to force CP to do something so we don't get |
|
- | 537 | * false positive when CP is just gived nothing to do. |
|
- | 538 | * |
|
- | 539 | **/ |
|
- | 540 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
|
- | 541 | { |
|
- | 542 | unsigned long cjiffies, elapsed; |
|
- | 543 | uint32_t rptr; |
|
- | 544 | ||
- | 545 | cjiffies = GetTimerTicks(); |
|
- | 546 | if (!time_after(cjiffies, ring->last_activity)) { |
|
- | 547 | /* likely a wrap around */ |
|
- | 548 | radeon_ring_lockup_update(ring); |
|
- | 549 | return false; |
|
- | 550 | } |
|
- | 551 | rptr = RREG32(ring->rptr_reg); |
|
- | 552 | ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; |
|
- | 553 | if (ring->rptr != ring->last_rptr) { |
|
- | 554 | /* CP is still working no lockup */ |
|
- | 555 | radeon_ring_lockup_update(ring); |
|
- | 556 | return false; |
|
- | 557 | } |
|
270 | return 0; |
558 | elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); |
- | 559 | if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) { |
|
- | 560 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); |
|
- | 561 | return true; |
|
- | 562 | } |
|
- | 563 | /* give a chance to the GPU ... */ |
|
- | 564 | return false; |
|
- | 565 | } |
|
- | 566 | ||
- | 567 | /** |
|
- | 568 | * radeon_ring_backup - Back up the content of a ring |
|
- | 569 | * |
|
- | 570 | * @rdev: radeon_device pointer |
|
- | 571 | * @ring: the ring we want to back up |
|
- | 572 | * |
|
- | 573 | * Saves all unprocessed commits from a ring, returns the number of dwords saved. |
|
- | 574 | */ |
|
- | 575 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, |
|
- | 576 | uint32_t **data) |
|
- | 577 | { |
|
- | 578 | unsigned size, ptr, i; |
|
- | 579 | ||
- | 580 | /* just in case lock the ring */ |
|
- | 581 | mutex_lock(&rdev->ring_lock); |
|
- | 582 | *data = NULL; |
|
- | 583 | ||
- | 584 | if (ring->ring_obj == NULL) { |
|
- | 585 | mutex_unlock(&rdev->ring_lock); |
|
- | 586 | return 0; |
|
- | 587 | } |
|
- | 588 | ||
271 | } |
589 | /* it doesn't make sense to save anything if all fences are signaled */ |
- | 590 | if (!radeon_fence_count_emitted(rdev, ring->idx)) { |
|
272 | 591 | mutex_unlock(&rdev->ring_lock); |
|
- | 592 | return 0; |
|
273 | void radeon_ring_commit(struct radeon_device *rdev) |
593 | } |
Line -... | Line 594... | ||
- | 594 | ||
- | 595 | /* calculate the number of dw on the ring */ |
|
- | 596 | if (ring->rptr_save_reg) |
|
- | 597 | ptr = RREG32(ring->rptr_save_reg); |
|
- | 598 | else if (rdev->wb.enabled) |
|
- | 599 | ptr = le32_to_cpu(*ring->next_rptr_cpu_addr); |
|
- | 600 | else { |
|
- | 601 | /* no way to read back the next rptr */ |
|
- | 602 | mutex_unlock(&rdev->ring_lock); |
|
- | 603 | return 0; |
|
- | 604 | } |
|
- | 605 | ||
- | 606 | size = ring->wptr + (ring->ring_size / 4); |
|
- | 607 | size -= ptr; |
|
- | 608 | size &= ring->ptr_mask; |
|
- | 609 | if (size == 0) { |
|
- | 610 | mutex_unlock(&rdev->ring_lock); |
|
- | 611 | return 0; |
|
- | 612 | } |
|
- | 613 | ||
- | 614 | /* and then save the content of the ring */ |
|
- | 615 | *data = kmalloc_array(size, sizeof(uint32_t), GFP_KERNEL); |
|
- | 616 | if (!*data) { |
|
- | 617 | mutex_unlock(&rdev->ring_lock); |
|
- | 618 | return 0; |
|
274 | { |
619 | } |
- | 620 | for (i = 0; i < size; ++i) { |
|
275 | unsigned count_dw_pad; |
621 | (*data)[i] = ring->ring[ptr++]; |
- | 622 | ptr &= ring->ptr_mask; |
|
- | 623 | } |
|
- | 624 | ||
- | 625 | mutex_unlock(&rdev->ring_lock); |
|
- | 626 | return size; |
|
276 | unsigned i; |
627 | } |
277 | 628 | ||
- | 629 | /** |
|
- | 630 | * radeon_ring_restore - append saved commands to the ring again |
|
- | 631 | * |
|
- | 632 | * @rdev: radeon_device pointer |
|
- | 633 | * @ring: ring to append commands to |
|
- | 634 | * @size: number of dwords we want to write |
|
- | 635 | * @data: saved commands |
|
- | 636 | * |
|
- | 637 | * Allocates space on the ring and restore the previously saved commands. |
|
- | 638 | */ |
|
278 | /* We pad to match fetch size */ |
639 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, |
Line -... | Line 640... | ||
- | 640 | unsigned size, uint32_t *data) |
|
- | 641 | { |
|
- | 642 | int i, r; |
|
- | 643 | ||
- | 644 | if (!size || !data) |
|
- | 645 | return 0; |
|
- | 646 | ||
- | 647 | /* restore the saved ring content */ |
|
- | 648 | r = radeon_ring_lock(rdev, ring, size); |
|
- | 649 | if (r) |
|
- | 650 | return r; |
|
- | 651 | ||
- | 652 | for (i = 0; i < size; ++i) { |
|
- | 653 | radeon_ring_write(ring, data[i]); |
|
- | 654 | } |
|
- | 655 | ||
279 | count_dw_pad = (rdev->cp.align_mask + 1) - |
656 | radeon_ring_unlock_commit(rdev, ring); |
- | 657 | kfree(data); |
|
- | 658 | return 0; |
|
280 | (rdev->cp.wptr & rdev->cp.align_mask); |
659 | } |
281 | for (i = 0; i < count_dw_pad; i++) { |
660 | |
Line 282... | Line 661... | ||
282 | radeon_ring_write(rdev, 2 << 30); |
661 | /** |
- | 662 | * radeon_ring_init - init driver ring struct. |
|
- | 663 | * |
|
- | 664 | * @rdev: radeon_device pointer |
|
- | 665 | * @ring: radeon_ring structure holding ring information |
|
- | 666 | * @ring_size: size of the ring |
|
- | 667 | * @rptr_offs: offset of the rptr writeback location in the WB buffer |
|
283 | } |
668 | * @rptr_reg: MMIO offset of the rptr register |
284 | DRM_MEMORYBARRIER(); |
669 | * @wptr_reg: MMIO offset of the wptr register |
285 | radeon_cp_commit(rdev); |
670 | * @ptr_reg_shift: bit offset of the rptr/wptr values |
286 | } |
671 | * @ptr_reg_mask: bit mask of the rptr/wptr values |
287 | 672 | * @nop: nop packet for this ring |
|
288 | void radeon_ring_unlock_commit(struct radeon_device *rdev) |
673 | * |
289 | { |
674 | * Initialize the driver information for the selected ring (all asics). |
290 | radeon_ring_commit(rdev); |
675 | * Returns 0 on success, error on failure. |
291 | mutex_unlock(&rdev->cp.mutex); |
676 | */ |
292 | } |
677 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, |
293 | 678 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
|
294 | void radeon_ring_unlock_undo(struct radeon_device *rdev) |
679 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) |
295 | { |
680 | { |
296 | rdev->cp.wptr = rdev->cp.wptr_old; |
681 | int r; |
297 | mutex_unlock(&rdev->cp.mutex); |
682 | |
298 | } |
683 | ring->ring_size = ring_size; |
299 | 684 | ring->rptr_offs = rptr_offs; |
|
300 | int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) |
685 | ring->rptr_reg = rptr_reg; |
301 | { |
686 | ring->wptr_reg = wptr_reg; |
302 | int r; |
687 | ring->ptr_reg_shift = ptr_reg_shift; |
303 | 688 | ring->ptr_reg_mask = ptr_reg_mask; |
|
304 | rdev->cp.ring_size = ring_size; |
689 | ring->nop = nop; |
305 | /* Allocate ring buffer */ |
690 | /* Allocate ring buffer */ |
306 | if (rdev->cp.ring_obj == NULL) { |
691 | if (ring->ring_obj == NULL) { |
307 | r = radeon_bo_create(rdev, rdev->cp.ring_size, PAGE_SIZE, true, |
692 | r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true, |
308 | RADEON_GEM_DOMAIN_GTT, |
693 | RADEON_GEM_DOMAIN_GTT, |
309 | &rdev->cp.ring_obj); |
694 | NULL, &ring->ring_obj); |
310 | if (r) { |
695 | if (r) { |
311 | dev_err(rdev->dev, "(%d) ring create failed\n", r); |
696 | dev_err(rdev->dev, "(%d) ring create failed\n", r); |
- | 697 | return r; |
|
- | 698 | } |
|
- | 699 | r = radeon_bo_reserve(ring->ring_obj, false); |
|
- | 700 | if (unlikely(r != 0)) |
|
- | 701 | return r; |
|
- | 702 | r = radeon_bo_pin(ring->ring_obj, RADEON_GEM_DOMAIN_GTT, |
|
- | 703 | &ring->gpu_addr); |
|
- | 704 | if (r) { |
|
- | 705 | radeon_bo_unreserve(ring->ring_obj); |
|
312 | return r; |
706 | dev_err(rdev->dev, "(%d) ring pin failed\n", r); |
313 | } |
707 | return r; |
Line -... | Line 708... | ||
- | 708 | } |
|
- | 709 | r = radeon_bo_kmap(ring->ring_obj, |
|
- | 710 | (void **)&ring->ring); |
|
- | 711 | radeon_bo_unreserve(ring->ring_obj); |
|
- | 712 | if (r) { |
|
- | 713 | dev_err(rdev->dev, "(%d) ring map failed\n", r); |
|
- | 714 | return r; |
|
- | 715 | } |
|
314 | r = radeon_bo_reserve(rdev->cp.ring_obj, false); |
716 | } |
315 | if (unlikely(r != 0)) |
717 | ring->ptr_mask = (ring->ring_size / 4) - 1; |
316 | return r; |
718 | ring->ring_free_dw = ring->ring_size / 4; |
317 | r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT, |
719 | if (rdev->wb.enabled) { |
Line 318... | Line 720... | ||
318 | &rdev->cp.gpu_addr); |
720 | u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); |
319 | if (r) { |
721 | ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; |
- | 722 | ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; |
|
320 | radeon_bo_unreserve(rdev->cp.ring_obj); |
723 | } |
321 | dev_err(rdev->dev, "(%d) ring pin failed\n", r); |
724 | if (radeon_debugfs_ring_init(rdev, ring)) { |
322 | return r; |
725 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
Line 323... | Line 726... | ||
323 | } |
726 | } |
324 | r = radeon_bo_kmap(rdev->cp.ring_obj, |
727 | radeon_ring_lockup_update(ring); |
325 | (void **)&rdev->cp.ring); |
728 | return 0; |
326 | radeon_bo_unreserve(rdev->cp.ring_obj); |
729 | } |
Line 354... | Line 757... | ||
354 | } |
757 | } |
355 | radeon_bo_unref(&ring_obj); |
758 | radeon_bo_unref(&ring_obj); |
356 | } |
759 | } |
357 | } |
760 | } |
Line 358... | Line -... | ||
358 | - | ||
359 | 761 | ||
360 | /* |
762 | /* |
361 | * Debugfs info |
763 | * Debugfs info |
362 | */ |
764 | */ |
- | 765 | #if defined(CONFIG_DEBUG_FS) |
|
363 | #if defined(CONFIG_DEBUG_FS) |
766 | |
364 | static int radeon_debugfs_ib_info(struct seq_file *m, void *data) |
767 | static int radeon_debugfs_ring_info(struct seq_file *m, void *data) |
365 | { |
768 | { |
- | 769 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
|
- | 770 | struct drm_device *dev = node->minor->dev; |
|
366 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
771 | struct radeon_device *rdev = dev->dev_private; |
- | 772 | int ridx = *(int*)node->info_ent->data; |
|
367 | struct radeon_ib *ib = node->info_ent->data; |
773 | struct radeon_ring *ring = &rdev->ring[ridx]; |
368 | unsigned i; |
774 | unsigned count, i, j; |
- | 775 | ||
- | 776 | radeon_ring_free_size(rdev, ring); |
|
- | 777 | count = (ring->ring_size / 4) - ring->ring_free_dw; |
|
- | 778 | seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); |
|
369 | 779 | seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); |
|
- | 780 | if (ring->rptr_save_reg) { |
|
370 | if (ib == NULL) { |
781 | seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, |
371 | return 0; |
782 | RREG32(ring->rptr_save_reg)); |
372 | } |
783 | } |
373 | seq_printf(m, "IB %04u\n", ib->idx); |
784 | seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); |
374 | seq_printf(m, "IB fence %p\n", ib->fence); |
785 | seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); |
- | 786 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); |
|
- | 787 | seq_printf(m, "%u dwords in ring\n", count); |
|
375 | seq_printf(m, "IB size %05u dwords\n", ib->length_dw); |
788 | i = ring->rptr; |
376 | for (i = 0; i < ib->length_dw; i++) { |
789 | for (j = 0; j <= count; j++) { |
- | 790 | seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); |
|
377 | seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]); |
791 | i = (i + 1) & ring->ptr_mask; |
378 | } |
792 | } |
379 | return 0; |
793 | return 0; |
Line -... | Line 794... | ||
- | 794 | } |
|
- | 795 | ||
- | 796 | static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX; |
|
- | 797 | static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX; |
|
- | 798 | static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; |
|
- | 799 | ||
- | 800 | static struct drm_info_list radeon_debugfs_ring_info_list[] = { |
|
- | 801 | {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index}, |
|
- | 802 | {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index}, |
|
- | 803 | {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index}, |
|
380 | } |
804 | }; |
381 | 805 | ||
382 | static int radeon_debugfs_ib_bogus_info(struct seq_file *m, void *data) |
806 | static int radeon_debugfs_sa_info(struct seq_file *m, void *data) |
383 | { |
807 | { |
384 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
808 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
- | 809 | struct drm_device *dev = node->minor->dev; |
|
385 | struct radeon_device *rdev = node->info_ent->data; |
810 | struct radeon_device *rdev = dev->dev_private; |
Line 386... | Line -... | ||
386 | struct radeon_ib *ib; |
- | |
387 | unsigned i; |
- | |
388 | - | ||
389 | mutex_lock(&rdev->ib_pool.mutex); |
- | |
390 | if (list_empty(&rdev->ib_pool.bogus_ib)) { |
- | |
391 | mutex_unlock(&rdev->ib_pool.mutex); |
- | |
392 | seq_printf(m, "no bogus IB recorded\n"); |
- | |
393 | return 0; |
- | |
394 | } |
- | |
395 | ib = list_first_entry(&rdev->ib_pool.bogus_ib, struct radeon_ib, list); |
- | |
396 | list_del_init(&ib->list); |
- | |
397 | mutex_unlock(&rdev->ib_pool.mutex); |
- | |
398 | seq_printf(m, "IB size %05u dwords\n", ib->length_dw); |
- | |
399 | for (i = 0; i < ib->length_dw; i++) { |
- | |
400 | seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]); |
- | |
401 | } |
811 | |
402 | vfree(ib->ptr); |
- | |
Line 403... | Line -... | ||
403 | kfree(ib); |
- | |
404 | return 0; |
- | |
- | 812 | radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m); |
|
Line 405... | Line 813... | ||
405 | } |
813 | |
406 | 814 | return 0; |
|
407 | static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE]; |
815 | |
- | 816 | } |
|
408 | static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32]; |
817 | |
Line 409... | Line 818... | ||
409 | 818 | static struct drm_info_list radeon_debugfs_sa_list[] = { |
|
410 | static struct drm_info_list radeon_debugfs_ib_bogus_info_list[] = { |
819 | {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL}, |
411 | {"radeon_ib_bogus", radeon_debugfs_ib_bogus_info, 0, NULL}, |
820 | }; |
412 | }; |
821 | |
- | 822 | #endif |
|
- | 823 | ||
- | 824 | static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring) |
|
413 | #endif |
825 | { |
- | 826 | #if defined(CONFIG_DEBUG_FS) |
|
- | 827 | unsigned i; |
|
- | 828 | for (i = 0; i < ARRAY_SIZE(radeon_debugfs_ring_info_list); ++i) { |
|
Line 414... | Line -... | ||
414 | - | ||
415 | int radeon_debugfs_ib_init(struct radeon_device *rdev) |
829 | struct drm_info_list *info = &radeon_debugfs_ring_info_list[i]; |
416 | { |
830 | int ridx = *(int*)radeon_debugfs_ring_info_list[i].data; |
417 | #if defined(CONFIG_DEBUG_FS) |
831 | unsigned r; |
418 | unsigned i; |
- | |
419 | int r; |
- | |
420 | - | ||
421 | radeon_debugfs_ib_bogus_info_list[0].data = rdev; |
- | |
422 | r = radeon_debugfs_add_files(rdev, radeon_debugfs_ib_bogus_info_list, 1); |
- | |
423 | if (r) |
- | |
424 | return r; |
832 | |
- | 833 | if (&rdev->ring[ridx] != ring) |
|
- | 834 | continue; |
|
- | 835 | ||
- | 836 | r = radeon_debugfs_add_files(rdev, info, 1); |
|
425 | for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { |
837 | if (r) |
- | 838 | return r; |
|
426 | sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i); |
839 | } |
- | 840 | #endif |
|
427 | radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i]; |
841 | return 0; |
428 | radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info; |
842 | } |
429 | radeon_debugfs_ib_list[i].driver_features = 0; |
843 | |
430 | radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i]; |
844 | static int radeon_debugfs_sa_init(struct radeon_device *rdev) |