Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jerome Glisse and committed by
Dave Airlie
9fc04b50 d54fbd49

+54 -54
+42 -42
drivers/gpu/drm/radeon/radeon.h
··· 157 157 158 158 159 159 /* 160 + * Mutex which allows recursive locking from the same process. 161 + */ 162 + struct radeon_mutex { 163 + struct mutex mutex; 164 + struct task_struct *owner; 165 + int level; 166 + }; 167 + 168 + static 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 + 175 + static 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 + 190 + static 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 201 * Dummy page 161 202 */ 162 203 struct radeon_dummy_page { ··· 639 598 * mutex protects scheduled_ibs, ready, alloc_bm 640 599 */ 641 600 struct radeon_ib_pool { 642 - struct mutex mutex; 601 + struct radeon_mutex mutex; 643 602 struct radeon_sa_manager sa_manager; 644 603 struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; 645 604 bool ready; ··· 1393 1352 volatile uint32_t *ptr; 1394 1353 u64 gpu_addr; 1395 1354 }; 1396 - 1397 - 1398 - /* 1399 - * Mutex which allows recursive locking from the same process. 1400 - */ 1401 - struct radeon_mutex { 1402 - struct mutex mutex; 1403 - struct task_struct *owner; 1404 - int level; 1405 - }; 1406 - 1407 - static inline void radeon_mutex_init(struct radeon_mutex *mutex) 1408 - { 1409 - mutex_init(&mutex->mutex); 1410 - mutex->owner = NULL; 1411 - mutex->level = 0; 1412 - } 1413 - 1414 - static inline void radeon_mutex_lock(struct radeon_mutex *mutex) 1415 - { 1416 - if (mutex_trylock(&mutex->mutex)) { 1417 - /* The mutex was unlocked before, so it's ours now */ 1418 - mutex->owner = current; 1419 - } else if (mutex->owner != current) { 1420 - /* Another process locked the mutex, take it */ 1421 - mutex_lock(&mutex->mutex); 1422 - mutex->owner = current; 1423 - } 1424 - /* Otherwise the mutex was already locked by this process */ 1425 - 1426 - mutex->level++; 1427 - } 1428 - 1429 - static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) 1430 - { 1431 - if (--mutex->level > 0) 1432 - return; 1433 - 1434 - mutex->owner = NULL; 1435 - mutex_unlock(&mutex->mutex); 1436 - } 1437 1355 1438 1356 1439 1357 /*
+1 -1
drivers/gpu/drm/radeon/radeon_device.c
··· 720 720 /* mutex initialization are all done here so we 721 721 * can recall function without having locking issues */ 722 722 radeon_mutex_init(&rdev->cs_mutex); 723 - mutex_init(&rdev->ib_pool.mutex); 723 + radeon_mutex_init(&rdev->ib_pool.mutex); 724 724 for (i = 0; i < RADEON_NUM_RINGS; ++i) 725 725 mutex_init(&rdev->ring[i].mutex); 726 726 mutex_init(&rdev->dc_hw_i2c_mutex);
+11 -11
drivers/gpu/drm/radeon/radeon_ring.c
··· 109 109 return r; 110 110 } 111 111 112 - mutex_lock(&rdev->ib_pool.mutex); 112 + radeon_mutex_lock(&rdev->ib_pool.mutex); 113 113 idx = rdev->ib_pool.head_id; 114 114 retry: 115 115 if (cretry > 5) { 116 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 118 radeon_fence_unref(&fence); 119 119 return -ENOMEM; 120 120 } ··· 139 139 */ 140 140 rdev->ib_pool.head_id = (1 + idx); 141 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 143 return 0; 144 144 } 145 145 } ··· 158 158 } 159 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 162 radeon_fence_unref(&fence); 163 163 return r; 164 164 } ··· 171 171 if (tmp == NULL) { 172 172 return; 173 173 } 174 - mutex_lock(&rdev->ib_pool.mutex); 174 + radeon_mutex_lock(&rdev->ib_pool.mutex); 175 175 if (tmp->fence && !tmp->fence->emitted) { 176 176 radeon_sa_bo_free(rdev, &tmp->sa_bo); 177 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 182 182 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) ··· 214 214 return r; 215 215 } 216 216 217 - mutex_lock(&rdev->ib_pool.mutex); 217 + radeon_mutex_lock(&rdev->ib_pool.mutex); 218 218 if (rdev->ib_pool.ready) { 219 - mutex_unlock(&rdev->ib_pool.mutex); 219 + radeon_mutex_unlock(&rdev->ib_pool.mutex); 220 220 radeon_sa_bo_manager_fini(rdev, &tmp); 221 221 return 0; 222 222 } ··· 239 239 if (radeon_debugfs_ring_init(rdev)) { 240 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 243 return 0; 244 244 } 245 245 ··· 247 247 { 248 248 unsigned i; 249 249 250 - mutex_lock(&rdev->ib_pool.mutex); 250 + radeon_mutex_lock(&rdev->ib_pool.mutex); 251 251 if (rdev->ib_pool.ready) { 252 252 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { 253 253 radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo); ··· 256 256 radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager); 257 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 262 262 int radeon_ib_pool_start(struct radeon_device *rdev)