Many modern CPUs and/or platforms choose to define their peripheral devices as cached coherent by default, to be specific, the PCH is capable of snooping CPU's cache. When hit the peripheral devices will access data directly from CPU's cache. This means that device drivers do not need to maintain the coherency issue between a processor and peripheral I/O for the cached buffers. Hence, it dosen't need us to sync manually on the software side, which is useful to avoid some overheads, especially for userspace, but userspace is not known yet.
Probe the hardware maintained cached coherent support of the host platform with the dev_is_dma_coherent() function, and store the result in struct etnaviv_drm_private. As this is a platform implementation-defined hardware feature and again is meant to be shared by all GPU cores. And expose it via etnaviv parameter mechanism to let userspace know. Please note that write-combine mapping out of scope of the discussion and therefore is not being addressed. Signed-off-by: Sui Jingfeng <sui.jingf...@linux.dev> --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 3 +++ drivers/gpu/drm/etnaviv/etnaviv_drv.h | 9 +++++++++ drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 4 ++++ include/uapi/drm/etnaviv_drm.h | 1 + 4 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index e3eb31ba9a2b..986fd68b489a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -5,6 +5,7 @@ #include <linux/component.h> #include <linux/dma-mapping.h> +#include <linux/dma-map-ops.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> @@ -57,6 +58,8 @@ static int etnaviv_private_init(struct device *dev, return -ENOMEM; } + priv->cached_coherent = dev_is_dma_coherent(dev); + return 0; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 1f9b50b5a6aa..4b59fdb457b7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -46,6 +46,15 @@ struct etnaviv_drm_private { struct xarray active_contexts; u32 next_context_id; + /* + * If true, the cached mapping is consistent for all CPU cores and + * peripheral bus masters in the system. It means that both of the + * CPU and GPU will see the same data if the buffer being accessed + * is cached. And the coherency is guaranteed by the host platform + * specific hardwares. + */ + bool cached_coherent; + /* list of GEM objects: */ struct mutex gem_lock; struct list_head gem_list; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 02d7efdc82c0..aa15682f94db 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -164,6 +164,10 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) *value = gpu->identity.eco_id; break; + case ETNAVIV_PARAM_CACHED_COHERENT: + *value = priv->cached_coherent; + break; + default: DBG("%s: invalid param: %u", dev_name(gpu->dev), param); return -EINVAL; diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h index af024d90453d..61eaa8cd0f5e 100644 --- a/include/uapi/drm/etnaviv_drm.h +++ b/include/uapi/drm/etnaviv_drm.h @@ -77,6 +77,7 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_PRODUCT_ID 0x1c #define ETNAVIV_PARAM_GPU_CUSTOMER_ID 0x1d #define ETNAVIV_PARAM_GPU_ECO_ID 0x1e +#define ETNAVIV_PARAM_CACHED_COHERENT 0x1f #define ETNA_MAX_PIPES 4 -- 2.34.1