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

Configure Feed

Select the types of activity you want to include in your feed.

drm/gem: Add ww_acquire_ctx support to drm_gem_lru_scan()

If the callback is going to have to attempt to grab more locks, it is
useful to have an ww_acquire_ctx to avoid locking order problems.

Why not use the drm_exec helper instead? Mainly because (a) where
ww_acquire_init() is called is awkward, and (b) we don't really
need to retry after backoff, we can just move on to the next object.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
Tested-by: Antonino Maniscalco <antomani103@gmail.com>
Reviewed-by: Antonino Maniscalco <antomani103@gmail.com>
Patchwork: https://patchwork.freedesktop.org/patch/661463/

authored by

Rob Clark and committed by
Rob Clark
02070f04 471920ce

+30 -18
+11 -3
drivers/gpu/drm/drm_gem.c
··· 1429 1429 * @nr_to_scan: The number of pages to try to reclaim 1430 1430 * @remaining: The number of pages left to reclaim, should be initialized by caller 1431 1431 * @shrink: Callback to try to shrink/reclaim the object. 1432 + * @ticket: Optional ww_acquire_ctx context to use for locking 1432 1433 */ 1433 1434 unsigned long 1434 1435 drm_gem_lru_scan(struct drm_gem_lru *lru, 1435 1436 unsigned int nr_to_scan, 1436 1437 unsigned long *remaining, 1437 - bool (*shrink)(struct drm_gem_object *obj)) 1438 + bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket), 1439 + struct ww_acquire_ctx *ticket) 1438 1440 { 1439 1441 struct drm_gem_lru still_in_lru; 1440 1442 struct drm_gem_object *obj; ··· 1469 1467 */ 1470 1468 mutex_unlock(lru->lock); 1471 1469 1470 + if (ticket) 1471 + ww_acquire_init(ticket, &reservation_ww_class); 1472 + 1472 1473 /* 1473 1474 * Note that this still needs to be trylock, since we can 1474 1475 * hit shrinker in response to trying to get backing pages 1475 1476 * for this obj (ie. while it's lock is already held) 1476 1477 */ 1477 - if (!dma_resv_trylock(obj->resv)) { 1478 + if (!ww_mutex_trylock(&obj->resv->lock, ticket)) { 1478 1479 *remaining += obj->size >> PAGE_SHIFT; 1479 1480 goto tail; 1480 1481 } 1481 1482 1482 - if (shrink(obj)) { 1483 + if (shrink(obj, ticket)) { 1483 1484 freed += obj->size >> PAGE_SHIFT; 1484 1485 1485 1486 /* ··· 1495 1490 } 1496 1491 1497 1492 dma_resv_unlock(obj->resv); 1493 + 1494 + if (ticket) 1495 + ww_acquire_fini(ticket); 1498 1496 1499 1497 tail: 1500 1498 drm_gem_object_put(obj);
+13 -11
drivers/gpu/drm/msm/msm_gem_shrinker.c
··· 44 44 } 45 45 46 46 static bool 47 - purge(struct drm_gem_object *obj) 47 + purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) 48 48 { 49 49 if (!is_purgeable(to_msm_bo(obj))) 50 50 return false; ··· 58 58 } 59 59 60 60 static bool 61 - evict(struct drm_gem_object *obj) 61 + evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) 62 62 { 63 63 if (is_unevictable(to_msm_bo(obj))) 64 64 return false; ··· 79 79 } 80 80 81 81 static bool 82 - active_purge(struct drm_gem_object *obj) 82 + active_purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) 83 83 { 84 84 if (!wait_for_idle(obj)) 85 85 return false; 86 86 87 - return purge(obj); 87 + return purge(obj, ticket); 88 88 } 89 89 90 90 static bool 91 - active_evict(struct drm_gem_object *obj) 91 + active_evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) 92 92 { 93 93 if (!wait_for_idle(obj)) 94 94 return false; 95 95 96 - return evict(obj); 96 + return evict(obj, ticket); 97 97 } 98 98 99 99 static unsigned long ··· 102 102 struct msm_drm_private *priv = shrinker->private_data; 103 103 struct { 104 104 struct drm_gem_lru *lru; 105 - bool (*shrink)(struct drm_gem_object *obj); 105 + bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket); 106 106 bool cond; 107 107 unsigned long freed; 108 108 unsigned long remaining; ··· 122 122 continue; 123 123 stages[i].freed = 124 124 drm_gem_lru_scan(stages[i].lru, nr, 125 - &stages[i].remaining, 126 - stages[i].shrink); 125 + &stages[i].remaining, 126 + stages[i].shrink, 127 + NULL); 127 128 nr -= stages[i].freed; 128 129 freed += stages[i].freed; 129 130 remaining += stages[i].remaining; ··· 165 164 static const int vmap_shrink_limit = 15; 166 165 167 166 static bool 168 - vmap_shrink(struct drm_gem_object *obj) 167 + vmap_shrink(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) 169 168 { 170 169 if (!is_vunmapable(to_msm_bo(obj))) 171 170 return false; ··· 193 192 unmapped += drm_gem_lru_scan(lrus[idx], 194 193 vmap_shrink_limit - unmapped, 195 194 &remaining, 196 - vmap_shrink); 195 + vmap_shrink, 196 + NULL); 197 197 } 198 198 199 199 *(unsigned long *)ptr += unmapped;
+6 -4
include/drm/drm_gem.h
··· 560 560 void drm_gem_lru_remove(struct drm_gem_object *obj); 561 561 void drm_gem_lru_move_tail_locked(struct drm_gem_lru *lru, struct drm_gem_object *obj); 562 562 void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); 563 - unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, 564 - unsigned int nr_to_scan, 565 - unsigned long *remaining, 566 - bool (*shrink)(struct drm_gem_object *obj)); 563 + unsigned long 564 + drm_gem_lru_scan(struct drm_gem_lru *lru, 565 + unsigned int nr_to_scan, 566 + unsigned long *remaining, 567 + bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket), 568 + struct ww_acquire_ctx *ticket); 567 569 568 570 int drm_gem_evict_locked(struct drm_gem_object *obj); 569 571