aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark2016-05-31 11:06:50 -0500
committerRob Clark2016-07-20 18:42:21 -0500
commiteb846d46bca614f24c50f3fa89f94a6820e16589 (patch)
treeef805cc2fe2f4ee02694eeeecbf3c8904d20ea47 /freedreno
parent0c270df8dfde6d6d7b7adb236cd3325f2c0115bd (diff)
downloadexternal-libdrm-eb846d46bca614f24c50f3fa89f94a6820e16589.tar.gz
external-libdrm-eb846d46bca614f24c50f3fa89f94a6820e16589.tar.xz
external-libdrm-eb846d46bca614f24c50f3fa89f94a6820e16589.zip
freedreno: add madvise support
With a new enough drm/msm, we can let the kernel know about buffers that are in the bo cache, so the kernel can free them under memory pressure. Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno')
-rw-r--r--freedreno/freedreno_bo_cache.c10
-rw-r--r--freedreno/freedreno_device.c10
-rw-r--r--freedreno/freedreno_priv.h9
-rw-r--r--freedreno/kgsl/kgsl_bo.c6
-rw-r--r--freedreno/msm/msm_bo.c20
5 files changed, 55 insertions, 0 deletions
diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c
index 17199d27..58d171eb 100644
--- a/freedreno/freedreno_bo_cache.c
+++ b/freedreno/freedreno_bo_cache.c
@@ -165,10 +165,18 @@ fd_bo_cache_alloc(struct fd_bo_cache *cache, uint32_t *size, uint32_t flags)
165 bucket = get_bucket(cache, *size); 165 bucket = get_bucket(cache, *size);
166 166
167 /* see if we can be green and recycle: */ 167 /* see if we can be green and recycle: */
168retry:
168 if (bucket) { 169 if (bucket) {
169 *size = bucket->size; 170 *size = bucket->size;
170 bo = find_in_bucket(bucket, flags); 171 bo = find_in_bucket(bucket, flags);
171 if (bo) { 172 if (bo) {
173 if (bo->funcs->madvise(bo, TRUE) <= 0) {
174 /* we've lost the backing pages, delete and try again: */
175 pthread_mutex_lock(&table_lock);
176 bo_del(bo);
177 pthread_mutex_unlock(&table_lock);
178 goto retry;
179 }
172 atomic_set(&bo->refcnt, 1); 180 atomic_set(&bo->refcnt, 1);
173 fd_device_ref(bo->dev); 181 fd_device_ref(bo->dev);
174 return bo; 182 return bo;
@@ -187,6 +195,8 @@ fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo)
187 if (bucket) { 195 if (bucket) {
188 struct timespec time; 196 struct timespec time;
189 197
198 bo->funcs->madvise(bo, FALSE);
199
190 clock_gettime(CLOCK_MONOTONIC, &time); 200 clock_gettime(CLOCK_MONOTONIC, &time);
191 201
192 bo->free_time = time.tv_sec; 202 bo->free_time = time.tv_sec;
diff --git a/freedreno/freedreno_device.c b/freedreno/freedreno_device.c
index 15e41f0e..027414ec 100644
--- a/freedreno/freedreno_device.c
+++ b/freedreno/freedreno_device.c
@@ -56,7 +56,15 @@ struct fd_device * fd_device_new(int fd)
56 56
57 if (!strcmp(version->name, "msm")) { 57 if (!strcmp(version->name, "msm")) {
58 DEBUG_MSG("msm DRM device"); 58 DEBUG_MSG("msm DRM device");
59 if (version->version_major != 1) {
60 ERROR_MSG("unsupported version: %u.%u.%u", version->version_major,
61 version->version_minor, version->version_patchlevel);
62 dev = NULL;
63 goto out;
64 }
65
59 dev = msm_device_new(fd); 66 dev = msm_device_new(fd);
67 dev->version = version->version_minor;
60#ifdef HAVE_FREEDRENO_KGSL 68#ifdef HAVE_FREEDRENO_KGSL
61 } else if (!strcmp(version->name, "kgsl")) { 69 } else if (!strcmp(version->name, "kgsl")) {
62 DEBUG_MSG("kgsl DRM device"); 70 DEBUG_MSG("kgsl DRM device");
@@ -66,6 +74,8 @@ struct fd_device * fd_device_new(int fd)
66 ERROR_MSG("unknown device: %s", version->name); 74 ERROR_MSG("unknown device: %s", version->name);
67 dev = NULL; 75 dev = NULL;
68 } 76 }
77
78out:
69 drmFreeVersion(version); 79 drmFreeVersion(version);
70 80
71 if (!dev) 81 if (!dev)
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h
index 4159e526..f3ddd77d 100644
--- a/freedreno/freedreno_priv.h
+++ b/freedreno/freedreno_priv.h
@@ -54,6 +54,13 @@
54#include "freedreno_ringbuffer.h" 54#include "freedreno_ringbuffer.h"
55#include "drm.h" 55#include "drm.h"
56 56
57#ifndef TRUE
58# define TRUE 1
59#endif
60#ifndef FALSE
61# define FALSE 0
62#endif
63
57struct fd_device_funcs { 64struct fd_device_funcs {
58 int (*bo_new_handle)(struct fd_device *dev, uint32_t size, 65 int (*bo_new_handle)(struct fd_device *dev, uint32_t size,
59 uint32_t flags, uint32_t *handle); 66 uint32_t flags, uint32_t *handle);
@@ -76,6 +83,7 @@ struct fd_bo_cache {
76 83
77struct fd_device { 84struct fd_device {
78 int fd; 85 int fd;
86 int version;
79 atomic_t refcnt; 87 atomic_t refcnt;
80 88
81 /* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects: 89 /* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects:
@@ -139,6 +147,7 @@ struct fd_bo_funcs {
139 int (*offset)(struct fd_bo *bo, uint64_t *offset); 147 int (*offset)(struct fd_bo *bo, uint64_t *offset);
140 int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op); 148 int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
141 void (*cpu_fini)(struct fd_bo *bo); 149 void (*cpu_fini)(struct fd_bo *bo);
150 int (*madvise)(struct fd_bo *bo, int willneed);
142 void (*destroy)(struct fd_bo *bo); 151 void (*destroy)(struct fd_bo *bo);
143}; 152};
144 153
diff --git a/freedreno/kgsl/kgsl_bo.c b/freedreno/kgsl/kgsl_bo.c
index 2b45b5e2..ab3485e3 100644
--- a/freedreno/kgsl/kgsl_bo.c
+++ b/freedreno/kgsl/kgsl_bo.c
@@ -116,6 +116,11 @@ static void kgsl_bo_cpu_fini(struct fd_bo *bo)
116{ 116{
117} 117}
118 118
119static int kgsl_bo_madvise(struct fd_bo *bo, int willneed)
120{
121 return willneed; /* not supported by kgsl */
122}
123
119static void kgsl_bo_destroy(struct fd_bo *bo) 124static void kgsl_bo_destroy(struct fd_bo *bo)
120{ 125{
121 struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); 126 struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo);
@@ -127,6 +132,7 @@ static const struct fd_bo_funcs funcs = {
127 .offset = kgsl_bo_offset, 132 .offset = kgsl_bo_offset,
128 .cpu_prep = kgsl_bo_cpu_prep, 133 .cpu_prep = kgsl_bo_cpu_prep,
129 .cpu_fini = kgsl_bo_cpu_fini, 134 .cpu_fini = kgsl_bo_cpu_fini,
135 .madvise = kgsl_bo_madvise,
130 .destroy = kgsl_bo_destroy, 136 .destroy = kgsl_bo_destroy,
131}; 137};
132 138
diff --git a/freedreno/msm/msm_bo.c b/freedreno/msm/msm_bo.c
index cd05a6cd..cfaec827 100644
--- a/freedreno/msm/msm_bo.c
+++ b/freedreno/msm/msm_bo.c
@@ -89,6 +89,25 @@ static void msm_bo_cpu_fini(struct fd_bo *bo)
89 drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req)); 89 drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
90} 90}
91 91
92static int msm_bo_madvise(struct fd_bo *bo, int willneed)
93{
94 struct drm_msm_gem_madvise req = {
95 .handle = bo->handle,
96 .madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
97 };
98 int ret;
99
100 /* older kernels do not support this: */
101 if (bo->dev->version < 1)
102 return willneed;
103
104 ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
105 if (ret)
106 return ret;
107
108 return req.retained;
109}
110
92static void msm_bo_destroy(struct fd_bo *bo) 111static void msm_bo_destroy(struct fd_bo *bo)
93{ 112{
94 struct msm_bo *msm_bo = to_msm_bo(bo); 113 struct msm_bo *msm_bo = to_msm_bo(bo);
@@ -100,6 +119,7 @@ static const struct fd_bo_funcs funcs = {
100 .offset = msm_bo_offset, 119 .offset = msm_bo_offset,
101 .cpu_prep = msm_bo_cpu_prep, 120 .cpu_prep = msm_bo_cpu_prep,
102 .cpu_fini = msm_bo_cpu_fini, 121 .cpu_fini = msm_bo_cpu_fini,
122 .madvise = msm_bo_madvise,
103 .destroy = msm_bo_destroy, 123 .destroy = msm_bo_destroy,
104}; 124};
105 125