aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 8930d66f2204..8339f7a47cb2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -920,17 +920,175 @@ static const struct drm_info_list amdgpu_debugfs_list[] = {
920 {"amdgpu_evict_gtt", &amdgpu_debugfs_evict_gtt}, 920 {"amdgpu_evict_gtt", &amdgpu_debugfs_evict_gtt},
921}; 921};
922 922
923static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring,
924 struct dma_fence **fences)
925{
926 struct amdgpu_fence_driver *drv = &ring->fence_drv;
927 uint32_t sync_seq, last_seq;
928
929 last_seq = atomic_read(&ring->fence_drv.last_seq);
930 sync_seq = ring->fence_drv.sync_seq;
931
932 last_seq &= drv->num_fences_mask;
933 sync_seq &= drv->num_fences_mask;
934
935 do {
936 struct dma_fence *fence, **ptr;
937
938 ++last_seq;
939 last_seq &= drv->num_fences_mask;
940 ptr = &drv->fences[last_seq];
941
942 fence = rcu_dereference_protected(*ptr, 1);
943 RCU_INIT_POINTER(*ptr, NULL);
944
945 if (!fence)
946 continue;
947
948 fences[last_seq] = fence;
949
950 } while (last_seq != sync_seq);
951}
952
953static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences,
954 int length)
955{
956 int i;
957 struct dma_fence *fence;
958
959 for (i = 0; i < length; i++) {
960 fence = fences[i];
961 if (!fence)
962 continue;
963 dma_fence_signal(fence);
964 dma_fence_put(fence);
965 }
966}
967
968static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
969{
970 struct drm_sched_job *s_job;
971 struct dma_fence *fence;
972
973 spin_lock(&sched->job_list_lock);
974 list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
975 fence = sched->ops->run_job(s_job);
976 dma_fence_put(fence);
977 }
978 spin_unlock(&sched->job_list_lock);
979}
980
981static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
982{
983 int r, resched, length;
984 struct amdgpu_ring *ring;
985 struct drm_sched_job *s_job;
986 struct amdgpu_job *job;
987 struct dma_fence **fences = NULL;
988 struct amdgpu_device *adev = (struct amdgpu_device *)data;
989
990 if (val >= AMDGPU_MAX_RINGS)
991 return -EINVAL;
992
993 ring = adev->rings[val];
994
995 if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread)
996 return -EINVAL;
997
998 /* the last preemption failed */
999 if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr))
1000 return -EBUSY;
1001
1002 length = ring->fence_drv.num_fences_mask + 1;
1003 fences = kcalloc(length, sizeof(void *), GFP_KERNEL);
1004 if (!fences)
1005 return -ENOMEM;
1006
1007 /* stop the scheduler */
1008 kthread_park(ring->sched.thread);
1009
1010 resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
1011
1012 /* preempt the IB */
1013 r = amdgpu_ring_preempt_ib(ring);
1014 if (r) {
1015 DRM_WARN("failed to preempt ring %d\n", ring->idx);
1016 goto failure;
1017 }
1018
1019 amdgpu_fence_process(ring);
1020
1021 if (atomic_read(&ring->fence_drv.last_seq) !=
1022 ring->fence_drv.sync_seq) {
1023 DRM_INFO("ring %d was preempted\n", ring->idx);
1024
1025 /* swap out the old fences */
1026 amdgpu_ib_preempt_fences_swap(ring, fences);
1027
1028 amdgpu_fence_driver_force_completion(ring);
1029
1030 s_job = list_first_entry_or_null(
1031 &ring->sched.ring_mirror_list,
1032 struct drm_sched_job, node);
1033 if (s_job) {
1034 job = to_amdgpu_job(s_job);
1035 /* mark the job as preempted */
1036 /* job->preemption_status |=
1037 AMDGPU_IB_PREEMPTED; */
1038 }
1039
1040 /* resubmit unfinished jobs */
1041 amdgpu_ib_preempt_job_recovery(&ring->sched);
1042
1043 /* wait for jobs finished */
1044 amdgpu_fence_wait_empty(ring);
1045
1046 /* signal the old fences */
1047 amdgpu_ib_preempt_signal_fences(fences, length);
1048 }
1049
1050failure:
1051 /* restart the scheduler */
1052 kthread_unpark(ring->sched.thread);
1053
1054 ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
1055
1056 if (fences)
1057 kfree(fences);
1058
1059 return 0;
1060}
1061
1062DEFINE_SIMPLE_ATTRIBUTE(fops_ib_preempt, NULL,
1063 amdgpu_debugfs_ib_preempt, "%llu\n");
1064
923int amdgpu_debugfs_init(struct amdgpu_device *adev) 1065int amdgpu_debugfs_init(struct amdgpu_device *adev)
924{ 1066{
1067 adev->debugfs_preempt =
1068 debugfs_create_file("amdgpu_preempt_ib", 0600,
1069 adev->ddev->primary->debugfs_root,
1070 (void *)adev, &fops_ib_preempt);
1071 if (!(adev->debugfs_preempt)) {
1072 DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n");
1073 return -EIO;
1074 }
1075
925 return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, 1076 return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list,
926 ARRAY_SIZE(amdgpu_debugfs_list)); 1077 ARRAY_SIZE(amdgpu_debugfs_list));
927} 1078}
928 1079
1080void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev)
1081{
1082 if (adev->debugfs_preempt)
1083 debugfs_remove(adev->debugfs_preempt);
1084}
1085
929#else 1086#else
930int amdgpu_debugfs_init(struct amdgpu_device *adev) 1087int amdgpu_debugfs_init(struct amdgpu_device *adev)
931{ 1088{
932 return 0; 1089 return 0;
933} 1090}
1091void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev) { }
934int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 1092int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
935{ 1093{
936 return 0; 1094 return 0;