diff options
author | Dave Airlie <airlied@redhat.com> | 2015-11-25 21:42:15 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-11-25 21:42:15 -0500 |
commit | 2f1371614a5d49428846b90673a89036518dffad (patch) | |
tree | 7c3d41f6baa9ad2e0c8d917acd8cc6e7ec8cfebd | |
parent | 78c4a49a69e910a162b05e4e8727b9bdbf948f13 (diff) | |
parent | 9c565e3386fdc804a61f8c116efc2c5999ba46e1 (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.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 122 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/sched_fence.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv730_dpm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770_dpm.c | 4 |
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 */ |
498 | struct amdgpu_bo_va { | 498 | struct 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 | ||
930 | struct amdgpu_vm { | 931 | struct 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 | ||
889 | out: | 886 | out: |
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 | ||
163 | static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r) | 156 | static 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 | ||
33 | static struct amd_sched_job * | 33 | static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity); |
34 | amd_sched_entity_pop_job(struct amd_sched_entity *entity); | ||
35 | static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); | 34 | static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); |
36 | 35 | ||
37 | struct kmem_cache *sched_fence_slab; | 36 | struct 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 | */ |
70 | static struct amd_sched_job * | 72 | static struct amd_sched_entity * |
71 | amd_sched_rq_select_job(struct amd_sched_rq *rq) | 73 | amd_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 | */ | ||
185 | static 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 | ||
231 | static 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 | |||
214 | static struct amd_sched_job * | 266 | static struct amd_sched_job * |
215 | amd_sched_entity_pop_job(struct amd_sched_entity *entity) | 267 | amd_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 | */ |
309 | static struct amd_sched_job * | 347 | static struct amd_sched_entity * |
310 | amd_sched_select_job(struct amd_gpu_scheduler *sched) | 348 | amd_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 | ||
325 | static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) | 363 | static 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 | |||
30 | struct amd_gpu_scheduler; | 32 | struct amd_gpu_scheduler; |
31 | struct amd_sched_rq; | 33 | struct amd_sched_rq; |
32 | 34 | ||
@@ -68,6 +70,7 @@ struct amd_sched_rq { | |||
68 | struct amd_sched_fence { | 70 | struct 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 | ||
135 | struct amd_sched_fence *amd_sched_fence_create( | 138 | struct 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); |
140 | void amd_sched_fence_scheduled(struct amd_sched_fence *fence); | ||
137 | void amd_sched_fence_signal(struct amd_sched_fence *fence); | 141 | void 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 | ||
60 | void 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 | |||
58 | static const char *amd_sched_fence_get_driver_name(struct fence *fence) | 71 | static 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) | |||
1418 | int rv770_set_sw_state(struct radeon_device *rdev) | 1418 | int 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 | ||