Message ID | 20200222024210.18697-4-yuq825@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/lima: add error debug functionality | expand |
Hi Qiang, I love your patch! Yet something to improve: [auto build test ERROR on drm-tip/drm-tip] [cannot apply to drm-exynos/exynos-drm-next drm-intel/for-linux-next tegra-drm/drm/tegra/for-next linus/master v5.6-rc2 next-20200221] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Qiang-Yu/drm-lima-add-error-debug-functionality/20200223-054634 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip config: mips-allyesconfig (attached as .config) compiler: mips-linux-gcc (GCC) 7.5.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.5.0 make.cross ARCH=mips If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/gpu/drm/lima/lima_sched.c: In function 'lima_sched_build_error_task_list': >> drivers/gpu/drm/lima/lima_sched.c:347:11: error: implicit declaration of function 'vmap'; did you mean 'bmap'? [-Werror=implicit-function-declaration] data = vmap(bo->base.pages, bo->heap_size >> PAGE_SHIFT, ^~~~ bmap >> drivers/gpu/drm/lima/lima_sched.c:348:9: error: 'VM_MAP' undeclared (first use in this function); did you mean 'VM_MPX'? VM_MAP, pgprot_writecombine(PAGE_KERNEL)); ^~~~~~ VM_MPX drivers/gpu/drm/lima/lima_sched.c:348:9: note: each undeclared identifier is reported only once for each function it appears in >> drivers/gpu/drm/lima/lima_sched.c:356:4: error: implicit declaration of function 'vunmap'; did you mean 'kunmap'? [-Werror=implicit-function-declaration] vunmap(data); ^~~~~~ kunmap cc1: some warnings being treated as errors vim +347 drivers/gpu/drm/lima/lima_sched.c 258 259 static void lima_sched_build_error_task_list(struct lima_sched_task *task) 260 { 261 struct lima_sched_error_task *et; 262 struct lima_sched_pipe *pipe = to_lima_pipe(task->base.sched); 263 struct lima_ip *ip = pipe->processor[0]; 264 int pipe_id = ip->id == lima_ip_gp ? lima_pipe_gp : lima_pipe_pp; 265 struct lima_device *dev = ip->dev; 266 struct lima_sched_context *sched_ctx = 267 container_of(task->base.entity, struct lima_sched_context, base); 268 struct lima_ctx *ctx = 269 container_of(sched_ctx, struct lima_ctx, context[pipe_id]); 270 struct lima_dump_task *dt; 271 struct lima_dump_chunk *chunk; 272 struct lima_dump_chunk_pid *pid_chunk; 273 struct lima_dump_chunk_buffer *buffer_chunk; 274 uint32_t size, task_size, mem_size; 275 int i; 276 277 mutex_lock(&dev->error_task_list_lock); 278 279 if (dev->dump.num_tasks >= lima_max_error_tasks) { 280 dev_info(dev->dev, "fail to save task state: error task list is full\n"); 281 goto out; 282 } 283 284 /* frame chunk */ 285 size = sizeof(struct lima_dump_chunk) + pipe->frame_size; 286 /* process name chunk */ 287 size += sizeof(struct lima_dump_chunk) + sizeof(ctx->pname); 288 /* pid chunk */ 289 size += sizeof(struct lima_dump_chunk); 290 /* buffer chunks */ 291 for (i = 0; i < task->num_bos; i++) { 292 struct lima_bo *bo = task->bos[i]; 293 294 size += sizeof(struct lima_dump_chunk); 295 size += bo->heap_size ? bo->heap_size : lima_bo_size(bo); 296 } 297 298 task_size = size + sizeof(struct lima_dump_task); 299 mem_size = task_size + sizeof(*et); 300 et = kvmalloc(mem_size, GFP_KERNEL); 301 if (!et) { 302 dev_err(dev->dev, "fail to alloc task dump buffer of size %x\n", 303 mem_size); 304 goto out; 305 } 306 307 et->data = et + 1; 308 et->size = task_size; 309 310 dt = et->data; 311 memset(dt, 0, sizeof(*dt)); 312 dt->id = pipe_id; 313 dt->size = size; 314 315 chunk = (struct lima_dump_chunk *)(dt + 1); 316 memset(chunk, 0, sizeof(*chunk)); 317 chunk->id = LIMA_DUMP_CHUNK_FRAME; 318 chunk->size = pipe->frame_size; 319 memcpy(chunk + 1, task->frame, pipe->frame_size); 320 dt->num_chunks++; 321 322 chunk = (void *)(chunk + 1) + chunk->size; 323 memset(chunk, 0, sizeof(*chunk)); 324 chunk->id = LIMA_DUMP_CHUNK_PROCESS_NAME; 325 chunk->size = sizeof(ctx->pname); 326 memcpy(chunk + 1, ctx->pname, sizeof(ctx->pname)); 327 dt->num_chunks++; 328 329 pid_chunk = (void *)(chunk + 1) + chunk->size; 330 memset(pid_chunk, 0, sizeof(*pid_chunk)); 331 pid_chunk->id = LIMA_DUMP_CHUNK_PROCESS_ID; 332 pid_chunk->pid = ctx->pid; 333 dt->num_chunks++; 334 335 buffer_chunk = (void *)(pid_chunk + 1) + pid_chunk->size; 336 for (i = 0; i < task->num_bos; i++) { 337 struct lima_bo *bo = task->bos[i]; 338 void *data; 339 340 memset(buffer_chunk, 0, sizeof(*buffer_chunk)); 341 buffer_chunk->id = LIMA_DUMP_CHUNK_BUFFER; 342 buffer_chunk->va = lima_vm_get_va(task->vm, bo); 343 344 if (bo->heap_size) { 345 buffer_chunk->size = bo->heap_size; 346 > 347 data = vmap(bo->base.pages, bo->heap_size >> PAGE_SHIFT, > 348 VM_MAP, pgprot_writecombine(PAGE_KERNEL)); 349 if (!data) { 350 kvfree(et); 351 goto out; 352 } 353 354 memcpy(buffer_chunk + 1, data, buffer_chunk->size); 355 > 356 vunmap(data); 357 } else { 358 buffer_chunk->size = lima_bo_size(bo); 359 360 data = drm_gem_shmem_vmap(&bo->base.base); 361 if (IS_ERR_OR_NULL(data)) { 362 kvfree(et); 363 goto out; 364 } 365 366 memcpy(buffer_chunk + 1, data, buffer_chunk->size); 367 368 drm_gem_shmem_vunmap(&bo->base.base, data); 369 } 370 371 buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size; 372 dt->num_chunks++; 373 } 374 375 list_add(&et->list, &dev->error_task_list); 376 dev->dump.size += et->size; 377 dev->dump.num_tasks++; 378 379 dev_info(dev->dev, "save error task state success\n"); 380 381 out: 382 mutex_unlock(&dev->error_task_list_lock); 383 } 384 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Fri, Feb 21, 2020 at 6:43 PM Qiang Yu <yuq825@gmail.com> wrote: > > 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 Looks like lima_sched.c is missing #include <linux/vmalloc.h> so kbuild bot complains > 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 | 128 +++++++++++++++++++++++++++++ > drivers/gpu/drm/lima/lima_sched.h | 7 ++ > 5 files changed, 233 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..cd1bf3ad9bb5 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -256,6 +256,132 @@ 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; > + uint32_t 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 +394,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..e29f5e3b675b 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; > + uint32_t size; > +}; > + > struct lima_sched_task { > struct drm_sched_job base; > > -- > 2.17.1 >
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..cd1bf3ad9bb5 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -256,6 +256,132 @@ 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; + uint32_t 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 +394,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..e29f5e3b675b 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; + uint32_t size; +}; + struct lima_sched_task { struct drm_sched_job base;
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 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 | 128 +++++++++++++++++++++++++++++ drivers/gpu/drm/lima/lima_sched.h | 7 ++ 5 files changed, 233 insertions(+) create mode 100644 drivers/gpu/drm/lima/lima_dump.h