summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2023-03-28 03:55:57 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2023-03-28 03:55:57 +0000
commit089446c4c0bcb81eb3b29f63d01a0b206be8d70b (patch)
treec4cf9d1fc3b6ddfdf197a999e41249572cc0fea1
parent54deeeef628a34783e00d12cb0248c4fad699a71 (diff)
drm/msm/gem: Prevent blocking within shrinker loop
From Dmitry Osipenko 96a5aee27439e56fca69628c3f87a042e7026b3e in linux-6.1.y/6.1.21 9630b585b607bd26f505d34620b14d75b9a5af7d in mainline linux
-rw-r--r--sys/dev/pci/drm/drm_gem.c9
-rw-r--r--sys/dev/pci/drm/include/drm/drm_gem.h4
2 files changed, 10 insertions, 3 deletions
diff --git a/sys/dev/pci/drm/drm_gem.c b/sys/dev/pci/drm/drm_gem.c
index d8884670a2c..b91420bf232 100644
--- a/sys/dev/pci/drm/drm_gem.c
+++ b/sys/dev/pci/drm/drm_gem.c
@@ -1660,10 +1660,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail);
*
* @lru: The LRU to scan
* @nr_to_scan: The number of pages to try to reclaim
+ * @remaining: The number of pages left to reclaim, should be initialized by caller
* @shrink: Callback to try to shrink/reclaim the object.
*/
unsigned long
-drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+drm_gem_lru_scan(struct drm_gem_lru *lru,
+ unsigned int nr_to_scan,
+ unsigned long *remaining,
bool (*shrink)(struct drm_gem_object *obj))
{
struct drm_gem_lru still_in_lru;
@@ -1702,8 +1705,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
* hit shrinker in response to trying to get backing pages
* for this obj (ie. while it's lock is already held)
*/
- if (!dma_resv_trylock(obj->resv))
+ if (!dma_resv_trylock(obj->resv)) {
+ *remaining += obj->size >> PAGE_SHIFT;
goto tail;
+ }
if (shrink(obj)) {
freed += obj->size >> PAGE_SHIFT;
diff --git a/sys/dev/pci/drm/include/drm/drm_gem.h b/sys/dev/pci/drm/include/drm/drm_gem.h
index cd878673149..4b4001f6a2a 100644
--- a/sys/dev/pci/drm/include/drm/drm_gem.h
+++ b/sys/dev/pci/drm/include/drm/drm_gem.h
@@ -495,7 +495,9 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
void drm_gem_lru_init(struct drm_gem_lru *lru, struct rwlock *lock);
void drm_gem_lru_remove(struct drm_gem_object *obj);
void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj);
-unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru,
+ unsigned int nr_to_scan,
+ unsigned long *remaining,
bool (*shrink)(struct drm_gem_object *obj));
void drm_ref(struct uvm_object *);