diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_fence.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 479 |
1 files changed, 349 insertions, 130 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 913787085dfa..995167025282 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -98,6 +98,25 @@ static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /** | 100 | /** |
101 | * radeon_fence_schedule_check - schedule lockup check | ||
102 | * | ||
103 | * @rdev: radeon_device pointer | ||
104 | * @ring: ring index we should work with | ||
105 | * | ||
106 | * Queues a delayed work item to check for lockups. | ||
107 | */ | ||
108 | static void radeon_fence_schedule_check(struct radeon_device *rdev, int ring) | ||
109 | { | ||
110 | /* | ||
111 | * Do not reset the timer here with mod_delayed_work, | ||
112 | * this can livelock in an interaction with TTM delayed destroy. | ||
113 | */ | ||
114 | queue_delayed_work(system_power_efficient_wq, | ||
115 | &rdev->fence_drv[ring].lockup_work, | ||
116 | RADEON_FENCE_JIFFIES_TIMEOUT); | ||
117 | } | ||
118 | |||
119 | /** | ||
101 | * radeon_fence_emit - emit a fence on the requested ring | 120 | * radeon_fence_emit - emit a fence on the requested ring |
102 | * | 121 | * |
103 | * @rdev: radeon_device pointer | 122 | * @rdev: radeon_device pointer |
@@ -111,30 +130,70 @@ int radeon_fence_emit(struct radeon_device *rdev, | |||
111 | struct radeon_fence **fence, | 130 | struct radeon_fence **fence, |
112 | int ring) | 131 | int ring) |
113 | { | 132 | { |
133 | u64 seq = ++rdev->fence_drv[ring].sync_seq[ring]; | ||
134 | |||
114 | /* we are protected by the ring emission mutex */ | 135 | /* we are protected by the ring emission mutex */ |
115 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); | 136 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); |
116 | if ((*fence) == NULL) { | 137 | if ((*fence) == NULL) { |
117 | return -ENOMEM; | 138 | return -ENOMEM; |
118 | } | 139 | } |
119 | kref_init(&((*fence)->kref)); | ||
120 | (*fence)->rdev = rdev; | 140 | (*fence)->rdev = rdev; |
121 | (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; | 141 | (*fence)->seq = seq; |
122 | (*fence)->ring = ring; | 142 | (*fence)->ring = ring; |
143 | fence_init(&(*fence)->base, &radeon_fence_ops, | ||
144 | &rdev->fence_queue.lock, rdev->fence_context + ring, seq); | ||
123 | radeon_fence_ring_emit(rdev, ring, *fence); | 145 | radeon_fence_ring_emit(rdev, ring, *fence); |
124 | trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); | 146 | trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); |
147 | radeon_fence_schedule_check(rdev, ring); | ||
125 | return 0; | 148 | return 0; |
126 | } | 149 | } |
127 | 150 | ||
128 | /** | 151 | /** |
129 | * radeon_fence_process - process a fence | 152 | * radeon_fence_check_signaled - callback from fence_queue |
153 | * | ||
154 | * this function is called with fence_queue lock held, which is also used | ||
155 | * for the fence locking itself, so unlocked variants are used for | ||
156 | * fence_signal, and remove_wait_queue. | ||
157 | */ | ||
158 | static int radeon_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key) | ||
159 | { | ||
160 | struct radeon_fence *fence; | ||
161 | u64 seq; | ||
162 | |||
163 | fence = container_of(wait, struct radeon_fence, fence_wake); | ||
164 | |||
165 | /* | ||
166 | * We cannot use radeon_fence_process here because we're already | ||
167 | * in the waitqueue, in a call from wake_up_all. | ||
168 | */ | ||
169 | seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq); | ||
170 | if (seq >= fence->seq) { | ||
171 | int ret = fence_signal_locked(&fence->base); | ||
172 | |||
173 | if (!ret) | ||
174 | FENCE_TRACE(&fence->base, "signaled from irq context\n"); | ||
175 | else | ||
176 | FENCE_TRACE(&fence->base, "was already signaled\n"); | ||
177 | |||
178 | radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring); | ||
179 | __remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake); | ||
180 | fence_put(&fence->base); | ||
181 | } else | ||
182 | FENCE_TRACE(&fence->base, "pending\n"); | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * radeon_fence_activity - check for fence activity | ||
130 | * | 188 | * |
131 | * @rdev: radeon_device pointer | 189 | * @rdev: radeon_device pointer |
132 | * @ring: ring index the fence is associated with | 190 | * @ring: ring index the fence is associated with |
133 | * | 191 | * |
134 | * Checks the current fence value and wakes the fence queue | 192 | * Checks the current fence value and calculates the last |
135 | * if the sequence number has increased (all asics). | 193 | * signalled fence value. Returns true if activity occured |
194 | * on the ring, and the fence_queue should be waken up. | ||
136 | */ | 195 | */ |
137 | void radeon_fence_process(struct radeon_device *rdev, int ring) | 196 | static bool radeon_fence_activity(struct radeon_device *rdev, int ring) |
138 | { | 197 | { |
139 | uint64_t seq, last_seq, last_emitted; | 198 | uint64_t seq, last_seq, last_emitted; |
140 | unsigned count_loop = 0; | 199 | unsigned count_loop = 0; |
@@ -190,23 +249,77 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) | |||
190 | } | 249 | } |
191 | } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq); | 250 | } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq); |
192 | 251 | ||
193 | if (wake) | 252 | if (seq < last_emitted) |
194 | wake_up_all(&rdev->fence_queue); | 253 | radeon_fence_schedule_check(rdev, ring); |
254 | |||
255 | return wake; | ||
195 | } | 256 | } |
196 | 257 | ||
197 | /** | 258 | /** |
198 | * radeon_fence_destroy - destroy a fence | 259 | * radeon_fence_check_lockup - check for hardware lockup |
199 | * | 260 | * |
200 | * @kref: fence kref | 261 | * @work: delayed work item |
201 | * | 262 | * |
202 | * Frees the fence object (all asics). | 263 | * Checks for fence activity and if there is none probe |
264 | * the hardware if a lockup occured. | ||
203 | */ | 265 | */ |
204 | static void radeon_fence_destroy(struct kref *kref) | 266 | static void radeon_fence_check_lockup(struct work_struct *work) |
205 | { | 267 | { |
206 | struct radeon_fence *fence; | 268 | struct radeon_fence_driver *fence_drv; |
269 | struct radeon_device *rdev; | ||
270 | int ring; | ||
271 | |||
272 | fence_drv = container_of(work, struct radeon_fence_driver, | ||
273 | lockup_work.work); | ||
274 | rdev = fence_drv->rdev; | ||
275 | ring = fence_drv - &rdev->fence_drv[0]; | ||
276 | |||
277 | if (!down_read_trylock(&rdev->exclusive_lock)) { | ||
278 | /* just reschedule the check if a reset is going on */ | ||
279 | radeon_fence_schedule_check(rdev, ring); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | if (fence_drv->delayed_irq && rdev->ddev->irq_enabled) { | ||
284 | unsigned long irqflags; | ||
285 | |||
286 | fence_drv->delayed_irq = false; | ||
287 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
288 | radeon_irq_set(rdev); | ||
289 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
290 | } | ||
291 | |||
292 | if (radeon_fence_activity(rdev, ring)) | ||
293 | wake_up_all(&rdev->fence_queue); | ||
207 | 294 | ||
208 | fence = container_of(kref, struct radeon_fence, kref); | 295 | else if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) { |
209 | kfree(fence); | 296 | |
297 | /* good news we believe it's a lockup */ | ||
298 | dev_warn(rdev->dev, "GPU lockup (current fence id " | ||
299 | "0x%016llx last fence id 0x%016llx on ring %d)\n", | ||
300 | (uint64_t)atomic64_read(&fence_drv->last_seq), | ||
301 | fence_drv->sync_seq[ring], ring); | ||
302 | |||
303 | /* remember that we need an reset */ | ||
304 | rdev->needs_reset = true; | ||
305 | wake_up_all(&rdev->fence_queue); | ||
306 | } | ||
307 | up_read(&rdev->exclusive_lock); | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * radeon_fence_process - process a fence | ||
312 | * | ||
313 | * @rdev: radeon_device pointer | ||
314 | * @ring: ring index the fence is associated with | ||
315 | * | ||
316 | * Checks the current fence value and wakes the fence queue | ||
317 | * if the sequence number has increased (all asics). | ||
318 | */ | ||
319 | void radeon_fence_process(struct radeon_device *rdev, int ring) | ||
320 | { | ||
321 | if (radeon_fence_activity(rdev, ring)) | ||
322 | wake_up_all(&rdev->fence_queue); | ||
210 | } | 323 | } |
211 | 324 | ||
212 | /** | 325 | /** |
@@ -237,6 +350,75 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | |||
237 | return false; | 350 | return false; |
238 | } | 351 | } |
239 | 352 | ||
353 | static bool radeon_fence_is_signaled(struct fence *f) | ||
354 | { | ||
355 | struct radeon_fence *fence = to_radeon_fence(f); | ||
356 | struct radeon_device *rdev = fence->rdev; | ||
357 | unsigned ring = fence->ring; | ||
358 | u64 seq = fence->seq; | ||
359 | |||
360 | if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) { | ||
361 | return true; | ||
362 | } | ||
363 | |||
364 | if (down_read_trylock(&rdev->exclusive_lock)) { | ||
365 | radeon_fence_process(rdev, ring); | ||
366 | up_read(&rdev->exclusive_lock); | ||
367 | |||
368 | if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) { | ||
369 | return true; | ||
370 | } | ||
371 | } | ||
372 | return false; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * radeon_fence_enable_signaling - enable signalling on fence | ||
377 | * @fence: fence | ||
378 | * | ||
379 | * This function is called with fence_queue lock held, and adds a callback | ||
380 | * to fence_queue that checks if this fence is signaled, and if so it | ||
381 | * signals the fence and removes itself. | ||
382 | */ | ||
383 | static bool radeon_fence_enable_signaling(struct fence *f) | ||
384 | { | ||
385 | struct radeon_fence *fence = to_radeon_fence(f); | ||
386 | struct radeon_device *rdev = fence->rdev; | ||
387 | |||
388 | if (atomic64_read(&rdev->fence_drv[fence->ring].last_seq) >= fence->seq) | ||
389 | return false; | ||
390 | |||
391 | if (down_read_trylock(&rdev->exclusive_lock)) { | ||
392 | radeon_irq_kms_sw_irq_get(rdev, fence->ring); | ||
393 | |||
394 | if (radeon_fence_activity(rdev, fence->ring)) | ||
395 | wake_up_all_locked(&rdev->fence_queue); | ||
396 | |||
397 | /* did fence get signaled after we enabled the sw irq? */ | ||
398 | if (atomic64_read(&rdev->fence_drv[fence->ring].last_seq) >= fence->seq) { | ||
399 | radeon_irq_kms_sw_irq_put(rdev, fence->ring); | ||
400 | up_read(&rdev->exclusive_lock); | ||
401 | return false; | ||
402 | } | ||
403 | |||
404 | up_read(&rdev->exclusive_lock); | ||
405 | } else { | ||
406 | /* we're probably in a lockup, lets not fiddle too much */ | ||
407 | if (radeon_irq_kms_sw_irq_get_delayed(rdev, fence->ring)) | ||
408 | rdev->fence_drv[fence->ring].delayed_irq = true; | ||
409 | radeon_fence_schedule_check(rdev, fence->ring); | ||
410 | } | ||
411 | |||
412 | fence->fence_wake.flags = 0; | ||
413 | fence->fence_wake.private = NULL; | ||
414 | fence->fence_wake.func = radeon_fence_check_signaled; | ||
415 | __add_wait_queue(&rdev->fence_queue, &fence->fence_wake); | ||
416 | fence_get(f); | ||
417 | |||
418 | FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring); | ||
419 | return true; | ||
420 | } | ||
421 | |||
240 | /** | 422 | /** |
241 | * radeon_fence_signaled - check if a fence has signaled | 423 | * radeon_fence_signaled - check if a fence has signaled |
242 | * | 424 | * |
@@ -247,14 +429,15 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | |||
247 | */ | 429 | */ |
248 | bool radeon_fence_signaled(struct radeon_fence *fence) | 430 | bool radeon_fence_signaled(struct radeon_fence *fence) |
249 | { | 431 | { |
250 | if (!fence) { | 432 | if (!fence) |
251 | return true; | 433 | return true; |
252 | } | 434 | |
253 | if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { | ||
254 | return true; | ||
255 | } | ||
256 | if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) { | 435 | if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) { |
257 | fence->seq = RADEON_FENCE_SIGNALED_SEQ; | 436 | int ret; |
437 | |||
438 | ret = fence_signal(&fence->base); | ||
439 | if (!ret) | ||
440 | FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n"); | ||
258 | return true; | 441 | return true; |
259 | } | 442 | } |
260 | return false; | 443 | return false; |
@@ -283,110 +466,70 @@ static bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) | |||
283 | } | 466 | } |
284 | 467 | ||
285 | /** | 468 | /** |
286 | * radeon_fence_wait_seq - wait for a specific sequence numbers | 469 | * radeon_fence_wait_seq_timeout - wait for a specific sequence numbers |
287 | * | 470 | * |
288 | * @rdev: radeon device pointer | 471 | * @rdev: radeon device pointer |
289 | * @target_seq: sequence number(s) we want to wait for | 472 | * @target_seq: sequence number(s) we want to wait for |
290 | * @intr: use interruptable sleep | 473 | * @intr: use interruptable sleep |
474 | * @timeout: maximum time to wait, or MAX_SCHEDULE_TIMEOUT for infinite wait | ||
291 | * | 475 | * |
292 | * Wait for the requested sequence number(s) to be written by any ring | 476 | * Wait for the requested sequence number(s) to be written by any ring |
293 | * (all asics). Sequnce number array is indexed by ring id. | 477 | * (all asics). Sequnce number array is indexed by ring id. |
294 | * @intr selects whether to use interruptable (true) or non-interruptable | 478 | * @intr selects whether to use interruptable (true) or non-interruptable |
295 | * (false) sleep when waiting for the sequence number. Helper function | 479 | * (false) sleep when waiting for the sequence number. Helper function |
296 | * for radeon_fence_wait_*(). | 480 | * for radeon_fence_wait_*(). |
297 | * Returns 0 if the sequence number has passed, error for all other cases. | 481 | * Returns remaining time if the sequence number has passed, 0 when |
482 | * the wait timeout, or an error for all other cases. | ||
298 | * -EDEADLK is returned when a GPU lockup has been detected. | 483 | * -EDEADLK is returned when a GPU lockup has been detected. |
299 | */ | 484 | */ |
300 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, | 485 | static long radeon_fence_wait_seq_timeout(struct radeon_device *rdev, |
301 | bool intr) | 486 | u64 *target_seq, bool intr, |
487 | long timeout) | ||
302 | { | 488 | { |
303 | uint64_t last_seq[RADEON_NUM_RINGS]; | 489 | long r; |
304 | bool signaled; | 490 | int i; |
305 | int i, r; | ||
306 | |||
307 | while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { | ||
308 | 491 | ||
309 | /* Save current sequence values, used to check for GPU lockups */ | 492 | if (radeon_fence_any_seq_signaled(rdev, target_seq)) |
310 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 493 | return timeout; |
311 | if (!target_seq[i]) | ||
312 | continue; | ||
313 | 494 | ||
314 | last_seq[i] = atomic64_read(&rdev->fence_drv[i].last_seq); | 495 | /* enable IRQs and tracing */ |
315 | trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]); | 496 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
316 | radeon_irq_kms_sw_irq_get(rdev, i); | 497 | if (!target_seq[i]) |
317 | } | 498 | continue; |
318 | 499 | ||
319 | if (intr) { | 500 | trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]); |
320 | r = wait_event_interruptible_timeout(rdev->fence_queue, ( | 501 | radeon_irq_kms_sw_irq_get(rdev, i); |
321 | (signaled = radeon_fence_any_seq_signaled(rdev, target_seq)) | 502 | } |
322 | || rdev->needs_reset), RADEON_FENCE_JIFFIES_TIMEOUT); | ||
323 | } else { | ||
324 | r = wait_event_timeout(rdev->fence_queue, ( | ||
325 | (signaled = radeon_fence_any_seq_signaled(rdev, target_seq)) | ||
326 | || rdev->needs_reset), RADEON_FENCE_JIFFIES_TIMEOUT); | ||
327 | } | ||
328 | 503 | ||
329 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 504 | if (intr) { |
330 | if (!target_seq[i]) | 505 | r = wait_event_interruptible_timeout(rdev->fence_queue, ( |
331 | continue; | 506 | radeon_fence_any_seq_signaled(rdev, target_seq) |
507 | || rdev->needs_reset), timeout); | ||
508 | } else { | ||
509 | r = wait_event_timeout(rdev->fence_queue, ( | ||
510 | radeon_fence_any_seq_signaled(rdev, target_seq) | ||
511 | || rdev->needs_reset), timeout); | ||
512 | } | ||
332 | 513 | ||
333 | radeon_irq_kms_sw_irq_put(rdev, i); | 514 | if (rdev->needs_reset) |
334 | trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]); | 515 | r = -EDEADLK; |
335 | } | ||
336 | 516 | ||
337 | if (unlikely(r < 0)) | 517 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
338 | return r; | 518 | if (!target_seq[i]) |
519 | continue; | ||
339 | 520 | ||
340 | if (unlikely(!signaled)) { | 521 | radeon_irq_kms_sw_irq_put(rdev, i); |
341 | if (rdev->needs_reset) | 522 | trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]); |
342 | return -EDEADLK; | ||
343 | |||
344 | /* we were interrupted for some reason and fence | ||
345 | * isn't signaled yet, resume waiting */ | ||
346 | if (r) | ||
347 | continue; | ||
348 | |||
349 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
350 | if (!target_seq[i]) | ||
351 | continue; | ||
352 | |||
353 | if (last_seq[i] != atomic64_read(&rdev->fence_drv[i].last_seq)) | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | if (i != RADEON_NUM_RINGS) | ||
358 | continue; | ||
359 | |||
360 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
361 | if (!target_seq[i]) | ||
362 | continue; | ||
363 | |||
364 | if (radeon_ring_is_lockup(rdev, i, &rdev->ring[i])) | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | if (i < RADEON_NUM_RINGS) { | ||
369 | /* good news we believe it's a lockup */ | ||
370 | dev_warn(rdev->dev, "GPU lockup (waiting for " | ||
371 | "0x%016llx last fence id 0x%016llx on" | ||
372 | " ring %d)\n", | ||
373 | target_seq[i], last_seq[i], i); | ||
374 | |||
375 | /* remember that we need an reset */ | ||
376 | rdev->needs_reset = true; | ||
377 | wake_up_all(&rdev->fence_queue); | ||
378 | return -EDEADLK; | ||
379 | } | ||
380 | } | ||
381 | } | 523 | } |
382 | return 0; | 524 | |
525 | return r; | ||
383 | } | 526 | } |
384 | 527 | ||
385 | /** | 528 | /** |
386 | * radeon_fence_wait - wait for a fence to signal | 529 | * radeon_fence_wait - wait for a fence to signal |
387 | * | 530 | * |
388 | * @fence: radeon fence object | 531 | * @fence: radeon fence object |
389 | * @intr: use interruptable sleep | 532 | * @intr: use interruptible sleep |
390 | * | 533 | * |
391 | * Wait for the requested fence to signal (all asics). | 534 | * Wait for the requested fence to signal (all asics). |
392 | * @intr selects whether to use interruptable (true) or non-interruptable | 535 | * @intr selects whether to use interruptable (true) or non-interruptable |
@@ -396,22 +539,26 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, | |||
396 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) | 539 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
397 | { | 540 | { |
398 | uint64_t seq[RADEON_NUM_RINGS] = {}; | 541 | uint64_t seq[RADEON_NUM_RINGS] = {}; |
399 | int r; | 542 | long r; |
400 | 543 | ||
401 | if (fence == NULL) { | 544 | /* |
402 | WARN(1, "Querying an invalid fence : %p !\n", fence); | 545 | * This function should not be called on !radeon fences. |
403 | return -EINVAL; | 546 | * If this is the case, it would mean this function can |
404 | } | 547 | * also be called on radeon fences belonging to another card. |
548 | * exclusive_lock is not held in that case. | ||
549 | */ | ||
550 | if (WARN_ON_ONCE(!to_radeon_fence(&fence->base))) | ||
551 | return fence_wait(&fence->base, intr); | ||
405 | 552 | ||
406 | seq[fence->ring] = fence->seq; | 553 | seq[fence->ring] = fence->seq; |
407 | if (seq[fence->ring] == RADEON_FENCE_SIGNALED_SEQ) | 554 | r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, MAX_SCHEDULE_TIMEOUT); |
408 | return 0; | 555 | if (r < 0) { |
409 | |||
410 | r = radeon_fence_wait_seq(fence->rdev, seq, intr); | ||
411 | if (r) | ||
412 | return r; | 556 | return r; |
557 | } | ||
413 | 558 | ||
414 | fence->seq = RADEON_FENCE_SIGNALED_SEQ; | 559 | r = fence_signal(&fence->base); |
560 | if (!r) | ||
561 | FENCE_TRACE(&fence->base, "signaled from fence_wait\n"); | ||
415 | return 0; | 562 | return 0; |
416 | } | 563 | } |
417 | 564 | ||
@@ -434,7 +581,7 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
434 | { | 581 | { |
435 | uint64_t seq[RADEON_NUM_RINGS]; | 582 | uint64_t seq[RADEON_NUM_RINGS]; |
436 | unsigned i, num_rings = 0; | 583 | unsigned i, num_rings = 0; |
437 | int r; | 584 | long r; |
438 | 585 | ||
439 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 586 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
440 | seq[i] = 0; | 587 | seq[i] = 0; |
@@ -445,18 +592,14 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
445 | 592 | ||
446 | seq[i] = fences[i]->seq; | 593 | seq[i] = fences[i]->seq; |
447 | ++num_rings; | 594 | ++num_rings; |
448 | |||
449 | /* test if something was allready signaled */ | ||
450 | if (seq[i] == RADEON_FENCE_SIGNALED_SEQ) | ||
451 | return 0; | ||
452 | } | 595 | } |
453 | 596 | ||
454 | /* nothing to wait for ? */ | 597 | /* nothing to wait for ? */ |
455 | if (num_rings == 0) | 598 | if (num_rings == 0) |
456 | return -ENOENT; | 599 | return -ENOENT; |
457 | 600 | ||
458 | r = radeon_fence_wait_seq(rdev, seq, intr); | 601 | r = radeon_fence_wait_seq_timeout(rdev, seq, intr, MAX_SCHEDULE_TIMEOUT); |
459 | if (r) { | 602 | if (r < 0) { |
460 | return r; | 603 | return r; |
461 | } | 604 | } |
462 | return 0; | 605 | return 0; |
@@ -475,6 +618,7 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
475 | int radeon_fence_wait_next(struct radeon_device *rdev, int ring) | 618 | int radeon_fence_wait_next(struct radeon_device *rdev, int ring) |
476 | { | 619 | { |
477 | uint64_t seq[RADEON_NUM_RINGS] = {}; | 620 | uint64_t seq[RADEON_NUM_RINGS] = {}; |
621 | long r; | ||
478 | 622 | ||
479 | seq[ring] = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; | 623 | seq[ring] = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; |
480 | if (seq[ring] >= rdev->fence_drv[ring].sync_seq[ring]) { | 624 | if (seq[ring] >= rdev->fence_drv[ring].sync_seq[ring]) { |
@@ -482,7 +626,10 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring) | |||
482 | already the last emited fence */ | 626 | already the last emited fence */ |
483 | return -ENOENT; | 627 | return -ENOENT; |
484 | } | 628 | } |
485 | return radeon_fence_wait_seq(rdev, seq, false); | 629 | r = radeon_fence_wait_seq_timeout(rdev, seq, false, MAX_SCHEDULE_TIMEOUT); |
630 | if (r < 0) | ||
631 | return r; | ||
632 | return 0; | ||
486 | } | 633 | } |
487 | 634 | ||
488 | /** | 635 | /** |
@@ -498,18 +645,18 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring) | |||
498 | int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) | 645 | int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) |
499 | { | 646 | { |
500 | uint64_t seq[RADEON_NUM_RINGS] = {}; | 647 | uint64_t seq[RADEON_NUM_RINGS] = {}; |
501 | int r; | 648 | long r; |
502 | 649 | ||
503 | seq[ring] = rdev->fence_drv[ring].sync_seq[ring]; | 650 | seq[ring] = rdev->fence_drv[ring].sync_seq[ring]; |
504 | if (!seq[ring]) | 651 | if (!seq[ring]) |
505 | return 0; | 652 | return 0; |
506 | 653 | ||
507 | r = radeon_fence_wait_seq(rdev, seq, false); | 654 | r = radeon_fence_wait_seq_timeout(rdev, seq, false, MAX_SCHEDULE_TIMEOUT); |
508 | if (r) { | 655 | if (r < 0) { |
509 | if (r == -EDEADLK) | 656 | if (r == -EDEADLK) |
510 | return -EDEADLK; | 657 | return -EDEADLK; |
511 | 658 | ||
512 | dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", | 659 | dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%ld)\n", |
513 | ring, r); | 660 | ring, r); |
514 | } | 661 | } |
515 | return 0; | 662 | return 0; |
@@ -525,7 +672,7 @@ int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) | |||
525 | */ | 672 | */ |
526 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) | 673 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) |
527 | { | 674 | { |
528 | kref_get(&fence->kref); | 675 | fence_get(&fence->base); |
529 | return fence; | 676 | return fence; |
530 | } | 677 | } |
531 | 678 | ||
@@ -542,7 +689,7 @@ void radeon_fence_unref(struct radeon_fence **fence) | |||
542 | 689 | ||
543 | *fence = NULL; | 690 | *fence = NULL; |
544 | if (tmp) { | 691 | if (tmp) { |
545 | kref_put(&tmp->kref, radeon_fence_destroy); | 692 | fence_put(&tmp->base); |
546 | } | 693 | } |
547 | } | 694 | } |
548 | 695 | ||
@@ -711,6 +858,9 @@ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) | |||
711 | rdev->fence_drv[ring].sync_seq[i] = 0; | 858 | rdev->fence_drv[ring].sync_seq[i] = 0; |
712 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); | 859 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); |
713 | rdev->fence_drv[ring].initialized = false; | 860 | rdev->fence_drv[ring].initialized = false; |
861 | INIT_DELAYED_WORK(&rdev->fence_drv[ring].lockup_work, | ||
862 | radeon_fence_check_lockup); | ||
863 | rdev->fence_drv[ring].rdev = rdev; | ||
714 | } | 864 | } |
715 | 865 | ||
716 | /** | 866 | /** |
@@ -758,8 +908,9 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) | |||
758 | r = radeon_fence_wait_empty(rdev, ring); | 908 | r = radeon_fence_wait_empty(rdev, ring); |
759 | if (r) { | 909 | if (r) { |
760 | /* no need to trigger GPU reset as we are unloading */ | 910 | /* no need to trigger GPU reset as we are unloading */ |
761 | radeon_fence_driver_force_completion(rdev); | 911 | radeon_fence_driver_force_completion(rdev, ring); |
762 | } | 912 | } |
913 | cancel_delayed_work_sync(&rdev->fence_drv[ring].lockup_work); | ||
763 | wake_up_all(&rdev->fence_queue); | 914 | wake_up_all(&rdev->fence_queue); |
764 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); | 915 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); |
765 | rdev->fence_drv[ring].initialized = false; | 916 | rdev->fence_drv[ring].initialized = false; |
@@ -771,18 +922,16 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) | |||
771 | * radeon_fence_driver_force_completion - force all fence waiter to complete | 922 | * radeon_fence_driver_force_completion - force all fence waiter to complete |
772 | * | 923 | * |
773 | * @rdev: radeon device pointer | 924 | * @rdev: radeon device pointer |
925 | * @ring: the ring to complete | ||
774 | * | 926 | * |
775 | * In case of GPU reset failure make sure no process keep waiting on fence | 927 | * In case of GPU reset failure make sure no process keep waiting on fence |
776 | * that will never complete. | 928 | * that will never complete. |
777 | */ | 929 | */ |
778 | void radeon_fence_driver_force_completion(struct radeon_device *rdev) | 930 | void radeon_fence_driver_force_completion(struct radeon_device *rdev, int ring) |
779 | { | 931 | { |
780 | int ring; | 932 | if (rdev->fence_drv[ring].initialized) { |
781 | |||
782 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { | ||
783 | if (!rdev->fence_drv[ring].initialized) | ||
784 | continue; | ||
785 | radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); | 933 | radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); |
934 | cancel_delayed_work_sync(&rdev->fence_drv[ring].lockup_work); | ||
786 | } | 935 | } |
787 | } | 936 | } |
788 | 937 | ||
@@ -833,6 +982,7 @@ static int radeon_debugfs_gpu_reset(struct seq_file *m, void *data) | |||
833 | down_read(&rdev->exclusive_lock); | 982 | down_read(&rdev->exclusive_lock); |
834 | seq_printf(m, "%d\n", rdev->needs_reset); | 983 | seq_printf(m, "%d\n", rdev->needs_reset); |
835 | rdev->needs_reset = true; | 984 | rdev->needs_reset = true; |
985 | wake_up_all(&rdev->fence_queue); | ||
836 | up_read(&rdev->exclusive_lock); | 986 | up_read(&rdev->exclusive_lock); |
837 | 987 | ||
838 | return 0; | 988 | return 0; |
@@ -852,3 +1002,72 @@ int radeon_debugfs_fence_init(struct radeon_device *rdev) | |||
852 | return 0; | 1002 | return 0; |
853 | #endif | 1003 | #endif |
854 | } | 1004 | } |
1005 | |||
1006 | static const char *radeon_fence_get_driver_name(struct fence *fence) | ||
1007 | { | ||
1008 | return "radeon"; | ||
1009 | } | ||
1010 | |||
1011 | static const char *radeon_fence_get_timeline_name(struct fence *f) | ||
1012 | { | ||
1013 | struct radeon_fence *fence = to_radeon_fence(f); | ||
1014 | switch (fence->ring) { | ||
1015 | case RADEON_RING_TYPE_GFX_INDEX: return "radeon.gfx"; | ||
1016 | case CAYMAN_RING_TYPE_CP1_INDEX: return "radeon.cp1"; | ||
1017 | case CAYMAN_RING_TYPE_CP2_INDEX: return "radeon.cp2"; | ||
1018 | case R600_RING_TYPE_DMA_INDEX: return "radeon.dma"; | ||
1019 | case CAYMAN_RING_TYPE_DMA1_INDEX: return "radeon.dma1"; | ||
1020 | case R600_RING_TYPE_UVD_INDEX: return "radeon.uvd"; | ||
1021 | case TN_RING_TYPE_VCE1_INDEX: return "radeon.vce1"; | ||
1022 | case TN_RING_TYPE_VCE2_INDEX: return "radeon.vce2"; | ||
1023 | default: WARN_ON_ONCE(1); return "radeon.unk"; | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | static inline bool radeon_test_signaled(struct radeon_fence *fence) | ||
1028 | { | ||
1029 | return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); | ||
1030 | } | ||
1031 | |||
1032 | static signed long radeon_fence_default_wait(struct fence *f, bool intr, | ||
1033 | signed long t) | ||
1034 | { | ||
1035 | struct radeon_fence *fence = to_radeon_fence(f); | ||
1036 | struct radeon_device *rdev = fence->rdev; | ||
1037 | bool signaled; | ||
1038 | |||
1039 | fence_enable_sw_signaling(&fence->base); | ||
1040 | |||
1041 | /* | ||
1042 | * This function has to return -EDEADLK, but cannot hold | ||
1043 | * exclusive_lock during the wait because some callers | ||
1044 | * may already hold it. This means checking needs_reset without | ||
1045 | * lock, and not fiddling with any gpu internals. | ||
1046 | * | ||
1047 | * The callback installed with fence_enable_sw_signaling will | ||
1048 | * run before our wait_event_*timeout call, so we will see | ||
1049 | * both the signaled fence and the changes to needs_reset. | ||
1050 | */ | ||
1051 | |||
1052 | if (intr) | ||
1053 | t = wait_event_interruptible_timeout(rdev->fence_queue, | ||
1054 | ((signaled = radeon_test_signaled(fence)) || | ||
1055 | rdev->needs_reset), t); | ||
1056 | else | ||
1057 | t = wait_event_timeout(rdev->fence_queue, | ||
1058 | ((signaled = radeon_test_signaled(fence)) || | ||
1059 | rdev->needs_reset), t); | ||
1060 | |||
1061 | if (t > 0 && !signaled) | ||
1062 | return -EDEADLK; | ||
1063 | return t; | ||
1064 | } | ||
1065 | |||
1066 | const struct fence_ops radeon_fence_ops = { | ||
1067 | .get_driver_name = radeon_fence_get_driver_name, | ||
1068 | .get_timeline_name = radeon_fence_get_timeline_name, | ||
1069 | .enable_signaling = radeon_fence_enable_signaling, | ||
1070 | .signaled = radeon_fence_is_signaled, | ||
1071 | .wait = radeon_fence_default_wait, | ||
1072 | .release = NULL, | ||
1073 | }; | ||