diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 12:52:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 12:52:16 -0400 |
commit | e9f37d3a8d126e73f5737ef548cdf6f618e295e4 (patch) | |
tree | 831eb4952637828a7bbafa361185e0ca57aa86ed /drivers/gpu/drm/radeon/radeon_ring.c | |
parent | 5fb6b953bb7aa86a9c8ea760934982cedc45c52b (diff) | |
parent | c39b06951f1dc2e384650288676c5b7dcc0ec92c (diff) |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"Highlights:
- drm:
Generic display port aux features, primary plane support, drm
master management fixes, logging cleanups, enforced locking checks
(instead of docs), documentation improvements, minor number
handling cleanup, pseudofs for shared inodes.
- ttm:
add ability to allocate from both ends
- i915:
broadwell features, power domain and runtime pm, per-process
address space infrastructure (not enabled)
- msm:
power management, hdmi audio support
- nouveau:
ongoing GPU fault recovery, initial maxwell support, random fixes
- exynos:
refactored driver to clean up a lot of abstraction, DP support
moved into drm, LVDS bridge support added, parallel panel support
- gma500:
SGX MMU support, SGX irq handling, asle irq work fixes
- radeon:
video engine bringup, ring handling fixes, use dp aux helpers
- vmwgfx:
add rendernode support"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (849 commits)
DRM: armada: fix corruption while loading cursors
drm/dp_helper: don't return EPROTO for defers (v2)
drm/bridge: export ptn3460_init function
drm/exynos: remove MODULE_DEVICE_TABLE definitions
ARM: dts: exynos4412-trats2: enable exynos/fimd node
ARM: dts: exynos4210-trats: enable exynos/fimd node
ARM: dts: exynos4412-trats2: add panel node
ARM: dts: exynos4210-trats: add panel node
ARM: dts: exynos4: add MIPI DSI Master node
drm/panel: add S6E8AA0 driver
ARM: dts: exynos4210-universal_c210: add proper panel node
drm/panel: add ld9040 driver
panel/ld9040: add DT bindings
panel/s6e8aa0: add DT bindings
drm/exynos: add DSIM driver
exynos/dsim: add DT bindings
drm/exynos: disallow fbdev initialization if no device is connected
drm/mipi_dsi: create dsi devices only for nodes with reg property
drm/mipi_dsi: add flags to DSI messages
Skip intel_crt_init for Dell XPS 8700
...
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_ring.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 119 |
1 files changed, 43 insertions, 76 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 15e44a7281ab..f8050f5429e2 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -63,7 +63,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, | |||
63 | { | 63 | { |
64 | int r; | 64 | int r; |
65 | 65 | ||
66 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); | 66 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256); |
67 | if (r) { | 67 | if (r) { |
68 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); | 68 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
69 | return r; | 69 | return r; |
@@ -145,6 +145,13 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | |||
145 | return r; | 145 | return r; |
146 | } | 146 | } |
147 | 147 | ||
148 | /* grab a vm id if necessary */ | ||
149 | if (ib->vm) { | ||
150 | struct radeon_fence *vm_id_fence; | ||
151 | vm_id_fence = radeon_vm_grab_id(rdev, ib->vm, ib->ring); | ||
152 | radeon_semaphore_sync_to(ib->semaphore, vm_id_fence); | ||
153 | } | ||
154 | |||
148 | /* sync with other rings */ | 155 | /* sync with other rings */ |
149 | r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring); | 156 | r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring); |
150 | if (r) { | 157 | if (r) { |
@@ -153,11 +160,9 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | |||
153 | return r; | 160 | return r; |
154 | } | 161 | } |
155 | 162 | ||
156 | /* if we can't remember our last VM flush then flush now! */ | 163 | if (ib->vm) |
157 | /* XXX figure out why we have to flush for every IB */ | 164 | radeon_vm_flush(rdev, ib->vm, ib->ring); |
158 | if (ib->vm /*&& !ib->vm->last_flush*/) { | 165 | |
159 | radeon_ring_vm_flush(rdev, ib->ring, ib->vm); | ||
160 | } | ||
161 | if (const_ib) { | 166 | if (const_ib) { |
162 | radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); | 167 | radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); |
163 | radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); | 168 | radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); |
@@ -172,10 +177,10 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | |||
172 | if (const_ib) { | 177 | if (const_ib) { |
173 | const_ib->fence = radeon_fence_ref(ib->fence); | 178 | const_ib->fence = radeon_fence_ref(ib->fence); |
174 | } | 179 | } |
175 | /* we just flushed the VM, remember that */ | 180 | |
176 | if (ib->vm && !ib->vm->last_flush) { | 181 | if (ib->vm) |
177 | ib->vm->last_flush = radeon_fence_ref(ib->fence); | 182 | radeon_vm_fence(rdev, ib->vm, ib->fence); |
178 | } | 183 | |
179 | radeon_ring_unlock_commit(rdev, ring); | 184 | radeon_ring_unlock_commit(rdev, ring); |
180 | return 0; | 185 | return 0; |
181 | } | 186 | } |
@@ -257,6 +262,7 @@ int radeon_ib_ring_tests(struct radeon_device *rdev) | |||
257 | r = radeon_ib_test(rdev, i, ring); | 262 | r = radeon_ib_test(rdev, i, ring); |
258 | if (r) { | 263 | if (r) { |
259 | ring->ready = false; | 264 | ring->ready = false; |
265 | rdev->needs_reset = false; | ||
260 | 266 | ||
261 | if (i == RADEON_RING_TYPE_GFX_INDEX) { | 267 | if (i == RADEON_RING_TYPE_GFX_INDEX) { |
262 | /* oh, oh, that's really bad */ | 268 | /* oh, oh, that's really bad */ |
@@ -342,13 +348,17 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | |||
342 | */ | 348 | */ |
343 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | 349 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
344 | { | 350 | { |
345 | ring->rptr = radeon_ring_get_rptr(rdev, ring); | 351 | uint32_t rptr = radeon_ring_get_rptr(rdev, ring); |
352 | |||
346 | /* This works because ring_size is a power of 2 */ | 353 | /* This works because ring_size is a power of 2 */ |
347 | ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4)); | 354 | ring->ring_free_dw = rptr + (ring->ring_size / 4); |
348 | ring->ring_free_dw -= ring->wptr; | 355 | ring->ring_free_dw -= ring->wptr; |
349 | ring->ring_free_dw &= ring->ptr_mask; | 356 | ring->ring_free_dw &= ring->ptr_mask; |
350 | if (!ring->ring_free_dw) { | 357 | if (!ring->ring_free_dw) { |
358 | /* this is an empty ring */ | ||
351 | ring->ring_free_dw = ring->ring_size / 4; | 359 | ring->ring_free_dw = ring->ring_size / 4; |
360 | /* update lockup info to avoid false positive */ | ||
361 | radeon_ring_lockup_update(rdev, ring); | ||
352 | } | 362 | } |
353 | } | 363 | } |
354 | 364 | ||
@@ -372,19 +382,13 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
372 | /* Align requested size with padding so unlock_commit can | 382 | /* Align requested size with padding so unlock_commit can |
373 | * pad safely */ | 383 | * pad safely */ |
374 | radeon_ring_free_size(rdev, ring); | 384 | radeon_ring_free_size(rdev, ring); |
375 | if (ring->ring_free_dw == (ring->ring_size / 4)) { | ||
376 | /* This is an empty ring update lockup info to avoid | ||
377 | * false positive. | ||
378 | */ | ||
379 | radeon_ring_lockup_update(ring); | ||
380 | } | ||
381 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; | 385 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; |
382 | while (ndw > (ring->ring_free_dw - 1)) { | 386 | while (ndw > (ring->ring_free_dw - 1)) { |
383 | radeon_ring_free_size(rdev, ring); | 387 | radeon_ring_free_size(rdev, ring); |
384 | if (ndw < ring->ring_free_dw) { | 388 | if (ndw < ring->ring_free_dw) { |
385 | break; | 389 | break; |
386 | } | 390 | } |
387 | r = radeon_fence_wait_next_locked(rdev, ring->idx); | 391 | r = radeon_fence_wait_next(rdev, ring->idx); |
388 | if (r) | 392 | if (r) |
389 | return r; | 393 | return r; |
390 | } | 394 | } |
@@ -478,39 +482,17 @@ void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *rin | |||
478 | } | 482 | } |
479 | 483 | ||
480 | /** | 484 | /** |
481 | * radeon_ring_force_activity - add some nop packets to the ring | ||
482 | * | ||
483 | * @rdev: radeon_device pointer | ||
484 | * @ring: radeon_ring structure holding ring information | ||
485 | * | ||
486 | * Add some nop packets to the ring to force activity (all asics). | ||
487 | * Used for lockup detection to see if the rptr is advancing. | ||
488 | */ | ||
489 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) | ||
490 | { | ||
491 | int r; | ||
492 | |||
493 | radeon_ring_free_size(rdev, ring); | ||
494 | if (ring->rptr == ring->wptr) { | ||
495 | r = radeon_ring_alloc(rdev, ring, 1); | ||
496 | if (!r) { | ||
497 | radeon_ring_write(ring, ring->nop); | ||
498 | radeon_ring_commit(rdev, ring); | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * radeon_ring_lockup_update - update lockup variables | 485 | * radeon_ring_lockup_update - update lockup variables |
505 | * | 486 | * |
506 | * @ring: radeon_ring structure holding ring information | 487 | * @ring: radeon_ring structure holding ring information |
507 | * | 488 | * |
508 | * Update the last rptr value and timestamp (all asics). | 489 | * Update the last rptr value and timestamp (all asics). |
509 | */ | 490 | */ |
510 | void radeon_ring_lockup_update(struct radeon_ring *ring) | 491 | void radeon_ring_lockup_update(struct radeon_device *rdev, |
492 | struct radeon_ring *ring) | ||
511 | { | 493 | { |
512 | ring->last_rptr = ring->rptr; | 494 | atomic_set(&ring->last_rptr, radeon_ring_get_rptr(rdev, ring)); |
513 | ring->last_activity = jiffies; | 495 | atomic64_set(&ring->last_activity, jiffies_64); |
514 | } | 496 | } |
515 | 497 | ||
516 | /** | 498 | /** |
@@ -518,40 +500,23 @@ void radeon_ring_lockup_update(struct radeon_ring *ring) | |||
518 | * @rdev: radeon device structure | 500 | * @rdev: radeon device structure |
519 | * @ring: radeon_ring structure holding ring information | 501 | * @ring: radeon_ring structure holding ring information |
520 | * | 502 | * |
521 | * We don't need to initialize the lockup tracking information as we will either | 503 | */ |
522 | * have CP rptr to a different value of jiffies wrap around which will force | ||
523 | * initialization of the lockup tracking informations. | ||
524 | * | ||
525 | * A possible false positivie is if we get call after while and last_cp_rptr == | ||
526 | * the current CP rptr, even if it's unlikely it might happen. To avoid this | ||
527 | * if the elapsed time since last call is bigger than 2 second than we return | ||
528 | * false and update the tracking information. Due to this the caller must call | ||
529 | * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported | ||
530 | * the fencing code should be cautious about that. | ||
531 | * | ||
532 | * Caller should write to the ring to force CP to do something so we don't get | ||
533 | * false positive when CP is just gived nothing to do. | ||
534 | * | ||
535 | **/ | ||
536 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | 504 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
537 | { | 505 | { |
538 | unsigned long cjiffies, elapsed; | 506 | uint32_t rptr = radeon_ring_get_rptr(rdev, ring); |
507 | uint64_t last = atomic64_read(&ring->last_activity); | ||
508 | uint64_t elapsed; | ||
539 | 509 | ||
540 | cjiffies = jiffies; | 510 | if (rptr != atomic_read(&ring->last_rptr)) { |
541 | if (!time_after(cjiffies, ring->last_activity)) { | 511 | /* ring is still working, no lockup */ |
542 | /* likely a wrap around */ | 512 | radeon_ring_lockup_update(rdev, ring); |
543 | radeon_ring_lockup_update(ring); | ||
544 | return false; | 513 | return false; |
545 | } | 514 | } |
546 | ring->rptr = radeon_ring_get_rptr(rdev, ring); | 515 | |
547 | if (ring->rptr != ring->last_rptr) { | 516 | elapsed = jiffies_to_msecs(jiffies_64 - last); |
548 | /* CP is still working no lockup */ | ||
549 | radeon_ring_lockup_update(ring); | ||
550 | return false; | ||
551 | } | ||
552 | elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); | ||
553 | if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) { | 517 | if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) { |
554 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); | 518 | dev_err(rdev->dev, "ring %d stalled for more than %llumsec\n", |
519 | ring->idx, elapsed); | ||
555 | return true; | 520 | return true; |
556 | } | 521 | } |
557 | /* give a chance to the GPU ... */ | 522 | /* give a chance to the GPU ... */ |
@@ -709,7 +674,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
709 | if (radeon_debugfs_ring_init(rdev, ring)) { | 674 | if (radeon_debugfs_ring_init(rdev, ring)) { |
710 | DRM_ERROR("Failed to register debugfs file for rings !\n"); | 675 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
711 | } | 676 | } |
712 | radeon_ring_lockup_update(ring); | 677 | radeon_ring_lockup_update(rdev, ring); |
713 | return 0; | 678 | return 0; |
714 | } | 679 | } |
715 | 680 | ||
@@ -780,8 +745,6 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
780 | 745 | ||
781 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", | 746 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", |
782 | ring->wptr, ring->wptr); | 747 | ring->wptr, ring->wptr); |
783 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", | ||
784 | ring->rptr, ring->rptr); | ||
785 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", | 748 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", |
786 | ring->last_semaphore_signal_addr); | 749 | ring->last_semaphore_signal_addr); |
787 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", | 750 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", |
@@ -814,6 +777,8 @@ static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; | |||
814 | static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX; | 777 | static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX; |
815 | static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; | 778 | static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; |
816 | static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX; | 779 | static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX; |
780 | static int si_vce1_index = TN_RING_TYPE_VCE1_INDEX; | ||
781 | static int si_vce2_index = TN_RING_TYPE_VCE2_INDEX; | ||
817 | 782 | ||
818 | static struct drm_info_list radeon_debugfs_ring_info_list[] = { | 783 | static struct drm_info_list radeon_debugfs_ring_info_list[] = { |
819 | {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index}, | 784 | {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index}, |
@@ -822,6 +787,8 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = { | |||
822 | {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index}, | 787 | {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index}, |
823 | {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index}, | 788 | {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index}, |
824 | {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index}, | 789 | {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index}, |
790 | {"radeon_ring_vce1", radeon_debugfs_ring_info, 0, &si_vce1_index}, | ||
791 | {"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index}, | ||
825 | }; | 792 | }; |
826 | 793 | ||
827 | static int radeon_debugfs_sa_info(struct seq_file *m, void *data) | 794 | static int radeon_debugfs_sa_info(struct seq_file *m, void *data) |