aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2012-01-23 11:52:15 -0500
committerDave Airlie <airlied@redhat.com>2012-01-25 04:42:06 -0500
commit9fc04b503df9a34ec1a691225445c5b7dfd022e7 (patch)
treeb8e95f24e697b0876cf4e28ead5c1b314af178bc
parentd54fbd49efe5c75bc7cf963bf065aef3fd22417a (diff)
drm/radeon: avoid deadlock if GPU lockup is detected in ib_pool_get
If GPU lockup is detected in ib_pool get we are holding the ib_pool mutex that will be needed by the GPU reset code. As ib_pool code is safe to be reentrant from GPU reset code we should not block if we are trying to get the ib pool lock on the behalf of the same userspace caller, thus use the radeon_mutex_lock helper. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h84
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c22
3 files changed, 54 insertions, 54 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 73e05cb85eca..1668ec1ee770 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -157,6 +157,47 @@ bool radeon_get_bios(struct radeon_device *rdev);
157 157
158 158
159/* 159/*
160 * Mutex which allows recursive locking from the same process.
161 */
162struct radeon_mutex {
163 struct mutex mutex;
164 struct task_struct *owner;
165 int level;
166};
167
168static inline void radeon_mutex_init(struct radeon_mutex *mutex)
169{
170 mutex_init(&mutex->mutex);
171 mutex->owner = NULL;
172 mutex->level = 0;
173}
174
175static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
176{
177 if (mutex_trylock(&mutex->mutex)) {
178 /* The mutex was unlocked before, so it's ours now */
179 mutex->owner = current;
180 } else if (mutex->owner != current) {
181 /* Another process locked the mutex, take it */
182 mutex_lock(&mutex->mutex);
183 mutex->owner = current;
184 }
185 /* Otherwise the mutex was already locked by this process */
186
187 mutex->level++;
188}
189
190static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
191{
192 if (--mutex->level > 0)
193 return;
194
195 mutex->owner = NULL;
196 mutex_unlock(&mutex->mutex);
197}
198
199
200/*
160 * Dummy page 201 * Dummy page
161 */ 202 */
162struct radeon_dummy_page { 203struct radeon_dummy_page {
@@ -598,7 +639,7 @@ struct radeon_ib {
598 * mutex protects scheduled_ibs, ready, alloc_bm 639 * mutex protects scheduled_ibs, ready, alloc_bm
599 */ 640 */
600struct radeon_ib_pool { 641struct radeon_ib_pool {
601 struct mutex mutex; 642 struct radeon_mutex mutex;
602 struct radeon_sa_manager sa_manager; 643 struct radeon_sa_manager sa_manager;
603 struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; 644 struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
604 bool ready; 645 bool ready;
@@ -1355,47 +1396,6 @@ struct r600_vram_scratch {
1355 1396
1356 1397
1357/* 1398/*
1358 * Mutex which allows recursive locking from the same process.
1359 */
1360struct radeon_mutex {
1361 struct mutex mutex;
1362 struct task_struct *owner;
1363 int level;
1364};
1365
1366static inline void radeon_mutex_init(struct radeon_mutex *mutex)
1367{
1368 mutex_init(&mutex->mutex);
1369 mutex->owner = NULL;
1370 mutex->level = 0;
1371}
1372
1373static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
1374{
1375 if (mutex_trylock(&mutex->mutex)) {
1376 /* The mutex was unlocked before, so it's ours now */
1377 mutex->owner = current;
1378 } else if (mutex->owner != current) {
1379 /* Another process locked the mutex, take it */
1380 mutex_lock(&mutex->mutex);
1381 mutex->owner = current;
1382 }
1383 /* Otherwise the mutex was already locked by this process */
1384
1385 mutex->level++;
1386}
1387
1388static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
1389{
1390 if (--mutex->level > 0)
1391 return;
1392
1393 mutex->owner = NULL;
1394 mutex_unlock(&mutex->mutex);
1395}
1396
1397
1398/*
1399 * Core structure, functions and helpers. 1399 * Core structure, functions and helpers.
1400 */ 1400 */
1401typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); 1401typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index a811bc64ad5c..cec51a5b69dd 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -720,7 +720,7 @@ int radeon_device_init(struct radeon_device *rdev,
720 /* mutex initialization are all done here so we 720 /* mutex initialization are all done here so we
721 * can recall function without having locking issues */ 721 * can recall function without having locking issues */
722 radeon_mutex_init(&rdev->cs_mutex); 722 radeon_mutex_init(&rdev->cs_mutex);
723 mutex_init(&rdev->ib_pool.mutex); 723 radeon_mutex_init(&rdev->ib_pool.mutex);
724 for (i = 0; i < RADEON_NUM_RINGS; ++i) 724 for (i = 0; i < RADEON_NUM_RINGS; ++i)
725 mutex_init(&rdev->ring[i].mutex); 725 mutex_init(&rdev->ring[i].mutex);
726 mutex_init(&rdev->dc_hw_i2c_mutex); 726 mutex_init(&rdev->dc_hw_i2c_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 1cb4b941be47..30a4c5014c8b 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -109,12 +109,12 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
109 return r; 109 return r;
110 } 110 }
111 111
112 mutex_lock(&rdev->ib_pool.mutex); 112 radeon_mutex_lock(&rdev->ib_pool.mutex);
113 idx = rdev->ib_pool.head_id; 113 idx = rdev->ib_pool.head_id;
114retry: 114retry:
115 if (cretry > 5) { 115 if (cretry > 5) {
116 dev_err(rdev->dev, "failed to get an ib after 5 retry\n"); 116 dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
117 mutex_unlock(&rdev->ib_pool.mutex); 117 radeon_mutex_unlock(&rdev->ib_pool.mutex);
118 radeon_fence_unref(&fence); 118 radeon_fence_unref(&fence);
119 return -ENOMEM; 119 return -ENOMEM;
120 } 120 }
@@ -139,7 +139,7 @@ retry:
139 */ 139 */
140 rdev->ib_pool.head_id = (1 + idx); 140 rdev->ib_pool.head_id = (1 + idx);
141 rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1); 141 rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
142 mutex_unlock(&rdev->ib_pool.mutex); 142 radeon_mutex_unlock(&rdev->ib_pool.mutex);
143 return 0; 143 return 0;
144 } 144 }
145 } 145 }
@@ -158,7 +158,7 @@ retry:
158 } 158 }
159 idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1); 159 idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
160 } 160 }
161 mutex_unlock(&rdev->ib_pool.mutex); 161 radeon_mutex_unlock(&rdev->ib_pool.mutex);
162 radeon_fence_unref(&fence); 162 radeon_fence_unref(&fence);
163 return r; 163 return r;
164} 164}
@@ -171,12 +171,12 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
171 if (tmp == NULL) { 171 if (tmp == NULL) {
172 return; 172 return;
173 } 173 }
174 mutex_lock(&rdev->ib_pool.mutex); 174 radeon_mutex_lock(&rdev->ib_pool.mutex);
175 if (tmp->fence && !tmp->fence->emitted) { 175 if (tmp->fence && !tmp->fence->emitted) {
176 radeon_sa_bo_free(rdev, &tmp->sa_bo); 176 radeon_sa_bo_free(rdev, &tmp->sa_bo);
177 radeon_fence_unref(&tmp->fence); 177 radeon_fence_unref(&tmp->fence);
178 } 178 }
179 mutex_unlock(&rdev->ib_pool.mutex); 179 radeon_mutex_unlock(&rdev->ib_pool.mutex);
180} 180}
181 181
182int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) 182int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
@@ -214,9 +214,9 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
214 return r; 214 return r;
215 } 215 }
216 216
217 mutex_lock(&rdev->ib_pool.mutex); 217 radeon_mutex_lock(&rdev->ib_pool.mutex);
218 if (rdev->ib_pool.ready) { 218 if (rdev->ib_pool.ready) {
219 mutex_unlock(&rdev->ib_pool.mutex); 219 radeon_mutex_unlock(&rdev->ib_pool.mutex);
220 radeon_sa_bo_manager_fini(rdev, &tmp); 220 radeon_sa_bo_manager_fini(rdev, &tmp);
221 return 0; 221 return 0;
222 } 222 }
@@ -239,7 +239,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
239 if (radeon_debugfs_ring_init(rdev)) { 239 if (radeon_debugfs_ring_init(rdev)) {
240 DRM_ERROR("Failed to register debugfs file for rings !\n"); 240 DRM_ERROR("Failed to register debugfs file for rings !\n");
241 } 241 }
242 mutex_unlock(&rdev->ib_pool.mutex); 242 radeon_mutex_unlock(&rdev->ib_pool.mutex);
243 return 0; 243 return 0;
244} 244}
245 245
@@ -247,7 +247,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
247{ 247{
248 unsigned i; 248 unsigned i;
249 249
250 mutex_lock(&rdev->ib_pool.mutex); 250 radeon_mutex_lock(&rdev->ib_pool.mutex);
251 if (rdev->ib_pool.ready) { 251 if (rdev->ib_pool.ready) {
252 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { 252 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
253 radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo); 253 radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
@@ -256,7 +256,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
256 radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager); 256 radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
257 rdev->ib_pool.ready = false; 257 rdev->ib_pool.ready = false;
258 } 258 }
259 mutex_unlock(&rdev->ib_pool.mutex); 259 radeon_mutex_unlock(&rdev->ib_pool.mutex);
260} 260}
261 261
262int radeon_ib_pool_start(struct radeon_device *rdev) 262int radeon_ib_pool_start(struct radeon_device *rdev)