mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-08 23:04:35 +08:00
drm/etnaviv: share a single cmdbuf suballoc region across all GPUs
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>
This commit is contained in:
parent
db82a0435b
commit
bffe5db81a
@ -13,13 +13,13 @@
|
|||||||
#include "etnaviv_mmu.h"
|
#include "etnaviv_mmu.h"
|
||||||
#include "etnaviv_perfmon.h"
|
#include "etnaviv_perfmon.h"
|
||||||
|
|
||||||
#define SUBALLOC_SIZE SZ_256K
|
#define SUBALLOC_SIZE SZ_512K
|
||||||
#define SUBALLOC_GRANULE SZ_4K
|
#define SUBALLOC_GRANULE SZ_4K
|
||||||
#define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE)
|
#define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE)
|
||||||
|
|
||||||
struct etnaviv_cmdbuf_suballoc {
|
struct etnaviv_cmdbuf_suballoc {
|
||||||
/* suballocated dma buffer properties */
|
/* suballocated dma buffer properties */
|
||||||
struct etnaviv_gpu *gpu;
|
struct device *dev;
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
dma_addr_t paddr;
|
dma_addr_t paddr;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ struct etnaviv_cmdbuf_suballoc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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;
|
struct etnaviv_cmdbuf_suballoc *suballoc;
|
||||||
int ret;
|
int ret;
|
||||||
@ -40,11 +40,11 @@ etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
|
|||||||
if (!suballoc)
|
if (!suballoc)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
suballoc->gpu = gpu;
|
suballoc->dev = dev;
|
||||||
mutex_init(&suballoc->lock);
|
mutex_init(&suballoc->lock);
|
||||||
init_waitqueue_head(&suballoc->free_event);
|
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);
|
&suballoc->paddr, GFP_KERNEL);
|
||||||
if (!suballoc->vaddr) {
|
if (!suballoc->vaddr) {
|
||||||
ret = -ENOMEM;
|
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)
|
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);
|
suballoc->paddr);
|
||||||
kfree(suballoc);
|
kfree(suballoc);
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ retry:
|
|||||||
suballoc->free_space,
|
suballoc->free_space,
|
||||||
msecs_to_jiffies(10 * 1000));
|
msecs_to_jiffies(10 * 1000));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
dev_err(suballoc->gpu->dev,
|
dev_err(suballoc->dev,
|
||||||
"Timeout waiting for cmdbuf space\n");
|
"Timeout waiting for cmdbuf space\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct etnaviv_gpu;
|
struct device;
|
||||||
struct etnaviv_iommu;
|
struct etnaviv_iommu;
|
||||||
struct etnaviv_vram_mapping;
|
struct etnaviv_vram_mapping;
|
||||||
struct etnaviv_cmdbuf_suballoc;
|
struct etnaviv_cmdbuf_suballoc;
|
||||||
@ -25,7 +25,7 @@ struct etnaviv_cmdbuf {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct etnaviv_cmdbuf_suballoc *
|
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);
|
void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);
|
||||||
int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc,
|
int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc,
|
||||||
struct etnaviv_iommu *mmu,
|
struct etnaviv_iommu *mmu,
|
||||||
|
@ -530,23 +530,32 @@ static int etnaviv_bind(struct device *dev)
|
|||||||
INIT_LIST_HEAD(&priv->gem_list);
|
INIT_LIST_HEAD(&priv->gem_list);
|
||||||
priv->num_gpus = 0;
|
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);
|
dev_set_drvdata(dev, drm);
|
||||||
|
|
||||||
ret = component_bind_all(dev, drm);
|
ret = component_bind_all(dev, drm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_bind;
|
goto out_destroy_suballoc;
|
||||||
|
|
||||||
load_gpu(drm);
|
load_gpu(drm);
|
||||||
|
|
||||||
ret = drm_dev_register(drm, 0);
|
ret = drm_dev_register(drm, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_register;
|
goto out_unbind;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_register:
|
out_unbind:
|
||||||
component_unbind_all(dev, drm);
|
component_unbind_all(dev, drm);
|
||||||
out_bind:
|
out_destroy_suballoc:
|
||||||
|
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
|
||||||
|
out_free_priv:
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
out_put:
|
out_put:
|
||||||
drm_dev_put(drm);
|
drm_dev_put(drm);
|
||||||
@ -565,6 +574,8 @@ static void etnaviv_unbind(struct device *dev)
|
|||||||
|
|
||||||
dev->dma_parms = NULL;
|
dev->dma_parms = NULL;
|
||||||
|
|
||||||
|
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
|
||||||
|
|
||||||
drm->dev_private = NULL;
|
drm->dev_private = NULL;
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ struct etnaviv_drm_private {
|
|||||||
struct device_dma_parameters dma_parms;
|
struct device_dma_parameters dma_parms;
|
||||||
struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
|
struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
|
||||||
|
|
||||||
|
struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
|
||||||
|
|
||||||
/* list of GEM objects: */
|
/* list of GEM objects: */
|
||||||
struct mutex gem_lock;
|
struct mutex gem_lock;
|
||||||
struct list_head gem_list;
|
struct list_head gem_list;
|
||||||
|
@ -496,7 +496,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|||||||
goto err_submit_ww_acquire;
|
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);
|
ALIGN(args->stream_size, 8) + 8);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_submit_objects;
|
goto err_submit_objects;
|
||||||
|
@ -693,6 +693,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
|
|||||||
|
|
||||||
int etnaviv_gpu_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;
|
int ret, i;
|
||||||
|
|
||||||
ret = pm_runtime_get_sync(gpu->dev);
|
ret = pm_runtime_get_sync(gpu->dev);
|
||||||
@ -760,23 +761,16 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu);
|
ret = etnaviv_cmdbuf_suballoc_map(priv->cmdbuf_suballoc, gpu->mmu,
|
||||||
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,
|
|
||||||
&gpu->cmdbuf_mapping,
|
&gpu->cmdbuf_mapping,
|
||||||
gpu->memory_base);
|
gpu->memory_base);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(gpu->dev, "failed to map cmdbuf suballoc\n");
|
dev_err(gpu->dev, "failed to map cmdbuf suballoc\n");
|
||||||
goto destroy_suballoc;
|
goto destroy_iommu;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create buffer: */
|
/* Create buffer: */
|
||||||
ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &gpu->buffer,
|
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
|
||||||
PAGE_SIZE);
|
PAGE_SIZE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(gpu->dev, "could not create command buffer\n");
|
dev_err(gpu->dev, "could not create command buffer\n");
|
||||||
@ -815,8 +809,6 @@ free_buffer:
|
|||||||
etnaviv_cmdbuf_free(&gpu->buffer);
|
etnaviv_cmdbuf_free(&gpu->buffer);
|
||||||
unmap_suballoc:
|
unmap_suballoc:
|
||||||
etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
|
etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
|
||||||
destroy_suballoc:
|
|
||||||
etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
|
|
||||||
destroy_iommu:
|
destroy_iommu:
|
||||||
etnaviv_iommu_destroy(gpu->mmu);
|
etnaviv_iommu_destroy(gpu->mmu);
|
||||||
fail:
|
fail:
|
||||||
@ -1692,7 +1684,6 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
|
|||||||
if (gpu->initialized) {
|
if (gpu->initialized) {
|
||||||
etnaviv_cmdbuf_free(&gpu->buffer);
|
etnaviv_cmdbuf_free(&gpu->buffer);
|
||||||
etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
|
etnaviv_cmdbuf_suballoc_unmap(gpu->mmu, &gpu->cmdbuf_mapping);
|
||||||
etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
|
|
||||||
etnaviv_iommu_destroy(gpu->mmu);
|
etnaviv_iommu_destroy(gpu->mmu);
|
||||||
gpu->initialized = false;
|
gpu->initialized = false;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,6 @@ struct etnaviv_gpu {
|
|||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
struct etnaviv_iommu *mmu;
|
struct etnaviv_iommu *mmu;
|
||||||
struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
|
|
||||||
|
|
||||||
/* Power Control: */
|
/* Power Control: */
|
||||||
struct clk *clk_bus;
|
struct clk *clk_bus;
|
||||||
|
Loading…
Reference in New Issue
Block a user