diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index b9eab542709..f80c549aa64 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -94,6 +94,10 @@ bo_new(struct fd_device *dev, uint32_t size, uint32_t flags, uint32_t handle; int ret; + /* demote cached-coherent to WC if not supported: */ + if ((flags & FD_BO_CACHED_COHERENT) && !dev->has_cached_coherent) + flags &= ~FD_BO_CACHED_COHERENT; + bo = fd_bo_cache_alloc(cache, &size, flags); if (bo) return bo; diff --git a/src/freedreno/drm/freedreno_drmif.h b/src/freedreno/drm/freedreno_drmif.h index 4050295438c..bcddf49b75e 100644 --- a/src/freedreno/drm/freedreno_drmif.h +++ b/src/freedreno/drm/freedreno_drmif.h @@ -97,9 +97,10 @@ struct fd_fence { }; /* bo flags: */ -#define FD_BO_GPUREADONLY BITSET_BIT(1) -#define FD_BO_SCANOUT BITSET_BIT(2) -/* Default caching is WRITECOMBINE, we can add new bo flags later for cached/etc */ +#define FD_BO_GPUREADONLY BITSET_BIT(1) +#define FD_BO_SCANOUT BITSET_BIT(2) +#define FD_BO_CACHED_COHERENT BITSET_BIT(3) +/* Default caching is WRITECOMBINE */ /* bo access flags: (keep aligned to MSM_PREP_x) */ #define FD_BO_PREP_READ BITSET_BIT(0) @@ -128,6 +129,8 @@ enum fd_version { FD_VERSION_SOFTPIN = 4, /* adds softpin, bo name, and dump flag */ FD_VERSION_ROBUSTNESS = 5, /* adds FD_NR_FAULTS and FD_PP_PGTABLE */ FD_VERSION_MEMORY_FD = 2, /* supports shared memory objects */ + FD_VERSION_SUSPENDS = 7, /* Adds MSM_PARAM_SUSPENDS to detect device suspend */ + FD_VERSION_CACHED_COHERENT = 8, /* Adds cached-coherent support (a6xx+) */ }; enum fd_version fd_device_version(struct fd_device *dev); diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index 8e8523abb47..b1616f68d95 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -130,7 +130,9 @@ struct fd_device { struct fd_bo_cache bo_cache; struct fd_bo_cache ring_cache; - int closefd; /* call close(fd) upon destruction */ + bool has_cached_coherent; + + bool closefd; /* call close(fd) upon destruction */ /* just for valgrind: */ int bo_size; diff --git a/src/freedreno/drm/msm_bo.c b/src/freedreno/drm/msm_bo.c index 3f43793648d..5963cac86b7 100644 --- a/src/freedreno/drm/msm_bo.c +++ b/src/freedreno/drm/msm_bo.c @@ -170,7 +170,6 @@ msm_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags, { struct drm_msm_gem_new req = { .size = size, - .flags = MSM_BO_WC, // TODO figure out proper flags.. }; int ret; @@ -180,6 +179,11 @@ msm_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags, if (flags & FD_BO_GPUREADONLY) req.flags |= MSM_BO_GPU_READONLY; + if (flags & FD_BO_CACHED_COHERENT) + req.flags |= MSM_BO_CACHED_COHERENT; + else + req.flags |= MSM_BO_WC; + ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req)); if (ret) return ret; diff --git a/src/freedreno/drm/msm_device.c b/src/freedreno/drm/msm_device.c index 93abf4844b2..a221fdc4cab 100644 --- a/src/freedreno/drm/msm_device.c +++ b/src/freedreno/drm/msm_device.c @@ -73,6 +73,27 @@ msm_device_new(int fd, drmVersionPtr version) util_queue_init(&msm_dev->submit_queue, "sq", 8, 1, 0, NULL); } + if (version->version_minor >= FD_VERSION_CACHED_COHERENT) { + struct drm_msm_gem_new new_req = { + .size = 0x1000, + .flags = MSM_BO_CACHED_COHERENT, + }; + + /* The kernel is new enough to support MSM_BO_CACHED_COHERENT, + * but that is not a guarantee that the device we are running + * on supports it. So do a test allocation to find out. + */ + if (!drmCommandWriteRead(fd, DRM_MSM_GEM_NEW, + &new_req, sizeof(new_req))) { + struct drm_gem_close close_req = { + .handle = new_req.handle, + }; + drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req); + + dev->has_cached_coherent = true; + } + } + dev->bo_size = sizeof(struct msm_bo); return dev;