drm/verisilicon: Add cache flush feature when dmabuf sync
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / verisilicon / vs_gem.c
index a8d1556..1a3f018 100644 (file)
 #include "vs_drv.h"
 #include "vs_gem.h"
 
+#ifdef CONFIG_SIFIVE_FLUSH
+#include <soc/sifive/sifive_ccache.h>
+#endif
+
 static const struct drm_gem_object_funcs vs_gem_default_funcs;
 
 static int vs_gem_alloc_buf(struct vs_gem_object *vs_obj)
@@ -220,6 +224,43 @@ static int vs_gem_mmap_obj(struct drm_gem_object *obj,
        return ret;
 }
 
+static int vs_gem_prime_end_cpu_access(struct dma_buf *buf,
+                                       enum dma_data_direction direction)
+{
+#ifdef CONFIG_SIFIVE_FLUSH
+       struct drm_gem_object *obj = buf->priv;
+       struct vs_gem_object *vs_obj = to_vs_gem_object(obj);
+
+       starfive_flush_dcache(vs_obj->dma_addr, vs_obj->size);
+#endif
+
+       return 0;
+}
+
+static struct dma_buf_ops vs_gem_prime_dmabuf_ops =  {
+       .cache_sgt_mapping = true,
+       .attach = drm_gem_map_attach,
+       .detach = drm_gem_map_detach,
+       .map_dma_buf = drm_gem_map_dma_buf,
+       .unmap_dma_buf = drm_gem_unmap_dma_buf,
+       .release = drm_gem_dmabuf_release,
+       .mmap = drm_gem_dmabuf_mmap,
+       .vmap = drm_gem_dmabuf_vmap,
+       .vunmap = drm_gem_dmabuf_vunmap,
+       .end_cpu_access = vs_gem_prime_end_cpu_access,
+};
+
+static struct dma_buf *vs_gem_prime_export(struct drm_gem_object *obj, int flags)
+{
+       struct dma_buf *dmabuf;
+
+       dmabuf =  drm_gem_prime_export(obj, flags);
+       if (!IS_ERR(dmabuf))
+               dmabuf->ops = &vs_gem_prime_dmabuf_ops;
+
+       return dmabuf;
+}
+
 struct sg_table *vs_gem_prime_get_sg_table(struct drm_gem_object *obj)
 {
        struct vs_gem_object *vs_obj = to_vs_gem_object(obj);
@@ -252,6 +293,7 @@ static const struct vm_operations_struct vs_vm_ops = {
 
 static const struct drm_gem_object_funcs vs_gem_default_funcs = {
        .free = vs_gem_free_object,
+       .export = vs_gem_prime_export,
        .get_sg_table = vs_gem_prime_get_sg_table,
        .vmap = vs_gem_prime_vmap,
        .vunmap = vs_gem_prime_vunmap,
@@ -280,6 +322,16 @@ int vs_gem_dumb_create(struct drm_file *file,
 struct drm_gem_object *vs_gem_prime_import(struct drm_device *dev,
                                           struct dma_buf *dma_buf)
 {
+       struct drm_gem_object *obj;
+
+       if (dma_buf->ops == &vs_gem_prime_dmabuf_ops) {
+               obj = dma_buf->priv;
+               if (obj->dev == dev) {
+                       drm_gem_object_get(obj);
+                       return obj;
+               }
+       }
+
        return drm_gem_prime_import_dev(dev, dma_buf, to_dma_dev(dev));
 }