aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-11-25 21:42:15 -0500
committerDave Airlie <airlied@redhat.com>2015-11-25 21:42:15 -0500
commit2f1371614a5d49428846b90673a89036518dffad (patch)
tree7c3d41f6baa9ad2e0c8d917acd8cc6e7ec8cfebd
parent78c4a49a69e910a162b05e4e8727b9bdbf948f13 (diff)
parent9c565e3386fdc804a61f8c116efc2c5999ba46e1 (diff)
Merge branch 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
Radeon and amdgpu fixes for 4.4: - DPM fixes for r7xx devices - VCE fixes for Stoney - GPUVM fixes - Scheduler fixes * 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux: drm/radeon: make some dpm errors debug only drm/radeon: make rv770_set_sw_state failures non-fatal drm/amdgpu: move dependency handling out of atomic section v2 drm/amdgpu: optimize scheduler fence handling drm/amdgpu: remove vm->mutex drm/amdgpu: add mutex for ba_va->valids/invalids drm/amdgpu: adapt vce session create interface changes drm/amdgpu: vce use multiple cache surface starting from stoney drm/amdgpu: reset vce trap interrupt flag
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c24
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c122
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.h5
-rw-r--r--drivers/gpu/drm/amd/scheduler/sched_fence.c13
-rw-r--r--drivers/gpu/drm/radeon/rv730_dpm.c2
-rw-r--r--drivers/gpu/drm/radeon/rv770_dpm.c4
11 files changed, 145 insertions, 76 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 306f75700bf8..251b14736de9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -496,6 +496,7 @@ struct amdgpu_bo_va_mapping {
496 496
497/* bo virtual addresses in a specific vm */ 497/* bo virtual addresses in a specific vm */
498struct amdgpu_bo_va { 498struct amdgpu_bo_va {
499 struct mutex mutex;
499 /* protected by bo being reserved */ 500 /* protected by bo being reserved */
500 struct list_head bo_list; 501 struct list_head bo_list;
501 struct fence *last_pt_update; 502 struct fence *last_pt_update;
@@ -928,8 +929,6 @@ struct amdgpu_vm_id {
928}; 929};
929 930
930struct amdgpu_vm { 931struct amdgpu_vm {
931 struct mutex mutex;
932
933 struct rb_root va; 932 struct rb_root va;
934 933
935 /* protecting invalidated */ 934 /* protecting invalidated */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 3afcf0237c25..1d44d508d4d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -784,8 +784,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
784{ 784{
785 struct amdgpu_device *adev = dev->dev_private; 785 struct amdgpu_device *adev = dev->dev_private;
786 union drm_amdgpu_cs *cs = data; 786 union drm_amdgpu_cs *cs = data;
787 struct amdgpu_fpriv *fpriv = filp->driver_priv;
788 struct amdgpu_vm *vm = &fpriv->vm;
789 struct amdgpu_cs_parser parser = {}; 787 struct amdgpu_cs_parser parser = {};
790 bool reserved_buffers = false; 788 bool reserved_buffers = false;
791 int i, r; 789 int i, r;
@@ -803,7 +801,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
803 r = amdgpu_cs_handle_lockup(adev, r); 801 r = amdgpu_cs_handle_lockup(adev, r);
804 return r; 802 return r;
805 } 803 }
806 mutex_lock(&vm->mutex);
807 r = amdgpu_cs_parser_relocs(&parser); 804 r = amdgpu_cs_parser_relocs(&parser);
808 if (r == -ENOMEM) 805 if (r == -ENOMEM)
809 DRM_ERROR("Not enough memory for command submission!\n"); 806 DRM_ERROR("Not enough memory for command submission!\n");
@@ -888,7 +885,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
888 885
889out: 886out:
890 amdgpu_cs_parser_fini(&parser, r, reserved_buffers); 887 amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
891 mutex_unlock(&vm->mutex);
892 r = amdgpu_cs_handle_lockup(adev, r); 888 r = amdgpu_cs_handle_lockup(adev, r);
893 return r; 889 return r;
894} 890}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 00c5b580f56c..fc32fc01a64b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -115,12 +115,9 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
115 struct amdgpu_vm *vm = &fpriv->vm; 115 struct amdgpu_vm *vm = &fpriv->vm;
116 struct amdgpu_bo_va *bo_va; 116 struct amdgpu_bo_va *bo_va;
117 int r; 117 int r;
118 mutex_lock(&vm->mutex);
119 r = amdgpu_bo_reserve(rbo, false); 118 r = amdgpu_bo_reserve(rbo, false);
120 if (r) { 119 if (r)
121 mutex_unlock(&vm->mutex);
122 return r; 120 return r;
123 }
124 121
125 bo_va = amdgpu_vm_bo_find(vm, rbo); 122 bo_va = amdgpu_vm_bo_find(vm, rbo);
126 if (!bo_va) { 123 if (!bo_va) {
@@ -129,7 +126,6 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
129 ++bo_va->ref_count; 126 ++bo_va->ref_count;
130 } 127 }
131 amdgpu_bo_unreserve(rbo); 128 amdgpu_bo_unreserve(rbo);
132 mutex_unlock(&vm->mutex);
133 return 0; 129 return 0;
134} 130}
135 131
@@ -142,10 +138,8 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
142 struct amdgpu_vm *vm = &fpriv->vm; 138 struct amdgpu_vm *vm = &fpriv->vm;
143 struct amdgpu_bo_va *bo_va; 139 struct amdgpu_bo_va *bo_va;
144 int r; 140 int r;
145 mutex_lock(&vm->mutex);
146 r = amdgpu_bo_reserve(rbo, true); 141 r = amdgpu_bo_reserve(rbo, true);
147 if (r) { 142 if (r) {
148 mutex_unlock(&vm->mutex);
149 dev_err(adev->dev, "leaking bo va because " 143 dev_err(adev->dev, "leaking bo va because "
150 "we fail to reserve bo (%d)\n", r); 144 "we fail to reserve bo (%d)\n", r);
151 return; 145 return;
@@ -157,7 +151,6 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
157 } 151 }
158 } 152 }
159 amdgpu_bo_unreserve(rbo); 153 amdgpu_bo_unreserve(rbo);
160 mutex_unlock(&vm->mutex);
161} 154}
162 155
163static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r) 156static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r)
@@ -553,7 +546,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
553 gobj = drm_gem_object_lookup(dev, filp, args->handle); 546 gobj = drm_gem_object_lookup(dev, filp, args->handle);
554 if (gobj == NULL) 547 if (gobj == NULL)
555 return -ENOENT; 548 return -ENOENT;
556 mutex_lock(&fpriv->vm.mutex);
557 rbo = gem_to_amdgpu_bo(gobj); 549 rbo = gem_to_amdgpu_bo(gobj);
558 INIT_LIST_HEAD(&list); 550 INIT_LIST_HEAD(&list);
559 INIT_LIST_HEAD(&duplicates); 551 INIT_LIST_HEAD(&duplicates);
@@ -568,7 +560,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
568 } 560 }
569 r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); 561 r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
570 if (r) { 562 if (r) {
571 mutex_unlock(&fpriv->vm.mutex);
572 drm_gem_object_unreference_unlocked(gobj); 563 drm_gem_object_unreference_unlocked(gobj);
573 return r; 564 return r;
574 } 565 }
@@ -577,7 +568,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
577 if (!bo_va) { 568 if (!bo_va) {
578 ttm_eu_backoff_reservation(&ticket, &list); 569 ttm_eu_backoff_reservation(&ticket, &list);
579 drm_gem_object_unreference_unlocked(gobj); 570 drm_gem_object_unreference_unlocked(gobj);
580 mutex_unlock(&fpriv->vm.mutex);
581 return -ENOENT; 571 return -ENOENT;
582 } 572 }
583 573
@@ -602,7 +592,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
602 ttm_eu_backoff_reservation(&ticket, &list); 592 ttm_eu_backoff_reservation(&ticket, &list);
603 if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) 593 if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
604 amdgpu_gem_va_update_vm(adev, bo_va, args->operation); 594 amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
605 mutex_unlock(&fpriv->vm.mutex); 595
606 drm_gem_object_unreference_unlocked(gobj); 596 drm_gem_object_unreference_unlocked(gobj);
607 return r; 597 return r;
608} 598}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 03f0c3bae516..a745eeeb5d82 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -392,7 +392,10 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
392 ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ 392 ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */
393 ib->ptr[ib->length_dw++] = handle; 393 ib->ptr[ib->length_dw++] = handle;
394 394
395 ib->ptr[ib->length_dw++] = 0x00000030; /* len */ 395 if ((ring->adev->vce.fw_version >> 24) >= 52)
396 ib->ptr[ib->length_dw++] = 0x00000040; /* len */
397 else
398 ib->ptr[ib->length_dw++] = 0x00000030; /* len */
396 ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */ 399 ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */
397 ib->ptr[ib->length_dw++] = 0x00000000; 400 ib->ptr[ib->length_dw++] = 0x00000000;
398 ib->ptr[ib->length_dw++] = 0x00000042; 401 ib->ptr[ib->length_dw++] = 0x00000042;
@@ -404,6 +407,12 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
404 ib->ptr[ib->length_dw++] = 0x00000100; 407 ib->ptr[ib->length_dw++] = 0x00000100;
405 ib->ptr[ib->length_dw++] = 0x0000000c; 408 ib->ptr[ib->length_dw++] = 0x0000000c;
406 ib->ptr[ib->length_dw++] = 0x00000000; 409 ib->ptr[ib->length_dw++] = 0x00000000;
410 if ((ring->adev->vce.fw_version >> 24) >= 52) {
411 ib->ptr[ib->length_dw++] = 0x00000000;
412 ib->ptr[ib->length_dw++] = 0x00000000;
413 ib->ptr[ib->length_dw++] = 0x00000000;
414 ib->ptr[ib->length_dw++] = 0x00000000;
415 }
407 416
408 ib->ptr[ib->length_dw++] = 0x00000014; /* len */ 417 ib->ptr[ib->length_dw++] = 0x00000014; /* len */
409 ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ 418 ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 159ce54bbd8d..ae037e5b6ad0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -922,8 +922,9 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev,
922 bo_va = list_first_entry(&vm->invalidated, 922 bo_va = list_first_entry(&vm->invalidated,
923 struct amdgpu_bo_va, vm_status); 923 struct amdgpu_bo_va, vm_status);
924 spin_unlock(&vm->status_lock); 924 spin_unlock(&vm->status_lock);
925 925 mutex_lock(&bo_va->mutex);
926 r = amdgpu_vm_bo_update(adev, bo_va, NULL); 926 r = amdgpu_vm_bo_update(adev, bo_va, NULL);
927 mutex_unlock(&bo_va->mutex);
927 if (r) 928 if (r)
928 return r; 929 return r;
929 930
@@ -967,7 +968,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
967 INIT_LIST_HEAD(&bo_va->valids); 968 INIT_LIST_HEAD(&bo_va->valids);
968 INIT_LIST_HEAD(&bo_va->invalids); 969 INIT_LIST_HEAD(&bo_va->invalids);
969 INIT_LIST_HEAD(&bo_va->vm_status); 970 INIT_LIST_HEAD(&bo_va->vm_status);
970 971 mutex_init(&bo_va->mutex);
971 list_add_tail(&bo_va->bo_list, &bo->va); 972 list_add_tail(&bo_va->bo_list, &bo->va);
972 973
973 return bo_va; 974 return bo_va;
@@ -1045,7 +1046,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
1045 mapping->offset = offset; 1046 mapping->offset = offset;
1046 mapping->flags = flags; 1047 mapping->flags = flags;
1047 1048
1049 mutex_lock(&bo_va->mutex);
1048 list_add(&mapping->list, &bo_va->invalids); 1050 list_add(&mapping->list, &bo_va->invalids);
1051 mutex_unlock(&bo_va->mutex);
1049 spin_lock(&vm->it_lock); 1052 spin_lock(&vm->it_lock);
1050 interval_tree_insert(&mapping->it, &vm->va); 1053 interval_tree_insert(&mapping->it, &vm->va);
1051 spin_unlock(&vm->it_lock); 1054 spin_unlock(&vm->it_lock);
@@ -1121,7 +1124,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
1121 bool valid = true; 1124 bool valid = true;
1122 1125
1123 saddr /= AMDGPU_GPU_PAGE_SIZE; 1126 saddr /= AMDGPU_GPU_PAGE_SIZE;
1124 1127 mutex_lock(&bo_va->mutex);
1125 list_for_each_entry(mapping, &bo_va->valids, list) { 1128 list_for_each_entry(mapping, &bo_va->valids, list) {
1126 if (mapping->it.start == saddr) 1129 if (mapping->it.start == saddr)
1127 break; 1130 break;
@@ -1135,10 +1138,12 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
1135 break; 1138 break;
1136 } 1139 }
1137 1140
1138 if (&mapping->list == &bo_va->invalids) 1141 if (&mapping->list == &bo_va->invalids) {
1142 mutex_unlock(&bo_va->mutex);
1139 return -ENOENT; 1143 return -ENOENT;
1144 }
1140 } 1145 }
1141 1146 mutex_unlock(&bo_va->mutex);
1142 list_del(&mapping->list); 1147 list_del(&mapping->list);
1143 spin_lock(&vm->it_lock); 1148 spin_lock(&vm->it_lock);
1144 interval_tree_remove(&mapping->it, &vm->va); 1149 interval_tree_remove(&mapping->it, &vm->va);
@@ -1190,8 +1195,8 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
1190 spin_unlock(&vm->it_lock); 1195 spin_unlock(&vm->it_lock);
1191 kfree(mapping); 1196 kfree(mapping);
1192 } 1197 }
1193
1194 fence_put(bo_va->last_pt_update); 1198 fence_put(bo_va->last_pt_update);
1199 mutex_destroy(&bo_va->mutex);
1195 kfree(bo_va); 1200 kfree(bo_va);
1196} 1201}
1197 1202
@@ -1236,7 +1241,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1236 vm->ids[i].id = 0; 1241 vm->ids[i].id = 0;
1237 vm->ids[i].flushed_updates = NULL; 1242 vm->ids[i].flushed_updates = NULL;
1238 } 1243 }
1239 mutex_init(&vm->mutex);
1240 vm->va = RB_ROOT; 1244 vm->va = RB_ROOT;
1241 spin_lock_init(&vm->status_lock); 1245 spin_lock_init(&vm->status_lock);
1242 INIT_LIST_HEAD(&vm->invalidated); 1246 INIT_LIST_HEAD(&vm->invalidated);
@@ -1320,7 +1324,6 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1320 fence_put(vm->ids[i].flushed_updates); 1324 fence_put(vm->ids[i].flushed_updates);
1321 } 1325 }
1322 1326
1323 mutex_destroy(&vm->mutex);
1324} 1327}
1325 1328
1326/** 1329/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 6a52db6ad8d7..370c6c9d81c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -40,6 +40,9 @@
40 40
41#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 41#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
42#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 42#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
43#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 0x8616
44#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 0x8617
45#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 0x8618
43 46
44#define VCE_V3_0_FW_SIZE (384 * 1024) 47#define VCE_V3_0_FW_SIZE (384 * 1024)
45#define VCE_V3_0_STACK_SIZE (64 * 1024) 48#define VCE_V3_0_STACK_SIZE (64 * 1024)
@@ -130,9 +133,11 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
130 133
131 /* set BUSY flag */ 134 /* set BUSY flag */
132 WREG32_P(mmVCE_STATUS, 1, ~1); 135 WREG32_P(mmVCE_STATUS, 1, ~1);
133 136 if (adev->asic_type >= CHIP_STONEY)
134 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, 137 WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
135 ~VCE_VCPU_CNTL__CLK_EN_MASK); 138 else
139 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
140 ~VCE_VCPU_CNTL__CLK_EN_MASK);
136 141
137 WREG32_P(mmVCE_SOFT_RESET, 142 WREG32_P(mmVCE_SOFT_RESET,
138 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 143 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
@@ -391,8 +396,12 @@ static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
391 WREG32(mmVCE_LMI_SWAP_CNTL, 0); 396 WREG32(mmVCE_LMI_SWAP_CNTL, 0);
392 WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 397 WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
393 WREG32(mmVCE_LMI_VM_CTRL, 0); 398 WREG32(mmVCE_LMI_VM_CTRL, 0);
394 399 if (adev->asic_type >= CHIP_STONEY) {
395 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8)); 400 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
401 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
402 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
403 } else
404 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
396 offset = AMDGPU_VCE_FIRMWARE_OFFSET; 405 offset = AMDGPU_VCE_FIRMWARE_OFFSET;
397 size = VCE_V3_0_FW_SIZE; 406 size = VCE_V3_0_FW_SIZE;
398 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 407 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
@@ -576,6 +585,11 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
576 struct amdgpu_iv_entry *entry) 585 struct amdgpu_iv_entry *entry)
577{ 586{
578 DRM_DEBUG("IH: VCE\n"); 587 DRM_DEBUG("IH: VCE\n");
588
589 WREG32_P(mmVCE_SYS_INT_STATUS,
590 VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK,
591 ~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK);
592
579 switch (entry->src_data) { 593 switch (entry->src_data) {
580 case 0: 594 case 0:
581 amdgpu_fence_process(&adev->vce.ring[0]); 595 amdgpu_fence_process(&adev->vce.ring[0]);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index ea30d6ad4c13..651129f2ec1d 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -30,8 +30,7 @@
30#define CREATE_TRACE_POINTS 30#define CREATE_TRACE_POINTS
31#include "gpu_sched_trace.h" 31#include "gpu_sched_trace.h"
32 32
33static struct amd_sched_job * 33static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity);
34amd_sched_entity_pop_job(struct amd_sched_entity *entity);
35static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); 34static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
36 35
37struct kmem_cache *sched_fence_slab; 36struct kmem_cache *sched_fence_slab;
@@ -64,36 +63,36 @@ static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
64} 63}
65 64
66/** 65/**
67 * Select next job from a specified run queue with round robin policy. 66 * Select an entity which could provide a job to run
68 * Return NULL if nothing available. 67 *
68 * @rq The run queue to check.
69 *
70 * Try to find a ready entity, returns NULL if none found.
69 */ 71 */
70static struct amd_sched_job * 72static struct amd_sched_entity *
71amd_sched_rq_select_job(struct amd_sched_rq *rq) 73amd_sched_rq_select_entity(struct amd_sched_rq *rq)
72{ 74{
73 struct amd_sched_entity *entity; 75 struct amd_sched_entity *entity;
74 struct amd_sched_job *sched_job;
75 76
76 spin_lock(&rq->lock); 77 spin_lock(&rq->lock);
77 78
78 entity = rq->current_entity; 79 entity = rq->current_entity;
79 if (entity) { 80 if (entity) {
80 list_for_each_entry_continue(entity, &rq->entities, list) { 81 list_for_each_entry_continue(entity, &rq->entities, list) {
81 sched_job = amd_sched_entity_pop_job(entity); 82 if (amd_sched_entity_is_ready(entity)) {
82 if (sched_job) {
83 rq->current_entity = entity; 83 rq->current_entity = entity;
84 spin_unlock(&rq->lock); 84 spin_unlock(&rq->lock);
85 return sched_job; 85 return entity;
86 } 86 }
87 } 87 }
88 } 88 }
89 89
90 list_for_each_entry(entity, &rq->entities, list) { 90 list_for_each_entry(entity, &rq->entities, list) {
91 91
92 sched_job = amd_sched_entity_pop_job(entity); 92 if (amd_sched_entity_is_ready(entity)) {
93 if (sched_job) {
94 rq->current_entity = entity; 93 rq->current_entity = entity;
95 spin_unlock(&rq->lock); 94 spin_unlock(&rq->lock);
96 return sched_job; 95 return entity;
97 } 96 }
98 97
99 if (entity == rq->current_entity) 98 if (entity == rq->current_entity)
@@ -177,6 +176,24 @@ static bool amd_sched_entity_is_idle(struct amd_sched_entity *entity)
177} 176}
178 177
179/** 178/**
179 * Check if entity is ready
180 *
181 * @entity The pointer to a valid scheduler entity
182 *
183 * Return true if entity could provide a job.
184 */
185static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity)
186{
187 if (kfifo_is_empty(&entity->job_queue))
188 return false;
189
190 if (ACCESS_ONCE(entity->dependency))
191 return false;
192
193 return true;
194}
195
196/**
180 * Destroy a context entity 197 * Destroy a context entity
181 * 198 *
182 * @sched Pointer to scheduler instance 199 * @sched Pointer to scheduler instance
@@ -211,32 +228,53 @@ static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb)
211 amd_sched_wakeup(entity->sched); 228 amd_sched_wakeup(entity->sched);
212} 229}
213 230
231static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity)
232{
233 struct amd_gpu_scheduler *sched = entity->sched;
234 struct fence * fence = entity->dependency;
235 struct amd_sched_fence *s_fence;
236
237 if (fence->context == entity->fence_context) {
238 /* We can ignore fences from ourself */
239 fence_put(entity->dependency);
240 return false;
241 }
242
243 s_fence = to_amd_sched_fence(fence);
244 if (s_fence && s_fence->sched == sched) {
245 /* Fence is from the same scheduler */
246 if (test_bit(AMD_SCHED_FENCE_SCHEDULED_BIT, &fence->flags)) {
247 /* Ignore it when it is already scheduled */
248 fence_put(entity->dependency);
249 return false;
250 }
251
252 /* Wait for fence to be scheduled */
253 entity->cb.func = amd_sched_entity_wakeup;
254 list_add_tail(&entity->cb.node, &s_fence->scheduled_cb);
255 return true;
256 }
257
258 if (!fence_add_callback(entity->dependency, &entity->cb,
259 amd_sched_entity_wakeup))
260 return true;
261
262 fence_put(entity->dependency);
263 return false;
264}
265
214static struct amd_sched_job * 266static struct amd_sched_job *
215amd_sched_entity_pop_job(struct amd_sched_entity *entity) 267amd_sched_entity_pop_job(struct amd_sched_entity *entity)
216{ 268{
217 struct amd_gpu_scheduler *sched = entity->sched; 269 struct amd_gpu_scheduler *sched = entity->sched;
218 struct amd_sched_job *sched_job; 270 struct amd_sched_job *sched_job;
219 271
220 if (ACCESS_ONCE(entity->dependency))
221 return NULL;
222
223 if (!kfifo_out_peek(&entity->job_queue, &sched_job, sizeof(sched_job))) 272 if (!kfifo_out_peek(&entity->job_queue, &sched_job, sizeof(sched_job)))
224 return NULL; 273 return NULL;
225 274
226 while ((entity->dependency = sched->ops->dependency(sched_job))) { 275 while ((entity->dependency = sched->ops->dependency(sched_job)))
227 276 if (amd_sched_entity_add_dependency_cb(entity))
228 if (entity->dependency->context == entity->fence_context) {
229 /* We can ignore fences from ourself */
230 fence_put(entity->dependency);
231 continue;
232 }
233
234 if (fence_add_callback(entity->dependency, &entity->cb,
235 amd_sched_entity_wakeup))
236 fence_put(entity->dependency);
237 else
238 return NULL; 277 return NULL;
239 }
240 278
241 return sched_job; 279 return sched_job;
242} 280}
@@ -304,22 +342,22 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched)
304} 342}
305 343
306/** 344/**
307 * Select next to run 345 * Select next entity to process
308*/ 346*/
309static struct amd_sched_job * 347static struct amd_sched_entity *
310amd_sched_select_job(struct amd_gpu_scheduler *sched) 348amd_sched_select_entity(struct amd_gpu_scheduler *sched)
311{ 349{
312 struct amd_sched_job *sched_job; 350 struct amd_sched_entity *entity;
313 351
314 if (!amd_sched_ready(sched)) 352 if (!amd_sched_ready(sched))
315 return NULL; 353 return NULL;
316 354
317 /* Kernel run queue has higher priority than normal run queue*/ 355 /* Kernel run queue has higher priority than normal run queue*/
318 sched_job = amd_sched_rq_select_job(&sched->kernel_rq); 356 entity = amd_sched_rq_select_entity(&sched->kernel_rq);
319 if (sched_job == NULL) 357 if (entity == NULL)
320 sched_job = amd_sched_rq_select_job(&sched->sched_rq); 358 entity = amd_sched_rq_select_entity(&sched->sched_rq);
321 359
322 return sched_job; 360 return entity;
323} 361}
324 362
325static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) 363static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
@@ -381,13 +419,16 @@ static int amd_sched_main(void *param)
381 unsigned long flags; 419 unsigned long flags;
382 420
383 wait_event_interruptible(sched->wake_up_worker, 421 wait_event_interruptible(sched->wake_up_worker,
384 kthread_should_stop() || 422 (entity = amd_sched_select_entity(sched)) ||
385 (sched_job = amd_sched_select_job(sched))); 423 kthread_should_stop());
386 424
425 if (!entity)
426 continue;
427
428 sched_job = amd_sched_entity_pop_job(entity);
387 if (!sched_job) 429 if (!sched_job)
388 continue; 430 continue;
389 431
390 entity = sched_job->s_entity;
391 s_fence = sched_job->s_fence; 432 s_fence = sched_job->s_fence;
392 433
393 if (sched->timeout != MAX_SCHEDULE_TIMEOUT) { 434 if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
@@ -400,6 +441,7 @@ static int amd_sched_main(void *param)
400 441
401 atomic_inc(&sched->hw_rq_count); 442 atomic_inc(&sched->hw_rq_count);
402 fence = sched->ops->run_job(sched_job); 443 fence = sched->ops->run_job(sched_job);
444 amd_sched_fence_scheduled(s_fence);
403 if (fence) { 445 if (fence) {
404 r = fence_add_callback(fence, &s_fence->cb, 446 r = fence_add_callback(fence, &s_fence->cb,
405 amd_sched_process_job); 447 amd_sched_process_job);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index 939692b14f4b..a0f0ae53aacd 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -27,6 +27,8 @@
27#include <linux/kfifo.h> 27#include <linux/kfifo.h>
28#include <linux/fence.h> 28#include <linux/fence.h>
29 29
30#define AMD_SCHED_FENCE_SCHEDULED_BIT FENCE_FLAG_USER_BITS
31
30struct amd_gpu_scheduler; 32struct amd_gpu_scheduler;
31struct amd_sched_rq; 33struct amd_sched_rq;
32 34
@@ -68,6 +70,7 @@ struct amd_sched_rq {
68struct amd_sched_fence { 70struct amd_sched_fence {
69 struct fence base; 71 struct fence base;
70 struct fence_cb cb; 72 struct fence_cb cb;
73 struct list_head scheduled_cb;
71 struct amd_gpu_scheduler *sched; 74 struct amd_gpu_scheduler *sched;
72 spinlock_t lock; 75 spinlock_t lock;
73 void *owner; 76 void *owner;
@@ -134,7 +137,7 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job);
134 137
135struct amd_sched_fence *amd_sched_fence_create( 138struct amd_sched_fence *amd_sched_fence_create(
136 struct amd_sched_entity *s_entity, void *owner); 139 struct amd_sched_entity *s_entity, void *owner);
140void amd_sched_fence_scheduled(struct amd_sched_fence *fence);
137void amd_sched_fence_signal(struct amd_sched_fence *fence); 141void amd_sched_fence_signal(struct amd_sched_fence *fence);
138 142
139
140#endif 143#endif
diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c
index 8d2130b9ff05..87c78eecea64 100644
--- a/drivers/gpu/drm/amd/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c
@@ -35,6 +35,8 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *s_entity
35 fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL); 35 fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
36 if (fence == NULL) 36 if (fence == NULL)
37 return NULL; 37 return NULL;
38
39 INIT_LIST_HEAD(&fence->scheduled_cb);
38 fence->owner = owner; 40 fence->owner = owner;
39 fence->sched = s_entity->sched; 41 fence->sched = s_entity->sched;
40 spin_lock_init(&fence->lock); 42 spin_lock_init(&fence->lock);
@@ -55,6 +57,17 @@ void amd_sched_fence_signal(struct amd_sched_fence *fence)
55 FENCE_TRACE(&fence->base, "was already signaled\n"); 57 FENCE_TRACE(&fence->base, "was already signaled\n");
56} 58}
57 59
60void amd_sched_fence_scheduled(struct amd_sched_fence *s_fence)
61{
62 struct fence_cb *cur, *tmp;
63
64 set_bit(AMD_SCHED_FENCE_SCHEDULED_BIT, &s_fence->base.flags);
65 list_for_each_entry_safe(cur, tmp, &s_fence->scheduled_cb, node) {
66 list_del_init(&cur->node);
67 cur->func(&s_fence->base, cur);
68 }
69}
70
58static const char *amd_sched_fence_get_driver_name(struct fence *fence) 71static const char *amd_sched_fence_get_driver_name(struct fence *fence)
59{ 72{
60 return "amd_sched"; 73 return "amd_sched";
diff --git a/drivers/gpu/drm/radeon/rv730_dpm.c b/drivers/gpu/drm/radeon/rv730_dpm.c
index 3f5e1cf138ba..d37ba2cb886e 100644
--- a/drivers/gpu/drm/radeon/rv730_dpm.c
+++ b/drivers/gpu/drm/radeon/rv730_dpm.c
@@ -464,7 +464,7 @@ void rv730_stop_dpm(struct radeon_device *rdev)
464 result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); 464 result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
465 465
466 if (result != PPSMC_Result_OK) 466 if (result != PPSMC_Result_OK)
467 DRM_ERROR("Could not force DPM to low\n"); 467 DRM_DEBUG("Could not force DPM to low\n");
468 468
469 WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); 469 WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
470 470
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
index b9c770745a7a..e830c8935db0 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -193,7 +193,7 @@ void rv770_stop_dpm(struct radeon_device *rdev)
193 result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); 193 result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
194 194
195 if (result != PPSMC_Result_OK) 195 if (result != PPSMC_Result_OK)
196 DRM_ERROR("Could not force DPM to low.\n"); 196 DRM_DEBUG("Could not force DPM to low.\n");
197 197
198 WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); 198 WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
199 199
@@ -1418,7 +1418,7 @@ int rv770_resume_smc(struct radeon_device *rdev)
1418int rv770_set_sw_state(struct radeon_device *rdev) 1418int rv770_set_sw_state(struct radeon_device *rdev)
1419{ 1419{
1420 if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) != PPSMC_Result_OK) 1420 if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) != PPSMC_Result_OK)
1421 return -EINVAL; 1421 DRM_DEBUG("rv770_set_sw_state failed\n");
1422 return 0; 1422 return 0;
1423} 1423}
1424 1424