diff options
author | Dave Airlie <airlied@redhat.com> | 2015-03-12 19:21:24 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-03-12 19:21:24 -0400 |
commit | e2cdcafa8a53228cb996b3c3a0a48efe91c57b8e (patch) | |
tree | 533e9ba8300907e8103657fbc56d973c5cf33ed6 /drivers/gpu | |
parent | 552d6643412980044dfb9b38fcfe0179dbd77b28 (diff) | |
parent | a17d4996e051e78d164989b894608cf37cd5110b (diff) |
Merge branch 'drm-fixes-4.0' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
Some additional radeon fixes for 4.0
* 'drm-fixes-4.0' of git://people.freedesktop.org/~agd5f/linux:
drm/radeon: drop setting UPLL to sleep mode
drm/radeon: fix wait to actually occur after the signaling callback
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 6 |
2 files changed, 47 insertions, 27 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index d13d1b5a859f..df09ca7c4889 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -1030,37 +1030,59 @@ static inline bool radeon_test_signaled(struct radeon_fence *fence) | |||
1030 | return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); | 1030 | return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | struct radeon_wait_cb { | ||
1034 | struct fence_cb base; | ||
1035 | struct task_struct *task; | ||
1036 | }; | ||
1037 | |||
1038 | static void | ||
1039 | radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb) | ||
1040 | { | ||
1041 | struct radeon_wait_cb *wait = | ||
1042 | container_of(cb, struct radeon_wait_cb, base); | ||
1043 | |||
1044 | wake_up_process(wait->task); | ||
1045 | } | ||
1046 | |||
1033 | static signed long radeon_fence_default_wait(struct fence *f, bool intr, | 1047 | static signed long radeon_fence_default_wait(struct fence *f, bool intr, |
1034 | signed long t) | 1048 | signed long t) |
1035 | { | 1049 | { |
1036 | struct radeon_fence *fence = to_radeon_fence(f); | 1050 | struct radeon_fence *fence = to_radeon_fence(f); |
1037 | struct radeon_device *rdev = fence->rdev; | 1051 | struct radeon_device *rdev = fence->rdev; |
1038 | bool signaled; | 1052 | struct radeon_wait_cb cb; |
1039 | 1053 | ||
1040 | fence_enable_sw_signaling(&fence->base); | 1054 | cb.task = current; |
1041 | 1055 | ||
1042 | /* | 1056 | if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb)) |
1043 | * This function has to return -EDEADLK, but cannot hold | 1057 | return t; |
1044 | * exclusive_lock during the wait because some callers | 1058 | |
1045 | * may already hold it. This means checking needs_reset without | 1059 | while (t > 0) { |
1046 | * lock, and not fiddling with any gpu internals. | 1060 | if (intr) |
1047 | * | 1061 | set_current_state(TASK_INTERRUPTIBLE); |
1048 | * The callback installed with fence_enable_sw_signaling will | 1062 | else |
1049 | * run before our wait_event_*timeout call, so we will see | 1063 | set_current_state(TASK_UNINTERRUPTIBLE); |
1050 | * both the signaled fence and the changes to needs_reset. | 1064 | |
1051 | */ | 1065 | /* |
1066 | * radeon_test_signaled must be called after | ||
1067 | * set_current_state to prevent a race with wake_up_process | ||
1068 | */ | ||
1069 | if (radeon_test_signaled(fence)) | ||
1070 | break; | ||
1071 | |||
1072 | if (rdev->needs_reset) { | ||
1073 | t = -EDEADLK; | ||
1074 | break; | ||
1075 | } | ||
1076 | |||
1077 | t = schedule_timeout(t); | ||
1078 | |||
1079 | if (t > 0 && intr && signal_pending(current)) | ||
1080 | t = -ERESTARTSYS; | ||
1081 | } | ||
1082 | |||
1083 | __set_current_state(TASK_RUNNING); | ||
1084 | fence_remove_callback(f, &cb.base); | ||
1052 | 1085 | ||
1053 | if (intr) | ||
1054 | t = wait_event_interruptible_timeout(rdev->fence_queue, | ||
1055 | ((signaled = radeon_test_signaled(fence)) || | ||
1056 | rdev->needs_reset), t); | ||
1057 | else | ||
1058 | t = wait_event_timeout(rdev->fence_queue, | ||
1059 | ((signaled = radeon_test_signaled(fence)) || | ||
1060 | rdev->needs_reset), t); | ||
1061 | |||
1062 | if (t > 0 && !signaled) | ||
1063 | return -EDEADLK; | ||
1064 | return t; | 1086 | return t; |
1065 | } | 1087 | } |
1066 | 1088 | ||
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e088e5558da0..a7fb2735d4a9 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -7130,8 +7130,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
7130 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); | 7130 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); |
7131 | 7131 | ||
7132 | if (!vclk || !dclk) { | 7132 | if (!vclk || !dclk) { |
7133 | /* keep the Bypass mode, put PLL to sleep */ | 7133 | /* keep the Bypass mode */ |
7134 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
7135 | return 0; | 7134 | return 0; |
7136 | } | 7135 | } |
7137 | 7136 | ||
@@ -7147,8 +7146,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
7147 | /* set VCO_MODE to 1 */ | 7146 | /* set VCO_MODE to 1 */ |
7148 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); | 7147 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); |
7149 | 7148 | ||
7150 | /* toggle UPLL_SLEEP to 1 then back to 0 */ | 7149 | /* disable sleep mode */ |
7151 | WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); | ||
7152 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); | 7150 | WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); |
7153 | 7151 | ||
7154 | /* deassert UPLL_RESET */ | 7152 | /* deassert UPLL_RESET */ |