aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_semaphore.c
diff options
context:
space:
mode:
authorChristian König <deathsimple@vodafone.de>2012-05-02 09:11:18 -0400
committerDave Airlie <airlied@redhat.com>2012-05-03 04:16:27 -0400
commit8f676c4c6f0f500616560f13c0276ab6b4e39a6a (patch)
tree722ab761de1b53460f4b0308c08f0e41a18b4b5c /drivers/gpu/drm/radeon/radeon_semaphore.c
parentbfb9a07785fea0c41dff1a38890bc9b4679a9430 (diff)
drm/radeon: fix a bug with the ring syncing code
Rings need to lock in order, otherwise the ring subsystem can deadlock. v2: fix error handling and number of locked doublewords. v3: stop creating unneeded semaphores. Signed-off-by: Christian König <deathsimple@vodafone.de> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_semaphore.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_semaphore.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 61dd4e3c9209..930a08af900f 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -149,6 +149,62 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
149 radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); 149 radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true);
150} 150}
151 151
152int radeon_semaphore_sync_rings(struct radeon_device *rdev,
153 struct radeon_semaphore *semaphore,
154 bool sync_to[RADEON_NUM_RINGS],
155 int dst_ring)
156{
157 int i, r;
158
159 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
160 unsigned num_ops = i == dst_ring ? RADEON_NUM_RINGS : 1;
161
162 /* don't lock unused rings */
163 if (!sync_to[i] && i != dst_ring)
164 continue;
165
166 /* prevent GPU deadlocks */
167 if (!rdev->ring[i].ready) {
168 dev_err(rdev->dev, "Trying to sync to a disabled ring!");
169 r = -EINVAL;
170 goto error;
171 }
172
173 r = radeon_ring_lock(rdev, &rdev->ring[i], num_ops * 8);
174 if (r)
175 goto error;
176 }
177
178 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
179 /* no need to sync to our own or unused rings */
180 if (!sync_to[i] || i == dst_ring)
181 continue;
182
183 radeon_semaphore_emit_signal(rdev, i, semaphore);
184 radeon_semaphore_emit_wait(rdev, dst_ring, semaphore);
185 }
186
187 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
188
189 /* don't unlock unused rings */
190 if (!sync_to[i] && i != dst_ring)
191 continue;
192
193 radeon_ring_unlock_commit(rdev, &rdev->ring[i]);
194 }
195
196 return 0;
197
198error:
199 /* unlock all locks taken so far */
200 for (--i; i >= 0; --i) {
201 if (sync_to[i] || i == dst_ring) {
202 radeon_ring_unlock_undo(rdev, &rdev->ring[i]);
203 }
204 }
205 return r;
206}
207
152void radeon_semaphore_free(struct radeon_device *rdev, 208void radeon_semaphore_free(struct radeon_device *rdev,
153 struct radeon_semaphore *semaphore) 209 struct radeon_semaphore *semaphore)
154{ 210{