diff options
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_cs.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 15 |
7 files changed, 122 insertions, 24 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 74c6b42d2597..7a445666e71f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -2654,6 +2654,35 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2654 | ib[idx+4] = upper_32_bits(offset) & 0xff; | 2654 | ib[idx+4] = upper_32_bits(offset) & 0xff; |
2655 | } | 2655 | } |
2656 | break; | 2656 | break; |
2657 | case PACKET3_MEM_WRITE: | ||
2658 | { | ||
2659 | u64 offset; | ||
2660 | |||
2661 | if (pkt->count != 3) { | ||
2662 | DRM_ERROR("bad MEM_WRITE (invalid count)\n"); | ||
2663 | return -EINVAL; | ||
2664 | } | ||
2665 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
2666 | if (r) { | ||
2667 | DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); | ||
2668 | return -EINVAL; | ||
2669 | } | ||
2670 | offset = radeon_get_ib_value(p, idx+0); | ||
2671 | offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; | ||
2672 | if (offset & 0x7) { | ||
2673 | DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); | ||
2674 | return -EINVAL; | ||
2675 | } | ||
2676 | if ((offset + 8) > radeon_bo_size(reloc->robj)) { | ||
2677 | DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", | ||
2678 | offset + 8, radeon_bo_size(reloc->robj)); | ||
2679 | return -EINVAL; | ||
2680 | } | ||
2681 | offset += reloc->lobj.gpu_offset; | ||
2682 | ib[idx+0] = offset; | ||
2683 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
2684 | break; | ||
2685 | } | ||
2657 | case PACKET3_COPY_DW: | 2686 | case PACKET3_COPY_DW: |
2658 | if (pkt->count != 4) { | 2687 | if (pkt->count != 4) { |
2659 | DRM_ERROR("bad COPY_DW (invalid count)\n"); | 2688 | DRM_ERROR("bad COPY_DW (invalid count)\n"); |
@@ -3287,6 +3316,7 @@ static bool evergreen_vm_reg_valid(u32 reg) | |||
3287 | 3316 | ||
3288 | /* check config regs */ | 3317 | /* check config regs */ |
3289 | switch (reg) { | 3318 | switch (reg) { |
3319 | case WAIT_UNTIL: | ||
3290 | case GRBM_GFX_INDEX: | 3320 | case GRBM_GFX_INDEX: |
3291 | case CP_STRMOUT_CNTL: | 3321 | case CP_STRMOUT_CNTL: |
3292 | case CP_COHER_CNTL: | 3322 | case CP_COHER_CNTL: |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0be768be530c..9ea13d07cc55 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -2294,6 +2294,35 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
2294 | ib[idx+4] = upper_32_bits(offset) & 0xff; | 2294 | ib[idx+4] = upper_32_bits(offset) & 0xff; |
2295 | } | 2295 | } |
2296 | break; | 2296 | break; |
2297 | case PACKET3_MEM_WRITE: | ||
2298 | { | ||
2299 | u64 offset; | ||
2300 | |||
2301 | if (pkt->count != 3) { | ||
2302 | DRM_ERROR("bad MEM_WRITE (invalid count)\n"); | ||
2303 | return -EINVAL; | ||
2304 | } | ||
2305 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
2306 | if (r) { | ||
2307 | DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); | ||
2308 | return -EINVAL; | ||
2309 | } | ||
2310 | offset = radeon_get_ib_value(p, idx+0); | ||
2311 | offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; | ||
2312 | if (offset & 0x7) { | ||
2313 | DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); | ||
2314 | return -EINVAL; | ||
2315 | } | ||
2316 | if ((offset + 8) > radeon_bo_size(reloc->robj)) { | ||
2317 | DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", | ||
2318 | offset + 8, radeon_bo_size(reloc->robj)); | ||
2319 | return -EINVAL; | ||
2320 | } | ||
2321 | offset += reloc->lobj.gpu_offset; | ||
2322 | ib[idx+0] = offset; | ||
2323 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
2324 | break; | ||
2325 | } | ||
2297 | case PACKET3_COPY_DW: | 2326 | case PACKET3_COPY_DW: |
2298 | if (pkt->count != 4) { | 2327 | if (pkt->count != 4) { |
2299 | DRM_ERROR("bad COPY_DW (invalid count)\n"); | 2328 | DRM_ERROR("bad COPY_DW (invalid count)\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5dc744d43d12..9b9422c4403a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -225,12 +225,13 @@ struct radeon_fence { | |||
225 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); | 225 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); |
226 | int radeon_fence_driver_init(struct radeon_device *rdev); | 226 | int radeon_fence_driver_init(struct radeon_device *rdev); |
227 | void radeon_fence_driver_fini(struct radeon_device *rdev); | 227 | void radeon_fence_driver_fini(struct radeon_device *rdev); |
228 | void radeon_fence_driver_force_completion(struct radeon_device *rdev); | ||
228 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); | 229 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); |
229 | void radeon_fence_process(struct radeon_device *rdev, int ring); | 230 | void radeon_fence_process(struct radeon_device *rdev, int ring); |
230 | bool radeon_fence_signaled(struct radeon_fence *fence); | 231 | bool radeon_fence_signaled(struct radeon_fence *fence); |
231 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); | 232 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); |
232 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); | 233 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); |
233 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); | 234 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); |
234 | int radeon_fence_wait_any(struct radeon_device *rdev, | 235 | int radeon_fence_wait_any(struct radeon_device *rdev, |
235 | struct radeon_fence **fences, | 236 | struct radeon_fence **fences, |
236 | bool intr); | 237 | bool intr); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 49b06590001e..cd756262924d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -1164,6 +1164,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
1164 | struct drm_crtc *crtc; | 1164 | struct drm_crtc *crtc; |
1165 | struct drm_connector *connector; | 1165 | struct drm_connector *connector; |
1166 | int i, r; | 1166 | int i, r; |
1167 | bool force_completion = false; | ||
1167 | 1168 | ||
1168 | if (dev == NULL || dev->dev_private == NULL) { | 1169 | if (dev == NULL || dev->dev_private == NULL) { |
1169 | return -ENODEV; | 1170 | return -ENODEV; |
@@ -1206,8 +1207,16 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
1206 | 1207 | ||
1207 | mutex_lock(&rdev->ring_lock); | 1208 | mutex_lock(&rdev->ring_lock); |
1208 | /* wait for gpu to finish processing current batch */ | 1209 | /* wait for gpu to finish processing current batch */ |
1209 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 1210 | for (i = 0; i < RADEON_NUM_RINGS; i++) { |
1210 | radeon_fence_wait_empty_locked(rdev, i); | 1211 | r = radeon_fence_wait_empty_locked(rdev, i); |
1212 | if (r) { | ||
1213 | /* delay GPU reset to resume */ | ||
1214 | force_completion = true; | ||
1215 | } | ||
1216 | } | ||
1217 | if (force_completion) { | ||
1218 | radeon_fence_driver_force_completion(rdev); | ||
1219 | } | ||
1211 | mutex_unlock(&rdev->ring_lock); | 1220 | mutex_unlock(&rdev->ring_lock); |
1212 | 1221 | ||
1213 | radeon_save_bios_scratch_regs(rdev); | 1222 | radeon_save_bios_scratch_regs(rdev); |
@@ -1338,7 +1347,6 @@ retry: | |||
1338 | } | 1347 | } |
1339 | 1348 | ||
1340 | radeon_restore_bios_scratch_regs(rdev); | 1349 | radeon_restore_bios_scratch_regs(rdev); |
1341 | drm_helper_resume_force_mode(rdev->ddev); | ||
1342 | 1350 | ||
1343 | if (!r) { | 1351 | if (!r) { |
1344 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1352 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
@@ -1358,11 +1366,14 @@ retry: | |||
1358 | } | 1366 | } |
1359 | } | 1367 | } |
1360 | } else { | 1368 | } else { |
1369 | radeon_fence_driver_force_completion(rdev); | ||
1361 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1370 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
1362 | kfree(ring_data[i]); | 1371 | kfree(ring_data[i]); |
1363 | } | 1372 | } |
1364 | } | 1373 | } |
1365 | 1374 | ||
1375 | drm_helper_resume_force_mode(rdev->ddev); | ||
1376 | |||
1366 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 1377 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
1367 | if (r) { | 1378 | if (r) { |
1368 | /* bad news, how to tell it to userspace ? */ | 1379 | /* bad news, how to tell it to userspace ? */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9b1a727d3c9e..ff7593498a74 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -68,9 +68,10 @@ | |||
68 | * 2.25.0 - eg+: new info request for num SE and num SH | 68 | * 2.25.0 - eg+: new info request for num SE and num SH |
69 | * 2.26.0 - r600-eg: fix htile size computation | 69 | * 2.26.0 - r600-eg: fix htile size computation |
70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA | 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA |
71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support | ||
71 | */ | 72 | */ |
72 | #define KMS_DRIVER_MAJOR 2 | 73 | #define KMS_DRIVER_MAJOR 2 |
73 | #define KMS_DRIVER_MINOR 27 | 74 | #define KMS_DRIVER_MINOR 28 |
74 | #define KMS_DRIVER_PATCHLEVEL 0 | 75 | #define KMS_DRIVER_PATCHLEVEL 0 |
75 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 76 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
76 | int radeon_driver_unload_kms(struct drm_device *dev); | 77 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 410a975a8eec..34356252567a 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | |||
609 | * Returns 0 if the fences have passed, error for all other cases. | 609 | * Returns 0 if the fences have passed, error for all other cases. |
610 | * Caller must hold ring lock. | 610 | * Caller must hold ring lock. |
611 | */ | 611 | */ |
612 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | 612 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) |
613 | { | 613 | { |
614 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; | 614 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; |
615 | int r; | ||
615 | 616 | ||
616 | while(1) { | 617 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); |
617 | int r; | 618 | if (r) { |
618 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); | ||
619 | if (r == -EDEADLK) { | 619 | if (r == -EDEADLK) { |
620 | mutex_unlock(&rdev->ring_lock); | 620 | return -EDEADLK; |
621 | r = radeon_gpu_reset(rdev); | ||
622 | mutex_lock(&rdev->ring_lock); | ||
623 | if (!r) | ||
624 | continue; | ||
625 | } | ||
626 | if (r) { | ||
627 | dev_err(rdev->dev, "error waiting for ring to become" | ||
628 | " idle (%d)\n", r); | ||
629 | } | 621 | } |
630 | return; | 622 | dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", |
623 | ring, r); | ||
631 | } | 624 | } |
625 | return 0; | ||
632 | } | 626 | } |
633 | 627 | ||
634 | /** | 628 | /** |
@@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct radeon_device *rdev) | |||
854 | */ | 848 | */ |
855 | void radeon_fence_driver_fini(struct radeon_device *rdev) | 849 | void radeon_fence_driver_fini(struct radeon_device *rdev) |
856 | { | 850 | { |
857 | int ring; | 851 | int ring, r; |
858 | 852 | ||
859 | mutex_lock(&rdev->ring_lock); | 853 | mutex_lock(&rdev->ring_lock); |
860 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { | 854 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { |
861 | if (!rdev->fence_drv[ring].initialized) | 855 | if (!rdev->fence_drv[ring].initialized) |
862 | continue; | 856 | continue; |
863 | radeon_fence_wait_empty_locked(rdev, ring); | 857 | r = radeon_fence_wait_empty_locked(rdev, ring); |
858 | if (r) { | ||
859 | /* no need to trigger GPU reset as we are unloading */ | ||
860 | radeon_fence_driver_force_completion(rdev); | ||
861 | } | ||
864 | wake_up_all(&rdev->fence_queue); | 862 | wake_up_all(&rdev->fence_queue); |
865 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); | 863 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); |
866 | rdev->fence_drv[ring].initialized = false; | 864 | rdev->fence_drv[ring].initialized = false; |
@@ -868,6 +866,25 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) | |||
868 | mutex_unlock(&rdev->ring_lock); | 866 | mutex_unlock(&rdev->ring_lock); |
869 | } | 867 | } |
870 | 868 | ||
869 | /** | ||
870 | * radeon_fence_driver_force_completion - force all fence waiter to complete | ||
871 | * | ||
872 | * @rdev: radeon device pointer | ||
873 | * | ||
874 | * In case of GPU reset failure make sure no process keep waiting on fence | ||
875 | * that will never complete. | ||
876 | */ | ||
877 | void radeon_fence_driver_force_completion(struct radeon_device *rdev) | ||
878 | { | ||
879 | int ring; | ||
880 | |||
881 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { | ||
882 | if (!rdev->fence_drv[ring].initialized) | ||
883 | continue; | ||
884 | radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); | ||
885 | } | ||
886 | } | ||
887 | |||
871 | 888 | ||
872 | /* | 889 | /* |
873 | * Fence debugfs | 890 | * Fence debugfs |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index aa14dbb7e4fb..0bfa656aa87d 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -234,7 +234,7 @@ static void radeon_set_power_state(struct radeon_device *rdev) | |||
234 | 234 | ||
235 | static void radeon_pm_set_clocks(struct radeon_device *rdev) | 235 | static void radeon_pm_set_clocks(struct radeon_device *rdev) |
236 | { | 236 | { |
237 | int i; | 237 | int i, r; |
238 | 238 | ||
239 | /* no need to take locks, etc. if nothing's going to change */ | 239 | /* no need to take locks, etc. if nothing's going to change */ |
240 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && | 240 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && |
@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
248 | /* wait for the rings to drain */ | 248 | /* wait for the rings to drain */ |
249 | for (i = 0; i < RADEON_NUM_RINGS; i++) { | 249 | for (i = 0; i < RADEON_NUM_RINGS; i++) { |
250 | struct radeon_ring *ring = &rdev->ring[i]; | 250 | struct radeon_ring *ring = &rdev->ring[i]; |
251 | if (ring->ready) | 251 | if (!ring->ready) { |
252 | radeon_fence_wait_empty_locked(rdev, i); | 252 | continue; |
253 | } | ||
254 | r = radeon_fence_wait_empty_locked(rdev, i); | ||
255 | if (r) { | ||
256 | /* needs a GPU reset dont reset here */ | ||
257 | mutex_unlock(&rdev->ring_lock); | ||
258 | up_write(&rdev->pm.mclk_lock); | ||
259 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
260 | return; | ||
261 | } | ||
253 | } | 262 | } |
254 | 263 | ||
255 | radeon_unmap_vram_bos(rdev); | 264 | radeon_unmap_vram_bos(rdev); |