drm/etnaviv: share a single cmdbuf suballoc region across all GPUs
authorLucas Stach <l.stach@pengutronix.de>
Fri, 5 Jul 2019 17:17:22 +0000 (19:17 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Thu, 15 Aug 2019 08:55:30 +0000 (10:55 +0200)
There is no need for each GPU to have it's own cmdbuf suballocation
region. Only allocate a single one for the the etnaviv virtual device
and share it across all GPUs.

As the suballoc space is now potentially shared by more hardware jobs
running in parallel, double its size to 512KB to avoid contention.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/etnaviv/etnaviv_drv.h
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h

index e842d988edd40263fb479800e3698f4fb5d2fead..b0babc0f7230917e1d945ce0e8eb7248d7219d11 100644 (file)
 #include "etnaviv_mmu.h"
 #include "etnaviv_perfmon.h"
 
-#define SUBALLOC_SIZE          SZ_256K
+#define SUBALLOC_SIZE          SZ_512K
 #define SUBALLOC_GRANULE       SZ_4K
 #define SUBALLOC_GRANULES      (SUBALLOC_SIZE / SUBALLOC_GRANULE)
 
 struct etnaviv_cmdbuf_suballoc {
        /* suballocated dma buffer properties */
-       struct etnaviv_gpu *gpu;
+       struct device *dev;
        void *vaddr;
        dma_addr_t paddr;
 
@@ -31,7 +31,7 @@ struct etnaviv_cmdbuf_suballoc {
 };
 
 struct etnaviv_cmdbuf_suballoc *
-etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
+etnaviv_cmdbuf_suballoc_new(struct device *dev)
 {
        struct etnaviv_cmdbuf_suballoc *suballoc;
        int ret;
@@ -40,11 +40,11 @@ etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
        if (!suballoc)
                return ERR_PTR(-ENOMEM);
 
-       suballoc->gpu = gpu;
+       suballoc->dev = dev;
        mutex_init(&suballoc->lock);
        init_waitqueue_head(&suballoc->free_event);
 
-       suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE,
+       suballoc->vaddr = dma_alloc_wc(dev, SUBALLOC_SIZE,
                                       &suballoc->paddr, GFP_KERNEL);
        if (!suballoc->vaddr) {
                ret = -ENOMEM;
@@ -76,7 +76,7 @@ void etnaviv_cmdbuf_suballoc_unmap(struct etnaviv_iommu *mmu,
 
 void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
 {
-       dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr,
+       dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr,
                    suballoc->paddr);
        kfree(suballoc);
 }
@@ -101,7 +101,7 @@ retry:
                                                       suballoc->free_space,
                                                       msecs_to_jiffies(10 * 1000));
                if (!ret) {
-                       dev_err(suballoc->gpu->dev,
+                       dev_err(suballoc->dev,
                                "Timeout waiting for cmdbuf space\n");
                        return -ETIMEDOUT;
                }
index 583f56bf011c639c4a280941916afebb7729430d..a28668e46e269fe3169f8d69ef5f899ce0de666f 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <linux/types.h>
 
-struct etnaviv_gpu;
+struct device;
 struct etnaviv_iommu;
 struct etnaviv_vram_mapping;
 struct etnaviv_cmdbuf_suballoc;
@@ -25,7 +25,7 @@ struct etnaviv_cmdbuf {
 };
 
 struct etnaviv_cmdbuf_suballoc *
-etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu);
+etnaviv_cmdbuf_suballoc_new(struct device *dev);
 void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);
 int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc,
                                struct etnaviv_iommu *mmu,
index 9d4404723489da8f2a722a9e65766293a97cc97c..5fa3aa7bdbc59c8def90b142879d3818b67d8d02 100644 (file)
@@ -530,23 +530,32 @@ static int etnaviv_bind(struct device *dev)
        INIT_LIST_HEAD(&priv->gem_list);
        priv->num_gpus = 0;
 
+       priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
+       if (IS_ERR(priv->cmdbuf_suballoc)) {
+               dev_err(drm->dev, "Failed to create cmdbuf suballocator\n");
+               ret = PTR_ERR(priv->cmdbuf_suballoc);
+               goto out_free_priv;
+       }
+
        dev_set_drvdata(dev, drm);
 
        ret = component_bind_all(dev, drm);
        if (ret < 0)
-               goto out_bind;
+               goto out_destroy_suballoc;
 
        load_gpu(drm);
 
        ret = drm_dev_register(drm, 0);
        if (ret)
-               goto out_register;
+               goto out_unbind;
 
        return 0;
 
-out_register:
+out_unbind:
        component_unbind_all(dev, drm);
-out_bind:
+out_destroy_suballoc:
+       etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
+out_free_priv:
        kfree(priv);
 out_put:
        drm_dev_put(drm);
@@ -565,6 +574,8 @@ static void etnaviv_unbind(struct device *dev)
 
        dev->dma_parms = NULL;
 
+       etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
+
        drm->dev_private = NULL;
        kfree(priv);
 
index eabe394c4e2545a86cd46c25b5b5dca08804fc8c..e052d7db66aefd55eef74941473c11c583adb33a 100644 (file)
@@ -36,6 +36,8 @@ struct etnaviv_drm_private {
        struct device_dma_parameters dma_parms;
        struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
 
+       struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
+
        /* list of GEM objects: */
        struct mutex gem_lock;
        struct list_head gem_list;
index f535a627f2972e4927c2a8eb25632bb8a42c8c7b..3f4f6ab388de83a32e3563f044f61ff207764b42 100644 (file)
@@ -496,7 +496,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
                goto err_submit_ww_acquire;
        }
 
-       ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &submit->cmdbuf,
+       ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
                                  ALIGN(args->stream_size, 8) + 8);
        if (ret)
                goto err_submit_objects;
index f00547b88a13af3d3ea4018cdf7522c446b010dd..179bc6c544ca0637b2caf7d3410928c2776e0381 100644 (file)
@@ -693,6 +693,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 {
+       struct etnaviv_drm_private *priv = gpu->drm->dev_private;
        int ret, i;
 
        ret = pm_runtime_get_sync(gpu->dev);
@@ -760,23 +761,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
                goto fail;
        }
 
-       gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu);
-       if (IS_ERR(gpu->cmdbuf_suballoc)) {
-               dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n");
-               ret = PTR_ERR(gpu->cmdbuf_suballoc);
-               goto destroy_iommu;
-       }
-
-       ret = etnaviv_cmdbuf_suballoc_map(gpu->cmdbuf_suballoc, gpu->mmu,
+       ret = etnaviv_cmdbuf_suballoc_map(priv->cmdbuf_suballoc, gpu->mmu,
                                          &gpu->cmdbuf_mapping,
                                          gpu->memory_base);
        if (ret) {
                dev_err(gpu->dev, "failed to map cmdbuf suballoc\n");
-               goto destroy_suballoc;
+               goto destroy_iommu;
        }
 
        /* Create buffer: */
-       ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &gpu->buffer,
+       ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
                                  PAGE_SIZE);
        if (ret) {
                dev_err(gpu->dev, "could not create command buffer\n");
@@ -815,8 +809,6 @@ free_buffer:
        etnaviv_cmdbuf_free(&gpu->buffer);
 unmap_suballoc:
        etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
-destroy_suballoc:
-       etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
 destroy_iommu:
        etnaviv_iommu_destroy(gpu->mmu);
 fail:
@@ -1692,7 +1684,6 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
        if (gpu->initialized) {
                etnaviv_cmdbuf_free(&gpu->buffer);
                etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
-               etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
                etnaviv_iommu_destroy(gpu->mmu);
                gpu->initialized = false;
        }
index 6a6add350d2d7f14319e637bec03665b0c405890..933c8d016f113e090845f8ce66c5306e7f5f0ac6 100644 (file)
@@ -137,7 +137,6 @@ struct etnaviv_gpu {
        int irq;
 
        struct etnaviv_iommu *mmu;
-       struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
 
        /* Power Control: */
        struct clk *clk_bus;