The inteldrm(4) driver keeps a cache of graphics objects, allegedly to
make things faster by avoiding cache flushes.  But those graphics
objects consume memory that we want to free if we need it for
something else.

The diff below hooks up the "shrinker" code in inteldrm(4) and calls
it from the pagedeamon if it thinks it needs to free up memory.

The diff still has some debug printfs such that we can tell that the
code is actually called.

Please test if you have inteldrm(4), esepcially on machines with
limited amounts of physical memory.


Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.50
diff -u -p -r1.50 drm_linux.c
--- dev/pci/drm/drm_linux.c     23 Oct 2019 10:17:40 -0000      1.50
+++ dev/pci/drm/drm_linux.c     27 Nov 2019 15:55:37 -0000
@@ -1867,3 +1867,29 @@ pci_resize_resource(struct pci_dev *pdev
 
        return 0;
 }
+
+TAILQ_HEAD(, shrinker) shrinkers = TAILQ_HEAD_INITIALIZER(shrinkers);
+
+int
+register_shrinker(struct shrinker *shrinker)
+{
+       TAILQ_INSERT_TAIL(&shrinkers, shrinker, next);
+       return 0;
+}
+
+void
+drmbackoff(long npages)
+{
+       struct shrink_control sc;
+       struct shrinker *shrinker;
+       u_long ret;
+
+       printf("%s: %ld\n", __func__, npages);
+       shrinker = TAILQ_FIRST(&shrinkers);
+       while (shrinker && npages > 0) {
+               sc.nr_to_scan = npages;
+               ret = shrinker->scan_objects(shrinker, &sc);
+               npages -= ret;
+               shrinker = TAILQ_NEXT(shrinker, next);
+       }
+}
Index: dev/pci/drm/i915/i915_drv.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.h,v
retrieving revision 1.89
diff -u -p -r1.89 i915_drv.h
--- dev/pci/drm/i915/i915_drv.h 13 Nov 2019 06:41:55 -0000      1.89
+++ dev/pci/drm/i915/i915_drv.h 27 Nov 2019 15:55:37 -0000
@@ -1072,9 +1072,7 @@ struct i915_gem_mm {
 
        struct notifier_block oom_notifier;
        struct notifier_block vmap_notifier;
-#ifdef notyet
        struct shrinker shrinker;
-#endif
 
        /** LRU list of objects with fence regs on them. */
        struct list_head fence_list;
Index: dev/pci/drm/i915/i915_gem_shrinker.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_gem_shrinker.c,v
retrieving revision 1.1
diff -u -p -r1.1 i915_gem_shrinker.c
--- dev/pci/drm/i915/i915_gem_shrinker.c        14 Apr 2019 10:14:51 -0000      
1.1
+++ dev/pci/drm/i915/i915_gem_shrinker.c        27 Nov 2019 15:55:37 -0000
@@ -36,7 +36,6 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 
-#ifdef notyet
 static bool shrinker_lock(struct drm_i915_private *i915, bool *unlock)
 {
        switch (mutex_trylock_recursive(&i915->drm.struct_mutex)) {
@@ -115,7 +114,6 @@ static bool unsafe_drop_pages(struct drm
                __i915_gem_object_put_pages(obj, I915_MM_SHRINKER);
        return !i915_gem_object_has_pages(obj);
 }
-#endif
 
 /**
  * i915_gem_shrink - Shrink buffer object caches
@@ -148,9 +146,6 @@ i915_gem_shrink(struct drm_i915_private 
                unsigned long *nr_scanned,
                unsigned flags)
 {
-       STUB();
-       return -ENOSYS;
-#ifdef notyet
        const struct {
                struct list_head *list;
                unsigned int bit;
@@ -163,6 +158,8 @@ i915_gem_shrink(struct drm_i915_private 
        unsigned long scanned = 0;
        bool unlock;
 
+       printf("%s: %ld\n", __func__, target);
+
        if (!shrinker_lock(i915, &unlock))
                return 0;
 
@@ -280,7 +277,6 @@ i915_gem_shrink(struct drm_i915_private 
        if (nr_scanned)
                *nr_scanned += scanned;
        return count;
-#endif
 }
 
 /**
@@ -311,7 +307,6 @@ unsigned long i915_gem_shrink_all(struct
        return freed;
 }
 
-#ifdef notyet
 static unsigned long
 i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
@@ -393,6 +388,7 @@ i915_gem_shrinker_scan(struct shrinker *
        return sc->nr_scanned ? freed : SHRINK_STOP;
 }
 
+#ifdef notyet
 static bool
 shrinker_lock_uninterruptible(struct drm_i915_private *i915, bool *unlock,
                              int timeout_ms)
@@ -513,13 +509,13 @@ out:
  */
 void i915_gem_shrinker_register(struct drm_i915_private *i915)
 {
-#ifdef notyet
        i915->mm.shrinker.scan_objects = i915_gem_shrinker_scan;
        i915->mm.shrinker.count_objects = i915_gem_shrinker_count;
        i915->mm.shrinker.seeks = DEFAULT_SEEKS;
        i915->mm.shrinker.batch = 4096;
        WARN_ON(register_shrinker(&i915->mm.shrinker));
 
+#ifdef notyet
        i915->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
        WARN_ON(register_oom_notifier(&i915->mm.oom_notifier));
 
Index: dev/pci/drm/include/linux/mm.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/mm.h,v
retrieving revision 1.2
diff -u -p -r1.2 mm.h
--- dev/pci/drm/include/linux/mm.h      8 May 2019 22:44:31 -0000       1.2
+++ dev/pci/drm/include/linux/mm.h      27 Nov 2019 15:55:37 -0000
@@ -78,4 +78,23 @@ get_order(size_t size)
        return flsl((size - 1) >> PAGE_SHIFT);
 }
 
+struct shrink_control {
+       u_long  nr_to_scan;
+       u_long  nr_scanned;
+};
+
+struct shrinker {
+       u_long  (*count_objects)(struct shrinker *, struct shrink_control *);
+       u_long  (*scan_objects)(struct shrinker *, struct shrink_control *);
+       long    batch;
+       int     seeks;
+       TAILQ_ENTRY(shrinker) next;
+};
+
+#define SHRINK_STOP    ~0UL
+
+#define DEFAULT_SEEKS  2
+
+int register_shrinker(struct shrinker *);
+
 #endif
Index: dev/pci/drm/include/linux/mutex.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/mutex.h,v
retrieving revision 1.1
diff -u -p -r1.1 mutex.h
--- dev/pci/drm/include/linux/mutex.h   14 Apr 2019 10:14:53 -0000      1.1
+++ dev/pci/drm/include/linux/mutex.h   27 Nov 2019 15:55:37 -0000
@@ -16,7 +16,23 @@
 #define mutex_lock_nested(rwl, sub)    rw_enter_write(rwl)
 #define mutex_trylock(rwl)             (rw_enter(rwl, RW_WRITE | RW_NOSLEEP) 
== 0)
 #define mutex_unlock(rwl)              rw_exit_write(rwl)
-#define mutex_is_locked(rwl)           (rw_status(rwl) == RW_WRITE)
+#define mutex_is_locked(rwl)           (rw_status(rwl) != 0)
 #define mutex_destroy(rwl)
+
+enum mutex_trylock_recursive_result {
+       MUTEX_TRYLOCK_FAILED,
+       MUTEX_TRYLOCK_SUCCESS,
+       MUTEX_TRYLOCK_RECURSIVE
+};
+
+static inline enum mutex_trylock_recursive_result
+mutex_trylock_recursive(struct rwlock *rwl)
+{
+       if (rw_status(rwl) == RW_WRITE)
+               return MUTEX_TRYLOCK_RECURSIVE;
+       if (mutex_trylock(rwl))
+               return MUTEX_TRYLOCK_SUCCESS;
+       return MUTEX_TRYLOCK_FAILED;
+}
 
 #endif
Index: dev/pci/drm/include/linux/swap.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/swap.h,v
retrieving revision 1.1
diff -u -p -r1.1 swap.h
--- dev/pci/drm/include/linux/swap.h    14 Apr 2019 10:14:53 -0000      1.1
+++ dev/pci/drm/include/linux/swap.h    27 Nov 2019 15:55:37 -0000
@@ -11,4 +11,6 @@ get_nr_swap_pages(void)
        return uvmexp.swpages - uvmexp.swpginuse;
 }
 
+#define current_is_kswapd()    0
+
 #endif
Index: uvm/uvm_pdaemon.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v
retrieving revision 1.83
diff -u -p -r1.83 uvm_pdaemon.c
--- uvm/uvm_pdaemon.c   3 Jul 2019 22:39:33 -0000       1.83
+++ uvm/uvm_pdaemon.c   27 Nov 2019 15:55:38 -0000
@@ -262,6 +262,8 @@ uvm_pageout(void *arg)
                        size = 16; /* XXX */
                uvm_unlock_pageq();
                (void) bufbackoff(&constraint, size * 2);
+               extern void drmbackoff(long);
+               drmbackoff(size * 2);
                uvm_lock_pageq();
 
                /* Scan if needed to meet our targets. */

Reply via email to