mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-23 13:29:33 +00:00
* Introducing Rockchip rk322x SoC support Main features: - Legacy kernel flavour based upon stable v2.x rk3288 Rockchip branch (https://github.com/rockchip-linux/kernel/tree/stable-4.4-rk3288-linux-v2.x) - Current kernel flavour based on mainline 5.6.y kernel - Mainline u-boot (v2020.04) - Single generic tv box target (rk322x-box) which boots on all the known tv boxes - Hardware devices (eMMC/NAND, led wiring configuration, SoC variant selection) modulation done by user at runtime via device tree overlays - a script (rk322x-config) is provided for autodetection and simple configuration by inexperienced users; - Bits added to armbian-hardware-optimization to set affinity for irq handlers - rk322x-box targets already added to targets.conf for automatic image creation * Removed disabled patches * Restored mysteriously removed comment character
4172 lines
119 KiB
Diff
4172 lines
119 KiB
Diff
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
index 8822ec13a0d6..cdebe9a9ade7 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
@@ -351,7 +351,7 @@ int panfrost_gpu_init(struct panfrost_device *pfdev)
|
|
return -ENODEV;
|
|
|
|
err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler,
|
|
- IRQF_SHARED, "gpu", pfdev);
|
|
+ IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev);
|
|
if (err) {
|
|
dev_err(pfdev->dev, "failed to request gpu irq");
|
|
return err;
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
|
|
index 9a1a72a748e7..7914b1570841 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
|
|
@@ -508,7 +508,7 @@ int panfrost_job_init(struct panfrost_device *pfdev)
|
|
return -ENODEV;
|
|
|
|
ret = devm_request_irq(pfdev->dev, irq, panfrost_job_irq_handler,
|
|
- IRQF_SHARED, "job", pfdev);
|
|
+ IRQF_SHARED, KBUILD_MODNAME "-job", pfdev);
|
|
if (ret) {
|
|
dev_err(pfdev->dev, "failed to request job irq");
|
|
return ret;
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
|
index 5d75f8cf6477..ed28aeba6d59 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
|
@@ -640,9 +640,11 @@ int panfrost_mmu_init(struct panfrost_device *pfdev)
|
|
if (irq <= 0)
|
|
return -ENODEV;
|
|
|
|
- err = devm_request_threaded_irq(pfdev->dev, irq, panfrost_mmu_irq_handler,
|
|
+ err = devm_request_threaded_irq(pfdev->dev, irq,
|
|
+ panfrost_mmu_irq_handler,
|
|
panfrost_mmu_irq_handler_thread,
|
|
- IRQF_SHARED, "mmu", pfdev);
|
|
+ IRQF_SHARED, KBUILD_MODNAME "-mmu",
|
|
+ pfdev);
|
|
|
|
if (err) {
|
|
dev_err(pfdev->dev, "failed to request mmu irq");
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From feabec154cc4e8e3e9f1005fc0fc2ad2d0d828ed Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Thu, 16 Jan 2020 21:11:53 +0800
|
|
Subject: [PATCH] drm/lima: update register info
|
|
|
|
From Mali r10p0 kernel driver source code.
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_regs.h | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h
|
|
index ace8ecefbe90..0124c90e0153 100644
|
|
--- a/drivers/gpu/drm/lima/lima_regs.h
|
|
+++ b/drivers/gpu/drm/lima/lima_regs.h
|
|
@@ -239,6 +239,7 @@
|
|
#define LIMA_MMU_STATUS_REPLAY_BUFFER_EMPTY BIT(4)
|
|
#define LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE BIT(5)
|
|
#define LIMA_MMU_STATUS_BUS_ID(x) ((x >> 6) & 0x1F)
|
|
+#define LIMA_MMU_STATUS_STALL_NOT_ACTIVE BIT(31)
|
|
#define LIMA_MMU_COMMAND 0x0008
|
|
#define LIMA_MMU_COMMAND_ENABLE_PAGING 0x00
|
|
#define LIMA_MMU_COMMAND_DISABLE_PAGING 0x01
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From a39f09230ca6ddf9e147e86c1bad9850913f6d52 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Thu, 16 Jan 2020 21:11:54 +0800
|
|
Subject: [PATCH] drm/lima: add lima_vm_map_bo
|
|
|
|
For dynamically mapping added backup memory of lima_bo to vm.
|
|
This is a preparation for adding heap buffer support.
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_vm.c | 42 ++++++++++++++++++++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_vm.h | 1 +
|
|
2 files changed, 43 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c
|
|
index 840e2350d872..2e513841de6c 100644
|
|
--- a/drivers/gpu/drm/lima/lima_vm.c
|
|
+++ b/drivers/gpu/drm/lima/lima_vm.c
|
|
@@ -277,3 +277,45 @@ void lima_vm_print(struct lima_vm *vm)
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, int pageoff)
|
|
+{
|
|
+ struct lima_bo_va *bo_va;
|
|
+ struct sg_dma_page_iter sg_iter;
|
|
+ int offset = 0, err;
|
|
+ u32 base;
|
|
+
|
|
+ mutex_lock(&bo->lock);
|
|
+
|
|
+ bo_va = lima_vm_bo_find(vm, bo);
|
|
+ if (!bo_va) {
|
|
+ err = -ENOENT;
|
|
+ goto err_out0;
|
|
+ }
|
|
+
|
|
+ mutex_lock(&vm->lock);
|
|
+
|
|
+ base = bo_va->node.start + (pageoff << PAGE_SHIFT);
|
|
+ for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter,
|
|
+ bo->base.sgt->nents, pageoff) {
|
|
+ err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter),
|
|
+ base + offset);
|
|
+ if (err)
|
|
+ goto err_out1;
|
|
+
|
|
+ offset += PAGE_SIZE;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&vm->lock);
|
|
+
|
|
+ mutex_unlock(&bo->lock);
|
|
+ return 0;
|
|
+
|
|
+err_out1:
|
|
+ if (offset)
|
|
+ lima_vm_unmap_range(vm, base, base + offset - 1);
|
|
+ mutex_unlock(&vm->lock);
|
|
+err_out0:
|
|
+ mutex_unlock(&bo->lock);
|
|
+ return err;
|
|
+}
|
|
diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h
|
|
index e0bdedcf14dd..22aeec77d84d 100644
|
|
--- a/drivers/gpu/drm/lima/lima_vm.h
|
|
+++ b/drivers/gpu/drm/lima/lima_vm.h
|
|
@@ -58,5 +58,6 @@ static inline void lima_vm_put(struct lima_vm *vm)
|
|
}
|
|
|
|
void lima_vm_print(struct lima_vm *vm);
|
|
+int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, int pageoff);
|
|
|
|
#endif
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 7855619e0208555bf2568e143747d86b882aa6f7 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Thu, 16 Jan 2020 21:11:55 +0800
|
|
Subject: [PATCH] drm/lima: support heap buffer creation
|
|
|
|
heap buffer is used as output of GP and input of PP for
|
|
Mali Utgard GPU. Size of heap buffer depends on the task
|
|
so is a runtime variable.
|
|
|
|
Previously we just create a large enough buffer as heap
|
|
buffer. Now we add a heap buffer type to be able to
|
|
increase the backup memory dynamically when GP fail due
|
|
to lack of heap memory.
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 6 +-
|
|
drivers/gpu/drm/lima/lima_drv.h | 1 +
|
|
drivers/gpu/drm/lima/lima_gem.c | 134 ++++++++++++++++++++++++++++++--
|
|
drivers/gpu/drm/lima/lima_gem.h | 4 +
|
|
drivers/gpu/drm/lima/lima_vm.c | 4 +-
|
|
include/uapi/drm/lima_drm.h | 9 ++-
|
|
6 files changed, 147 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 124efe4fa97b..18f88aaef1a2 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -15,10 +15,14 @@
|
|
#include "lima_vm.h"
|
|
|
|
int lima_sched_timeout_ms;
|
|
+uint lima_heap_init_nr_pages = 8;
|
|
|
|
MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms");
|
|
module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
|
|
|
|
+MODULE_PARM_DESC(heap_init_nr_pages, "heap buffer init number of pages");
|
|
+module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444);
|
|
+
|
|
static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)
|
|
{
|
|
struct drm_lima_get_param *args = data;
|
|
@@ -68,7 +72,7 @@ static int lima_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_
|
|
if (args->pad)
|
|
return -EINVAL;
|
|
|
|
- if (args->flags)
|
|
+ if (args->flags & ~(LIMA_BO_FLAG_HEAP))
|
|
return -EINVAL;
|
|
|
|
if (args->size == 0)
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h
|
|
index 69c7344715c9..f492ecc6a5d9 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.h
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.h
|
|
@@ -9,6 +9,7 @@
|
|
#include "lima_ctx.h"
|
|
|
|
extern int lima_sched_timeout_ms;
|
|
+extern uint lima_heap_init_nr_pages;
|
|
|
|
struct lima_vm;
|
|
struct lima_bo;
|
|
diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
|
|
index d0059d8c97d8..5404e0d668db 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gem.c
|
|
+++ b/drivers/gpu/drm/lima/lima_gem.c
|
|
@@ -4,6 +4,8 @@
|
|
#include <linux/mm.h>
|
|
#include <linux/sync_file.h>
|
|
#include <linux/pagemap.h>
|
|
+#include <linux/shmem_fs.h>
|
|
+#include <linux/dma-mapping.h>
|
|
|
|
#include <drm/drm_file.h>
|
|
#include <drm/drm_syncobj.h>
|
|
@@ -15,6 +17,83 @@
|
|
#include "lima_gem.h"
|
|
#include "lima_vm.h"
|
|
|
|
+int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
|
|
+{
|
|
+ struct page **pages;
|
|
+ struct address_space *mapping = bo->base.base.filp->f_mapping;
|
|
+ struct device *dev = bo->base.base.dev->dev;
|
|
+ size_t old_size = bo->heap_size;
|
|
+ size_t new_size = bo->heap_size ? bo->heap_size * 2 :
|
|
+ (lima_heap_init_nr_pages << PAGE_SHIFT);
|
|
+ struct sg_table sgt;
|
|
+ int i, ret;
|
|
+
|
|
+ if (bo->heap_size >= bo->base.base.size)
|
|
+ return -ENOSPC;
|
|
+
|
|
+ new_size = min(new_size, bo->base.base.size);
|
|
+
|
|
+ mutex_lock(&bo->base.pages_lock);
|
|
+
|
|
+ if (bo->base.pages) {
|
|
+ pages = bo->base.pages;
|
|
+ } else {
|
|
+ pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
|
|
+ sizeof(*pages), GFP_KERNEL | __GFP_ZERO);
|
|
+ if (!pages) {
|
|
+ mutex_unlock(&bo->base.pages_lock);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ bo->base.pages = pages;
|
|
+ bo->base.pages_use_count = 1;
|
|
+
|
|
+ mapping_set_unevictable(mapping);
|
|
+ }
|
|
+
|
|
+ for (i = old_size >> PAGE_SHIFT; i < new_size >> PAGE_SHIFT; i++) {
|
|
+ struct page *page = shmem_read_mapping_page(mapping, i);
|
|
+
|
|
+ if (IS_ERR(page)) {
|
|
+ mutex_unlock(&bo->base.pages_lock);
|
|
+ return PTR_ERR(page);
|
|
+ }
|
|
+ pages[i] = page;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&bo->base.pages_lock);
|
|
+
|
|
+ ret = sg_alloc_table_from_pages(&sgt, pages, i, 0,
|
|
+ new_size, GFP_KERNEL);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (bo->base.sgt) {
|
|
+ dma_unmap_sg(dev, bo->base.sgt->sgl,
|
|
+ bo->base.sgt->nents, DMA_BIDIRECTIONAL);
|
|
+ sg_free_table(bo->base.sgt);
|
|
+ } else {
|
|
+ bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
|
|
+ if (!bo->base.sgt) {
|
|
+ sg_free_table(&sgt);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ dma_map_sg(dev, sgt.sgl, sgt.nents, DMA_BIDIRECTIONAL);
|
|
+
|
|
+ *bo->base.sgt = sgt;
|
|
+
|
|
+ if (vm) {
|
|
+ ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ bo->heap_size = new_size;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
|
u32 size, u32 flags, u32 *handle)
|
|
{
|
|
@@ -22,7 +101,8 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
|
gfp_t mask;
|
|
struct drm_gem_shmem_object *shmem;
|
|
struct drm_gem_object *obj;
|
|
- struct sg_table *sgt;
|
|
+ struct lima_bo *bo;
|
|
+ bool is_heap = flags & LIMA_BO_FLAG_HEAP;
|
|
|
|
shmem = drm_gem_shmem_create(dev, size);
|
|
if (IS_ERR(shmem))
|
|
@@ -36,10 +116,18 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
|
mask |= __GFP_DMA32;
|
|
mapping_set_gfp_mask(obj->filp->f_mapping, mask);
|
|
|
|
- sgt = drm_gem_shmem_get_pages_sgt(obj);
|
|
- if (IS_ERR(sgt)) {
|
|
- err = PTR_ERR(sgt);
|
|
- goto out;
|
|
+ if (is_heap) {
|
|
+ bo = to_lima_bo(obj);
|
|
+ err = lima_heap_alloc(bo, NULL);
|
|
+ if (err)
|
|
+ goto out;
|
|
+ } else {
|
|
+ struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(obj);
|
|
+
|
|
+ if (IS_ERR(sgt)) {
|
|
+ err = PTR_ERR(sgt);
|
|
+ goto out;
|
|
+ }
|
|
}
|
|
|
|
err = drm_gem_handle_create(file, obj, handle);
|
|
@@ -79,17 +167,47 @@ static void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *f
|
|
lima_vm_bo_del(vm, bo);
|
|
}
|
|
|
|
+static int lima_gem_pin(struct drm_gem_object *obj)
|
|
+{
|
|
+ struct lima_bo *bo = to_lima_bo(obj);
|
|
+
|
|
+ if (bo->heap_size)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return drm_gem_shmem_pin(obj);
|
|
+}
|
|
+
|
|
+static void *lima_gem_vmap(struct drm_gem_object *obj)
|
|
+{
|
|
+ struct lima_bo *bo = to_lima_bo(obj);
|
|
+
|
|
+ if (bo->heap_size)
|
|
+ return ERR_PTR(-EINVAL);
|
|
+
|
|
+ return drm_gem_shmem_vmap(obj);
|
|
+}
|
|
+
|
|
+static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
|
|
+{
|
|
+ struct lima_bo *bo = to_lima_bo(obj);
|
|
+
|
|
+ if (bo->heap_size)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return drm_gem_shmem_mmap(obj, vma);
|
|
+}
|
|
+
|
|
static const struct drm_gem_object_funcs lima_gem_funcs = {
|
|
.free = lima_gem_free_object,
|
|
.open = lima_gem_object_open,
|
|
.close = lima_gem_object_close,
|
|
.print_info = drm_gem_shmem_print_info,
|
|
- .pin = drm_gem_shmem_pin,
|
|
+ .pin = lima_gem_pin,
|
|
.unpin = drm_gem_shmem_unpin,
|
|
.get_sg_table = drm_gem_shmem_get_sg_table,
|
|
- .vmap = drm_gem_shmem_vmap,
|
|
+ .vmap = lima_gem_vmap,
|
|
.vunmap = drm_gem_shmem_vunmap,
|
|
- .mmap = drm_gem_shmem_mmap,
|
|
+ .mmap = lima_gem_mmap,
|
|
};
|
|
|
|
struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size)
|
|
diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h
|
|
index 1800feb3e47f..ccea06142f4b 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gem.h
|
|
+++ b/drivers/gpu/drm/lima/lima_gem.h
|
|
@@ -7,12 +7,15 @@
|
|
#include <drm/drm_gem_shmem_helper.h>
|
|
|
|
struct lima_submit;
|
|
+struct lima_vm;
|
|
|
|
struct lima_bo {
|
|
struct drm_gem_shmem_object base;
|
|
|
|
struct mutex lock;
|
|
struct list_head va;
|
|
+
|
|
+ size_t heap_size;
|
|
};
|
|
|
|
static inline struct lima_bo *
|
|
@@ -31,6 +34,7 @@ static inline struct dma_resv *lima_bo_resv(struct lima_bo *bo)
|
|
return bo->base.base.resv;
|
|
}
|
|
|
|
+int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm);
|
|
struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size);
|
|
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
|
u32 size, u32 flags, u32 *handle);
|
|
diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c
|
|
index 2e513841de6c..5b92fb82674a 100644
|
|
--- a/drivers/gpu/drm/lima/lima_vm.c
|
|
+++ b/drivers/gpu/drm/lima/lima_vm.c
|
|
@@ -155,6 +155,7 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create)
|
|
void lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo)
|
|
{
|
|
struct lima_bo_va *bo_va;
|
|
+ u32 size;
|
|
|
|
mutex_lock(&bo->lock);
|
|
|
|
@@ -166,8 +167,9 @@ void lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo)
|
|
|
|
mutex_lock(&vm->lock);
|
|
|
|
+ size = bo->heap_size ? bo->heap_size : bo_va->node.size;
|
|
lima_vm_unmap_range(vm, bo_va->node.start,
|
|
- bo_va->node.start + bo_va->node.size - 1);
|
|
+ bo_va->node.start + size - 1);
|
|
|
|
drm_mm_remove_node(&bo_va->node);
|
|
|
|
diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h
|
|
index 95a00fb867e6..1ec58d652a5a 100644
|
|
--- a/include/uapi/drm/lima_drm.h
|
|
+++ b/include/uapi/drm/lima_drm.h
|
|
@@ -32,12 +32,19 @@ struct drm_lima_get_param {
|
|
__u64 value; /* out, parameter value */
|
|
};
|
|
|
|
+/*
|
|
+ * heap buffer dynamically increase backup memory size when GP task fail
|
|
+ * due to lack of heap memory. size field of heap buffer is an up bound of
|
|
+ * the backup memory which can be set to a fairly large value.
|
|
+ */
|
|
+#define LIMA_BO_FLAG_HEAP (1 << 0)
|
|
+
|
|
/**
|
|
* create a buffer for used by GPU
|
|
*/
|
|
struct drm_lima_gem_create {
|
|
__u32 size; /* in, buffer size */
|
|
- __u32 flags; /* in, currently no flags, must be zero */
|
|
+ __u32 flags; /* in, buffer flags */
|
|
__u32 handle; /* out, GEM buffer handle */
|
|
__u32 pad; /* pad, must be zero */
|
|
};
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From a9e57ad7709f2f0794da7ec3ef69fa0075c715d5 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Thu, 16 Jan 2020 21:11:56 +0800
|
|
Subject: [PATCH] drm/lima: recover task by enlarging heap buffer
|
|
|
|
Increase heap buffer backup memory when GP receive PLBU
|
|
out of memory interrupt, then resume the task.
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_gp.c | 58 +++++++++++++++++++++++++++++--
|
|
drivers/gpu/drm/lima/lima_mmu.c | 5 +++
|
|
drivers/gpu/drm/lima/lima_mmu.h | 1 +
|
|
drivers/gpu/drm/lima/lima_sched.c | 35 ++++++++++++++++---
|
|
drivers/gpu/drm/lima/lima_sched.h | 6 ++++
|
|
5 files changed, 98 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
|
|
index ccf49faedebf..52b210f9a605 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gp.c
|
|
+++ b/drivers/gpu/drm/lima/lima_gp.c
|
|
@@ -11,6 +11,8 @@
|
|
#include "lima_device.h"
|
|
#include "lima_gp.h"
|
|
#include "lima_regs.h"
|
|
+#include "lima_gem.h"
|
|
+#include "lima_vm.h"
|
|
|
|
#define gp_write(reg, data) writel(data, ip->iomem + reg)
|
|
#define gp_read(reg) readl(ip->iomem + reg)
|
|
@@ -20,6 +22,7 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data)
|
|
struct lima_ip *ip = data;
|
|
struct lima_device *dev = ip->dev;
|
|
struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
|
|
+ struct lima_sched_task *task = pipe->current_task;
|
|
u32 state = gp_read(LIMA_GP_INT_STAT);
|
|
u32 status = gp_read(LIMA_GP_STATUS);
|
|
bool done = false;
|
|
@@ -29,8 +32,16 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data)
|
|
return IRQ_NONE;
|
|
|
|
if (state & LIMA_GP_IRQ_MASK_ERROR) {
|
|
- dev_err(dev->dev, "gp error irq state=%x status=%x\n",
|
|
- state, status);
|
|
+ if ((state & LIMA_GP_IRQ_MASK_ERROR) ==
|
|
+ LIMA_GP_IRQ_PLBU_OUT_OF_MEM) {
|
|
+ dev_dbg(dev->dev, "gp out of heap irq status=%x\n",
|
|
+ status);
|
|
+ } else {
|
|
+ dev_err(dev->dev, "gp error irq state=%x status=%x\n",
|
|
+ state, status);
|
|
+ if (task)
|
|
+ task->recoverable = false;
|
|
+ }
|
|
|
|
/* mask all interrupts before hard reset */
|
|
gp_write(LIMA_GP_INT_MASK, 0);
|
|
@@ -43,6 +54,7 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data)
|
|
bool active = status & (LIMA_GP_STATUS_VS_ACTIVE |
|
|
LIMA_GP_STATUS_PLBU_ACTIVE);
|
|
done = valid && !active;
|
|
+ pipe->error = false;
|
|
}
|
|
|
|
gp_write(LIMA_GP_INT_CLEAR, state);
|
|
@@ -121,6 +133,22 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe,
|
|
u32 cmd = 0;
|
|
int i;
|
|
|
|
+ /* update real heap buffer size for GP */
|
|
+ for (i = 0; i < task->num_bos; i++) {
|
|
+ struct lima_bo *bo = task->bos[i];
|
|
+
|
|
+ if (bo->heap_size &&
|
|
+ lima_vm_get_va(task->vm, bo) ==
|
|
+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]) {
|
|
+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
|
|
+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] +
|
|
+ bo->heap_size;
|
|
+ task->recoverable = true;
|
|
+ task->heap = bo;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (f[LIMA_GP_VSCL_START_ADDR >> 2] !=
|
|
f[LIMA_GP_VSCL_END_ADDR >> 2])
|
|
cmd |= LIMA_GP_CMD_START_VS;
|
|
@@ -184,6 +212,31 @@ static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe)
|
|
lima_sched_pipe_task_done(pipe);
|
|
}
|
|
|
|
+static int lima_gp_task_recover(struct lima_sched_pipe *pipe)
|
|
+{
|
|
+ struct lima_ip *ip = pipe->processor[0];
|
|
+ struct lima_sched_task *task = pipe->current_task;
|
|
+ struct drm_lima_gp_frame *frame = task->frame;
|
|
+ u32 *f = frame->frame;
|
|
+ size_t fail_size =
|
|
+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] -
|
|
+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2];
|
|
+
|
|
+ if (fail_size == task->heap->heap_size) {
|
|
+ int ret;
|
|
+
|
|
+ ret = lima_heap_alloc(task->heap, task->vm);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
|
|
+ gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
|
|
+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size);
|
|
+ gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void lima_gp_print_version(struct lima_ip *ip)
|
|
{
|
|
u32 version, major, minor;
|
|
@@ -270,6 +323,7 @@ int lima_gp_pipe_init(struct lima_device *dev)
|
|
pipe->task_fini = lima_gp_task_fini;
|
|
pipe->task_error = lima_gp_task_error;
|
|
pipe->task_mmu_error = lima_gp_task_mmu_error;
|
|
+ pipe->task_recover = lima_gp_task_recover;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c
|
|
index 97ec09dee572..f79d2af427e7 100644
|
|
--- a/drivers/gpu/drm/lima/lima_mmu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_mmu.c
|
|
@@ -99,6 +99,11 @@ void lima_mmu_fini(struct lima_ip *ip)
|
|
|
|
}
|
|
|
|
+void lima_mmu_flush_tlb(struct lima_ip *ip)
|
|
+{
|
|
+ mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE);
|
|
+}
|
|
+
|
|
void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h
|
|
index 8c78319bcc8e..4f8ccbebcba1 100644
|
|
--- a/drivers/gpu/drm/lima/lima_mmu.h
|
|
+++ b/drivers/gpu/drm/lima/lima_mmu.h
|
|
@@ -10,6 +10,7 @@ struct lima_vm;
|
|
int lima_mmu_init(struct lima_ip *ip);
|
|
void lima_mmu_fini(struct lima_ip *ip);
|
|
|
|
+void lima_mmu_flush_tlb(struct lima_ip *ip);
|
|
void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm);
|
|
void lima_mmu_page_fault_resume(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index b561dd05bd62..3886999b4533 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -313,6 +313,26 @@ static const struct drm_sched_backend_ops lima_sched_ops = {
|
|
.free_job = lima_sched_free_job,
|
|
};
|
|
|
|
+static void lima_sched_recover_work(struct work_struct *work)
|
|
+{
|
|
+ struct lima_sched_pipe *pipe =
|
|
+ container_of(work, struct lima_sched_pipe, recover_work);
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < pipe->num_l2_cache; i++)
|
|
+ lima_l2_cache_flush(pipe->l2_cache[i]);
|
|
+
|
|
+ if (pipe->bcast_mmu) {
|
|
+ lima_mmu_flush_tlb(pipe->bcast_mmu);
|
|
+ } else {
|
|
+ for (i = 0; i < pipe->num_mmu; i++)
|
|
+ lima_mmu_flush_tlb(pipe->mmu[i]);
|
|
+ }
|
|
+
|
|
+ if (pipe->task_recover(pipe))
|
|
+ drm_sched_fault(&pipe->base);
|
|
+}
|
|
+
|
|
int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
|
|
{
|
|
unsigned int timeout = lima_sched_timeout_ms > 0 ?
|
|
@@ -321,6 +341,8 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
|
|
pipe->fence_context = dma_fence_context_alloc(1);
|
|
spin_lock_init(&pipe->fence_lock);
|
|
|
|
+ INIT_WORK(&pipe->recover_work, lima_sched_recover_work);
|
|
+
|
|
return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0,
|
|
msecs_to_jiffies(timeout), name);
|
|
}
|
|
@@ -332,11 +354,14 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
|
|
|
|
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
|
{
|
|
- if (pipe->error)
|
|
- drm_sched_fault(&pipe->base);
|
|
- else {
|
|
- struct lima_sched_task *task = pipe->current_task;
|
|
-
|
|
+ struct lima_sched_task *task = pipe->current_task;
|
|
+
|
|
+ if (pipe->error) {
|
|
+ if (task && task->recoverable)
|
|
+ schedule_work(&pipe->recover_work);
|
|
+ else
|
|
+ drm_sched_fault(&pipe->base);
|
|
+ } else {
|
|
pipe->task_fini(pipe);
|
|
dma_fence_signal(task->fence);
|
|
}
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h
|
|
index 1d814fecbcc0..d64393fb50a9 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.h
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.h
|
|
@@ -20,6 +20,9 @@ struct lima_sched_task {
|
|
struct lima_bo **bos;
|
|
int num_bos;
|
|
|
|
+ bool recoverable;
|
|
+ struct lima_bo *heap;
|
|
+
|
|
/* pipe fence */
|
|
struct dma_fence *fence;
|
|
};
|
|
@@ -68,6 +71,9 @@ struct lima_sched_pipe {
|
|
void (*task_fini)(struct lima_sched_pipe *pipe);
|
|
void (*task_error)(struct lima_sched_pipe *pipe);
|
|
void (*task_mmu_error)(struct lima_sched_pipe *pipe);
|
|
+ int (*task_recover)(struct lima_sched_pipe *pipe);
|
|
+
|
|
+ struct work_struct recover_work;
|
|
};
|
|
|
|
int lima_sched_task_init(struct lima_sched_task *task,
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 6e3dc43aea43e83182588b79dd85e9c5f4d1d033 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Thu, 16 Jan 2020 21:11:57 +0800
|
|
Subject: [PATCH] drm/lima: increase driver version to 1.1
|
|
|
|
Increase driver version for mesa driver to identify
|
|
the support of new heap buffer interface.
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 18f88aaef1a2..2daac64d8955 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -245,6 +245,12 @@ static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = {
|
|
|
|
DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops);
|
|
|
|
+/**
|
|
+ * Changelog:
|
|
+ *
|
|
+ * - 1.1.0 - add heap buffer support
|
|
+ */
|
|
+
|
|
static struct drm_driver lima_drm_driver = {
|
|
.driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,
|
|
.open = lima_drm_driver_open,
|
|
@@ -254,9 +260,9 @@ static struct drm_driver lima_drm_driver = {
|
|
.fops = &lima_drm_driver_fops,
|
|
.name = "lima",
|
|
.desc = "lima DRM",
|
|
- .date = "20190217",
|
|
+ .date = "20191231",
|
|
.major = 1,
|
|
- .minor = 0,
|
|
+ .minor = 1,
|
|
.patchlevel = 0,
|
|
|
|
.gem_create_object = lima_gem_create_object,
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 1a3901778598bc71d64bdbb71ea2278113aeb611 Mon Sep 17 00:00:00 2001
|
|
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Date: Fri, 14 Feb 2020 19:50:26 -0800
|
|
Subject: [PATCH] drm/lima: fix recovering from PLBU out of memory
|
|
|
|
It looks like on PLBU_OUT_OF_MEM interrupt we need to resume from where we
|
|
stopped, i.e. new PLBU heap start is old end. Also update end address
|
|
in GP frame to grow heap on 2nd and subsequent out of memory interrupts.
|
|
|
|
Fixes: 2081e8dcf1ee ("drm/lima: recover task by enlarging heap buffer")
|
|
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_gp.c | 7 ++++++-
|
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
|
|
index 52b210f9a605..d8841c870d90 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gp.c
|
|
+++ b/drivers/gpu/drm/lima/lima_gp.c
|
|
@@ -231,8 +231,13 @@ static int lima_gp_task_recover(struct lima_sched_pipe *pipe)
|
|
}
|
|
|
|
gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
|
|
+ /* Resume from where we stopped, i.e. new start is old end */
|
|
+ gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
|
|
+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
|
|
+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
|
|
+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size;
|
|
gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
|
|
- f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size);
|
|
+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
|
|
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
|
|
return 0;
|
|
}
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 619bbf1237ff25c39fbef0809bdfb28aa691e925 Mon Sep 17 00:00:00 2001
|
|
From: Nicolas Boichat <drinkcat@chromium.org>
|
|
Date: Fri, 7 Feb 2020 13:26:23 +0800
|
|
Subject: [PATCH] drm/panfrost: Improve error reporting in
|
|
panfrost_gpu_power_on
|
|
|
|
It is useful to know which component cannot be powered on.
|
|
|
|
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
|
|
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
|
|
Reviewed-by: Steven Price <steven.price@arm.com>
|
|
Signed-off-by: Rob Herring <robh@kernel.org>
|
|
---
|
|
drivers/gpu/drm/panfrost/panfrost_gpu.c | 14 ++++++++++----
|
|
1 file changed, 10 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
index cdebe9a9ade7..2881f439ff85 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
@@ -308,21 +308,27 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev)
|
|
gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present);
|
|
ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO,
|
|
val, val == pfdev->features.l2_present, 100, 1000);
|
|
+ if (ret)
|
|
+ dev_err(pfdev->dev, "error powering up gpu L2");
|
|
|
|
gpu_write(pfdev, STACK_PWRON_LO, pfdev->features.stack_present);
|
|
- ret |= readl_relaxed_poll_timeout(pfdev->iomem + STACK_READY_LO,
|
|
+ ret = readl_relaxed_poll_timeout(pfdev->iomem + STACK_READY_LO,
|
|
val, val == pfdev->features.stack_present, 100, 1000);
|
|
+ if (ret)
|
|
+ dev_err(pfdev->dev, "error powering up gpu stack");
|
|
|
|
gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present);
|
|
- ret |= readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO,
|
|
+ ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO,
|
|
val, val == pfdev->features.shader_present, 100, 1000);
|
|
+ if (ret)
|
|
+ dev_err(pfdev->dev, "error powering up gpu shader");
|
|
|
|
gpu_write(pfdev, TILER_PWRON_LO, pfdev->features.tiler_present);
|
|
- ret |= readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO,
|
|
+ ret = readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO,
|
|
val, val == pfdev->features.tiler_present, 100, 1000);
|
|
|
|
if (ret)
|
|
- dev_err(pfdev->dev, "error powering up gpu");
|
|
+ dev_err(pfdev->dev, "error powering up gpu tiler");
|
|
}
|
|
|
|
void panfrost_gpu_power_off(struct panfrost_device *pfdev)
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 96780fcbe44b27fda4c273d5b9b726dc4ba1ab5b Mon Sep 17 00:00:00 2001
|
|
From: Nicolas Boichat <drinkcat@chromium.org>
|
|
Date: Fri, 7 Feb 2020 13:26:24 +0800
|
|
Subject: [PATCH] drm/panfrost: Add support for multiple regulators
|
|
|
|
Some GPUs, namely, the bifrost/g72 part on MT8183, have a second
|
|
regulator for their SRAM, let's add support for that.
|
|
|
|
We extend the framework in a generic manner so that we could
|
|
support more than 2 regulators, if required.
|
|
|
|
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
|
|
Reviewed-by: Steven Price <steven.price@arm.com>
|
|
Reviwed-by: Mark Brown <broonie@kernel.org>
|
|
Signed-off-by: Rob Herring <robh@kernel.org>
|
|
---
|
|
drivers/gpu/drm/panfrost/panfrost_device.c | 26 +++++++++++++-------
|
|
drivers/gpu/drm/panfrost/panfrost_device.h | 15 +++++++++++-
|
|
drivers/gpu/drm/panfrost/panfrost_drv.c | 28 +++++++++++++++-------
|
|
3 files changed, 51 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
index 238fb6d54df4..3720d50f6d9f 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
@@ -87,18 +87,27 @@ static void panfrost_clk_fini(struct panfrost_device *pfdev)
|
|
|
|
static int panfrost_regulator_init(struct panfrost_device *pfdev)
|
|
{
|
|
- int ret;
|
|
+ int ret, i;
|
|
|
|
- pfdev->regulator = devm_regulator_get(pfdev->dev, "mali");
|
|
- if (IS_ERR(pfdev->regulator)) {
|
|
- ret = PTR_ERR(pfdev->regulator);
|
|
- dev_err(pfdev->dev, "failed to get regulator: %d\n", ret);
|
|
+ if (WARN(pfdev->comp->num_supplies > ARRAY_SIZE(pfdev->regulators),
|
|
+ "Too many supplies in compatible structure.\n"))
|
|
+ return -EINVAL;
|
|
+
|
|
+ for (i = 0; i < pfdev->comp->num_supplies; i++)
|
|
+ pfdev->regulators[i].supply = pfdev->comp->supply_names[i];
|
|
+
|
|
+ ret = devm_regulator_bulk_get(pfdev->dev,
|
|
+ pfdev->comp->num_supplies,
|
|
+ pfdev->regulators);
|
|
+ if (ret < 0) {
|
|
+ dev_err(pfdev->dev, "failed to get regulators: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
- ret = regulator_enable(pfdev->regulator);
|
|
+ ret = regulator_bulk_enable(pfdev->comp->num_supplies,
|
|
+ pfdev->regulators);
|
|
if (ret < 0) {
|
|
- dev_err(pfdev->dev, "failed to enable regulator: %d\n", ret);
|
|
+ dev_err(pfdev->dev, "failed to enable regulators: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
@@ -107,7 +116,8 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev)
|
|
|
|
static void panfrost_regulator_fini(struct panfrost_device *pfdev)
|
|
{
|
|
- regulator_disable(pfdev->regulator);
|
|
+ regulator_bulk_disable(pfdev->comp->num_supplies,
|
|
+ pfdev->regulators);
|
|
}
|
|
|
|
int panfrost_device_init(struct panfrost_device *pfdev)
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
index 06713811b92c..c9468bc5573a 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
@@ -7,6 +7,7 @@
|
|
|
|
#include <linux/atomic.h>
|
|
#include <linux/io-pgtable.h>
|
|
+#include <linux/regulator/consumer.h>
|
|
#include <linux/spinlock.h>
|
|
#include <drm/drm_device.h>
|
|
#include <drm/drm_mm.h>
|
|
@@ -19,6 +20,7 @@ struct panfrost_job;
|
|
struct panfrost_perfcnt;
|
|
|
|
#define NUM_JOB_SLOTS 3
|
|
+#define MAX_REGULATORS 2
|
|
|
|
struct panfrost_features {
|
|
u16 id;
|
|
@@ -51,6 +53,16 @@ struct panfrost_features {
|
|
unsigned long hw_issues[64 / BITS_PER_LONG];
|
|
};
|
|
|
|
+/*
|
|
+ * Features that cannot be automatically detected and need matching using the
|
|
+ * compatible string, typically SoC-specific.
|
|
+ */
|
|
+struct panfrost_compatible {
|
|
+ /* Supplies count and names. */
|
|
+ int num_supplies;
|
|
+ const char * const *supply_names;
|
|
+};
|
|
+
|
|
struct panfrost_device {
|
|
struct device *dev;
|
|
struct drm_device *ddev;
|
|
@@ -59,10 +71,11 @@ struct panfrost_device {
|
|
void __iomem *iomem;
|
|
struct clk *clock;
|
|
struct clk *bus_clock;
|
|
- struct regulator *regulator;
|
|
+ struct regulator_bulk_data regulators[MAX_REGULATORS];
|
|
struct reset_control *rstc;
|
|
|
|
struct panfrost_features features;
|
|
+ const struct panfrost_compatible *comp;
|
|
|
|
spinlock_t as_lock;
|
|
unsigned long as_in_use_mask;
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
index b7a618db3ee2..4d0850752623 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
@@ -584,6 +584,10 @@ static int panfrost_probe(struct platform_device *pdev)
|
|
|
|
platform_set_drvdata(pdev, pfdev);
|
|
|
|
+ pfdev->comp = of_device_get_match_data(&pdev->dev);
|
|
+ if (!pfdev->comp)
|
|
+ return -ENODEV;
|
|
+
|
|
/* Allocate and initialze the DRM device. */
|
|
ddev = drm_dev_alloc(&panfrost_drm_driver, &pdev->dev);
|
|
if (IS_ERR(ddev))
|
|
@@ -655,16 +659,22 @@ static int panfrost_remove(struct platform_device *pdev)
|
|
return 0;
|
|
}
|
|
|
|
+const char * const default_supplies[] = { "mali" };
|
|
+static const struct panfrost_compatible default_data = {
|
|
+ .num_supplies = ARRAY_SIZE(default_supplies),
|
|
+ .supply_names = default_supplies,
|
|
+};
|
|
+
|
|
static const struct of_device_id dt_match[] = {
|
|
- { .compatible = "arm,mali-t604" },
|
|
- { .compatible = "arm,mali-t624" },
|
|
- { .compatible = "arm,mali-t628" },
|
|
- { .compatible = "arm,mali-t720" },
|
|
- { .compatible = "arm,mali-t760" },
|
|
- { .compatible = "arm,mali-t820" },
|
|
- { .compatible = "arm,mali-t830" },
|
|
- { .compatible = "arm,mali-t860" },
|
|
- { .compatible = "arm,mali-t880" },
|
|
+ { .compatible = "arm,mali-t604", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t624", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t628", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t720", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t760", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t820", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t830", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t860", .data = &default_data, },
|
|
+ { .compatible = "arm,mali-t880", .data = &default_data, },
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(of, dt_match);
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 7de0cdd88c14fec1927a563e843fae6e6c79f6be Mon Sep 17 00:00:00 2001
|
|
From: Nicolas Boichat <drinkcat@chromium.org>
|
|
Date: Fri, 7 Feb 2020 13:26:25 +0800
|
|
Subject: [PATCH] drm/panfrost: Add support for multiple power domains
|
|
|
|
When there is a single power domain per device, the core will
|
|
ensure the power domain is switched on (so it is technically
|
|
equivalent to having not power domain specified at all).
|
|
|
|
However, when there are multiple domains, as in MT8183 Bifrost
|
|
GPU, we need to handle them in driver code.
|
|
|
|
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
|
|
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
|
|
Reviewed-by: Steven Price <steven.price@arm.com>
|
|
Signed-off-by: Rob Herring <robh@kernel.org>
|
|
---
|
|
drivers/gpu/drm/panfrost/panfrost_device.c | 97 ++++++++++++++++++++--
|
|
drivers/gpu/drm/panfrost/panfrost_device.h | 11 +++
|
|
drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +
|
|
3 files changed, 102 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
index 3720d50f6d9f..8136babd3ba9 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
|
|
@@ -5,6 +5,7 @@
|
|
#include <linux/clk.h>
|
|
#include <linux/reset.h>
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/pm_domain.h>
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include "panfrost_device.h"
|
|
@@ -120,6 +121,79 @@ static void panfrost_regulator_fini(struct panfrost_device *pfdev)
|
|
pfdev->regulators);
|
|
}
|
|
|
|
+static void panfrost_pm_domain_fini(struct panfrost_device *pfdev)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(pfdev->pm_domain_devs); i++) {
|
|
+ if (!pfdev->pm_domain_devs[i])
|
|
+ break;
|
|
+
|
|
+ if (pfdev->pm_domain_links[i])
|
|
+ device_link_del(pfdev->pm_domain_links[i]);
|
|
+
|
|
+ dev_pm_domain_detach(pfdev->pm_domain_devs[i], true);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int panfrost_pm_domain_init(struct panfrost_device *pfdev)
|
|
+{
|
|
+ int err;
|
|
+ int i, num_domains;
|
|
+
|
|
+ num_domains = of_count_phandle_with_args(pfdev->dev->of_node,
|
|
+ "power-domains",
|
|
+ "#power-domain-cells");
|
|
+
|
|
+ /*
|
|
+ * Single domain is handled by the core, and, if only a single power
|
|
+ * the power domain is requested, the property is optional.
|
|
+ */
|
|
+ if (num_domains < 2 && pfdev->comp->num_pm_domains < 2)
|
|
+ return 0;
|
|
+
|
|
+ if (num_domains != pfdev->comp->num_pm_domains) {
|
|
+ dev_err(pfdev->dev,
|
|
+ "Incorrect number of power domains: %d provided, %d needed\n",
|
|
+ num_domains, pfdev->comp->num_pm_domains);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (WARN(num_domains > ARRAY_SIZE(pfdev->pm_domain_devs),
|
|
+ "Too many supplies in compatible structure.\n"))
|
|
+ return -EINVAL;
|
|
+
|
|
+ for (i = 0; i < num_domains; i++) {
|
|
+ pfdev->pm_domain_devs[i] =
|
|
+ dev_pm_domain_attach_by_name(pfdev->dev,
|
|
+ pfdev->comp->pm_domain_names[i]);
|
|
+ if (IS_ERR_OR_NULL(pfdev->pm_domain_devs[i])) {
|
|
+ err = PTR_ERR(pfdev->pm_domain_devs[i]) ? : -ENODATA;
|
|
+ pfdev->pm_domain_devs[i] = NULL;
|
|
+ dev_err(pfdev->dev,
|
|
+ "failed to get pm-domain %s(%d): %d\n",
|
|
+ pfdev->comp->pm_domain_names[i], i, err);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ pfdev->pm_domain_links[i] = device_link_add(pfdev->dev,
|
|
+ pfdev->pm_domain_devs[i], DL_FLAG_PM_RUNTIME |
|
|
+ DL_FLAG_STATELESS | DL_FLAG_RPM_ACTIVE);
|
|
+ if (!pfdev->pm_domain_links[i]) {
|
|
+ dev_err(pfdev->pm_domain_devs[i],
|
|
+ "adding device link failed!\n");
|
|
+ err = -ENODEV;
|
|
+ goto err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err:
|
|
+ panfrost_pm_domain_fini(pfdev);
|
|
+ return err;
|
|
+}
|
|
+
|
|
int panfrost_device_init(struct panfrost_device *pfdev)
|
|
{
|
|
int err;
|
|
@@ -150,37 +224,43 @@ int panfrost_device_init(struct panfrost_device *pfdev)
|
|
goto err_out1;
|
|
}
|
|
|
|
+ err = panfrost_pm_domain_init(pfdev);
|
|
+ if (err)
|
|
+ goto err_out2;
|
|
+
|
|
res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0);
|
|
pfdev->iomem = devm_ioremap_resource(pfdev->dev, res);
|
|
if (IS_ERR(pfdev->iomem)) {
|
|
dev_err(pfdev->dev, "failed to ioremap iomem\n");
|
|
err = PTR_ERR(pfdev->iomem);
|
|
- goto err_out2;
|
|
+ goto err_out3;
|
|
}
|
|
|
|
err = panfrost_gpu_init(pfdev);
|
|
if (err)
|
|
- goto err_out2;
|
|
+ goto err_out3;
|
|
|
|
err = panfrost_mmu_init(pfdev);
|
|
if (err)
|
|
- goto err_out3;
|
|
+ goto err_out4;
|
|
|
|
err = panfrost_job_init(pfdev);
|
|
if (err)
|
|
- goto err_out4;
|
|
+ goto err_out5;
|
|
|
|
err = panfrost_perfcnt_init(pfdev);
|
|
if (err)
|
|
- goto err_out5;
|
|
+ goto err_out6;
|
|
|
|
return 0;
|
|
-err_out5:
|
|
+err_out6:
|
|
panfrost_job_fini(pfdev);
|
|
-err_out4:
|
|
+err_out5:
|
|
panfrost_mmu_fini(pfdev);
|
|
-err_out3:
|
|
+err_out4:
|
|
panfrost_gpu_fini(pfdev);
|
|
+err_out3:
|
|
+ panfrost_pm_domain_fini(pfdev);
|
|
err_out2:
|
|
panfrost_reset_fini(pfdev);
|
|
err_out1:
|
|
@@ -196,6 +276,7 @@ void panfrost_device_fini(struct panfrost_device *pfdev)
|
|
panfrost_job_fini(pfdev);
|
|
panfrost_mmu_fini(pfdev);
|
|
panfrost_gpu_fini(pfdev);
|
|
+ panfrost_pm_domain_fini(pfdev);
|
|
panfrost_reset_fini(pfdev);
|
|
panfrost_regulator_fini(pfdev);
|
|
panfrost_clk_fini(pfdev);
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
index c9468bc5573a..c30c719a8059 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
|
|
@@ -21,6 +21,7 @@ struct panfrost_perfcnt;
|
|
|
|
#define NUM_JOB_SLOTS 3
|
|
#define MAX_REGULATORS 2
|
|
+#define MAX_PM_DOMAINS 3
|
|
|
|
struct panfrost_features {
|
|
u16 id;
|
|
@@ -61,6 +62,13 @@ struct panfrost_compatible {
|
|
/* Supplies count and names. */
|
|
int num_supplies;
|
|
const char * const *supply_names;
|
|
+ /*
|
|
+ * Number of power domains required, note that values 0 and 1 are
|
|
+ * handled identically, as only values > 1 need special handling.
|
|
+ */
|
|
+ int num_pm_domains;
|
|
+ /* Only required if num_pm_domains > 1. */
|
|
+ const char * const *pm_domain_names;
|
|
};
|
|
|
|
struct panfrost_device {
|
|
@@ -73,6 +81,9 @@ struct panfrost_device {
|
|
struct clk *bus_clock;
|
|
struct regulator_bulk_data regulators[MAX_REGULATORS];
|
|
struct reset_control *rstc;
|
|
+ /* pm_domains for devices with more than one. */
|
|
+ struct device *pm_domain_devs[MAX_PM_DOMAINS];
|
|
+ struct device_link *pm_domain_links[MAX_PM_DOMAINS];
|
|
|
|
struct panfrost_features features;
|
|
const struct panfrost_compatible *comp;
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
index 4d0850752623..a6e162236d67 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
@@ -663,6 +663,8 @@ const char * const default_supplies[] = { "mali" };
|
|
static const struct panfrost_compatible default_data = {
|
|
.num_supplies = ARRAY_SIZE(default_supplies),
|
|
.supply_names = default_supplies,
|
|
+ .num_pm_domains = 1, /* optional */
|
|
+ .pm_domain_names = NULL,
|
|
};
|
|
|
|
static const struct of_device_id dt_match[] = {
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 4a210ebba6b01cb060a1de524d5d000981025b5b Mon Sep 17 00:00:00 2001
|
|
From: kbuild test robot <lkp@intel.com>
|
|
Date: Thu, 27 Feb 2020 09:41:46 +0800
|
|
Subject: [PATCH] drm/panfrost: default_supplies[] can be static
|
|
|
|
Fixes: 3e1399bccf51 ("drm/panfrost: Add support for multiple regulators")
|
|
Signed-off-by: kbuild test robot <lkp@intel.com>
|
|
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
|
|
Signed-off-by: Rob Herring <robh@kernel.org>
|
|
---
|
|
drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
index a6e162236d67..882fecc33fdb 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
|
@@ -659,7 +659,7 @@ static int panfrost_remove(struct platform_device *pdev)
|
|
return 0;
|
|
}
|
|
|
|
-const char * const default_supplies[] = { "mali" };
|
|
+static const char * const default_supplies[] = { "mali" };
|
|
static const struct panfrost_compatible default_data = {
|
|
.num_supplies = ARRAY_SIZE(default_supplies),
|
|
.supply_names = default_supplies,
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 95695d5e36c49319b2cc6eabae04d32a13ca962e Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Sat, 22 Feb 2020 10:42:06 +0800
|
|
Subject: [PATCH] drm/lima: save process info for debug usage
|
|
|
|
When task fail, we can find its process with this information.
|
|
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_ctx.c | 3 +++
|
|
drivers/gpu/drm/lima/lima_ctx.h | 5 +++++
|
|
2 files changed, 8 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c
|
|
index 22fff6caa961..891d5cd5019a 100644
|
|
--- a/drivers/gpu/drm/lima/lima_ctx.c
|
|
+++ b/drivers/gpu/drm/lima/lima_ctx.c
|
|
@@ -27,6 +27,9 @@ int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id)
|
|
if (err < 0)
|
|
goto err_out0;
|
|
|
|
+ ctx->pid = task_pid_nr(current);
|
|
+ get_task_comm(ctx->pname, current);
|
|
+
|
|
return 0;
|
|
|
|
err_out0:
|
|
diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h
|
|
index 6154e5c9bfe4..74e2be09090f 100644
|
|
--- a/drivers/gpu/drm/lima/lima_ctx.h
|
|
+++ b/drivers/gpu/drm/lima/lima_ctx.h
|
|
@@ -5,6 +5,7 @@
|
|
#define __LIMA_CTX_H__
|
|
|
|
#include <linux/xarray.h>
|
|
+#include <linux/sched.h>
|
|
|
|
#include "lima_device.h"
|
|
|
|
@@ -13,6 +14,10 @@ struct lima_ctx {
|
|
struct lima_device *dev;
|
|
struct lima_sched_context context[lima_pipe_num];
|
|
atomic_t guilty;
|
|
+
|
|
+ /* debug info */
|
|
+ char pname[TASK_COMM_LEN];
|
|
+ pid_t pid;
|
|
};
|
|
|
|
struct lima_ctx_mgr {
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From c70385c2415949d2a8eecdb3242b0e27fcc56c25 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Sat, 22 Feb 2020 10:42:07 +0800
|
|
Subject: [PATCH] drm/lima: add max_error_tasks module parameter
|
|
|
|
Limit error tasks to save.
|
|
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 4 ++++
|
|
drivers/gpu/drm/lima/lima_drv.h | 1 +
|
|
2 files changed, 5 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 2daac64d8955..e235d4545b6c 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -16,6 +16,7 @@
|
|
|
|
int lima_sched_timeout_ms;
|
|
uint lima_heap_init_nr_pages = 8;
|
|
+uint lima_max_error_tasks;
|
|
|
|
MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms");
|
|
module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
|
|
@@ -23,6 +24,9 @@ module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
|
|
MODULE_PARM_DESC(heap_init_nr_pages, "heap buffer init number of pages");
|
|
module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444);
|
|
|
|
+MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save");
|
|
+module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644);
|
|
+
|
|
static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)
|
|
{
|
|
struct drm_lima_get_param *args = data;
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h
|
|
index f492ecc6a5d9..fdbd4077c768 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.h
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.h
|
|
@@ -10,6 +10,7 @@
|
|
|
|
extern int lima_sched_timeout_ms;
|
|
extern uint lima_heap_init_nr_pages;
|
|
+extern uint lima_max_error_tasks;
|
|
|
|
struct lima_vm;
|
|
struct lima_bo;
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 3090b38955b4cb7c17b724fbdda56f5cab02e327 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Sat, 7 Mar 2020 21:44:23 +0800
|
|
Subject: [PATCH] drm/lima: save task info dump when task fail
|
|
|
|
Save all information to start a task which can be exported to user
|
|
for debug usage. Dump file data format is specified in lima_dump.h
|
|
|
|
v2:
|
|
Add include header to address build robot complain.
|
|
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_device.c | 13 +++
|
|
drivers/gpu/drm/lima/lima_device.h | 8 ++
|
|
drivers/gpu/drm/lima/lima_dump.h | 77 +++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_sched.c | 130 +++++++++++++++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_sched.h | 7 ++
|
|
5 files changed, 235 insertions(+)
|
|
create mode 100644 drivers/gpu/drm/lima/lima_dump.h
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index 19829b543024..42a00171fea5 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -344,6 +344,12 @@ int lima_device_init(struct lima_device *ldev)
|
|
if (err)
|
|
goto err_out5;
|
|
|
|
+ ldev->dump.magic = LIMA_DUMP_MAGIC;
|
|
+ ldev->dump.version_major = LIMA_DUMP_MAJOR;
|
|
+ ldev->dump.version_minor = LIMA_DUMP_MINOR;
|
|
+ INIT_LIST_HEAD(&ldev->error_task_list);
|
|
+ mutex_init(&ldev->error_task_list_lock);
|
|
+
|
|
dev_info(ldev->dev, "bus rate = %lu\n", clk_get_rate(ldev->clk_bus));
|
|
dev_info(ldev->dev, "mod rate = %lu", clk_get_rate(ldev->clk_gpu));
|
|
|
|
@@ -370,6 +376,13 @@ int lima_device_init(struct lima_device *ldev)
|
|
void lima_device_fini(struct lima_device *ldev)
|
|
{
|
|
int i;
|
|
+ struct lima_sched_error_task *et, *tmp;
|
|
+
|
|
+ list_for_each_entry_safe(et, tmp, &ldev->error_task_list, list) {
|
|
+ list_del(&et->list);
|
|
+ kvfree(et);
|
|
+ }
|
|
+ mutex_destroy(&ldev->error_task_list_lock);
|
|
|
|
lima_fini_pp_pipe(ldev);
|
|
lima_fini_gp_pipe(ldev);
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index 31158d86271c..f17173f47f26 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -6,8 +6,11 @@
|
|
|
|
#include <drm/drm_device.h>
|
|
#include <linux/delay.h>
|
|
+#include <linux/list.h>
|
|
+#include <linux/mutex.h>
|
|
|
|
#include "lima_sched.h"
|
|
+#include "lima_dump.h"
|
|
|
|
enum lima_gpu_id {
|
|
lima_gpu_mali400 = 0,
|
|
@@ -94,6 +97,11 @@ struct lima_device {
|
|
|
|
u32 *dlbu_cpu;
|
|
dma_addr_t dlbu_dma;
|
|
+
|
|
+ /* debug info */
|
|
+ struct lima_dump_head dump;
|
|
+ struct list_head error_task_list;
|
|
+ struct mutex error_task_list_lock;
|
|
};
|
|
|
|
static inline struct lima_device *
|
|
diff --git a/drivers/gpu/drm/lima/lima_dump.h b/drivers/gpu/drm/lima/lima_dump.h
|
|
new file mode 100644
|
|
index 000000000000..ca243d99c51b
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/lima/lima_dump.h
|
|
@@ -0,0 +1,77 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
|
+/* Copyright 2020 Qiang Yu <yuq825@gmail.com> */
|
|
+
|
|
+#ifndef __LIMA_DUMP_H__
|
|
+#define __LIMA_DUMP_H__
|
|
+
|
|
+#include <linux/types.h>
|
|
+
|
|
+/**
|
|
+ * dump file format for all the information to start a lima task
|
|
+ *
|
|
+ * top level format
|
|
+ * | magic code "LIMA" | format version | num tasks | data size |
|
|
+ * | reserved | reserved | reserved | reserved |
|
|
+ * | task 1 ID | task 1 size | num chunks | reserved | task 1 data |
|
|
+ * | task 2 ID | task 2 size | num chunks | reserved | task 2 data |
|
|
+ * ...
|
|
+ *
|
|
+ * task data format
|
|
+ * | chunk 1 ID | chunk 1 size | reserved | reserved | chunk 1 data |
|
|
+ * | chunk 2 ID | chunk 2 size | reserved | reserved | chunk 2 data |
|
|
+ * ...
|
|
+ *
|
|
+ */
|
|
+
|
|
+#define LIMA_DUMP_MAJOR 1
|
|
+#define LIMA_DUMP_MINOR 0
|
|
+
|
|
+#define LIMA_DUMP_MAGIC 0x414d494c
|
|
+
|
|
+struct lima_dump_head {
|
|
+ __u32 magic;
|
|
+ __u16 version_major;
|
|
+ __u16 version_minor;
|
|
+ __u32 num_tasks;
|
|
+ __u32 size;
|
|
+ __u32 reserved[4];
|
|
+};
|
|
+
|
|
+#define LIMA_DUMP_TASK_GP 0
|
|
+#define LIMA_DUMP_TASK_PP 1
|
|
+#define LIMA_DUMP_TASK_NUM 2
|
|
+
|
|
+struct lima_dump_task {
|
|
+ __u32 id;
|
|
+ __u32 size;
|
|
+ __u32 num_chunks;
|
|
+ __u32 reserved;
|
|
+};
|
|
+
|
|
+#define LIMA_DUMP_CHUNK_FRAME 0
|
|
+#define LIMA_DUMP_CHUNK_BUFFER 1
|
|
+#define LIMA_DUMP_CHUNK_PROCESS_NAME 2
|
|
+#define LIMA_DUMP_CHUNK_PROCESS_ID 3
|
|
+#define LIMA_DUMP_CHUNK_NUM 4
|
|
+
|
|
+struct lima_dump_chunk {
|
|
+ __u32 id;
|
|
+ __u32 size;
|
|
+ __u32 reserved[2];
|
|
+};
|
|
+
|
|
+struct lima_dump_chunk_buffer {
|
|
+ __u32 id;
|
|
+ __u32 size;
|
|
+ __u32 va;
|
|
+ __u32 reserved;
|
|
+};
|
|
+
|
|
+struct lima_dump_chunk_pid {
|
|
+ __u32 id;
|
|
+ __u32 size;
|
|
+ __u32 pid;
|
|
+ __u32 reserved;
|
|
+};
|
|
+
|
|
+#endif
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index 3886999b4533..86192422a689 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -4,6 +4,7 @@
|
|
#include <linux/kthread.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/xarray.h>
|
|
+#include <linux/vmalloc.h>
|
|
|
|
#include "lima_drv.h"
|
|
#include "lima_sched.h"
|
|
@@ -256,6 +257,133 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
return task->fence;
|
|
}
|
|
|
|
+static void lima_sched_build_error_task_list(struct lima_sched_task *task)
|
|
+{
|
|
+ struct lima_sched_error_task *et;
|
|
+ struct lima_sched_pipe *pipe = to_lima_pipe(task->base.sched);
|
|
+ struct lima_ip *ip = pipe->processor[0];
|
|
+ int pipe_id = ip->id == lima_ip_gp ? lima_pipe_gp : lima_pipe_pp;
|
|
+ struct lima_device *dev = ip->dev;
|
|
+ struct lima_sched_context *sched_ctx =
|
|
+ container_of(task->base.entity,
|
|
+ struct lima_sched_context, base);
|
|
+ struct lima_ctx *ctx =
|
|
+ container_of(sched_ctx, struct lima_ctx, context[pipe_id]);
|
|
+ struct lima_dump_task *dt;
|
|
+ struct lima_dump_chunk *chunk;
|
|
+ struct lima_dump_chunk_pid *pid_chunk;
|
|
+ struct lima_dump_chunk_buffer *buffer_chunk;
|
|
+ u32 size, task_size, mem_size;
|
|
+ int i;
|
|
+
|
|
+ mutex_lock(&dev->error_task_list_lock);
|
|
+
|
|
+ if (dev->dump.num_tasks >= lima_max_error_tasks) {
|
|
+ dev_info(dev->dev, "fail to save task state: error task list is full\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* frame chunk */
|
|
+ size = sizeof(struct lima_dump_chunk) + pipe->frame_size;
|
|
+ /* process name chunk */
|
|
+ size += sizeof(struct lima_dump_chunk) + sizeof(ctx->pname);
|
|
+ /* pid chunk */
|
|
+ size += sizeof(struct lima_dump_chunk);
|
|
+ /* buffer chunks */
|
|
+ for (i = 0; i < task->num_bos; i++) {
|
|
+ struct lima_bo *bo = task->bos[i];
|
|
+
|
|
+ size += sizeof(struct lima_dump_chunk);
|
|
+ size += bo->heap_size ? bo->heap_size : lima_bo_size(bo);
|
|
+ }
|
|
+
|
|
+ task_size = size + sizeof(struct lima_dump_task);
|
|
+ mem_size = task_size + sizeof(*et);
|
|
+ et = kvmalloc(mem_size, GFP_KERNEL);
|
|
+ if (!et) {
|
|
+ dev_err(dev->dev, "fail to alloc task dump buffer of size %x\n",
|
|
+ mem_size);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ et->data = et + 1;
|
|
+ et->size = task_size;
|
|
+
|
|
+ dt = et->data;
|
|
+ memset(dt, 0, sizeof(*dt));
|
|
+ dt->id = pipe_id;
|
|
+ dt->size = size;
|
|
+
|
|
+ chunk = (struct lima_dump_chunk *)(dt + 1);
|
|
+ memset(chunk, 0, sizeof(*chunk));
|
|
+ chunk->id = LIMA_DUMP_CHUNK_FRAME;
|
|
+ chunk->size = pipe->frame_size;
|
|
+ memcpy(chunk + 1, task->frame, pipe->frame_size);
|
|
+ dt->num_chunks++;
|
|
+
|
|
+ chunk = (void *)(chunk + 1) + chunk->size;
|
|
+ memset(chunk, 0, sizeof(*chunk));
|
|
+ chunk->id = LIMA_DUMP_CHUNK_PROCESS_NAME;
|
|
+ chunk->size = sizeof(ctx->pname);
|
|
+ memcpy(chunk + 1, ctx->pname, sizeof(ctx->pname));
|
|
+ dt->num_chunks++;
|
|
+
|
|
+ pid_chunk = (void *)(chunk + 1) + chunk->size;
|
|
+ memset(pid_chunk, 0, sizeof(*pid_chunk));
|
|
+ pid_chunk->id = LIMA_DUMP_CHUNK_PROCESS_ID;
|
|
+ pid_chunk->pid = ctx->pid;
|
|
+ dt->num_chunks++;
|
|
+
|
|
+ buffer_chunk = (void *)(pid_chunk + 1) + pid_chunk->size;
|
|
+ for (i = 0; i < task->num_bos; i++) {
|
|
+ struct lima_bo *bo = task->bos[i];
|
|
+ void *data;
|
|
+
|
|
+ memset(buffer_chunk, 0, sizeof(*buffer_chunk));
|
|
+ buffer_chunk->id = LIMA_DUMP_CHUNK_BUFFER;
|
|
+ buffer_chunk->va = lima_vm_get_va(task->vm, bo);
|
|
+
|
|
+ if (bo->heap_size) {
|
|
+ buffer_chunk->size = bo->heap_size;
|
|
+
|
|
+ data = vmap(bo->base.pages, bo->heap_size >> PAGE_SHIFT,
|
|
+ VM_MAP, pgprot_writecombine(PAGE_KERNEL));
|
|
+ if (!data) {
|
|
+ kvfree(et);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ memcpy(buffer_chunk + 1, data, buffer_chunk->size);
|
|
+
|
|
+ vunmap(data);
|
|
+ } else {
|
|
+ buffer_chunk->size = lima_bo_size(bo);
|
|
+
|
|
+ data = drm_gem_shmem_vmap(&bo->base.base);
|
|
+ if (IS_ERR_OR_NULL(data)) {
|
|
+ kvfree(et);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ memcpy(buffer_chunk + 1, data, buffer_chunk->size);
|
|
+
|
|
+ drm_gem_shmem_vunmap(&bo->base.base, data);
|
|
+ }
|
|
+
|
|
+ buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size;
|
|
+ dt->num_chunks++;
|
|
+ }
|
|
+
|
|
+ list_add(&et->list, &dev->error_task_list);
|
|
+ dev->dump.size += et->size;
|
|
+ dev->dump.num_tasks++;
|
|
+
|
|
+ dev_info(dev->dev, "save error task state success\n");
|
|
+
|
|
+out:
|
|
+ mutex_unlock(&dev->error_task_list_lock);
|
|
+}
|
|
+
|
|
static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
{
|
|
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
|
@@ -268,6 +396,8 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
|
|
drm_sched_increase_karma(&task->base);
|
|
|
|
+ lima_sched_build_error_task_list(task);
|
|
+
|
|
pipe->task_error(pipe);
|
|
|
|
if (pipe->bcast_mmu)
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h
|
|
index d64393fb50a9..a1496cb7bc41 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.h
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.h
|
|
@@ -5,9 +5,16 @@
|
|
#define __LIMA_SCHED_H__
|
|
|
|
#include <drm/gpu_scheduler.h>
|
|
+#include <linux/list.h>
|
|
|
|
struct lima_vm;
|
|
|
|
+struct lima_sched_error_task {
|
|
+ struct list_head list;
|
|
+ void *data;
|
|
+ u32 size;
|
|
+};
|
|
+
|
|
struct lima_sched_task {
|
|
struct drm_sched_job base;
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 3b95414439abca4e9129238481a36ee9025a8889 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Sat, 22 Feb 2020 10:42:09 +0800
|
|
Subject: [PATCH] drm/lima: add error sysfs to export error task dump
|
|
|
|
Export /sys/class/drm/cardX/device/error sysfs for user read out
|
|
error task dump file.
|
|
|
|
Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 94 +++++++++++++++++++++++++++++++++
|
|
1 file changed, 94 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index e235d4545b6c..97ed70c36340 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -276,6 +276,93 @@ static struct drm_driver lima_drm_driver = {
|
|
.gem_prime_mmap = drm_gem_prime_mmap,
|
|
};
|
|
|
|
+struct lima_block_reader {
|
|
+ void *dst;
|
|
+ size_t base;
|
|
+ size_t count;
|
|
+ size_t off;
|
|
+ ssize_t read;
|
|
+};
|
|
+
|
|
+static bool lima_read_block(struct lima_block_reader *reader,
|
|
+ void *src, size_t src_size)
|
|
+{
|
|
+ size_t max_off = reader->base + src_size;
|
|
+
|
|
+ if (reader->off < max_off) {
|
|
+ size_t size = min_t(size_t, max_off - reader->off,
|
|
+ reader->count);
|
|
+
|
|
+ memcpy(reader->dst, src + (reader->off - reader->base), size);
|
|
+
|
|
+ reader->dst += size;
|
|
+ reader->off += size;
|
|
+ reader->read += size;
|
|
+ reader->count -= size;
|
|
+ }
|
|
+
|
|
+ reader->base = max_off;
|
|
+
|
|
+ return !!reader->count;
|
|
+}
|
|
+
|
|
+static ssize_t lima_error_state_read(struct file *filp, struct kobject *kobj,
|
|
+ struct bin_attribute *attr, char *buf,
|
|
+ loff_t off, size_t count)
|
|
+{
|
|
+ struct device *dev = kobj_to_dev(kobj);
|
|
+ struct lima_device *ldev = dev_get_drvdata(dev);
|
|
+ struct lima_sched_error_task *et;
|
|
+ struct lima_block_reader reader = {
|
|
+ .dst = buf,
|
|
+ .count = count,
|
|
+ .off = off,
|
|
+ };
|
|
+
|
|
+ mutex_lock(&ldev->error_task_list_lock);
|
|
+
|
|
+ if (lima_read_block(&reader, &ldev->dump, sizeof(ldev->dump))) {
|
|
+ list_for_each_entry(et, &ldev->error_task_list, list) {
|
|
+ if (!lima_read_block(&reader, et->data, et->size))
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ldev->error_task_list_lock);
|
|
+ return reader.read;
|
|
+}
|
|
+
|
|
+static ssize_t lima_error_state_write(struct file *file, struct kobject *kobj,
|
|
+ struct bin_attribute *attr, char *buf,
|
|
+ loff_t off, size_t count)
|
|
+{
|
|
+ struct device *dev = kobj_to_dev(kobj);
|
|
+ struct lima_device *ldev = dev_get_drvdata(dev);
|
|
+ struct lima_sched_error_task *et, *tmp;
|
|
+
|
|
+ mutex_lock(&ldev->error_task_list_lock);
|
|
+
|
|
+ list_for_each_entry_safe(et, tmp, &ldev->error_task_list, list) {
|
|
+ list_del(&et->list);
|
|
+ kvfree(et);
|
|
+ }
|
|
+
|
|
+ ldev->dump.size = 0;
|
|
+ ldev->dump.num_tasks = 0;
|
|
+
|
|
+ mutex_unlock(&ldev->error_task_list_lock);
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct bin_attribute lima_error_state_attr = {
|
|
+ .attr.name = "error",
|
|
+ .attr.mode = 0600,
|
|
+ .size = 0,
|
|
+ .read = lima_error_state_read,
|
|
+ .write = lima_error_state_write,
|
|
+};
|
|
+
|
|
static int lima_pdev_probe(struct platform_device *pdev)
|
|
{
|
|
struct lima_device *ldev;
|
|
@@ -318,6 +405,11 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
if (err < 0)
|
|
goto err_out2;
|
|
|
|
+ platform_set_drvdata(pdev, ldev);
|
|
+
|
|
+ if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
|
|
+ dev_warn(ldev->dev, "fail to create error state sysfs\n");
|
|
+
|
|
return 0;
|
|
|
|
err_out2:
|
|
@@ -334,6 +426,8 @@ static int lima_pdev_remove(struct platform_device *pdev)
|
|
struct lima_device *ldev = platform_get_drvdata(pdev);
|
|
struct drm_device *ddev = ldev->ddev;
|
|
|
|
+ sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
|
|
+ platform_set_drvdata(pdev, NULL);
|
|
drm_dev_unregister(ddev);
|
|
lima_device_fini(ldev);
|
|
drm_dev_put(ddev);
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From e58efe898da54ddc1148539961ef3aeefe19fc80 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Sat, 7 Mar 2020 21:54:38 +0800
|
|
Subject: [PATCH] drm/lima: add trace point for tasks
|
|
|
|
track lima task start which can be combined with
|
|
dma_fence_signal to identify task execution time.
|
|
|
|
example command to record:
|
|
|
|
trace-cmd record -i \
|
|
-e "lima:lima_task_submit" -e "lima:lima_task_run" \
|
|
-e "*fence:*fence_signaled" -e "drm:drm_vblank_event" \
|
|
-e "drm:drm_vblank_event_queued" sleep 4
|
|
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/Makefile | 3 +-
|
|
drivers/gpu/drm/lima/lima_sched.c | 5 +++-
|
|
drivers/gpu/drm/lima/lima_sched.h | 1 +
|
|
drivers/gpu/drm/lima/lima_trace.c | 7 +++++
|
|
drivers/gpu/drm/lima/lima_trace.h | 50 +++++++++++++++++++++++++++++++
|
|
5 files changed, 64 insertions(+), 2 deletions(-)
|
|
create mode 100644 drivers/gpu/drm/lima/lima_trace.c
|
|
create mode 100644 drivers/gpu/drm/lima/lima_trace.h
|
|
|
|
diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile
|
|
index a85444b0a1d4..6e7b788408e8 100644
|
|
--- a/drivers/gpu/drm/lima/Makefile
|
|
+++ b/drivers/gpu/drm/lima/Makefile
|
|
@@ -14,6 +14,7 @@ lima-y := \
|
|
lima_sched.o \
|
|
lima_ctx.o \
|
|
lima_dlbu.o \
|
|
- lima_bcast.o
|
|
+ lima_bcast.o \
|
|
+ lima_trace.o
|
|
|
|
obj-$(CONFIG_DRM_LIMA) += lima.o
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index 86192422a689..4fbf2c489507 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -3,7 +3,6 @@
|
|
|
|
#include <linux/kthread.h>
|
|
#include <linux/slab.h>
|
|
-#include <linux/xarray.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include "lima_drv.h"
|
|
@@ -12,6 +11,7 @@
|
|
#include "lima_mmu.h"
|
|
#include "lima_l2_cache.h"
|
|
#include "lima_gem.h"
|
|
+#include "lima_trace.h"
|
|
|
|
struct lima_fence {
|
|
struct dma_fence base;
|
|
@@ -177,6 +177,7 @@ struct dma_fence *lima_sched_context_queue_task(struct lima_sched_context *conte
|
|
{
|
|
struct dma_fence *fence = dma_fence_get(&task->base.s_fence->finished);
|
|
|
|
+ trace_lima_task_submit(task);
|
|
drm_sched_entity_push_job(&task->base, &context->base);
|
|
return fence;
|
|
}
|
|
@@ -251,6 +252,8 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
if (last_vm)
|
|
lima_vm_put(last_vm);
|
|
|
|
+ trace_lima_task_run(task);
|
|
+
|
|
pipe->error = false;
|
|
pipe->task_run(pipe, task);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h
|
|
index a1496cb7bc41..02dfa14d7083 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.h
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.h
|
|
@@ -6,6 +6,7 @@
|
|
|
|
#include <drm/gpu_scheduler.h>
|
|
#include <linux/list.h>
|
|
+#include <linux/xarray.h>
|
|
|
|
struct lima_vm;
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_trace.c b/drivers/gpu/drm/lima/lima_trace.c
|
|
new file mode 100644
|
|
index 000000000000..ea1c7289bebc
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/lima/lima_trace.c
|
|
@@ -0,0 +1,7 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR MIT
|
|
+/* Copyright 2020 Qiang Yu <yuq825@gmail.com> */
|
|
+
|
|
+#include "lima_sched.h"
|
|
+
|
|
+#define CREATE_TRACE_POINTS
|
|
+#include "lima_trace.h"
|
|
diff --git a/drivers/gpu/drm/lima/lima_trace.h b/drivers/gpu/drm/lima/lima_trace.h
|
|
new file mode 100644
|
|
index 000000000000..3a430e93d384
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/lima/lima_trace.h
|
|
@@ -0,0 +1,50 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
|
+/* Copyright 2020 Qiang Yu <yuq825@gmail.com> */
|
|
+
|
|
+#if !defined(_LIMA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
+#define _LIMA_TRACE_H_
|
|
+
|
|
+#include <linux/tracepoint.h>
|
|
+
|
|
+#undef TRACE_SYSTEM
|
|
+#define TRACE_SYSTEM lima
|
|
+#define TRACE_INCLUDE_FILE lima_trace
|
|
+
|
|
+DECLARE_EVENT_CLASS(lima_task,
|
|
+ TP_PROTO(struct lima_sched_task *task),
|
|
+ TP_ARGS(task),
|
|
+ TP_STRUCT__entry(
|
|
+ __field(uint64_t, task_id)
|
|
+ __field(unsigned int, context)
|
|
+ __field(unsigned int, seqno)
|
|
+ __string(pipe, task->base.sched->name)
|
|
+ ),
|
|
+
|
|
+ TP_fast_assign(
|
|
+ __entry->task_id = task->base.id;
|
|
+ __entry->context = task->base.s_fence->finished.context;
|
|
+ __entry->seqno = task->base.s_fence->finished.seqno;
|
|
+ __assign_str(pipe, task->base.sched->name)
|
|
+ ),
|
|
+
|
|
+ TP_printk("task=%llu, context=%u seqno=%u pipe=%s",
|
|
+ __entry->task_id, __entry->context, __entry->seqno,
|
|
+ __get_str(pipe))
|
|
+);
|
|
+
|
|
+DEFINE_EVENT(lima_task, lima_task_submit,
|
|
+ TP_PROTO(struct lima_sched_task *task),
|
|
+ TP_ARGS(task)
|
|
+);
|
|
+
|
|
+DEFINE_EVENT(lima_task, lima_task_run,
|
|
+ TP_PROTO(struct lima_sched_task *task),
|
|
+ TP_ARGS(task)
|
|
+);
|
|
+
|
|
+#endif
|
|
+
|
|
+/* This part must be outside protection */
|
|
+#undef TRACE_INCLUDE_PATH
|
|
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/lima
|
|
+#include <trace/define_trace.h>
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From f567d140f87225a04ba6c6035b4a0b79e816f9a9 Mon Sep 17 00:00:00 2001
|
|
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
Date: Thu, 19 Mar 2020 21:34:27 +0100
|
|
Subject: [PATCH] drm/lima: Add optional devfreq and cooling device support
|
|
|
|
Most platforms with a Mali-400 or Mali-450 GPU also have support for
|
|
changing the GPU clock frequency. Add devfreq support so the GPU clock
|
|
rate is updated based on the actual GPU usage when the
|
|
"operating-points-v2" property is present in the board.dts.
|
|
|
|
The actual devfreq code is taken from panfrost_devfreq.c and modified so
|
|
it matches what the lima hardware needs:
|
|
- a call to dev_pm_opp_set_clkname() during initialization because there
|
|
are two clocks on Mali-4x0 IPs. "core" is the one that actually clocks
|
|
the GPU so we need to control it using devfreq.
|
|
- locking when reading or writing the devfreq statistics because (unlike
|
|
than panfrost) we have multiple PP and GP IRQs which may finish jobs
|
|
concurrently.
|
|
|
|
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/Kconfig | 2 +
|
|
drivers/gpu/drm/lima/Makefile | 3 +-
|
|
drivers/gpu/drm/lima/lima_devfreq.c | 234 ++++++++++++++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_devfreq.h | 41 +++++
|
|
drivers/gpu/drm/lima/lima_device.c | 4 +
|
|
drivers/gpu/drm/lima/lima_device.h | 3 +
|
|
drivers/gpu/drm/lima/lima_drv.c | 14 +-
|
|
drivers/gpu/drm/lima/lima_sched.c | 7 +
|
|
drivers/gpu/drm/lima/lima_sched.h | 3 +
|
|
9 files changed, 308 insertions(+), 3 deletions(-)
|
|
create mode 100644 drivers/gpu/drm/lima/lima_devfreq.c
|
|
create mode 100644 drivers/gpu/drm/lima/lima_devfreq.h
|
|
|
|
diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig
|
|
index d589f09d04d9..fa1d4f5df31e 100644
|
|
--- a/drivers/gpu/drm/lima/Kconfig
|
|
+++ b/drivers/gpu/drm/lima/Kconfig
|
|
@@ -10,5 +10,7 @@ config DRM_LIMA
|
|
depends on OF
|
|
select DRM_SCHED
|
|
select DRM_GEM_SHMEM_HELPER
|
|
+ select PM_DEVFREQ
|
|
+ select DEVFREQ_GOV_SIMPLE_ONDEMAND
|
|
help
|
|
DRM driver for ARM Mali 400/450 GPUs.
|
|
diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile
|
|
index 6e7b788408e8..ca2097b8e1ad 100644
|
|
--- a/drivers/gpu/drm/lima/Makefile
|
|
+++ b/drivers/gpu/drm/lima/Makefile
|
|
@@ -15,6 +15,7 @@ lima-y := \
|
|
lima_ctx.o \
|
|
lima_dlbu.o \
|
|
lima_bcast.o \
|
|
- lima_trace.o
|
|
+ lima_trace.o \
|
|
+ lima_devfreq.o
|
|
|
|
obj-$(CONFIG_DRM_LIMA) += lima.o
|
|
diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
new file mode 100644
|
|
index 000000000000..8c4d21d07529
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
@@ -0,0 +1,234 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * Copyright 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
+ *
|
|
+ * Based on panfrost_devfreq.c:
|
|
+ * Copyright 2019 Collabora ltd.
|
|
+ */
|
|
+#include <linux/clk.h>
|
|
+#include <linux/devfreq.h>
|
|
+#include <linux/devfreq_cooling.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/pm_opp.h>
|
|
+#include <linux/property.h>
|
|
+
|
|
+#include "lima_device.h"
|
|
+#include "lima_devfreq.h"
|
|
+
|
|
+static void lima_devfreq_update_utilization(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ ktime_t now, last;
|
|
+
|
|
+ now = ktime_get();
|
|
+ last = devfreq->time_last_update;
|
|
+
|
|
+ if (devfreq->busy_count > 0)
|
|
+ devfreq->busy_time += ktime_sub(now, last);
|
|
+ else
|
|
+ devfreq->idle_time += ktime_sub(now, last);
|
|
+
|
|
+ devfreq->time_last_update = now;
|
|
+}
|
|
+
|
|
+static int lima_devfreq_target(struct device *dev, unsigned long *freq,
|
|
+ u32 flags)
|
|
+{
|
|
+ struct dev_pm_opp *opp;
|
|
+ int err;
|
|
+
|
|
+ opp = devfreq_recommended_opp(dev, freq, flags);
|
|
+ if (IS_ERR(opp))
|
|
+ return PTR_ERR(opp);
|
|
+ dev_pm_opp_put(opp);
|
|
+
|
|
+ err = dev_pm_opp_set_rate(dev, *freq);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void lima_devfreq_reset(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ devfreq->busy_time = 0;
|
|
+ devfreq->idle_time = 0;
|
|
+ devfreq->time_last_update = ktime_get();
|
|
+}
|
|
+
|
|
+static int lima_devfreq_get_dev_status(struct device *dev,
|
|
+ struct devfreq_dev_status *status)
|
|
+{
|
|
+ struct lima_device *ldev = dev_get_drvdata(dev);
|
|
+ struct lima_devfreq *devfreq = &ldev->devfreq;
|
|
+ unsigned long irqflags;
|
|
+
|
|
+ status->current_frequency = clk_get_rate(ldev->clk_gpu);
|
|
+
|
|
+ spin_lock_irqsave(&devfreq->lock, irqflags);
|
|
+
|
|
+ lima_devfreq_update_utilization(devfreq);
|
|
+
|
|
+ status->total_time = ktime_to_ns(ktime_add(devfreq->busy_time,
|
|
+ devfreq->idle_time));
|
|
+ status->busy_time = ktime_to_ns(devfreq->busy_time);
|
|
+
|
|
+ lima_devfreq_reset(devfreq);
|
|
+
|
|
+ spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
|
+
|
|
+ dev_dbg(ldev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n",
|
|
+ status->busy_time, status->total_time,
|
|
+ status->busy_time / (status->total_time / 100),
|
|
+ status->current_frequency / 1000 / 1000);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct devfreq_dev_profile lima_devfreq_profile = {
|
|
+ .polling_ms = 50, /* ~3 frames */
|
|
+ .target = lima_devfreq_target,
|
|
+ .get_dev_status = lima_devfreq_get_dev_status,
|
|
+};
|
|
+
|
|
+void lima_devfreq_fini(struct lima_device *ldev)
|
|
+{
|
|
+ struct lima_devfreq *devfreq = &ldev->devfreq;
|
|
+
|
|
+ if (devfreq->cooling) {
|
|
+ devfreq_cooling_unregister(devfreq->cooling);
|
|
+ devfreq->cooling = NULL;
|
|
+ }
|
|
+
|
|
+ if (devfreq->devfreq) {
|
|
+ devm_devfreq_remove_device(&ldev->pdev->dev,
|
|
+ devfreq->devfreq);
|
|
+ devfreq->devfreq = NULL;
|
|
+ }
|
|
+
|
|
+ if (devfreq->opp_of_table_added) {
|
|
+ dev_pm_opp_of_remove_table(&ldev->pdev->dev);
|
|
+ devfreq->opp_of_table_added = false;
|
|
+ }
|
|
+
|
|
+ if (devfreq->regulators_opp_table) {
|
|
+ dev_pm_opp_put_regulators(devfreq->regulators_opp_table);
|
|
+ devfreq->regulators_opp_table = NULL;
|
|
+ }
|
|
+
|
|
+ if (devfreq->clkname_opp_table) {
|
|
+ dev_pm_opp_put_clkname(devfreq->clkname_opp_table);
|
|
+ devfreq->clkname_opp_table = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+int lima_devfreq_init(struct lima_device *ldev)
|
|
+{
|
|
+ struct thermal_cooling_device *cooling;
|
|
+ struct device *dev = &ldev->pdev->dev;
|
|
+ struct opp_table *opp_table;
|
|
+ struct devfreq *devfreq;
|
|
+ struct lima_devfreq *ldevfreq = &ldev->devfreq;
|
|
+ struct dev_pm_opp *opp;
|
|
+ unsigned long cur_freq;
|
|
+ int ret;
|
|
+
|
|
+ if (!device_property_present(dev, "operating-points-v2"))
|
|
+ /* Optional, continue without devfreq */
|
|
+ return 0;
|
|
+
|
|
+ spin_lock_init(&ldevfreq->lock);
|
|
+
|
|
+ opp_table = dev_pm_opp_set_clkname(dev, "core");
|
|
+ if (IS_ERR(opp_table)) {
|
|
+ ret = PTR_ERR(opp_table);
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ ldevfreq->clkname_opp_table = opp_table;
|
|
+
|
|
+ opp_table = dev_pm_opp_set_regulators(dev,
|
|
+ (const char *[]){ "mali" },
|
|
+ 1);
|
|
+ if (IS_ERR(opp_table)) {
|
|
+ ret = PTR_ERR(opp_table);
|
|
+
|
|
+ /* Continue if the optional regulator is missing */
|
|
+ if (ret != -ENODEV)
|
|
+ goto err_fini;
|
|
+ } else {
|
|
+ ldevfreq->regulators_opp_table = opp_table;
|
|
+ }
|
|
+
|
|
+ ret = dev_pm_opp_of_add_table(dev);
|
|
+ if (ret)
|
|
+ goto err_fini;
|
|
+ ldevfreq->opp_of_table_added = true;
|
|
+
|
|
+ lima_devfreq_reset(ldevfreq);
|
|
+
|
|
+ cur_freq = clk_get_rate(ldev->clk_gpu);
|
|
+
|
|
+ opp = devfreq_recommended_opp(dev, &cur_freq, 0);
|
|
+ if (IS_ERR(opp)) {
|
|
+ ret = PTR_ERR(opp);
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ lima_devfreq_profile.initial_freq = cur_freq;
|
|
+ dev_pm_opp_put(opp);
|
|
+
|
|
+ devfreq = devm_devfreq_add_device(dev, &lima_devfreq_profile,
|
|
+ DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
|
|
+ if (IS_ERR(devfreq)) {
|
|
+ dev_err(dev, "Couldn't initialize GPU devfreq\n");
|
|
+ ret = PTR_ERR(devfreq);
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ ldevfreq->devfreq = devfreq;
|
|
+
|
|
+ cooling = of_devfreq_cooling_register(dev->of_node, devfreq);
|
|
+ if (IS_ERR(cooling))
|
|
+ dev_info(dev, "Failed to register cooling device\n");
|
|
+ else
|
|
+ ldevfreq->cooling = cooling;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_fini:
|
|
+ lima_devfreq_fini(ldev);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void lima_devfreq_record_busy(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ unsigned long irqflags;
|
|
+
|
|
+ if (!devfreq->devfreq)
|
|
+ return;
|
|
+
|
|
+ spin_lock_irqsave(&devfreq->lock, irqflags);
|
|
+
|
|
+ lima_devfreq_update_utilization(devfreq);
|
|
+
|
|
+ devfreq->busy_count++;
|
|
+
|
|
+ spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
|
+}
|
|
+
|
|
+void lima_devfreq_record_idle(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ unsigned long irqflags;
|
|
+
|
|
+ if (!devfreq->devfreq)
|
|
+ return;
|
|
+
|
|
+ spin_lock_irqsave(&devfreq->lock, irqflags);
|
|
+
|
|
+ lima_devfreq_update_utilization(devfreq);
|
|
+
|
|
+ WARN_ON(--devfreq->busy_count < 0);
|
|
+
|
|
+ spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
|
+}
|
|
diff --git a/drivers/gpu/drm/lima/lima_devfreq.h b/drivers/gpu/drm/lima/lima_devfreq.h
|
|
new file mode 100644
|
|
index 000000000000..8d71ba9fb22a
|
|
--- /dev/null
|
|
+++ b/drivers/gpu/drm/lima/lima_devfreq.h
|
|
@@ -0,0 +1,41 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+/* Copyright 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com> */
|
|
+
|
|
+#ifndef __LIMA_DEVFREQ_H__
|
|
+#define __LIMA_DEVFREQ_H__
|
|
+
|
|
+#include <linux/spinlock.h>
|
|
+#include <linux/ktime.h>
|
|
+
|
|
+struct devfreq;
|
|
+struct opp_table;
|
|
+struct thermal_cooling_device;
|
|
+
|
|
+struct lima_device;
|
|
+
|
|
+struct lima_devfreq {
|
|
+ struct devfreq *devfreq;
|
|
+ struct opp_table *clkname_opp_table;
|
|
+ struct opp_table *regulators_opp_table;
|
|
+ struct thermal_cooling_device *cooling;
|
|
+ bool opp_of_table_added;
|
|
+
|
|
+ ktime_t busy_time;
|
|
+ ktime_t idle_time;
|
|
+ ktime_t time_last_update;
|
|
+ int busy_count;
|
|
+ /*
|
|
+ * Protect busy_time, idle_time, time_last_update and busy_count
|
|
+ * because these can be updated concurrently, for example by the GP
|
|
+ * and PP interrupts.
|
|
+ */
|
|
+ spinlock_t lock;
|
|
+};
|
|
+
|
|
+int lima_devfreq_init(struct lima_device *ldev);
|
|
+void lima_devfreq_fini(struct lima_device *ldev);
|
|
+
|
|
+void lima_devfreq_record_busy(struct lima_devfreq *devfreq);
|
|
+void lima_devfreq_record_idle(struct lima_devfreq *devfreq);
|
|
+
|
|
+#endif
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index 42a00171fea5..247f51fd40a2 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -214,6 +214,8 @@ static int lima_init_gp_pipe(struct lima_device *dev)
|
|
struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
|
|
int err;
|
|
|
|
+ pipe->ldev = dev;
|
|
+
|
|
err = lima_sched_pipe_init(pipe, "gp");
|
|
if (err)
|
|
return err;
|
|
@@ -244,6 +246,8 @@ static int lima_init_pp_pipe(struct lima_device *dev)
|
|
struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
|
|
int err, i;
|
|
|
|
+ pipe->ldev = dev;
|
|
+
|
|
err = lima_sched_pipe_init(pipe, "pp");
|
|
if (err)
|
|
return err;
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index f17173f47f26..06fd9636dd72 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -11,6 +11,7 @@
|
|
|
|
#include "lima_sched.h"
|
|
#include "lima_dump.h"
|
|
+#include "lima_devfreq.h"
|
|
|
|
enum lima_gpu_id {
|
|
lima_gpu_mali400 = 0,
|
|
@@ -98,6 +99,8 @@ struct lima_device {
|
|
u32 *dlbu_cpu;
|
|
dma_addr_t dlbu_dma;
|
|
|
|
+ struct lima_devfreq devfreq;
|
|
+
|
|
/* debug info */
|
|
struct lima_dump_head dump;
|
|
struct list_head error_task_list;
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 97ed70c36340..bbbdc8455e2f 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <drm/drm_prime.h>
|
|
#include <drm/lima_drm.h>
|
|
|
|
+#include "lima_device.h"
|
|
#include "lima_drv.h"
|
|
#include "lima_gem.h"
|
|
#include "lima_vm.h"
|
|
@@ -397,13 +398,19 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
if (err)
|
|
goto err_out1;
|
|
|
|
+ err = lima_devfreq_init(ldev);
|
|
+ if (err) {
|
|
+ dev_err(&pdev->dev, "Fatal error during devfreq init\n");
|
|
+ goto err_out2;
|
|
+ }
|
|
+
|
|
/*
|
|
* Register the DRM device with the core and the connectors with
|
|
* sysfs.
|
|
*/
|
|
err = drm_dev_register(ddev, 0);
|
|
if (err < 0)
|
|
- goto err_out2;
|
|
+ goto err_out3;
|
|
|
|
platform_set_drvdata(pdev, ldev);
|
|
|
|
@@ -412,8 +419,10 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
|
|
return 0;
|
|
|
|
-err_out2:
|
|
+err_out3:
|
|
lima_device_fini(ldev);
|
|
+err_out2:
|
|
+ lima_devfreq_fini(ldev);
|
|
err_out1:
|
|
drm_dev_put(ddev);
|
|
err_out0:
|
|
@@ -429,6 +438,7 @@ static int lima_pdev_remove(struct platform_device *pdev)
|
|
sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
|
|
platform_set_drvdata(pdev, NULL);
|
|
drm_dev_unregister(ddev);
|
|
+ lima_devfreq_fini(ldev);
|
|
lima_device_fini(ldev);
|
|
drm_dev_put(ddev);
|
|
lima_sched_slab_fini();
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index 4fbf2c489507..a2db1c937424 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -5,6 +5,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
+#include "lima_devfreq.h"
|
|
#include "lima_drv.h"
|
|
#include "lima_sched.h"
|
|
#include "lima_vm.h"
|
|
@@ -216,6 +217,8 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
*/
|
|
ret = dma_fence_get(task->fence);
|
|
|
|
+ lima_devfreq_record_busy(&pipe->ldev->devfreq);
|
|
+
|
|
pipe->current_task = task;
|
|
|
|
/* this is needed for MMU to work correctly, otherwise GP/PP
|
|
@@ -418,6 +421,8 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
pipe->current_vm = NULL;
|
|
pipe->current_task = NULL;
|
|
|
|
+ lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
|
+
|
|
drm_sched_resubmit_jobs(&pipe->base);
|
|
drm_sched_start(&pipe->base, true);
|
|
}
|
|
@@ -497,5 +502,7 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
|
} else {
|
|
pipe->task_fini(pipe);
|
|
dma_fence_signal(task->fence);
|
|
+
|
|
+ lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
|
}
|
|
}
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h
|
|
index 02dfa14d7083..90f03c48ef4a 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.h
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.h
|
|
@@ -8,6 +8,7 @@
|
|
#include <linux/list.h>
|
|
#include <linux/xarray.h>
|
|
|
|
+struct lima_device;
|
|
struct lima_vm;
|
|
|
|
struct lima_sched_error_task {
|
|
@@ -52,6 +53,8 @@ struct lima_sched_pipe {
|
|
u32 fence_seqno;
|
|
spinlock_t fence_lock;
|
|
|
|
+ struct lima_device *ldev;
|
|
+
|
|
struct lima_sched_task *current_task;
|
|
struct lima_vm *current_vm;
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 60e8ac9f8b772f5f3cbab5e361531d625444a320 Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Tue, 21 Apr 2020 23:51:36 +0100
|
|
Subject: [PATCH] drm/lima: Clean up IRQ warnings
|
|
|
|
Use the optional form of platform_get_irq() for blocks that legitimately
|
|
may not be present, to avoid getting an annoying barrage of spurious
|
|
warnings for non-existent PPs on configurations like Mali-450 MP2.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_device.c | 7 +++++--
|
|
1 file changed, 5 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index 247f51fd40a2..c334d297796a 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -171,8 +171,10 @@ static void lima_regulator_fini(struct lima_device *dev)
|
|
|
|
static int lima_init_ip(struct lima_device *dev, int index)
|
|
{
|
|
+ struct platform_device *pdev = to_platform_device(dev->dev);
|
|
struct lima_ip_desc *desc = lima_ip_desc + index;
|
|
struct lima_ip *ip = dev->ip + index;
|
|
+ const char *irq_name = desc->irq_name;
|
|
int offset = desc->offset[dev->id];
|
|
bool must = desc->must_have[dev->id];
|
|
int err;
|
|
@@ -183,8 +185,9 @@ static int lima_init_ip(struct lima_device *dev, int index)
|
|
ip->dev = dev;
|
|
ip->id = index;
|
|
ip->iomem = dev->iomem + offset;
|
|
- if (desc->irq_name) {
|
|
- err = platform_get_irq_byname(dev->pdev, desc->irq_name);
|
|
+ if (irq_name) {
|
|
+ err = must ? platform_get_irq_byname(pdev, irq_name) :
|
|
+ platform_get_irq_byname_optional(pdev, irq_name);
|
|
if (err < 0)
|
|
goto out;
|
|
ip->irq = err;
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 8bb48350b7a927e98b59299ba82c4231fef9816c Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Tue, 21 Apr 2020 23:51:37 +0100
|
|
Subject: [PATCH] drm/lima: Clean up redundant pdev pointer
|
|
|
|
There's no point explicitly tracking the platform device when it can be
|
|
trivially derived from the regular device pointer in the couple of
|
|
places it's ever used.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_devfreq.c | 7 +++----
|
|
drivers/gpu/drm/lima/lima_device.c | 5 ++---
|
|
drivers/gpu/drm/lima/lima_device.h | 1 -
|
|
drivers/gpu/drm/lima/lima_drv.c | 1 -
|
|
4 files changed, 5 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
index 8c4d21d07529..1d479b5924fe 100644
|
|
--- a/drivers/gpu/drm/lima/lima_devfreq.c
|
|
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
@@ -101,13 +101,12 @@ void lima_devfreq_fini(struct lima_device *ldev)
|
|
}
|
|
|
|
if (devfreq->devfreq) {
|
|
- devm_devfreq_remove_device(&ldev->pdev->dev,
|
|
- devfreq->devfreq);
|
|
+ devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
|
|
devfreq->devfreq = NULL;
|
|
}
|
|
|
|
if (devfreq->opp_of_table_added) {
|
|
- dev_pm_opp_of_remove_table(&ldev->pdev->dev);
|
|
+ dev_pm_opp_of_remove_table(ldev->dev);
|
|
devfreq->opp_of_table_added = false;
|
|
}
|
|
|
|
@@ -125,7 +124,7 @@ void lima_devfreq_fini(struct lima_device *ldev)
|
|
int lima_devfreq_init(struct lima_device *ldev)
|
|
{
|
|
struct thermal_cooling_device *cooling;
|
|
- struct device *dev = &ldev->pdev->dev;
|
|
+ struct device *dev = ldev->dev;
|
|
struct opp_table *opp_table;
|
|
struct devfreq *devfreq;
|
|
struct lima_devfreq *ldevfreq = &ldev->devfreq;
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index c334d297796a..29285dedd124 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -297,8 +297,8 @@ static void lima_fini_pp_pipe(struct lima_device *dev)
|
|
|
|
int lima_device_init(struct lima_device *ldev)
|
|
{
|
|
+ struct platform_device *pdev = to_platform_device(ldev->dev);
|
|
int err, i;
|
|
- struct resource *res;
|
|
|
|
dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32));
|
|
|
|
@@ -329,8 +329,7 @@ int lima_device_init(struct lima_device *ldev)
|
|
} else
|
|
ldev->va_end = LIMA_VA_RESERVE_END;
|
|
|
|
- res = platform_get_resource(ldev->pdev, IORESOURCE_MEM, 0);
|
|
- ldev->iomem = devm_ioremap_resource(ldev->dev, res);
|
|
+ ldev->iomem = devm_platform_ioremap_resource(pdev, 0);
|
|
if (IS_ERR(ldev->iomem)) {
|
|
dev_err(ldev->dev, "fail to ioremap iomem\n");
|
|
err = PTR_ERR(ldev->iomem);
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index 06fd9636dd72..99b1fb147dad 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -76,7 +76,6 @@ enum lima_pipe_id {
|
|
struct lima_device {
|
|
struct device *dev;
|
|
struct drm_device *ddev;
|
|
- struct platform_device *pdev;
|
|
|
|
enum lima_gpu_id id;
|
|
u32 gp_version;
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index bbbdc8455e2f..4e5dd75822c0 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -380,7 +380,6 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
goto err_out0;
|
|
}
|
|
|
|
- ldev->pdev = pdev;
|
|
ldev->dev = &pdev->dev;
|
|
ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev);
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 82f5f9c4e3bca70b8c6c745be7a0c794d0fded53 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:42 +0800
|
|
Subject: [PATCH] drm/lima: use module_platform_driver helper
|
|
|
|
Simplify module init/exit with module_platform_driver.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 12 +-----------
|
|
1 file changed, 1 insertion(+), 11 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 4e5dd75822c0..3d63d496cfc2 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -460,17 +460,7 @@ static struct platform_driver lima_platform_driver = {
|
|
},
|
|
};
|
|
|
|
-static int __init lima_init(void)
|
|
-{
|
|
- return platform_driver_register(&lima_platform_driver);
|
|
-}
|
|
-module_init(lima_init);
|
|
-
|
|
-static void __exit lima_exit(void)
|
|
-{
|
|
- platform_driver_unregister(&lima_platform_driver);
|
|
-}
|
|
-module_exit(lima_exit);
|
|
+module_platform_driver(lima_platform_driver);
|
|
|
|
MODULE_AUTHOR("Lima Project Developers");
|
|
MODULE_DESCRIPTION("Lima DRM Driver");
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 2cb93a9b51b7c7105fc6baa0799c9474693c15a6 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:43 +0800
|
|
Subject: [PATCH] drm/lima: print process name and pid when task error
|
|
|
|
When error task list is full, print the process info where
|
|
the error task come from for debug usage.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_sched.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index a2db1c937424..387f9439450a 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -285,7 +285,8 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task)
|
|
mutex_lock(&dev->error_task_list_lock);
|
|
|
|
if (dev->dump.num_tasks >= lima_max_error_tasks) {
|
|
- dev_info(dev->dev, "fail to save task state: error task list is full\n");
|
|
+ dev_info(dev->dev, "fail to save task state from %s pid %d: "
|
|
+ "error task list is full\n", ctx->pname, ctx->pid);
|
|
goto out;
|
|
}
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 392cc15d77ef4f3dacff6b991690882051b683ad Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:44 +0800
|
|
Subject: [PATCH] drm/lima: check vm != NULL in lima_vm_put
|
|
|
|
No need to handle this check before calling lima_vm_put.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_sched.c | 7 ++-----
|
|
drivers/gpu/drm/lima/lima_vm.h | 3 ++-
|
|
2 files changed, 4 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index 387f9439450a..3ac5797e31fc 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -252,8 +252,7 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
lima_mmu_switch_vm(pipe->mmu[i], vm);
|
|
}
|
|
|
|
- if (last_vm)
|
|
- lima_vm_put(last_vm);
|
|
+ lima_vm_put(last_vm);
|
|
|
|
trace_lima_task_run(task);
|
|
|
|
@@ -416,9 +415,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
lima_mmu_page_fault_resume(pipe->mmu[i]);
|
|
}
|
|
|
|
- if (pipe->current_vm)
|
|
- lima_vm_put(pipe->current_vm);
|
|
-
|
|
+ lima_vm_put(pipe->current_vm);
|
|
pipe->current_vm = NULL;
|
|
pipe->current_task = NULL;
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h
|
|
index 22aeec77d84d..3a7c74822d8b 100644
|
|
--- a/drivers/gpu/drm/lima/lima_vm.h
|
|
+++ b/drivers/gpu/drm/lima/lima_vm.h
|
|
@@ -54,7 +54,8 @@ static inline struct lima_vm *lima_vm_get(struct lima_vm *vm)
|
|
|
|
static inline void lima_vm_put(struct lima_vm *vm)
|
|
{
|
|
- kref_put(&vm->refcount, lima_vm_release);
|
|
+ if (vm)
|
|
+ kref_put(&vm->refcount, lima_vm_release);
|
|
}
|
|
|
|
void lima_vm_print(struct lima_vm *vm);
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 60fd3f2cb896fe4727ad7da32aaa85b4baedb097 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:45 +0800
|
|
Subject: [PATCH] drm/lima: always set page directory when switch vm
|
|
|
|
We need to flush TLB anyway before every task start, and the
|
|
page directory will be set to empty vm after suspend/resume,
|
|
so always set it to the task vm even no ctx switch happens.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_mmu.c | 3 +--
|
|
drivers/gpu/drm/lima/lima_sched.c | 14 ++++----------
|
|
2 files changed, 5 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c
|
|
index f79d2af427e7..c26b751b0f9d 100644
|
|
--- a/drivers/gpu/drm/lima/lima_mmu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_mmu.c
|
|
@@ -113,8 +113,7 @@ void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm)
|
|
LIMA_MMU_STATUS, v,
|
|
v & LIMA_MMU_STATUS_STALL_ACTIVE);
|
|
|
|
- if (vm)
|
|
- mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma);
|
|
+ mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma);
|
|
|
|
/* flush the TLB */
|
|
mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE);
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index 3ac5797e31fc..eb46db0717cd 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -200,7 +200,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
|
struct lima_fence *fence;
|
|
struct dma_fence *ret;
|
|
- struct lima_vm *vm = NULL, *last_vm = NULL;
|
|
int i;
|
|
|
|
/* after GPU reset */
|
|
@@ -239,21 +238,16 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
for (i = 0; i < pipe->num_l2_cache; i++)
|
|
lima_l2_cache_flush(pipe->l2_cache[i]);
|
|
|
|
- if (task->vm != pipe->current_vm) {
|
|
- vm = lima_vm_get(task->vm);
|
|
- last_vm = pipe->current_vm;
|
|
- pipe->current_vm = task->vm;
|
|
- }
|
|
+ lima_vm_put(pipe->current_vm);
|
|
+ pipe->current_vm = lima_vm_get(task->vm);
|
|
|
|
if (pipe->bcast_mmu)
|
|
- lima_mmu_switch_vm(pipe->bcast_mmu, vm);
|
|
+ lima_mmu_switch_vm(pipe->bcast_mmu, pipe->current_vm);
|
|
else {
|
|
for (i = 0; i < pipe->num_mmu; i++)
|
|
- lima_mmu_switch_vm(pipe->mmu[i], vm);
|
|
+ lima_mmu_switch_vm(pipe->mmu[i], pipe->current_vm);
|
|
}
|
|
|
|
- lima_vm_put(last_vm);
|
|
-
|
|
trace_lima_task_run(task);
|
|
|
|
pipe->error = false;
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From e88c2e9bf4d246ef449323208fc731aad659fc43 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:46 +0800
|
|
Subject: [PATCH] drm/lima: add lima_devfreq_resume/suspend
|
|
|
|
Used for device resume/suspend in the following commits.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_devfreq.c | 24 ++++++++++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_devfreq.h | 3 +++
|
|
2 files changed, 27 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
index 1d479b5924fe..bbe02817721b 100644
|
|
--- a/drivers/gpu/drm/lima/lima_devfreq.c
|
|
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
|
|
@@ -231,3 +231,27 @@ void lima_devfreq_record_idle(struct lima_devfreq *devfreq)
|
|
|
|
spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
|
}
|
|
+
|
|
+int lima_devfreq_resume(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ unsigned long irqflags;
|
|
+
|
|
+ if (!devfreq->devfreq)
|
|
+ return 0;
|
|
+
|
|
+ spin_lock_irqsave(&devfreq->lock, irqflags);
|
|
+
|
|
+ lima_devfreq_reset(devfreq);
|
|
+
|
|
+ spin_unlock_irqrestore(&devfreq->lock, irqflags);
|
|
+
|
|
+ return devfreq_resume_device(devfreq->devfreq);
|
|
+}
|
|
+
|
|
+int lima_devfreq_suspend(struct lima_devfreq *devfreq)
|
|
+{
|
|
+ if (!devfreq->devfreq)
|
|
+ return 0;
|
|
+
|
|
+ return devfreq_suspend_device(devfreq->devfreq);
|
|
+}
|
|
diff --git a/drivers/gpu/drm/lima/lima_devfreq.h b/drivers/gpu/drm/lima/lima_devfreq.h
|
|
index 8d71ba9fb22a..5eed2975a375 100644
|
|
--- a/drivers/gpu/drm/lima/lima_devfreq.h
|
|
+++ b/drivers/gpu/drm/lima/lima_devfreq.h
|
|
@@ -38,4 +38,7 @@ void lima_devfreq_fini(struct lima_device *ldev);
|
|
void lima_devfreq_record_busy(struct lima_devfreq *devfreq);
|
|
void lima_devfreq_record_idle(struct lima_devfreq *devfreq);
|
|
|
|
+int lima_devfreq_resume(struct lima_devfreq *devfreq);
|
|
+int lima_devfreq_suspend(struct lima_devfreq *devfreq);
|
|
+
|
|
#endif
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 1f828aa538ce8def9479aec4669b655ff7e9cbf0 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:47 +0800
|
|
Subject: [PATCH] drm/lima: power down ip blocks when pmu exit
|
|
|
|
Prepare resume/suspend PM.
|
|
|
|
v2:
|
|
Fix lima_pmu_wait_cmd timeout when mali400 case.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_device.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_pmu.c | 53 +++++++++++++++++++++++++++++-
|
|
2 files changed, 54 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index 99b1fb147dad..9cd2718079bd 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -64,6 +64,8 @@ struct lima_ip {
|
|
bool async_reset;
|
|
/* l2 cache */
|
|
spinlock_t lock;
|
|
+ /* pmu */
|
|
+ u32 mask;
|
|
} data;
|
|
};
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c
|
|
index 571f6d661581..d476569f2043 100644
|
|
--- a/drivers/gpu/drm/lima/lima_pmu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_pmu.c
|
|
@@ -21,7 +21,7 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip)
|
|
v, v & LIMA_PMU_INT_CMD_MASK,
|
|
100, 100000);
|
|
if (err) {
|
|
- dev_err(dev->dev, "timeout wait pmd cmd\n");
|
|
+ dev_err(dev->dev, "timeout wait pmu cmd\n");
|
|
return err;
|
|
}
|
|
|
|
@@ -29,6 +29,40 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip)
|
|
return 0;
|
|
}
|
|
|
|
+static u32 lima_pmu_get_ip_mask(struct lima_ip *ip)
|
|
+{
|
|
+ struct lima_device *dev = ip->dev;
|
|
+ u32 ret = 0;
|
|
+ int i;
|
|
+
|
|
+ ret |= LIMA_PMU_POWER_GP0_MASK;
|
|
+
|
|
+ if (dev->id == lima_gpu_mali400) {
|
|
+ ret |= LIMA_PMU_POWER_L2_MASK;
|
|
+ for (i = 0; i < 4; i++) {
|
|
+ if (dev->ip[lima_ip_pp0 + i].present)
|
|
+ ret |= LIMA_PMU_POWER_PP_MASK(i);
|
|
+ }
|
|
+ } else {
|
|
+ if (dev->ip[lima_ip_pp0].present)
|
|
+ ret |= LIMA450_PMU_POWER_PP0_MASK;
|
|
+ for (i = lima_ip_pp1; i <= lima_ip_pp3; i++) {
|
|
+ if (dev->ip[i].present) {
|
|
+ ret |= LIMA450_PMU_POWER_PP13_MASK;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) {
|
|
+ if (dev->ip[i].present) {
|
|
+ ret |= LIMA450_PMU_POWER_PP47_MASK;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int lima_pmu_init(struct lima_ip *ip)
|
|
{
|
|
int err;
|
|
@@ -56,5 +90,22 @@ int lima_pmu_init(struct lima_ip *ip)
|
|
|
|
void lima_pmu_fini(struct lima_ip *ip)
|
|
{
|
|
+ u32 stat;
|
|
+
|
|
+ if (!ip->data.mask)
|
|
+ ip->data.mask = lima_pmu_get_ip_mask(ip);
|
|
|
|
+ stat = ~pmu_read(LIMA_PMU_STATUS) & ip->data.mask;
|
|
+ if (stat) {
|
|
+ pmu_write(LIMA_PMU_POWER_DOWN, stat);
|
|
+
|
|
+ /* Don't wait for interrupt on Mali400 if all domains are
|
|
+ * powered off because the HW won't generate an interrupt
|
|
+ * in this case.
|
|
+ */
|
|
+ if (ip->dev->id == lima_gpu_mali400)
|
|
+ pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK);
|
|
+ else
|
|
+ lima_pmu_wait_cmd(ip);
|
|
+ }
|
|
}
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From e7a53d7606fd2e3d6f513f4d8440e2243a9968ae Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:48 +0800
|
|
Subject: [PATCH] drm/lima: add resume/suspend callback for each ip
|
|
|
|
For called when PM do resume/suspend.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_bcast.c | 25 ++++++++++++---
|
|
drivers/gpu/drm/lima/lima_bcast.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_device.c | 4 +++
|
|
drivers/gpu/drm/lima/lima_device.h | 2 +-
|
|
drivers/gpu/drm/lima/lima_dlbu.c | 17 +++++++++-
|
|
drivers/gpu/drm/lima/lima_dlbu.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_gp.c | 21 +++++++++++--
|
|
drivers/gpu/drm/lima/lima_gp.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_l2_cache.c | 38 +++++++++++++++++------
|
|
drivers/gpu/drm/lima/lima_l2_cache.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_mmu.c | 46 ++++++++++++++++++++--------
|
|
drivers/gpu/drm/lima/lima_mmu.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_pmu.c | 24 +++++++++++++--
|
|
drivers/gpu/drm/lima/lima_pmu.h | 2 ++
|
|
drivers/gpu/drm/lima/lima_pp.c | 31 +++++++++++++++++--
|
|
drivers/gpu/drm/lima/lima_pp.h | 4 +++
|
|
16 files changed, 187 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c
|
|
index 288398027bfa..fbc43f243c54 100644
|
|
--- a/drivers/gpu/drm/lima/lima_bcast.c
|
|
+++ b/drivers/gpu/drm/lima/lima_bcast.c
|
|
@@ -26,18 +26,33 @@ void lima_bcast_enable(struct lima_device *dev, int num_pp)
|
|
bcast_write(LIMA_BCAST_BROADCAST_MASK, mask);
|
|
}
|
|
|
|
+static int lima_bcast_hw_init(struct lima_ip *ip)
|
|
+{
|
|
+ bcast_write(LIMA_BCAST_BROADCAST_MASK, ip->data.mask << 16);
|
|
+ bcast_write(LIMA_BCAST_INTERRUPT_MASK, ip->data.mask);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int lima_bcast_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_bcast_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_bcast_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
int lima_bcast_init(struct lima_ip *ip)
|
|
{
|
|
- int i, mask = 0;
|
|
+ int i;
|
|
|
|
for (i = lima_ip_pp0; i <= lima_ip_pp7; i++) {
|
|
if (ip->dev->ip[i].present)
|
|
- mask |= 1 << (i - lima_ip_pp0);
|
|
+ ip->data.mask |= 1 << (i - lima_ip_pp0);
|
|
}
|
|
|
|
- bcast_write(LIMA_BCAST_BROADCAST_MASK, mask << 16);
|
|
- bcast_write(LIMA_BCAST_INTERRUPT_MASK, mask);
|
|
- return 0;
|
|
+ return lima_bcast_hw_init(ip);
|
|
}
|
|
|
|
void lima_bcast_fini(struct lima_ip *ip)
|
|
diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h
|
|
index c47e58563d0a..465ee587bceb 100644
|
|
--- a/drivers/gpu/drm/lima/lima_bcast.h
|
|
+++ b/drivers/gpu/drm/lima/lima_bcast.h
|
|
@@ -6,6 +6,8 @@
|
|
|
|
struct lima_ip;
|
|
|
|
+int lima_bcast_resume(struct lima_ip *ip);
|
|
+void lima_bcast_suspend(struct lima_ip *ip);
|
|
int lima_bcast_init(struct lima_ip *ip);
|
|
void lima_bcast_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index 29285dedd124..a2d4ec75b3b3 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -25,6 +25,8 @@ struct lima_ip_desc {
|
|
|
|
int (*init)(struct lima_ip *ip);
|
|
void (*fini)(struct lima_ip *ip);
|
|
+ int (*resume)(struct lima_ip *ip);
|
|
+ void (*suspend)(struct lima_ip *ip);
|
|
};
|
|
|
|
#define LIMA_IP_DESC(ipname, mst0, mst1, off0, off1, func, irq) \
|
|
@@ -41,6 +43,8 @@ struct lima_ip_desc {
|
|
}, \
|
|
.init = lima_##func##_init, \
|
|
.fini = lima_##func##_fini, \
|
|
+ .resume = lima_##func##_resume, \
|
|
+ .suspend = lima_##func##_suspend, \
|
|
}
|
|
|
|
static struct lima_ip_desc lima_ip_desc[lima_ip_num] = {
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index 9cd2718079bd..d9df1b45dfa9 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -64,7 +64,7 @@ struct lima_ip {
|
|
bool async_reset;
|
|
/* l2 cache */
|
|
spinlock_t lock;
|
|
- /* pmu */
|
|
+ /* pmu/bcast */
|
|
u32 mask;
|
|
} data;
|
|
};
|
|
diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c
|
|
index 8399ceffb94b..c1d5ea35daa7 100644
|
|
--- a/drivers/gpu/drm/lima/lima_dlbu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_dlbu.c
|
|
@@ -42,7 +42,7 @@ void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg)
|
|
dlbu_write(LIMA_DLBU_START_TILE_POS, reg[3]);
|
|
}
|
|
|
|
-int lima_dlbu_init(struct lima_ip *ip)
|
|
+static int lima_dlbu_hw_init(struct lima_ip *ip)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
|
|
@@ -52,6 +52,21 @@ int lima_dlbu_init(struct lima_ip *ip)
|
|
return 0;
|
|
}
|
|
|
|
+int lima_dlbu_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_dlbu_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_dlbu_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
+int lima_dlbu_init(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_dlbu_hw_init(ip);
|
|
+}
|
|
+
|
|
void lima_dlbu_fini(struct lima_ip *ip)
|
|
{
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h
|
|
index 16f877984466..be71daaaee89 100644
|
|
--- a/drivers/gpu/drm/lima/lima_dlbu.h
|
|
+++ b/drivers/gpu/drm/lima/lima_dlbu.h
|
|
@@ -12,6 +12,8 @@ void lima_dlbu_disable(struct lima_device *dev);
|
|
|
|
void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg);
|
|
|
|
+int lima_dlbu_resume(struct lima_ip *ip);
|
|
+void lima_dlbu_suspend(struct lima_ip *ip);
|
|
int lima_dlbu_init(struct lima_ip *ip);
|
|
void lima_dlbu_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
|
|
index d8841c870d90..8dd501b7a3d0 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gp.c
|
|
+++ b/drivers/gpu/drm/lima/lima_gp.c
|
|
@@ -274,6 +274,23 @@ static void lima_gp_print_version(struct lima_ip *ip)
|
|
static struct kmem_cache *lima_gp_task_slab;
|
|
static int lima_gp_task_slab_refcnt;
|
|
|
|
+static int lima_gp_hw_init(struct lima_ip *ip)
|
|
+{
|
|
+ ip->data.async_reset = false;
|
|
+ lima_gp_soft_reset_async(ip);
|
|
+ return lima_gp_soft_reset_async_wait(ip);
|
|
+}
|
|
+
|
|
+int lima_gp_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_gp_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_gp_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
int lima_gp_init(struct lima_ip *ip)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
@@ -281,9 +298,7 @@ int lima_gp_init(struct lima_ip *ip)
|
|
|
|
lima_gp_print_version(ip);
|
|
|
|
- ip->data.async_reset = false;
|
|
- lima_gp_soft_reset_async(ip);
|
|
- err = lima_gp_soft_reset_async_wait(ip);
|
|
+ err = lima_gp_hw_init(ip);
|
|
if (err)
|
|
return err;
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_gp.h b/drivers/gpu/drm/lima/lima_gp.h
|
|
index 516e5c1babbb..02ec9af78a51 100644
|
|
--- a/drivers/gpu/drm/lima/lima_gp.h
|
|
+++ b/drivers/gpu/drm/lima/lima_gp.h
|
|
@@ -7,6 +7,8 @@
|
|
struct lima_ip;
|
|
struct lima_device;
|
|
|
|
+int lima_gp_resume(struct lima_ip *ip);
|
|
+void lima_gp_suspend(struct lima_ip *ip);
|
|
int lima_gp_init(struct lima_ip *ip);
|
|
void lima_gp_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c b/drivers/gpu/drm/lima/lima_l2_cache.c
|
|
index 6873a7af5a5c..c4080a02957b 100644
|
|
--- a/drivers/gpu/drm/lima/lima_l2_cache.c
|
|
+++ b/drivers/gpu/drm/lima/lima_l2_cache.c
|
|
@@ -38,9 +38,35 @@ int lima_l2_cache_flush(struct lima_ip *ip)
|
|
return ret;
|
|
}
|
|
|
|
+static int lima_l2_cache_hw_init(struct lima_ip *ip)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ err = lima_l2_cache_flush(ip);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ l2_cache_write(LIMA_L2_CACHE_ENABLE,
|
|
+ LIMA_L2_CACHE_ENABLE_ACCESS |
|
|
+ LIMA_L2_CACHE_ENABLE_READ_ALLOCATE);
|
|
+ l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int lima_l2_cache_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_l2_cache_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_l2_cache_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
int lima_l2_cache_init(struct lima_ip *ip)
|
|
{
|
|
- int i, err;
|
|
+ int i;
|
|
u32 size;
|
|
struct lima_device *dev = ip->dev;
|
|
|
|
@@ -63,15 +89,7 @@ int lima_l2_cache_init(struct lima_ip *ip)
|
|
1 << (size & 0xff),
|
|
1 << ((size >> 24) & 0xff));
|
|
|
|
- err = lima_l2_cache_flush(ip);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- l2_cache_write(LIMA_L2_CACHE_ENABLE,
|
|
- LIMA_L2_CACHE_ENABLE_ACCESS|LIMA_L2_CACHE_ENABLE_READ_ALLOCATE);
|
|
- l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c);
|
|
-
|
|
- return 0;
|
|
+ return lima_l2_cache_hw_init(ip);
|
|
}
|
|
|
|
void lima_l2_cache_fini(struct lima_ip *ip)
|
|
diff --git a/drivers/gpu/drm/lima/lima_l2_cache.h b/drivers/gpu/drm/lima/lima_l2_cache.h
|
|
index c63fb676ff14..1aeeefd53fb9 100644
|
|
--- a/drivers/gpu/drm/lima/lima_l2_cache.h
|
|
+++ b/drivers/gpu/drm/lima/lima_l2_cache.h
|
|
@@ -6,6 +6,8 @@
|
|
|
|
struct lima_ip;
|
|
|
|
+int lima_l2_cache_resume(struct lima_ip *ip);
|
|
+void lima_l2_cache_suspend(struct lima_ip *ip);
|
|
int lima_l2_cache_init(struct lima_ip *ip);
|
|
void lima_l2_cache_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c
|
|
index c26b751b0f9d..a1ae6c252dc2 100644
|
|
--- a/drivers/gpu/drm/lima/lima_mmu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_mmu.c
|
|
@@ -59,12 +59,44 @@ static irqreturn_t lima_mmu_irq_handler(int irq, void *data)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
-int lima_mmu_init(struct lima_ip *ip)
|
|
+static int lima_mmu_hw_init(struct lima_ip *ip)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
int err;
|
|
u32 v;
|
|
|
|
+ mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET);
|
|
+ err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET,
|
|
+ LIMA_MMU_DTE_ADDR, v, v == 0);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ mmu_write(LIMA_MMU_INT_MASK,
|
|
+ LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR);
|
|
+ mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma);
|
|
+ return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING,
|
|
+ LIMA_MMU_STATUS, v,
|
|
+ v & LIMA_MMU_STATUS_PAGING_ENABLED);
|
|
+}
|
|
+
|
|
+int lima_mmu_resume(struct lima_ip *ip)
|
|
+{
|
|
+ if (ip->id == lima_ip_ppmmu_bcast)
|
|
+ return 0;
|
|
+
|
|
+ return lima_mmu_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_mmu_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
+int lima_mmu_init(struct lima_ip *ip)
|
|
+{
|
|
+ struct lima_device *dev = ip->dev;
|
|
+ int err;
|
|
+
|
|
if (ip->id == lima_ip_ppmmu_bcast)
|
|
return 0;
|
|
|
|
@@ -74,12 +106,6 @@ int lima_mmu_init(struct lima_ip *ip)
|
|
return -EIO;
|
|
}
|
|
|
|
- mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET);
|
|
- err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET,
|
|
- LIMA_MMU_DTE_ADDR, v, v == 0);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
err = devm_request_irq(dev->dev, ip->irq, lima_mmu_irq_handler,
|
|
IRQF_SHARED, lima_ip_name(ip), ip);
|
|
if (err) {
|
|
@@ -87,11 +113,7 @@ int lima_mmu_init(struct lima_ip *ip)
|
|
return err;
|
|
}
|
|
|
|
- mmu_write(LIMA_MMU_INT_MASK, LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR);
|
|
- mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma);
|
|
- return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING,
|
|
- LIMA_MMU_STATUS, v,
|
|
- v & LIMA_MMU_STATUS_PAGING_ENABLED);
|
|
+ return lima_mmu_hw_init(ip);
|
|
}
|
|
|
|
void lima_mmu_fini(struct lima_ip *ip)
|
|
diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h
|
|
index 4f8ccbebcba1..f0c97ac75ea0 100644
|
|
--- a/drivers/gpu/drm/lima/lima_mmu.h
|
|
+++ b/drivers/gpu/drm/lima/lima_mmu.h
|
|
@@ -7,6 +7,8 @@
|
|
struct lima_ip;
|
|
struct lima_vm;
|
|
|
|
+int lima_mmu_resume(struct lima_ip *ip);
|
|
+void lima_mmu_suspend(struct lima_ip *ip);
|
|
int lima_mmu_init(struct lima_ip *ip);
|
|
void lima_mmu_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c
|
|
index d476569f2043..e397e1146e96 100644
|
|
--- a/drivers/gpu/drm/lima/lima_pmu.c
|
|
+++ b/drivers/gpu/drm/lima/lima_pmu.c
|
|
@@ -63,7 +63,7 @@ static u32 lima_pmu_get_ip_mask(struct lima_ip *ip)
|
|
return ret;
|
|
}
|
|
|
|
-int lima_pmu_init(struct lima_ip *ip)
|
|
+static int lima_pmu_hw_init(struct lima_ip *ip)
|
|
{
|
|
int err;
|
|
u32 stat;
|
|
@@ -88,7 +88,7 @@ int lima_pmu_init(struct lima_ip *ip)
|
|
return 0;
|
|
}
|
|
|
|
-void lima_pmu_fini(struct lima_ip *ip)
|
|
+static void lima_pmu_hw_fini(struct lima_ip *ip)
|
|
{
|
|
u32 stat;
|
|
|
|
@@ -109,3 +109,23 @@ void lima_pmu_fini(struct lima_ip *ip)
|
|
lima_pmu_wait_cmd(ip);
|
|
}
|
|
}
|
|
+
|
|
+int lima_pmu_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_pmu_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_pmu_suspend(struct lima_ip *ip)
|
|
+{
|
|
+ lima_pmu_hw_fini(ip);
|
|
+}
|
|
+
|
|
+int lima_pmu_init(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_pmu_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_pmu_fini(struct lima_ip *ip)
|
|
+{
|
|
+ lima_pmu_hw_fini(ip);
|
|
+}
|
|
diff --git a/drivers/gpu/drm/lima/lima_pmu.h b/drivers/gpu/drm/lima/lima_pmu.h
|
|
index a2a18775eb07..652dc7af3047 100644
|
|
--- a/drivers/gpu/drm/lima/lima_pmu.h
|
|
+++ b/drivers/gpu/drm/lima/lima_pmu.h
|
|
@@ -6,6 +6,8 @@
|
|
|
|
struct lima_ip;
|
|
|
|
+int lima_pmu_resume(struct lima_ip *ip);
|
|
+void lima_pmu_suspend(struct lima_ip *ip);
|
|
int lima_pmu_init(struct lima_ip *ip);
|
|
void lima_pmu_fini(struct lima_ip *ip);
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c
|
|
index 8fef224b93c8..33f01383409c 100644
|
|
--- a/drivers/gpu/drm/lima/lima_pp.c
|
|
+++ b/drivers/gpu/drm/lima/lima_pp.c
|
|
@@ -223,6 +223,23 @@ static void lima_pp_print_version(struct lima_ip *ip)
|
|
lima_ip_name(ip), name, major, minor);
|
|
}
|
|
|
|
+static int lima_pp_hw_init(struct lima_ip *ip)
|
|
+{
|
|
+ ip->data.async_reset = false;
|
|
+ lima_pp_soft_reset_async(ip);
|
|
+ return lima_pp_soft_reset_async_wait(ip);
|
|
+}
|
|
+
|
|
+int lima_pp_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return lima_pp_hw_init(ip);
|
|
+}
|
|
+
|
|
+void lima_pp_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
int lima_pp_init(struct lima_ip *ip)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
@@ -230,9 +247,7 @@ int lima_pp_init(struct lima_ip *ip)
|
|
|
|
lima_pp_print_version(ip);
|
|
|
|
- ip->data.async_reset = false;
|
|
- lima_pp_soft_reset_async(ip);
|
|
- err = lima_pp_soft_reset_async_wait(ip);
|
|
+ err = lima_pp_hw_init(ip);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -254,6 +269,16 @@ void lima_pp_fini(struct lima_ip *ip)
|
|
|
|
}
|
|
|
|
+int lima_pp_bcast_resume(struct lima_ip *ip)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void lima_pp_bcast_suspend(struct lima_ip *ip)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
int lima_pp_bcast_init(struct lima_ip *ip)
|
|
{
|
|
struct lima_device *dev = ip->dev;
|
|
diff --git a/drivers/gpu/drm/lima/lima_pp.h b/drivers/gpu/drm/lima/lima_pp.h
|
|
index bf60c77b2633..16ec96de15a9 100644
|
|
--- a/drivers/gpu/drm/lima/lima_pp.h
|
|
+++ b/drivers/gpu/drm/lima/lima_pp.h
|
|
@@ -7,9 +7,13 @@
|
|
struct lima_ip;
|
|
struct lima_device;
|
|
|
|
+int lima_pp_resume(struct lima_ip *ip);
|
|
+void lima_pp_suspend(struct lima_ip *ip);
|
|
int lima_pp_init(struct lima_ip *ip);
|
|
void lima_pp_fini(struct lima_ip *ip);
|
|
|
|
+int lima_pp_bcast_resume(struct lima_ip *ip);
|
|
+void lima_pp_bcast_suspend(struct lima_ip *ip);
|
|
int lima_pp_bcast_init(struct lima_ip *ip);
|
|
void lima_pp_bcast_fini(struct lima_ip *ip);
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 26ee4346a85cd75c531cb31dc1fe66e43226f275 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:49 +0800
|
|
Subject: [PATCH] drm/lima: separate clk/regulator enable/disable function
|
|
|
|
For being used by both device init/fini and suspend/resume.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_device.c | 105 +++++++++++++++++++----------
|
|
1 file changed, 68 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index a2d4ec75b3b3..1d9b7f415da1 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -81,26 +81,10 @@ const char *lima_ip_name(struct lima_ip *ip)
|
|
return lima_ip_desc[ip->id].name;
|
|
}
|
|
|
|
-static int lima_clk_init(struct lima_device *dev)
|
|
+static int lima_clk_enable(struct lima_device *dev)
|
|
{
|
|
int err;
|
|
|
|
- dev->clk_bus = devm_clk_get(dev->dev, "bus");
|
|
- if (IS_ERR(dev->clk_bus)) {
|
|
- err = PTR_ERR(dev->clk_bus);
|
|
- if (err != -EPROBE_DEFER)
|
|
- dev_err(dev->dev, "get bus clk failed %d\n", err);
|
|
- return err;
|
|
- }
|
|
-
|
|
- dev->clk_gpu = devm_clk_get(dev->dev, "core");
|
|
- if (IS_ERR(dev->clk_gpu)) {
|
|
- err = PTR_ERR(dev->clk_gpu);
|
|
- if (err != -EPROBE_DEFER)
|
|
- dev_err(dev->dev, "get core clk failed %d\n", err);
|
|
- return err;
|
|
- }
|
|
-
|
|
err = clk_prepare_enable(dev->clk_bus);
|
|
if (err)
|
|
return err;
|
|
@@ -109,15 +93,7 @@ static int lima_clk_init(struct lima_device *dev)
|
|
if (err)
|
|
goto error_out0;
|
|
|
|
- dev->reset = devm_reset_control_array_get_optional_shared(dev->dev);
|
|
-
|
|
- if (IS_ERR(dev->reset)) {
|
|
- err = PTR_ERR(dev->reset);
|
|
- if (err != -EPROBE_DEFER)
|
|
- dev_err(dev->dev, "get reset controller failed %d\n",
|
|
- err);
|
|
- goto error_out1;
|
|
- } else if (dev->reset != NULL) {
|
|
+ if (dev->reset) {
|
|
err = reset_control_deassert(dev->reset);
|
|
if (err) {
|
|
dev_err(dev->dev,
|
|
@@ -135,14 +111,76 @@ static int lima_clk_init(struct lima_device *dev)
|
|
return err;
|
|
}
|
|
|
|
-static void lima_clk_fini(struct lima_device *dev)
|
|
+static void lima_clk_disable(struct lima_device *dev)
|
|
{
|
|
- if (dev->reset != NULL)
|
|
+ if (dev->reset)
|
|
reset_control_assert(dev->reset);
|
|
clk_disable_unprepare(dev->clk_gpu);
|
|
clk_disable_unprepare(dev->clk_bus);
|
|
}
|
|
|
|
+static int lima_clk_init(struct lima_device *dev)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ dev->clk_bus = devm_clk_get(dev->dev, "bus");
|
|
+ if (IS_ERR(dev->clk_bus)) {
|
|
+ err = PTR_ERR(dev->clk_bus);
|
|
+ if (err != -EPROBE_DEFER)
|
|
+ dev_err(dev->dev, "get bus clk failed %d\n", err);
|
|
+ dev->clk_bus = NULL;
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ dev->clk_gpu = devm_clk_get(dev->dev, "core");
|
|
+ if (IS_ERR(dev->clk_gpu)) {
|
|
+ err = PTR_ERR(dev->clk_gpu);
|
|
+ if (err != -EPROBE_DEFER)
|
|
+ dev_err(dev->dev, "get core clk failed %d\n", err);
|
|
+ dev->clk_gpu = NULL;
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ dev->reset = devm_reset_control_array_get_optional_shared(dev->dev);
|
|
+ if (IS_ERR(dev->reset)) {
|
|
+ err = PTR_ERR(dev->reset);
|
|
+ if (err != -EPROBE_DEFER)
|
|
+ dev_err(dev->dev, "get reset controller failed %d\n",
|
|
+ err);
|
|
+ dev->reset = NULL;
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ return lima_clk_enable(dev);
|
|
+}
|
|
+
|
|
+static void lima_clk_fini(struct lima_device *dev)
|
|
+{
|
|
+ lima_clk_disable(dev);
|
|
+}
|
|
+
|
|
+static int lima_regulator_enable(struct lima_device *dev)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!dev->regulator)
|
|
+ return 0;
|
|
+
|
|
+ ret = regulator_enable(dev->regulator);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void lima_regulator_disable(struct lima_device *dev)
|
|
+{
|
|
+ if (dev->regulator)
|
|
+ regulator_disable(dev->regulator);
|
|
+}
|
|
+
|
|
static int lima_regulator_init(struct lima_device *dev)
|
|
{
|
|
int ret;
|
|
@@ -158,19 +196,12 @@ static int lima_regulator_init(struct lima_device *dev)
|
|
return ret;
|
|
}
|
|
|
|
- ret = regulator_enable(dev->regulator);
|
|
- if (ret < 0) {
|
|
- dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
+ return lima_regulator_enable(dev);
|
|
}
|
|
|
|
static void lima_regulator_fini(struct lima_device *dev)
|
|
{
|
|
- if (dev->regulator)
|
|
- regulator_disable(dev->regulator);
|
|
+ lima_regulator_disable(dev);
|
|
}
|
|
|
|
static int lima_init_ip(struct lima_device *dev, int index)
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 90f27ceb82a87cabf926e65748bdd60cf0e191b6 Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:50 +0800
|
|
Subject: [PATCH] drm/lima: add pm resume/suspend ops
|
|
|
|
Add driver pm system and runtime hardware resume/suspend ops.
|
|
Note this won't enable runtime pm of the device yet.
|
|
|
|
v2:
|
|
Do clock and power gating when suspend/resume.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_device.c | 90 ++++++++++++++++++++++++++++++
|
|
drivers/gpu/drm/lima/lima_device.h | 3 +
|
|
drivers/gpu/drm/lima/lima_drv.c | 7 +++
|
|
3 files changed, 100 insertions(+)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
|
|
index 1d9b7f415da1..65fdca366e41 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.c
|
|
+++ b/drivers/gpu/drm/lima/lima_device.c
|
|
@@ -247,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index)
|
|
desc->fini(ip);
|
|
}
|
|
|
|
+static int lima_resume_ip(struct lima_device *ldev, int index)
|
|
+{
|
|
+ struct lima_ip_desc *desc = lima_ip_desc + index;
|
|
+ struct lima_ip *ip = ldev->ip + index;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (ip->present)
|
|
+ ret = desc->resume(ip);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void lima_suspend_ip(struct lima_device *ldev, int index)
|
|
+{
|
|
+ struct lima_ip_desc *desc = lima_ip_desc + index;
|
|
+ struct lima_ip *ip = ldev->ip + index;
|
|
+
|
|
+ if (ip->present)
|
|
+ desc->suspend(ip);
|
|
+}
|
|
+
|
|
static int lima_init_gp_pipe(struct lima_device *dev)
|
|
{
|
|
struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
|
|
@@ -441,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev)
|
|
|
|
lima_clk_fini(ldev);
|
|
}
|
|
+
|
|
+int lima_device_resume(struct device *dev)
|
|
+{
|
|
+ struct lima_device *ldev = dev_get_drvdata(dev);
|
|
+ int i, err;
|
|
+
|
|
+ err = lima_clk_enable(ldev);
|
|
+ if (err) {
|
|
+ dev_err(dev, "resume clk fail %d\n", err);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ err = lima_regulator_enable(ldev);
|
|
+ if (err) {
|
|
+ dev_err(dev, "resume regulator fail %d\n", err);
|
|
+ goto err_out0;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < lima_ip_num; i++) {
|
|
+ err = lima_resume_ip(ldev, i);
|
|
+ if (err) {
|
|
+ dev_err(dev, "resume ip %d fail\n", i);
|
|
+ goto err_out1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ err = lima_devfreq_resume(&ldev->devfreq);
|
|
+ if (err) {
|
|
+ dev_err(dev, "devfreq resume fail\n");
|
|
+ goto err_out1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_out1:
|
|
+ while (--i >= 0)
|
|
+ lima_suspend_ip(ldev, i);
|
|
+ lima_regulator_disable(ldev);
|
|
+err_out0:
|
|
+ lima_clk_disable(ldev);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+int lima_device_suspend(struct device *dev)
|
|
+{
|
|
+ struct lima_device *ldev = dev_get_drvdata(dev);
|
|
+ int i, err;
|
|
+
|
|
+ /* check any task running */
|
|
+ for (i = 0; i < lima_pipe_num; i++) {
|
|
+ if (atomic_read(&ldev->pipe[i].base.hw_rq_count))
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ err = lima_devfreq_suspend(&ldev->devfreq);
|
|
+ if (err) {
|
|
+ dev_err(dev, "devfreq suspend fail\n");
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ for (i = lima_ip_num - 1; i >= 0; i--)
|
|
+ lima_suspend_ip(ldev, i);
|
|
+
|
|
+ lima_regulator_disable(ldev);
|
|
+
|
|
+ lima_clk_disable(ldev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h
|
|
index d9df1b45dfa9..41b9d7b4bcc7 100644
|
|
--- a/drivers/gpu/drm/lima/lima_device.h
|
|
+++ b/drivers/gpu/drm/lima/lima_device.h
|
|
@@ -140,4 +140,7 @@ static inline int lima_poll_timeout(struct lima_ip *ip, lima_poll_func_t func,
|
|
return 0;
|
|
}
|
|
|
|
+int lima_device_suspend(struct device *dev);
|
|
+int lima_device_resume(struct device *dev);
|
|
+
|
|
#endif
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index 3d63d496cfc2..f3fe0a2f764b 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -5,6 +5,7 @@
|
|
#include <linux/of_platform.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/slab.h>
|
|
+#include <linux/pm_runtime.h>
|
|
#include <drm/drm_ioctl.h>
|
|
#include <drm/drm_drv.h>
|
|
#include <drm/drm_prime.h>
|
|
@@ -451,11 +452,17 @@ static const struct of_device_id dt_match[] = {
|
|
};
|
|
MODULE_DEVICE_TABLE(of, dt_match);
|
|
|
|
+static const struct dev_pm_ops lima_pm_ops = {
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
|
+ SET_RUNTIME_PM_OPS(lima_device_suspend, lima_device_resume, NULL)
|
|
+};
|
|
+
|
|
static struct platform_driver lima_platform_driver = {
|
|
.probe = lima_pdev_probe,
|
|
.remove = lima_pdev_remove,
|
|
.driver = {
|
|
.name = "lima",
|
|
+ .pm = &lima_pm_ops,
|
|
.of_match_table = dt_match,
|
|
},
|
|
};
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 77f3ae2361292cef89c0a06e745991cefb52fcdc Mon Sep 17 00:00:00 2001
|
|
From: Qiang Yu <yuq825@gmail.com>
|
|
Date: Tue, 21 Apr 2020 21:35:51 +0800
|
|
Subject: [PATCH] drm/lima: enable runtime pm
|
|
|
|
Enable runtime pm by default so GPU suspend when idle
|
|
for 200ms. This value can be changed by
|
|
autosuspend_delay_ms in device's power sysfs dir.
|
|
|
|
On Allwinner H3 lima_device_resume takes ~40us and
|
|
lima_device_suspend takes ~20us.
|
|
|
|
Tested-by: Bhushan Shah <bshah@kde.org>
|
|
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
|
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
drivers/gpu/drm/lima/lima_drv.c | 21 ++++++++++++----
|
|
drivers/gpu/drm/lima/lima_sched.c | 41 +++++++++++++++++++++++++++----
|
|
2 files changed, 52 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
|
index f3fe0a2f764b..a831565af813 100644
|
|
--- a/drivers/gpu/drm/lima/lima_drv.c
|
|
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
|
@@ -404,6 +404,12 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
goto err_out2;
|
|
}
|
|
|
|
+ pm_runtime_set_active(ldev->dev);
|
|
+ pm_runtime_mark_last_busy(ldev->dev);
|
|
+ pm_runtime_set_autosuspend_delay(ldev->dev, 200);
|
|
+ pm_runtime_use_autosuspend(ldev->dev);
|
|
+ pm_runtime_enable(ldev->dev);
|
|
+
|
|
/*
|
|
* Register the DRM device with the core and the connectors with
|
|
* sysfs.
|
|
@@ -412,17 +418,16 @@ static int lima_pdev_probe(struct platform_device *pdev)
|
|
if (err < 0)
|
|
goto err_out3;
|
|
|
|
- platform_set_drvdata(pdev, ldev);
|
|
-
|
|
if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
|
|
dev_warn(ldev->dev, "fail to create error state sysfs\n");
|
|
|
|
return 0;
|
|
|
|
err_out3:
|
|
- lima_device_fini(ldev);
|
|
-err_out2:
|
|
+ pm_runtime_disable(ldev->dev);
|
|
lima_devfreq_fini(ldev);
|
|
+err_out2:
|
|
+ lima_device_fini(ldev);
|
|
err_out1:
|
|
drm_dev_put(ddev);
|
|
err_out0:
|
|
@@ -436,10 +441,16 @@ static int lima_pdev_remove(struct platform_device *pdev)
|
|
struct drm_device *ddev = ldev->ddev;
|
|
|
|
sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
|
|
- platform_set_drvdata(pdev, NULL);
|
|
+
|
|
drm_dev_unregister(ddev);
|
|
+
|
|
+ /* stop autosuspend to make sure device is in active state */
|
|
+ pm_runtime_set_autosuspend_delay(ldev->dev, -1);
|
|
+ pm_runtime_disable(ldev->dev);
|
|
+
|
|
lima_devfreq_fini(ldev);
|
|
lima_device_fini(ldev);
|
|
+
|
|
drm_dev_put(ddev);
|
|
lima_sched_slab_fini();
|
|
return 0;
|
|
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
|
|
index eb46db0717cd..e6cefda00279 100644
|
|
--- a/drivers/gpu/drm/lima/lima_sched.c
|
|
+++ b/drivers/gpu/drm/lima/lima_sched.c
|
|
@@ -4,6 +4,7 @@
|
|
#include <linux/kthread.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/vmalloc.h>
|
|
+#include <linux/pm_runtime.h>
|
|
|
|
#include "lima_devfreq.h"
|
|
#include "lima_drv.h"
|
|
@@ -194,13 +195,36 @@ static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job,
|
|
return NULL;
|
|
}
|
|
|
|
+static int lima_pm_busy(struct lima_device *ldev)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* resume GPU if it has been suspended by runtime PM */
|
|
+ ret = pm_runtime_get_sync(ldev->dev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ lima_devfreq_record_busy(&ldev->devfreq);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void lima_pm_idle(struct lima_device *ldev)
|
|
+{
|
|
+ lima_devfreq_record_idle(&ldev->devfreq);
|
|
+
|
|
+ /* GPU can do auto runtime suspend */
|
|
+ pm_runtime_mark_last_busy(ldev->dev);
|
|
+ pm_runtime_put_autosuspend(ldev->dev);
|
|
+}
|
|
+
|
|
static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
{
|
|
struct lima_sched_task *task = to_lima_task(job);
|
|
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
|
+ struct lima_device *ldev = pipe->ldev;
|
|
struct lima_fence *fence;
|
|
struct dma_fence *ret;
|
|
- int i;
|
|
+ int i, err;
|
|
|
|
/* after GPU reset */
|
|
if (job->s_fence->finished.error < 0)
|
|
@@ -209,6 +233,13 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
fence = lima_fence_create(pipe);
|
|
if (!fence)
|
|
return NULL;
|
|
+
|
|
+ err = lima_pm_busy(ldev);
|
|
+ if (err < 0) {
|
|
+ dma_fence_put(&fence->base);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
task->fence = &fence->base;
|
|
|
|
/* for caller usage of the fence, otherwise irq handler
|
|
@@ -216,8 +247,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
|
*/
|
|
ret = dma_fence_get(task->fence);
|
|
|
|
- lima_devfreq_record_busy(&pipe->ldev->devfreq);
|
|
-
|
|
pipe->current_task = task;
|
|
|
|
/* this is needed for MMU to work correctly, otherwise GP/PP
|
|
@@ -388,6 +417,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
{
|
|
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
|
struct lima_sched_task *task = to_lima_task(job);
|
|
+ struct lima_device *ldev = pipe->ldev;
|
|
|
|
if (!pipe->error)
|
|
DRM_ERROR("lima job timeout\n");
|
|
@@ -413,7 +443,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
|
|
pipe->current_vm = NULL;
|
|
pipe->current_task = NULL;
|
|
|
|
- lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
|
+ lima_pm_idle(ldev);
|
|
|
|
drm_sched_resubmit_jobs(&pipe->base);
|
|
drm_sched_start(&pipe->base, true);
|
|
@@ -485,6 +515,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
|
|
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
|
{
|
|
struct lima_sched_task *task = pipe->current_task;
|
|
+ struct lima_device *ldev = pipe->ldev;
|
|
|
|
if (pipe->error) {
|
|
if (task && task->recoverable)
|
|
@@ -495,6 +526,6 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
|
|
pipe->task_fini(pipe);
|
|
dma_fence_signal(task->fence);
|
|
|
|
- lima_devfreq_record_idle(&pipe->ldev->devfreq);
|
|
+ lima_pm_idle(ldev);
|
|
}
|
|
}
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 5f88c11fbc001f7cd701af13a4a40c94572848c7 Mon Sep 17 00:00:00 2001
|
|
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
Date: Thu, 19 Mar 2020 21:34:26 +0100
|
|
Subject: [PATCH] dt-bindings: gpu: mali-utgard: Add the #cooling-cells
|
|
property
|
|
|
|
The GPU can be one of the big heat sources on a SoC. Allow the
|
|
"#cooling-cells" property to be specified for ARM Mali Utgard GPUs so
|
|
the GPU clock speeds (and voltages) can be reduced to prevent a SoC from
|
|
overheating.
|
|
|
|
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
Reviewed-by: Qiang Yu <yuq825@gmail.com>
|
|
---
|
|
Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
|
|
index afde81be3c29..33548ca2a759 100644
|
|
--- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
|
|
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
|
|
@@ -107,6 +107,9 @@ properties:
|
|
|
|
operating-points-v2: true
|
|
|
|
+ "#cooling-cells":
|
|
+ const: 2
|
|
+
|
|
required:
|
|
- compatible
|
|
- reg
|
|
@@ -162,6 +165,7 @@ examples:
|
|
clocks = <&ccu 1>, <&ccu 2>;
|
|
clock-names = "bus", "core";
|
|
resets = <&ccu 1>;
|
|
+ #cooling-cells = <2>;
|
|
};
|
|
|
|
...
|
|
--
|
|
2.17.1
|
|
|