Skip to content

Commit

Permalink
Merge tag 'drm-etnaviv-next-2024-11-07' of https://git.pengutronix.de…
Browse files Browse the repository at this point in the history
…/git/lst/linux into drm-next

- improve handling of DMA address limited systems
- improve GPU hangcheck
- fix address space collision on >= 4K CPU pages
- flush all known writeback caches before memory release
- various code cleanups

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Lucas Stach <l.stach@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/c84075a0257e7bee222d008fa3118117422d664e.camel@pengutronix.de
  • Loading branch information
Dave Airlie committed Nov 8, 2024
2 parents 1f8bdc3 + 2c7ac7d commit 35a6e15
Show file tree
Hide file tree
Showing 14 changed files with 108 additions and 92 deletions.
3 changes: 2 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
} else {
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
VIVS_GL_FLUSH_CACHE_DEPTH |
VIVS_GL_FLUSH_CACHE_COLOR);
VIVS_GL_FLUSH_CACHE_COLOR |
VIVS_GL_FLUSH_CACHE_SHADER_L1);
if (has_blt) {
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#include <linux/dma-mapping.h>

#include <drm/drm_mm.h>

#include "etnaviv_cmdbuf.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
Expand Down Expand Up @@ -55,6 +53,7 @@ etnaviv_cmdbuf_suballoc_new(struct device *dev)
return suballoc;

free_suballoc:
mutex_destroy(&suballoc->lock);
kfree(suballoc);

return ERR_PTR(ret);
Expand All @@ -79,6 +78,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
{
dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr,
suballoc->paddr);
mutex_destroy(&suballoc->lock);
kfree(suballoc);
}

Expand Down
21 changes: 16 additions & 5 deletions drivers/gpu/drm/etnaviv/etnaviv_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,16 @@ static int etnaviv_bind(struct device *dev)
priv->num_gpus = 0;
priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;

/*
* If the GPU is part of a system with DMA addressing limitations,
* request pages for our SHM backend buffers from the DMA32 zone to
* hopefully avoid performance killing SWIOTLB bounce buffering.
*/
if (dma_addressing_limited(dev)) {
priv->shm_gfp_mask |= GFP_DMA32;
priv->shm_gfp_mask &= ~__GFP_HIGHMEM;
}

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");
Expand All @@ -564,6 +574,7 @@ static int etnaviv_bind(struct device *dev)
out_destroy_suballoc:
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
out_free_priv:
mutex_destroy(&priv->gem_lock);
kfree(priv);
out_put:
drm_dev_put(drm);
Expand Down Expand Up @@ -608,7 +619,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
if (!of_device_is_available(core_node))
continue;

drm_of_component_match_add(&pdev->dev, &match,
drm_of_component_match_add(dev, &match,
component_compare_of, core_node);
}
} else {
Expand All @@ -631,9 +642,9 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* bit to make sure we are allocating the command buffers and
* TLBs in the lower 4 GiB address space.
*/
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
dev_dbg(&pdev->dev, "No suitable DMA available\n");
if (dma_set_mask(dev, DMA_BIT_MASK(40)) ||
dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) {
dev_dbg(dev, "No suitable DMA available\n");
return -ENODEV;
}

Expand All @@ -644,7 +655,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
*/
first_node = etnaviv_of_first_available_node();
if (first_node) {
of_dma_configure(&pdev->dev, first_node, true);
of_dma_configure(dev, first_node, true);
of_node_put(first_node);
}

Expand Down
14 changes: 7 additions & 7 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
etnaviv_obj->ops->release(etnaviv_obj);
drm_gem_object_release(obj);

mutex_destroy(&etnaviv_obj->lock);
kfree(etnaviv_obj);
}

Expand Down Expand Up @@ -543,7 +544,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
.vm_ops = &vm_ops,
};

static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
{
struct etnaviv_gem_object *etnaviv_obj;
Expand All @@ -570,6 +571,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
if (!etnaviv_obj)
return -ENOMEM;

etnaviv_obj->size = ALIGN(size, SZ_4K);
etnaviv_obj->flags = flags;
etnaviv_obj->ops = ops;

Expand All @@ -590,15 +592,13 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
struct drm_gem_object *obj = NULL;
int ret;

size = PAGE_ALIGN(size);

ret = etnaviv_gem_new_impl(dev, flags, &etnaviv_gem_shmem_ops, &obj);
ret = etnaviv_gem_new_impl(dev, size, flags, &etnaviv_gem_shmem_ops, &obj);
if (ret)
goto fail;

lockdep_set_class(&to_etnaviv_bo(obj)->lock, &etnaviv_shm_lock_class);

ret = drm_gem_object_init(dev, obj, size);
ret = drm_gem_object_init(dev, obj, PAGE_ALIGN(size));
if (ret)
goto fail;

Expand Down Expand Up @@ -627,7 +627,7 @@ int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
struct drm_gem_object *obj;
int ret;

ret = etnaviv_gem_new_impl(dev, flags, ops, &obj);
ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj);
if (ret)
return ret;

Expand Down Expand Up @@ -686,7 +686,7 @@ static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
kfree(etnaviv_obj->sgt);
}
if (etnaviv_obj->pages) {
int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
unsigned int npages = etnaviv_obj->base.size >> PAGE_SHIFT;

unpin_user_pages(etnaviv_obj->pages, npages);
kvfree(etnaviv_obj->pages);
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ struct etnaviv_gem_object {
const struct etnaviv_gem_ops *ops;
struct mutex lock;

/*
* The actual size that is visible to the GPU, not necessarily
* PAGE_SIZE aligned, but should be aligned to GPU page size.
*/
u32 size;
u32 flags;

struct list_head gem_node;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static struct lock_class_key etnaviv_prime_lock_class;
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
int npages = obj->size >> PAGE_SHIFT;
unsigned int npages = obj->size >> PAGE_SHIFT;

if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */
return ERR_PTR(-EINVAL);
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <drm/drm_file.h>
#include <linux/dma-fence-array.h>
#include <linux/file.h>
#include <linux/pm_runtime.h>
#include <linux/dma-resv.h>
#include <linux/sync_file.h>
#include <linux/uaccess.h>
Expand Down
64 changes: 29 additions & 35 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,8 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
continue;
}

/* disable debug registers, as they are not normally needed */
control |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
/* enable debug register access */
control &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);

failed = false;
Expand Down Expand Up @@ -839,17 +839,8 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
if (ret)
goto fail;

/*
* If the GPU is part of a system with DMA addressing limitations,
* request pages for our SHM backend buffers from the DMA32 zone to
* hopefully avoid performance killing SWIOTLB bounce buffering.
*/
if (dma_addressing_limited(gpu->dev))
priv->shm_gfp_mask |= GFP_DMA32;

/* Create buffer: */
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
PAGE_SIZE);
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, SZ_4K);
if (ret) {
dev_err(gpu->dev, "could not create command buffer\n");
goto fail;
Expand Down Expand Up @@ -1330,17 +1321,16 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
{
u32 val;

mutex_lock(&gpu->lock);

/* disable clock gating */
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);

/* enable debug register */
val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
val &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);

sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);

mutex_unlock(&gpu->lock);
}

static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
Expand All @@ -1350,23 +1340,22 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
unsigned int i;
u32 val;

mutex_lock(&gpu->lock);

sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);

/* enable clock gating */
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);

mutex_unlock(&gpu->lock);

for (i = 0; i < submit->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;

*pmr->bo_vma = pmr->sequence;
}

/* disable debug register */
val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
val |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);

/* enable clock gating */
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
}


Expand Down Expand Up @@ -1862,7 +1851,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (!gpu)
return -ENOMEM;

gpu->dev = &pdev->dev;
gpu->dev = dev;
mutex_init(&gpu->lock);
mutex_init(&gpu->sched_lock);

Expand All @@ -1876,8 +1865,8 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (gpu->irq < 0)
return gpu->irq;

err = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, 0,
dev_name(gpu->dev), gpu);
err = devm_request_irq(dev, gpu->irq, irq_handler, 0,
dev_name(dev), gpu);
if (err) {
dev_err(dev, "failed to request IRQ%u: %d\n", gpu->irq, err);
return err;
Expand Down Expand Up @@ -1914,13 +1903,13 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
* autosuspend delay is rather arbitary: no measurements have
* yet been performed to determine an appropriate value.
*/
pm_runtime_use_autosuspend(gpu->dev);
pm_runtime_set_autosuspend_delay(gpu->dev, 200);
pm_runtime_enable(gpu->dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 200);
pm_runtime_enable(dev);

err = component_add(&pdev->dev, &gpu_ops);
err = component_add(dev, &gpu_ops);
if (err < 0) {
dev_err(&pdev->dev, "failed to register component: %d\n", err);
dev_err(dev, "failed to register component: %d\n", err);
return err;
}

Expand All @@ -1929,8 +1918,13 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)

static void etnaviv_gpu_platform_remove(struct platform_device *pdev)
{
struct etnaviv_gpu *gpu = dev_get_drvdata(&pdev->dev);

component_del(&pdev->dev, &gpu_ops);
pm_runtime_disable(&pdev->dev);

mutex_destroy(&gpu->lock);
mutex_destroy(&gpu->sched_lock);
}

static int etnaviv_gpu_rpm_suspend(struct device *dev)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct etnaviv_gpu {

/* hang detection */
u32 hangcheck_dma_addr;
u32 hangcheck_primid;
u32 hangcheck_fence;

void __iomem *mmio;
Expand Down
Loading

0 comments on commit 35a6e15

Please sign in to comment.