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>main
parent
0c270df8df
commit
eb846d46bc
|
@ -165,10 +165,18 @@ fd_bo_cache_alloc(struct fd_bo_cache *cache, uint32_t *size, uint32_t flags)
|
||||||
bucket = get_bucket(cache, *size);
|
bucket = get_bucket(cache, *size);
|
||||||
|
|
||||||
/* see if we can be green and recycle: */
|
/* see if we can be green and recycle: */
|
||||||
|
retry:
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
*size = bucket->size;
|
*size = bucket->size;
|
||||||
bo = find_in_bucket(bucket, flags);
|
bo = find_in_bucket(bucket, flags);
|
||||||
if (bo) {
|
if (bo) {
|
||||||
|
if (bo->funcs->madvise(bo, TRUE) <= 0) {
|
||||||
|
/* we've lost the backing pages, delete and try again: */
|
||||||
|
pthread_mutex_lock(&table_lock);
|
||||||
|
bo_del(bo);
|
||||||
|
pthread_mutex_unlock(&table_lock);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
atomic_set(&bo->refcnt, 1);
|
atomic_set(&bo->refcnt, 1);
|
||||||
fd_device_ref(bo->dev);
|
fd_device_ref(bo->dev);
|
||||||
return bo;
|
return bo;
|
||||||
|
@ -187,6 +195,8 @@ fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo)
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
struct timespec time;
|
struct timespec time;
|
||||||
|
|
||||||
|
bo->funcs->madvise(bo, FALSE);
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||||
|
|
||||||
bo->free_time = time.tv_sec;
|
bo->free_time = time.tv_sec;
|
||||||
|
|
|
@ -56,7 +56,15 @@ struct fd_device * fd_device_new(int fd)
|
||||||
|
|
||||||
if (!strcmp(version->name, "msm")) {
|
if (!strcmp(version->name, "msm")) {
|
||||||
DEBUG_MSG("msm DRM device");
|
DEBUG_MSG("msm DRM device");
|
||||||
|
if (version->version_major != 1) {
|
||||||
|
ERROR_MSG("unsupported version: %u.%u.%u", version->version_major,
|
||||||
|
version->version_minor, version->version_patchlevel);
|
||||||
|
dev = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
dev = msm_device_new(fd);
|
dev = msm_device_new(fd);
|
||||||
|
dev->version = version->version_minor;
|
||||||
#ifdef HAVE_FREEDRENO_KGSL
|
#ifdef HAVE_FREEDRENO_KGSL
|
||||||
} else if (!strcmp(version->name, "kgsl")) {
|
} else if (!strcmp(version->name, "kgsl")) {
|
||||||
DEBUG_MSG("kgsl DRM device");
|
DEBUG_MSG("kgsl DRM device");
|
||||||
|
@ -66,6 +74,8 @@ struct fd_device * fd_device_new(int fd)
|
||||||
ERROR_MSG("unknown device: %s", version->name);
|
ERROR_MSG("unknown device: %s", version->name);
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
drmFreeVersion(version);
|
drmFreeVersion(version);
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
|
|
@ -54,6 +54,13 @@
|
||||||
#include "freedreno_ringbuffer.h"
|
#include "freedreno_ringbuffer.h"
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
# define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
# define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
struct fd_device_funcs {
|
struct fd_device_funcs {
|
||||||
int (*bo_new_handle)(struct fd_device *dev, uint32_t size,
|
int (*bo_new_handle)(struct fd_device *dev, uint32_t size,
|
||||||
uint32_t flags, uint32_t *handle);
|
uint32_t flags, uint32_t *handle);
|
||||||
|
@ -76,6 +83,7 @@ struct fd_bo_cache {
|
||||||
|
|
||||||
struct fd_device {
|
struct fd_device {
|
||||||
int fd;
|
int fd;
|
||||||
|
int version;
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
|
|
||||||
/* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects:
|
/* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects:
|
||||||
|
@ -139,6 +147,7 @@ struct fd_bo_funcs {
|
||||||
int (*offset)(struct fd_bo *bo, uint64_t *offset);
|
int (*offset)(struct fd_bo *bo, uint64_t *offset);
|
||||||
int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
|
int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
|
||||||
void (*cpu_fini)(struct fd_bo *bo);
|
void (*cpu_fini)(struct fd_bo *bo);
|
||||||
|
int (*madvise)(struct fd_bo *bo, int willneed);
|
||||||
void (*destroy)(struct fd_bo *bo);
|
void (*destroy)(struct fd_bo *bo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,11 @@ static void kgsl_bo_cpu_fini(struct fd_bo *bo)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kgsl_bo_madvise(struct fd_bo *bo, int willneed)
|
||||||
|
{
|
||||||
|
return willneed; /* not supported by kgsl */
|
||||||
|
}
|
||||||
|
|
||||||
static void kgsl_bo_destroy(struct fd_bo *bo)
|
static void kgsl_bo_destroy(struct fd_bo *bo)
|
||||||
{
|
{
|
||||||
struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo);
|
struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo);
|
||||||
|
@ -127,6 +132,7 @@ static const struct fd_bo_funcs funcs = {
|
||||||
.offset = kgsl_bo_offset,
|
.offset = kgsl_bo_offset,
|
||||||
.cpu_prep = kgsl_bo_cpu_prep,
|
.cpu_prep = kgsl_bo_cpu_prep,
|
||||||
.cpu_fini = kgsl_bo_cpu_fini,
|
.cpu_fini = kgsl_bo_cpu_fini,
|
||||||
|
.madvise = kgsl_bo_madvise,
|
||||||
.destroy = kgsl_bo_destroy,
|
.destroy = kgsl_bo_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,25 @@ static void msm_bo_cpu_fini(struct fd_bo *bo)
|
||||||
drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
|
drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int msm_bo_madvise(struct fd_bo *bo, int willneed)
|
||||||
|
{
|
||||||
|
struct drm_msm_gem_madvise req = {
|
||||||
|
.handle = bo->handle,
|
||||||
|
.madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* older kernels do not support this: */
|
||||||
|
if (bo->dev->version < 1)
|
||||||
|
return willneed;
|
||||||
|
|
||||||
|
ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return req.retained;
|
||||||
|
}
|
||||||
|
|
||||||
static void msm_bo_destroy(struct fd_bo *bo)
|
static void msm_bo_destroy(struct fd_bo *bo)
|
||||||
{
|
{
|
||||||
struct msm_bo *msm_bo = to_msm_bo(bo);
|
struct msm_bo *msm_bo = to_msm_bo(bo);
|
||||||
|
@ -100,6 +119,7 @@ static const struct fd_bo_funcs funcs = {
|
||||||
.offset = msm_bo_offset,
|
.offset = msm_bo_offset,
|
||||||
.cpu_prep = msm_bo_cpu_prep,
|
.cpu_prep = msm_bo_cpu_prep,
|
||||||
.cpu_fini = msm_bo_cpu_fini,
|
.cpu_fini = msm_bo_cpu_fini,
|
||||||
|
.madvise = msm_bo_madvise,
|
||||||
.destroy = msm_bo_destroy,
|
.destroy = msm_bo_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue