From: Jose Maria Casanova Crespo <[email protected]> v3d_csd_job_timedout() only treats a change in CSD_CURRENT_CFG4, the number of batches still to be started, as progress. Once the last batch has started, CFG4 no longer changes until the dispatch completes, so the batches still in flight must complete within one timeout period.
Since V3D 7.1 the dispatcher can keep up to MAX_SG_ID + 1 supergroups in flight. With supergroups of different lengths, the ones still running after the last batch starts can take longer than that while they keep completing, and the job is reset although it is making progress. On V3D 7.x, CSD_EXT_STATUS reports how many supergroup IDs are allocated. An ID is released when its supergroup completes, and none is allocated after the last batch has started, so the count only decreases until the dispatch completes. Treat a change of that count as progress too, starting from zero IDs when the job is started. V3D 4.2 has no register that reports supergroup completion, so it keeps the current behaviour. Signed-off-by: Jose Maria Casanova Crespo <[email protected]> Signed-off-by: Maíra Canal <[email protected]> --- drivers/gpu/drm/v3d/v3d_drv.h | 2 +- drivers/gpu/drm/v3d/v3d_regs.h | 5 +++++ drivers/gpu/drm/v3d/v3d_sched.c | 14 +++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 29fa14be130b..deac9e6a2e42 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -426,7 +426,7 @@ struct v3d_tfu_job { struct v3d_csd_job { struct v3d_job base; - u32 timedout_batches; + u32 timedout_batches, timedout_sg_ids; struct drm_v3d_submit_csd args; }; diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h index c1870265eaee..8b8199ecb086 100644 --- a/drivers/gpu/drm/v3d/v3d_regs.h +++ b/drivers/gpu/drm/v3d/v3d_regs.h @@ -412,6 +412,11 @@ # define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH BIT(1) # define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0) +/* V3D 7.x+ only */ +#define V3D_V7_CSD_EXT_STATUS 0x00904 +# define V3D_V7_CSD_EXT_STATUS_NUM_ALLOCED_SG_IDS_MASK V3D_MASK(9, 3) +# define V3D_V7_CSD_EXT_STATUS_NUM_ALLOCED_SG_IDS_SHIFT 3 + #define V3D_CSD_QUEUED_CFG0(ver) ((ver >= 71) ? 0x00930 : 0x00904) # define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16) # define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16 diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 002116efc874..b9e0b7babaf9 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -361,6 +361,7 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) job->base.irq_fence = dma_fence_get(fence); job->timedout_batches = job->args.cfg[4]; + job->timedout_sg_ids = 0; trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno); @@ -776,12 +777,23 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job) struct v3d_csd_job *job = to_csd_job(sched_job); struct v3d_dev *v3d = job->base.v3d; u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4(v3d->ver)); + u32 sg_ids = 0; + + /* Once the last batch has started, CFG4 no longer changes until the + * dispatch completes. On V3D 7.x, supergroups that complete in that + * window release their ID, so count that as progress too. + */ + if (v3d->ver >= V3D_GEN_71) { + sg_ids = V3D_GET_FIELD(V3D_CORE_READ(0, V3D_V7_CSD_EXT_STATUS), + V3D_V7_CSD_EXT_STATUS_NUM_ALLOCED_SG_IDS); + } /* If we've made progress, skip reset, add the job to the pending * list, and let the timer get rearmed. */ - if (job->timedout_batches != batches) { + if (job->timedout_batches != batches || job->timedout_sg_ids != sg_ids) { job->timedout_batches = batches; + job->timedout_sg_ids = sg_ids; return DRM_GPU_SCHED_STAT_NO_HANG; } -- 2.56.0
