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); |
