diff options
author | Dave Airlie <airlied@redhat.com> | 2020-04-22 10:40:34 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-04-22 10:41:35 +1000 |
commit | 1aa63ddf726ea049279989b93b69b57ce6efd75b (patch) | |
tree | b2850db923425621e7830918569572de9a22c86b /drivers/gpu/drm/lima/lima_sched.c | |
parent | 774f1eeb18b016eee460e060a786eee83b14d007 (diff) | |
parent | 14d0066b8477775971db7d0ef03c86fefe4d5bf2 (diff) |
Merge tag 'drm-misc-next-2020-04-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.8:
UAPI Changes:
- drm: error out with EBUSY when device has existing master
- drm: rework SET_MASTER and DROP_MASTER perm handling
Cross-subsystem Changes:
- mm: export two symbols from slub/slob
- fbdev: savage: fix -Wextra build warning
- video: omap2: Use scnprintf() for avoiding potential buffer overflow
Core Changes:
- Remove drm_pci.h
- drm_pci_{alloc/free)() are now legacy
- Introduce managed DRM resourcesA
- Allow drivers to subclass struct drm_framebuffer
- Introduce struct drm_afbc_framebuffer and helpers
- fbdev: remove return value from generic fbdev setup
- Introduce simple-encoder helper
- vram-helpers: set fence on plane
- dp_mst: ACT timeout improvements
- dp_mst: Remove drm_dp_mst_has_audio()
- TTM: ttm_trace_dma_{map/unmap}() cleanups
- dma-buf: add flag for PCIP2P support
- EDID: Various improvements
- Encoder: cleanup semantics of possible_clones and possible_crtcs
- VBLANK documentation updates
- Writeback documentation updates
Driver Changes:
- Convert several drivers to i2c_new_client_device()
- Drop explicit drm_mode_config_cleanup() calls from drivers
- Auto-release device structures with drmm_add_final_kfree()
- Init bfdev console after registering DRM device
- Make various .debugfs functions return 0 unconditionally; ignore errors
- video: Use scnprintf() to avoid buffer overflows
- Convert drivers to simple encoders
- drm/amdgpu: note that we can handle peer2peer DMA-buf
- drm/amdgpu: add support for exporting VRAM using DMA-buf v3
- drm/kirin: Revert change to register connectors
- drm/lima: Add optional devfreq and cooling device support
- drm/lima: Various improvements wrt. task handling
- drm/panel: nt39016: Support multiple modes and 50Hz
- drm/panel: Support Leadtek LTK050H3146W
- drm/rockchip: Add support for afbc
- drm/virtio: Various cleanups
- drm/hisilicon/hibmc: Enforce 128-byte stride alignment
- drm/qxl: Fix notify port address of cursor ring buffer
- drm/sun4i: Improvements to format handling
- drm/bridge: dw-hdmi: Various improvements
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20200414090738.GA16827@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/lima/lima_sched.c')
-rw-r--r-- | drivers/gpu/drm/lima/lima_sched.c | 142 |
1 files changed, 141 insertions, 1 deletions
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index 3886999b4533..a2db1c937424 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -3,14 +3,16 @@ #include <linux/kthread.h> #include <linux/slab.h> -#include <linux/xarray.h> +#include <linux/vmalloc.h> +#include "lima_devfreq.h" #include "lima_drv.h" #include "lima_sched.h" #include "lima_vm.h" #include "lima_mmu.h" #include "lima_l2_cache.h" #include "lima_gem.h" +#include "lima_trace.h" struct lima_fence { struct dma_fence base; @@ -176,6 +178,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; } @@ -214,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 @@ -250,12 +255,141 @@ 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); 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 +402,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) @@ -285,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); } @@ -364,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); } } |