Message ID | 20250122140818.45172-3-phasta@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | drm/sched: Use struct for drm_sched_init() params | expand |
On Wed, Jan 22, 2025 at 03:08:20PM +0100, Philipp Stanner wrote: > drm_sched_init() has a great many parameters and upcoming new > functionality for the scheduler might add even more. Generally, the > great number of parameters reduces readability and has already caused > one missnaming in: > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in nouveau_sched_init()"). > > Introduce a new struct for the scheduler init parameters and port all > users. > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > --- > Howdy, > > I have a patch-series in the pipe that will add a `flags` argument to > drm_sched_init(). I thought it would be wise to first rework the API as > detailed in this patch. It's really a lot of parameters by now, and I > would expect that it might get more and more over the years for special > use cases etc. > > Regards, > P. > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++------ > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > include/drm/gpu_scheduler.h | 35 +++++- > 14 files changed, 311 insertions(+), 139 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > index cd4fac120834..c1f03eb5f5ea 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > @@ -2821,6 +2821,9 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) > { > long timeout; > int r, i; > + struct drm_sched_init_params params; > + > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); I think we should drop the memset() and just write it as: struct drm_sched_init_params params = {}; <snip> > diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h > index 95e17504e46a..1a834ef43862 100644 > --- a/include/drm/gpu_scheduler.h > +++ b/include/drm/gpu_scheduler.h > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > struct device *dev; > }; > > +/** > + * struct drm_sched_init_params - parameters for initializing a DRM GPU scheduler Since this is a separate structure now, I think we should point out which fields are mandatory to set and which of those have a valid default to zero. > + * > + * @ops: backend operations provided by the driver > + * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is > + * allocated and used > + * @num_rqs: Number of run-queues. This is at most DRM_SCHED_PRIORITY_COUNT, > + * as there's usually one run-queue per priority, but could be less. > + * @credit_limit: the number of credits this scheduler can hold from all jobs > + * @hang_limit: number of times to allow a job to hang before dropping it > + * @timeout: timeout value in jiffies for the scheduler > + * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is > + * used > + * @score: optional score atomic shared with other schedulers > + * @name: name used for debugging > + * @dev: associated device. Used for debugging > + */ > +struct drm_sched_init_params { > + const struct drm_sched_backend_ops *ops; > + struct workqueue_struct *submit_wq; > + struct workqueue_struct *timeout_wq; > + u32 num_rqs, credit_limit; > + unsigned int hang_limit; > + long timeout; > + atomic_t *score; > + const char *name; > + struct device *dev; > +}; > + > int drm_sched_init(struct drm_gpu_scheduler *sched, > - const struct drm_sched_backend_ops *ops, > - struct workqueue_struct *submit_wq, > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > - long timeout, struct workqueue_struct *timeout_wq, > - atomic_t *score, const char *name, struct device *dev); > + const struct drm_sched_init_params *params); > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > int drm_sched_job_init(struct drm_sched_job *job, > -- > 2.47.1 >
Am 22.01.25 um 15:08 schrieb Philipp Stanner: > drm_sched_init() has a great many parameters and upcoming new > functionality for the scheduler might add even more. Generally, the > great number of parameters reduces readability and has already caused > one missnaming in: > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in nouveau_sched_init()"). > > Introduce a new struct for the scheduler init parameters and port all > users. > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > --- > Howdy, > > I have a patch-series in the pipe that will add a `flags` argument to > drm_sched_init(). I thought it would be wise to first rework the API as > detailed in this patch. It's really a lot of parameters by now, and I > would expect that it might get more and more over the years for special > use cases etc. > > Regards, > P. > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++------ > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > include/drm/gpu_scheduler.h | 35 +++++- > 14 files changed, 311 insertions(+), 139 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > index cd4fac120834..c1f03eb5f5ea 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > @@ -2821,6 +2821,9 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) > { > long timeout; > int r, i; > + struct drm_sched_init_params params; Please keep the reverse xmas tree ordering for variable declaration. E.g. long lines first and variables like "i" and "r" last. Apart from that looks like a good idea to me. > + > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { > struct amdgpu_ring *ring = adev->rings[i]; > @@ -2844,12 +2847,18 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) > break; > } > > - r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - ring->num_hw_submission, 0, > - timeout, adev->reset_domain->wq, > - ring->sched_score, ring->name, > - adev->dev); > + params.ops = &amdgpu_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = ring->num_hw_submission; > + params.hang_limit = 0; Could we please remove the hang limit as first step to get this awful feature deprecated? Thanks, Christian. > + params.timeout = timeout; > + params.timeout_wq = adev->reset_domain->wq; > + params.score = ring->sched_score; > + params.name = ring->name; > + params.dev = adev->dev; > + > + r = drm_sched_init(&ring->sched, ¶ms); > if (r) { > DRM_ERROR("Failed to create scheduler on ring %s.\n", > ring->name); > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > index 5b67eda122db..7d8517f1963e 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit) > int etnaviv_sched_init(struct etnaviv_gpu *gpu) > { > int ret; > + struct drm_sched_init_params params; > > - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - etnaviv_hw_jobs_limit, etnaviv_job_hang_limit, > - msecs_to_jiffies(500), NULL, NULL, > - dev_name(gpu->dev), gpu->dev); > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > + params.ops = &etnaviv_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = etnaviv_hw_jobs_limit; > + params.hang_limit = etnaviv_job_hang_limit; > + params.timeout = msecs_to_jiffies(500); > + params.timeout_wq = NULL; /* Use the system_wq. */ > + params.score = NULL; > + params.name = dev_name(gpu->dev); > + params.dev = gpu->dev; > + > + ret = drm_sched_init(&gpu->sched, ¶ms); > if (ret) > return ret; > > diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c > index c4f08432882b..03a2ce1a88e7 100644 > --- a/drivers/gpu/drm/imagination/pvr_queue.c > +++ b/drivers/gpu/drm/imagination/pvr_queue.c > @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, > }; > struct pvr_device *pvr_dev = ctx->pvr_dev; > struct drm_gpu_scheduler *sched; > + struct drm_sched_init_params sched_params; > struct pvr_queue *queue; > int ctx_state_size, err; > void *cpu_map; > > + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > + > if (WARN_ON(type >= sizeof(props))) > return ERR_PTR(-EINVAL); > > @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, > > queue->timeline_ufo.value = cpu_map; > > - err = drm_sched_init(&queue->scheduler, > - &pvr_queue_sched_ops, > - pvr_dev->sched_wq, 1, 64 * 1024, 1, > - msecs_to_jiffies(500), > - pvr_dev->sched_wq, NULL, "pvr-queue", > - pvr_dev->base.dev); > + sched_params.ops = &pvr_queue_sched_ops; > + sched_params.submit_wq = pvr_dev->sched_wq; > + sched_params.num_rqs = 1; > + sched_params.credit_limit = 64 * 1024; > + sched_params.hang_limit = 1; > + sched_params.timeout = msecs_to_jiffies(500); > + sched_params.timeout_wq = pvr_dev->sched_wq; > + sched_params.score = NULL; > + sched_params.name = "pvr-queue"; > + sched_params.dev = pvr_dev->base.dev; > + > + err = drm_sched_init(&queue->scheduler, &sched_params); > if (err) > goto err_release_ufo; > > diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c > index b40c90e97d7e..a64c50fb6d1e 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct work_struct *work) > > int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) > { > + struct drm_sched_init_params params; > unsigned int timeout = lima_sched_timeout_ms > 0 ? > lima_sched_timeout_ms : 10000; > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > 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, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - 1, > - lima_job_hang_limit, > - msecs_to_jiffies(timeout), NULL, > - NULL, name, pipe->ldev->dev); > + params.ops = &lima_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = 1; > + params.hang_limit = lima_job_hang_limit; > + params.timeout = msecs_to_jiffies(timeout); > + params.timeout_wq = NULL; /* Use the system_wq. */ > + params.score = NULL; > + params.name = name; > + params.dev = pipe->ldev->dev; > + > + return drm_sched_init(&pipe->base, ¶ms); > } > > void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) > diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c > index c803556a8f64..49a2c7422dc6 100644 > --- a/drivers/gpu/drm/msm/msm_ringbuffer.c > +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c > @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops msm_sched_ops = { > struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > void *memptrs, uint64_t memptrs_iova) > { > + struct drm_sched_init_params params; > struct msm_ringbuffer *ring; > - long sched_timeout; > char name[32]; > int ret; > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */ > BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); > > @@ -95,13 +97,19 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > ring->memptrs = memptrs; > ring->memptrs_iova = memptrs_iova; > > - /* currently managing hangcheck ourselves: */ > - sched_timeout = MAX_SCHEDULE_TIMEOUT; > + params.ops = &msm_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = num_hw_submissions; > + params.hang_limit = 0; > + /* currently managing hangcheck ourselves: */ > + params.timeout = MAX_SCHEDULE_TIMEOUT; > + params.timeout_wq = NULL; /* Use the system_wq. */ > + params.score = NULL; > + params.name = to_msm_bo(ring->bo)->name; > + params.dev = gpu->dev->dev; > > - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - num_hw_submissions, 0, sched_timeout, > - NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); > + ret = drm_sched_init(&ring->sched, ¶ms); > if (ret) { > goto fail; > } > diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c > index 4412f2711fb5..f20c2e612750 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_sched.c > +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c > @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, > { > struct drm_gpu_scheduler *drm_sched = &sched->base; > struct drm_sched_entity *entity = &sched->entity; > - const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > + struct drm_sched_init_params params; > int ret; > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > if (!wq) { > wq = alloc_workqueue("nouveau_sched_wq_%d", 0, WQ_MAX_ACTIVE, > current->pid); > @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, > sched->wq = wq; > } > > - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, > - NOUVEAU_SCHED_PRIORITY_COUNT, > - credit_limit, 0, timeout, > - NULL, NULL, "nouveau_sched", drm->dev->dev); > + params.ops = &nouveau_sched_ops; > + params.submit_wq = wq; > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = credit_limit; > + params.hang_limit = 0; > + params.timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > + params.timeout_wq = NULL; /* Use the system_wq. */ > + params.score = NULL; > + params.name = "nouveau_sched"; > + params.dev = drm->dev->dev; > + > + ret = drm_sched_init(drm_sched, ¶ms); > if (ret) > goto fail_wq; > > diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c > index 9b8e82fb8bc4..6b509ff446b5 100644 > --- a/drivers/gpu/drm/panfrost/panfrost_job.c > +++ b/drivers/gpu/drm/panfrost/panfrost_job.c > @@ -836,10 +836,13 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) > > int panfrost_job_init(struct panfrost_device *pfdev) > { > + struct drm_sched_init_params params; > struct panfrost_job_slot *js; > unsigned int nentries = 2; > int ret, j; > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > /* All GPUs have two entries per queue, but without jobchain > * disambiguation stopping the right job in the close path is tricky, > * so let's just advertise one entry in that case. > @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device *pfdev) > if (!pfdev->reset.wq) > return -ENOMEM; > > + params.ops = &panfrost_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params.credit_limit = nentries; > + params.hang_limit = 0; > + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > + params.timeout_wq = pfdev->reset.wq; > + params.score = NULL; > + params.name = "pan_js"; > + params.dev = pfdev->dev; > + > for (j = 0; j < NUM_JOB_SLOTS; j++) { > js->queue[j].fence_context = dma_fence_context_alloc(1); > > - ret = drm_sched_init(&js->queue[j].sched, > - &panfrost_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - nentries, 0, > - msecs_to_jiffies(JOB_TIMEOUT_MS), > - pfdev->reset.wq, > - NULL, "pan_js", pfdev->dev); > + ret = drm_sched_init(&js->queue[j].sched, ¶ms); > if (ret) { > dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret); > goto err_sched; > diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c > index a49132f3778b..4362442cbfd8 100644 > --- a/drivers/gpu/drm/panthor/panthor_mmu.c > +++ b/drivers/gpu/drm/panthor/panthor_mmu.c > @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, > u64 full_va_range = 1ull << va_bits; > struct drm_gem_object *dummy_gem; > struct drm_gpu_scheduler *sched; > + struct drm_sched_init_params sched_params; > struct io_pgtable_cfg pgtbl_cfg; > u64 mair, min_va, va_range; > struct panthor_vm *vm; > @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, > goto err_free_vm; > } > > + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > + > mutex_init(&vm->heaps.lock); > vm->for_mcu = for_mcu; > vm->ptdev = ptdev; > @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, > goto err_mm_takedown; > } > > + sched_params.ops = &panthor_vm_bind_ops; > + sched_params.submit_wq = ptdev->mmu->vm.wq; > + sched_params.num_rqs = 1; > + sched_params.credit_limit = 1; > + sched_params.hang_limit = 0; > /* Bind operations are synchronous for now, no timeout needed. */ > - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq, > - 1, 1, 0, > - MAX_SCHEDULE_TIMEOUT, NULL, NULL, > - "panthor-vm-bind", ptdev->base.dev); > + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; > + sched_params.timeout_wq = NULL; /* Use the system_wq. */ > + sched_params.score = NULL; > + sched_params.name = "panthor-vm-bind"; > + sched_params.dev = ptdev->base.dev; > + ret = drm_sched_init(&vm->sched, &sched_params); > if (ret) > goto err_free_io_pgtable; > > diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c > index ef4bec7ff9c7..a324346d302f 100644 > --- a/drivers/gpu/drm/panthor/panthor_sched.c > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, > const struct drm_panthor_queue_create *args) > { > struct drm_gpu_scheduler *drm_sched; > + struct drm_sched_init_params sched_params; > struct panthor_queue *queue; > int ret; > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, > if (!queue) > return ERR_PTR(-ENOMEM); > > + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > + > queue->fence_ctx.id = dma_fence_context_alloc(1); > spin_lock_init(&queue->fence_ctx.lock); > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, > if (ret) > goto err_free_queue; > > + sched_params.ops = &panthor_queue_sched_ops; > + sched_params.submit_wq = group->ptdev->scheduler->wq; > + sched_params.num_rqs = 1; > /* > - * Credit limit argument tells us the total number of instructions > + * The credit limit argument tells us the total number of instructions > * across all CS slots in the ringbuffer, with some jobs requiring > * twice as many as others, depending on their profiling status. > */ > - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, > - group->ptdev->scheduler->wq, 1, > - args->ringbuf_size / sizeof(u64), > - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > - group->ptdev->reset.wq, > - NULL, "panthor-queue", group->ptdev->base.dev); > + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); > + sched_params.hang_limit = 0; > + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > + sched_params.timeout_wq = group->ptdev->reset.wq; > + sched_params.score = NULL; > + sched_params.name = "panthor-queue"; > + sched_params.dev = group->ptdev->base.dev; > + > + ret = drm_sched_init(&queue->scheduler, &sched_params); > if (ret) > goto err_free_queue; > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c > index 57da84908752..27db748a5269 100644 > --- a/drivers/gpu/drm/scheduler/sched_main.c > +++ b/drivers/gpu/drm/scheduler/sched_main.c > @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct work_struct *w) > * drm_sched_init - Init a gpu scheduler instance > * > * @sched: scheduler instance > - * @ops: backend operations for this scheduler > - * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is > - * allocated and used > - * @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT > - * @credit_limit: the number of credits this scheduler can hold from all jobs > - * @hang_limit: number of times to allow a job to hang before dropping it > - * @timeout: timeout value in jiffies for the scheduler > - * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is > - * used > - * @score: optional score atomic shared with other schedulers > - * @name: name used for debugging > - * @dev: target &struct device > + * @params: scheduler initialization parameters > * > * Return 0 on success, otherwise error code. > */ > int drm_sched_init(struct drm_gpu_scheduler *sched, > - const struct drm_sched_backend_ops *ops, > - struct workqueue_struct *submit_wq, > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > - long timeout, struct workqueue_struct *timeout_wq, > - atomic_t *score, const char *name, struct device *dev) > + const struct drm_sched_init_params *params) > { > int i; > > - sched->ops = ops; > - sched->credit_limit = credit_limit; > - sched->name = name; > - sched->timeout = timeout; > - sched->timeout_wq = timeout_wq ? : system_wq; > - sched->hang_limit = hang_limit; > - sched->score = score ? score : &sched->_score; > - sched->dev = dev; > + sched->ops = params->ops; > + sched->credit_limit = params->credit_limit; > + sched->name = params->name; > + sched->timeout = params->timeout; > + sched->timeout_wq = params->timeout_wq ? : system_wq; > + sched->hang_limit = params->hang_limit; > + sched->score = params->score ? params->score : &sched->_score; > + sched->dev = params->dev; > > - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { > + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { > /* This is a gross violation--tell drivers what the problem is. > */ > drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n", > @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, > return 0; > } > > - if (submit_wq) { > - sched->submit_wq = submit_wq; > + if (params->submit_wq) { > + sched->submit_wq = params->submit_wq; > sched->own_submit_wq = false; > } else { > #ifdef CONFIG_LOCKDEP > - sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name, > - WQ_MEM_RECLAIM, > - &drm_sched_lockdep_map); > + sched->submit_wq = alloc_ordered_workqueue_lockdep_map( > + params->name, WQ_MEM_RECLAIM, > + &drm_sched_lockdep_map); > #else > - sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM); > + sched->submit_wq = alloc_ordered_workqueue(params->name, WQ_MEM_RECLAIM); > #endif > if (!sched->submit_wq) > return -ENOMEM; > @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, > sched->own_submit_wq = true; > } > > - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq), > + sched->sched_rq = kmalloc_array(params->num_rqs, sizeof(*sched->sched_rq), > GFP_KERNEL | __GFP_ZERO); > if (!sched->sched_rq) > goto Out_check_own; > - sched->num_rqs = num_rqs; > + sched->num_rqs = params->num_rqs; > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { > sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL); > if (!sched->sched_rq[i]) > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c > index 99ac4995b5a1..716e6d074d87 100644 > --- a/drivers/gpu/drm/v3d/v3d_sched.c > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { > .free_job = v3d_cpu_job_free > }; > > +/* > + * v3d's scheduler instances are all identical, except for ops and name. > + */ > +static void > +v3d_common_sched_init(struct drm_sched_init_params *params, struct device *dev) > +{ > + memset(params, 0, sizeof(struct drm_sched_init_params)); > + > + params->submit_wq = NULL; /* Use the system_wq. */ > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params->credit_limit = 1; > + params->hang_limit = 0; > + params->timeout = msecs_to_jiffies(500); > + params->timeout_wq = NULL; /* Use the system_wq. */ > + params->score = NULL; > + params->dev = dev; > +} > + > +static int > +v3d_bin_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_bin_sched_ops; > + params.name = "v3d_bin"; > + > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, ¶ms); > +} > + > +static int > +v3d_render_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_render_sched_ops; > + params.name = "v3d_render"; > + > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, ¶ms); > +} > + > +static int > +v3d_tfu_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_tfu_sched_ops; > + params.name = "v3d_tfu"; > + > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, ¶ms); > +} > + > +static int > +v3d_csd_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_csd_sched_ops; > + params.name = "v3d_csd"; > + > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, ¶ms); > +} > + > +static int > +v3d_cache_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_cache_clean_sched_ops; > + params.name = "v3d_cache_clean"; > + > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, ¶ms); > +} > + > +static int > +v3d_cpu_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_cpu_sched_ops; > + params.name = "v3d_cpu"; > + > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, ¶ms); > +} > + > int > v3d_sched_init(struct v3d_dev *v3d) > { > - int hw_jobs_limit = 1; > - int job_hang_limit = 0; > - int hang_limit_ms = 500; > int ret; > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > - &v3d_bin_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_bin", v3d->drm.dev); > + ret = v3d_bin_sched_init(v3d); > if (ret) > return ret; > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > - &v3d_render_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_render", v3d->drm.dev); > + ret = v3d_render_sched_init(v3d); > if (ret) > goto fail; > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > - &v3d_tfu_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_tfu", v3d->drm.dev); > + ret = v3d_tfu_sched_init(v3d); > if (ret) > goto fail; > > if (v3d_has_csd(v3d)) { > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > - &v3d_csd_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_csd", v3d->drm.dev); > + ret = v3d_csd_sched_init(v3d); > if (ret) > goto fail; > > - ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > - &v3d_cache_clean_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_cache_clean", v3d->drm.dev); > + ret = v3d_cache_sched_init(v3d); > if (ret) > goto fail; > } > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > - &v3d_cpu_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - 1, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_cpu", v3d->drm.dev); > + ret = v3d_cpu_sched_init(v3d); > if (ret) > goto fail; > > diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c > index a8c416a48812..7f29b7f04af4 100644 > --- a/drivers/gpu/drm/xe/xe_execlist.c > +++ b/drivers/gpu/drm/xe/xe_execlist.c > @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops drm_sched_ops = { > static int execlist_exec_queue_init(struct xe_exec_queue *q) > { > struct drm_gpu_scheduler *sched; > + struct drm_sched_init_params params; > struct xe_execlist_exec_queue *exl; > struct xe_device *xe = gt_to_xe(q->gt); > int err; > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > xe_assert(xe, !xe_device_uc_enabled(xe)); > > drm_info(&xe->drm, "Enabling execlist submission (GuC submission disabled)\n"); > @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q) > > exl->q = q; > > - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, > - q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, > - XE_SCHED_HANG_LIMIT, XE_SCHED_JOB_TIMEOUT, > - NULL, NULL, q->hwe->name, > - gt_to_xe(q->gt)->drm.dev); > + params.ops = &drm_sched_ops; > + params.submit_wq = NULL; /* Use the system_wq. */ > + params.num_rqs = 1; > + params.credit_limit = q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES; > + params.hang_limit = XE_SCHED_HANG_LIMIT; > + params.timeout = XE_SCHED_JOB_TIMEOUT; > + params.timeout_wq = NULL; /* Use the system_wq. */ > + params.score = NULL; > + params.name = q->hwe->name; > + params.dev = gt_to_xe(q->gt)->drm.dev; > + > + err = drm_sched_init(&exl->sched, ¶ms); > if (err) > goto err_free; > > diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > index 50361b4638f9..2129fee83f25 100644 > --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler *sched, > atomic_t *score, const char *name, > struct device *dev) > { > + struct drm_sched_init_params params; > + > sched->ops = xe_ops; > INIT_LIST_HEAD(&sched->msgs); > INIT_WORK(&sched->work_process_msg, xe_sched_process_msg_work); > > - return drm_sched_init(&sched->base, ops, submit_wq, 1, hw_submission, > - hang_limit, timeout, timeout_wq, score, name, > - dev); > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > + > + params.ops = ops; > + params.submit_wq = submit_wq; > + params.num_rqs = 1; > + params.credit_limit = hw_submission; > + params.hang_limit = hang_limit; > + params.timeout = timeout; > + params.timeout_wq = timeout_wq; > + params.score = score; > + params.name = name; > + params.dev = dev; > + > + return drm_sched_init(&sched->base, ¶ms); > } > > void xe_sched_fini(struct xe_gpu_scheduler *sched) > diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h > index 95e17504e46a..1a834ef43862 100644 > --- a/include/drm/gpu_scheduler.h > +++ b/include/drm/gpu_scheduler.h > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > struct device *dev; > }; > > +/** > + * struct drm_sched_init_params - parameters for initializing a DRM GPU scheduler > + * > + * @ops: backend operations provided by the driver > + * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is > + * allocated and used > + * @num_rqs: Number of run-queues. This is at most DRM_SCHED_PRIORITY_COUNT, > + * as there's usually one run-queue per priority, but could be less. > + * @credit_limit: the number of credits this scheduler can hold from all jobs > + * @hang_limit: number of times to allow a job to hang before dropping it > + * @timeout: timeout value in jiffies for the scheduler > + * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is > + * used > + * @score: optional score atomic shared with other schedulers > + * @name: name used for debugging > + * @dev: associated device. Used for debugging > + */ > +struct drm_sched_init_params { > + const struct drm_sched_backend_ops *ops; > + struct workqueue_struct *submit_wq; > + struct workqueue_struct *timeout_wq; > + u32 num_rqs, credit_limit; > + unsigned int hang_limit; > + long timeout; > + atomic_t *score; > + const char *name; > + struct device *dev; > +}; > + > int drm_sched_init(struct drm_gpu_scheduler *sched, > - const struct drm_sched_backend_ops *ops, > - struct workqueue_struct *submit_wq, > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > - long timeout, struct workqueue_struct *timeout_wq, > - atomic_t *score, const char *name, struct device *dev); > + const struct drm_sched_init_params *params); > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > int drm_sched_job_init(struct drm_sched_job *job,
On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: > Am 22.01.25 um 15:08 schrieb Philipp Stanner: > > drm_sched_init() has a great many parameters and upcoming new > > functionality for the scheduler might add even more. Generally, the > > great number of parameters reduces readability and has already > > caused > > one missnaming in: > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > nouveau_sched_init()"). > > > > Introduce a new struct for the scheduler init parameters and port > > all > > users. > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > --- > > Howdy, > > > > I have a patch-series in the pipe that will add a `flags` argument > > to > > drm_sched_init(). I thought it would be wise to first rework the > > API as > > detailed in this patch. It's really a lot of parameters by now, and > > I > > would expect that it might get more and more over the years for > > special > > use cases etc. > > > > Regards, > > P. > > --- > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++- > > ----- > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > include/drm/gpu_scheduler.h | 35 +++++- > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > index cd4fac120834..c1f03eb5f5ea 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > @@ -2821,6 +2821,9 @@ static int > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > { > > long timeout; > > int r, i; > > + struct drm_sched_init_params params; > > Please keep the reverse xmas tree ordering for variable declaration. > E.g. long lines first and variables like "i" and "r" last. Okay dokay > > Apart from that looks like a good idea to me. > > > > + > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { > > struct amdgpu_ring *ring = adev->rings[i]; > > @@ -2844,12 +2847,18 @@ static int > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > break; > > } > > > > - r = drm_sched_init(&ring->sched, > > &amdgpu_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - ring->num_hw_submission, 0, > > - timeout, adev->reset_domain- > > >wq, > > - ring->sched_score, ring->name, > > - adev->dev); > > + params.ops = &amdgpu_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = ring->num_hw_submission; > > + params.hang_limit = 0; > > Could we please remove the hang limit as first step to get this awful > feature deprecated? Remove it? From the struct you mean? We can mark it as deprecated in the docstring of the new struct. That's what you mean, don't you? P. > > Thanks, > Christian. > > > + params.timeout = timeout; > > + params.timeout_wq = adev->reset_domain->wq; > > + params.score = ring->sched_score; > > + params.name = ring->name; > > + params.dev = adev->dev; > > + > > + r = drm_sched_init(&ring->sched, ¶ms); > > if (r) { > > DRM_ERROR("Failed to create scheduler on > > ring %s.\n", > > ring->name); > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > index 5b67eda122db..7d8517f1963e 100644 > > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct > > etnaviv_gem_submit *submit) > > int etnaviv_sched_init(struct etnaviv_gpu *gpu) > > { > > int ret; > > + struct drm_sched_init_params params; > > > > - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, > > NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - etnaviv_hw_jobs_limit, > > etnaviv_job_hang_limit, > > - msecs_to_jiffies(500), NULL, NULL, > > - dev_name(gpu->dev), gpu->dev); > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > + params.ops = &etnaviv_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = etnaviv_hw_jobs_limit; > > + params.hang_limit = etnaviv_job_hang_limit; > > + params.timeout = msecs_to_jiffies(500); > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > + params.score = NULL; > > + params.name = dev_name(gpu->dev); > > + params.dev = gpu->dev; > > + > > + ret = drm_sched_init(&gpu->sched, ¶ms); > > if (ret) > > return ret; > > > > diff --git a/drivers/gpu/drm/imagination/pvr_queue.c > > b/drivers/gpu/drm/imagination/pvr_queue.c > > index c4f08432882b..03a2ce1a88e7 100644 > > --- a/drivers/gpu/drm/imagination/pvr_queue.c > > +++ b/drivers/gpu/drm/imagination/pvr_queue.c > > @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct > > pvr_context *ctx, > > }; > > struct pvr_device *pvr_dev = ctx->pvr_dev; > > struct drm_gpu_scheduler *sched; > > + struct drm_sched_init_params sched_params; > > struct pvr_queue *queue; > > int ctx_state_size, err; > > void *cpu_map; > > > > + memset(&sched_params, 0, sizeof(struct > > drm_sched_init_params)); > > + > > if (WARN_ON(type >= sizeof(props))) > > return ERR_PTR(-EINVAL); > > > > @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct > > pvr_context *ctx, > > > > queue->timeline_ufo.value = cpu_map; > > > > - err = drm_sched_init(&queue->scheduler, > > - &pvr_queue_sched_ops, > > - pvr_dev->sched_wq, 1, 64 * 1024, 1, > > - msecs_to_jiffies(500), > > - pvr_dev->sched_wq, NULL, "pvr-queue", > > - pvr_dev->base.dev); > > + sched_params.ops = &pvr_queue_sched_ops; > > + sched_params.submit_wq = pvr_dev->sched_wq; > > + sched_params.num_rqs = 1; > > + sched_params.credit_limit = 64 * 1024; > > + sched_params.hang_limit = 1; > > + sched_params.timeout = msecs_to_jiffies(500); > > + sched_params.timeout_wq = pvr_dev->sched_wq; > > + sched_params.score = NULL; > > + sched_params.name = "pvr-queue"; > > + sched_params.dev = pvr_dev->base.dev; > > + > > + err = drm_sched_init(&queue->scheduler, &sched_params); > > if (err) > > goto err_release_ufo; > > > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > > b/drivers/gpu/drm/lima/lima_sched.c > > index b40c90e97d7e..a64c50fb6d1e 100644 > > --- a/drivers/gpu/drm/lima/lima_sched.c > > +++ b/drivers/gpu/drm/lima/lima_sched.c > > @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct > > work_struct *work) > > > > int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char > > *name) > > { > > + struct drm_sched_init_params params; > > unsigned int timeout = lima_sched_timeout_ms > 0 ? > > lima_sched_timeout_ms : 10000; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > 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, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - 1, > > - lima_job_hang_limit, > > - msecs_to_jiffies(timeout), NULL, > > - NULL, name, pipe->ldev->dev); > > + params.ops = &lima_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = 1; > > + params.hang_limit = lima_job_hang_limit; > > + params.timeout = msecs_to_jiffies(timeout); > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > + params.score = NULL; > > + params.name = name; > > + params.dev = pipe->ldev->dev; > > + > > + return drm_sched_init(&pipe->base, ¶ms); > > } > > > > void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) > > diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c > > b/drivers/gpu/drm/msm/msm_ringbuffer.c > > index c803556a8f64..49a2c7422dc6 100644 > > --- a/drivers/gpu/drm/msm/msm_ringbuffer.c > > +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c > > @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops > > msm_sched_ops = { > > struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, > > int id, > > void *memptrs, uint64_t memptrs_iova) > > { > > + struct drm_sched_init_params params; > > struct msm_ringbuffer *ring; > > - long sched_timeout; > > char name[32]; > > int ret; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a > > power of 2 */ > > BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); > > > > @@ -95,13 +97,19 @@ struct msm_ringbuffer > > *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > > ring->memptrs = memptrs; > > ring->memptrs_iova = memptrs_iova; > > > > - /* currently managing hangcheck ourselves: */ > > - sched_timeout = MAX_SCHEDULE_TIMEOUT; > > + params.ops = &msm_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = num_hw_submissions; > > + params.hang_limit = 0; > > + /* currently managing hangcheck ourselves: */ > > + params.timeout = MAX_SCHEDULE_TIMEOUT; > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > + params.score = NULL; > > + params.name = to_msm_bo(ring->bo)->name; > > + params.dev = gpu->dev->dev; > > > > - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - num_hw_submissions, 0, sched_timeout, > > - NULL, NULL, to_msm_bo(ring->bo)- > > >name, gpu->dev->dev); > > + ret = drm_sched_init(&ring->sched, ¶ms); > > if (ret) { > > goto fail; > > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c > > b/drivers/gpu/drm/nouveau/nouveau_sched.c > > index 4412f2711fb5..f20c2e612750 100644 > > --- a/drivers/gpu/drm/nouveau/nouveau_sched.c > > +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c > > @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched > > *sched, struct nouveau_drm *drm, > > { > > struct drm_gpu_scheduler *drm_sched = &sched->base; > > struct drm_sched_entity *entity = &sched->entity; > > - const long timeout = > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > + struct drm_sched_init_params params; > > int ret; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > if (!wq) { > > wq = alloc_workqueue("nouveau_sched_wq_%d", 0, > > WQ_MAX_ACTIVE, > > current->pid); > > @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched > > *sched, struct nouveau_drm *drm, > > sched->wq = wq; > > } > > > > - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, > > - NOUVEAU_SCHED_PRIORITY_COUNT, > > - credit_limit, 0, timeout, > > - NULL, NULL, "nouveau_sched", drm- > > >dev->dev); > > + params.ops = &nouveau_sched_ops; > > + params.submit_wq = wq; > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = credit_limit; > > + params.hang_limit = 0; > > + params.timeout = > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > + params.score = NULL; > > + params.name = "nouveau_sched"; > > + params.dev = drm->dev->dev; > > + > > + ret = drm_sched_init(drm_sched, ¶ms); > > if (ret) > > goto fail_wq; > > > > diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c > > b/drivers/gpu/drm/panfrost/panfrost_job.c > > index 9b8e82fb8bc4..6b509ff446b5 100644 > > --- a/drivers/gpu/drm/panfrost/panfrost_job.c > > +++ b/drivers/gpu/drm/panfrost/panfrost_job.c > > @@ -836,10 +836,13 @@ static irqreturn_t > > panfrost_job_irq_handler(int irq, void *data) > > > > int panfrost_job_init(struct panfrost_device *pfdev) > > { > > + struct drm_sched_init_params params; > > struct panfrost_job_slot *js; > > unsigned int nentries = 2; > > int ret, j; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > /* All GPUs have two entries per queue, but without > > jobchain > > * disambiguation stopping the right job in the close path > > is tricky, > > * so let's just advertise one entry in that case. > > @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device > > *pfdev) > > if (!pfdev->reset.wq) > > return -ENOMEM; > > > > + params.ops = &panfrost_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params.credit_limit = nentries; > > + params.hang_limit = 0; > > + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > + params.timeout_wq = pfdev->reset.wq; > > + params.score = NULL; > > + params.name = "pan_js"; > > + params.dev = pfdev->dev; > > + > > for (j = 0; j < NUM_JOB_SLOTS; j++) { > > js->queue[j].fence_context = > > dma_fence_context_alloc(1); > > > > - ret = drm_sched_init(&js->queue[j].sched, > > - &panfrost_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - nentries, 0, > > - > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > - pfdev->reset.wq, > > - NULL, "pan_js", pfdev->dev); > > + ret = drm_sched_init(&js->queue[j].sched, > > ¶ms); > > if (ret) { > > dev_err(pfdev->dev, "Failed to create > > scheduler: %d.", ret); > > goto err_sched; > > diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c > > b/drivers/gpu/drm/panthor/panthor_mmu.c > > index a49132f3778b..4362442cbfd8 100644 > > --- a/drivers/gpu/drm/panthor/panthor_mmu.c > > +++ b/drivers/gpu/drm/panthor/panthor_mmu.c > > @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device > > *ptdev, bool for_mcu, > > u64 full_va_range = 1ull << va_bits; > > struct drm_gem_object *dummy_gem; > > struct drm_gpu_scheduler *sched; > > + struct drm_sched_init_params sched_params; > > struct io_pgtable_cfg pgtbl_cfg; > > u64 mair, min_va, va_range; > > struct panthor_vm *vm; > > @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device > > *ptdev, bool for_mcu, > > goto err_free_vm; > > } > > > > + memset(&sched_params, 0, sizeof(struct > > drm_sched_init_params)); > > + > > mutex_init(&vm->heaps.lock); > > vm->for_mcu = for_mcu; > > vm->ptdev = ptdev; > > @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device > > *ptdev, bool for_mcu, > > goto err_mm_takedown; > > } > > > > + sched_params.ops = &panthor_vm_bind_ops; > > + sched_params.submit_wq = ptdev->mmu->vm.wq; > > + sched_params.num_rqs = 1; > > + sched_params.credit_limit = 1; > > + sched_params.hang_limit = 0; > > /* Bind operations are synchronous for now, no timeout > > needed. */ > > - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, > > ptdev->mmu->vm.wq, > > - 1, 1, 0, > > - MAX_SCHEDULE_TIMEOUT, NULL, NULL, > > - "panthor-vm-bind", ptdev->base.dev); > > + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; > > + sched_params.timeout_wq = NULL; /* Use the system_wq. */ > > + sched_params.score = NULL; > > + sched_params.name = "panthor-vm-bind"; > > + sched_params.dev = ptdev->base.dev; > > + ret = drm_sched_init(&vm->sched, &sched_params); > > if (ret) > > goto err_free_io_pgtable; > > > > diff --git a/drivers/gpu/drm/panthor/panthor_sched.c > > b/drivers/gpu/drm/panthor/panthor_sched.c > > index ef4bec7ff9c7..a324346d302f 100644 > > --- a/drivers/gpu/drm/panthor/panthor_sched.c > > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group > > *group, > > const struct drm_panthor_queue_create *args) > > { > > struct drm_gpu_scheduler *drm_sched; > > + struct drm_sched_init_params sched_params; > > struct panthor_queue *queue; > > int ret; > > > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group > > *group, > > if (!queue) > > return ERR_PTR(-ENOMEM); > > > > + memset(&sched_params, 0, sizeof(struct > > drm_sched_init_params)); > > + > > queue->fence_ctx.id = dma_fence_context_alloc(1); > > spin_lock_init(&queue->fence_ctx.lock); > > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group > > *group, > > if (ret) > > goto err_free_queue; > > > > + sched_params.ops = &panthor_queue_sched_ops; > > + sched_params.submit_wq = group->ptdev->scheduler->wq; > > + sched_params.num_rqs = 1; > > /* > > - * Credit limit argument tells us the total number of > > instructions > > + * The credit limit argument tells us the total number of > > instructions > > * across all CS slots in the ringbuffer, with some jobs > > requiring > > * twice as many as others, depending on their profiling > > status. > > */ > > - ret = drm_sched_init(&queue->scheduler, > > &panthor_queue_sched_ops, > > - group->ptdev->scheduler->wq, 1, > > - args->ringbuf_size / sizeof(u64), > > - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > > - group->ptdev->reset.wq, > > - NULL, "panthor-queue", group->ptdev- > > >base.dev); > > + sched_params.credit_limit = args->ringbuf_size / > > sizeof(u64); > > + sched_params.hang_limit = 0; > > + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > + sched_params.timeout_wq = group->ptdev->reset.wq; > > + sched_params.score = NULL; > > + sched_params.name = "panthor-queue"; > > + sched_params.dev = group->ptdev->base.dev; > > + > > + ret = drm_sched_init(&queue->scheduler, &sched_params); > > if (ret) > > goto err_free_queue; > > > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > > b/drivers/gpu/drm/scheduler/sched_main.c > > index 57da84908752..27db748a5269 100644 > > --- a/drivers/gpu/drm/scheduler/sched_main.c > > +++ b/drivers/gpu/drm/scheduler/sched_main.c > > @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct > > work_struct *w) > > * drm_sched_init - Init a gpu scheduler instance > > * > > * @sched: scheduler instance > > - * @ops: backend operations for this scheduler > > - * @submit_wq: workqueue to use for submission. If NULL, an > > ordered wq is > > - * allocated and used > > - * @num_rqs: number of runqueues, one for each priority, up to > > DRM_SCHED_PRIORITY_COUNT > > - * @credit_limit: the number of credits this scheduler can hold > > from all jobs > > - * @hang_limit: number of times to allow a job to hang before > > dropping it > > - * @timeout: timeout value in jiffies for the scheduler > > - * @timeout_wq: workqueue to use for timeout work. If NULL, the > > system_wq is > > - * used > > - * @score: optional score atomic shared with other schedulers > > - * @name: name used for debugging > > - * @dev: target &struct device > > + * @params: scheduler initialization parameters > > * > > * Return 0 on success, otherwise error code. > > */ > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > - const struct drm_sched_backend_ops *ops, > > - struct workqueue_struct *submit_wq, > > - u32 num_rqs, u32 credit_limit, unsigned int > > hang_limit, > > - long timeout, struct workqueue_struct > > *timeout_wq, > > - atomic_t *score, const char *name, struct > > device *dev) > > + const struct drm_sched_init_params *params) > > { > > int i; > > > > - sched->ops = ops; > > - sched->credit_limit = credit_limit; > > - sched->name = name; > > - sched->timeout = timeout; > > - sched->timeout_wq = timeout_wq ? : system_wq; > > - sched->hang_limit = hang_limit; > > - sched->score = score ? score : &sched->_score; > > - sched->dev = dev; > > + sched->ops = params->ops; > > + sched->credit_limit = params->credit_limit; > > + sched->name = params->name; > > + sched->timeout = params->timeout; > > + sched->timeout_wq = params->timeout_wq ? : system_wq; > > + sched->hang_limit = params->hang_limit; > > + sched->score = params->score ? params->score : &sched- > > >_score; > > + sched->dev = params->dev; > > > > - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > /* This is a gross violation--tell drivers what > > the problem is. > > */ > > drm_err(sched, "%s: num_rqs cannot be greater than > > DRM_SCHED_PRIORITY_COUNT\n", > > @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler > > *sched, > > return 0; > > } > > > > - if (submit_wq) { > > - sched->submit_wq = submit_wq; > > + if (params->submit_wq) { > > + sched->submit_wq = params->submit_wq; > > sched->own_submit_wq = false; > > } else { > > #ifdef CONFIG_LOCKDEP > > - sched->submit_wq = > > alloc_ordered_workqueue_lockdep_map(name, > > - > > WQ_MEM_RECLAIM, > > - > > &drm_sched_lockdep_map); > > + sched->submit_wq = > > alloc_ordered_workqueue_lockdep_map( > > + params->name, > > WQ_MEM_RECLAIM, > > + &drm_sched_lockdep_map); > > #else > > - sched->submit_wq = alloc_ordered_workqueue(name, > > WQ_MEM_RECLAIM); > > + sched->submit_wq = alloc_ordered_workqueue(params- > > >name, WQ_MEM_RECLAIM); > > #endif > > if (!sched->submit_wq) > > return -ENOMEM; > > @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler > > *sched, > > sched->own_submit_wq = true; > > } > > > > - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched- > > >sched_rq), > > + sched->sched_rq = kmalloc_array(params->num_rqs, > > sizeof(*sched->sched_rq), > > GFP_KERNEL | __GFP_ZERO); > > if (!sched->sched_rq) > > goto Out_check_own; > > - sched->num_rqs = num_rqs; > > + sched->num_rqs = params->num_rqs; > > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; > > i++) { > > sched->sched_rq[i] = kzalloc(sizeof(*sched- > > >sched_rq[i]), GFP_KERNEL); > > if (!sched->sched_rq[i]) > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > b/drivers/gpu/drm/v3d/v3d_sched.c > > index 99ac4995b5a1..716e6d074d87 100644 > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops > > v3d_cpu_sched_ops = { > > .free_job = v3d_cpu_job_free > > }; > > > > +/* > > + * v3d's scheduler instances are all identical, except for ops and > > name. > > + */ > > +static void > > +v3d_common_sched_init(struct drm_sched_init_params *params, struct > > device *dev) > > +{ > > + memset(params, 0, sizeof(struct drm_sched_init_params)); > > + > > + params->submit_wq = NULL; /* Use the system_wq. */ > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params->credit_limit = 1; > > + params->hang_limit = 0; > > + params->timeout = msecs_to_jiffies(500); > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > + params->score = NULL; > > + params->dev = dev; > > +} > > + > > +static int > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_bin_sched_ops; > > + params.name = "v3d_bin"; > > + > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_render_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_render_sched_ops; > > + params.name = "v3d_render"; > > + > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_tfu_sched_ops; > > + params.name = "v3d_tfu"; > > + > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_csd_sched_ops; > > + params.name = "v3d_csd"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_cache_clean_sched_ops; > > + params.name = "v3d_cache_clean"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_cpu_sched_ops; > > + params.name = "v3d_cpu"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > ¶ms); > > +} > > + > > int > > v3d_sched_init(struct v3d_dev *v3d) > > { > > - int hw_jobs_limit = 1; > > - int job_hang_limit = 0; > > - int hang_limit_ms = 500; > > int ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > - &v3d_bin_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_bin", v3d->drm.dev); > > + ret = v3d_bin_sched_init(v3d); > > if (ret) > > return ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > - &v3d_render_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_render", v3d->drm.dev); > > + ret = v3d_render_sched_init(v3d); > > if (ret) > > goto fail; > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > - &v3d_tfu_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_tfu", v3d->drm.dev); > > + ret = v3d_tfu_sched_init(v3d); > > if (ret) > > goto fail; > > > > if (v3d_has_csd(v3d)) { > > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > > - &v3d_csd_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, > > job_hang_limit, > > - > > msecs_to_jiffies(hang_limit_ms), NULL, > > - NULL, "v3d_csd", v3d- > > >drm.dev); > > + ret = v3d_csd_sched_init(v3d); > > if (ret) > > goto fail; > > > > - ret = drm_sched_init(&v3d- > > >queue[V3D_CACHE_CLEAN].sched, > > - &v3d_cache_clean_sched_ops, > > NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, > > job_hang_limit, > > - > > msecs_to_jiffies(hang_limit_ms), NULL, > > - NULL, "v3d_cache_clean", v3d- > > >drm.dev); > > + ret = v3d_cache_sched_init(v3d); > > if (ret) > > goto fail; > > } > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > - &v3d_cpu_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - 1, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_cpu", v3d->drm.dev); > > + ret = v3d_cpu_sched_init(v3d); > > if (ret) > > goto fail; > > > > diff --git a/drivers/gpu/drm/xe/xe_execlist.c > > b/drivers/gpu/drm/xe/xe_execlist.c > > index a8c416a48812..7f29b7f04af4 100644 > > --- a/drivers/gpu/drm/xe/xe_execlist.c > > +++ b/drivers/gpu/drm/xe/xe_execlist.c > > @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops > > drm_sched_ops = { > > static int execlist_exec_queue_init(struct xe_exec_queue *q) > > { > > struct drm_gpu_scheduler *sched; > > + struct drm_sched_init_params params; > > struct xe_execlist_exec_queue *exl; > > struct xe_device *xe = gt_to_xe(q->gt); > > int err; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > xe_assert(xe, !xe_device_uc_enabled(xe)); > > > > drm_info(&xe->drm, "Enabling execlist submission (GuC > > submission disabled)\n"); > > @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct > > xe_exec_queue *q) > > > > exl->q = q; > > > > - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, > > - q->lrc[0]->ring.size / > > MAX_JOB_SIZE_BYTES, > > - XE_SCHED_HANG_LIMIT, > > XE_SCHED_JOB_TIMEOUT, > > - NULL, NULL, q->hwe->name, > > - gt_to_xe(q->gt)->drm.dev); > > + params.ops = &drm_sched_ops; > > + params.submit_wq = NULL; /* Use the system_wq. */ > > + params.num_rqs = 1; > > + params.credit_limit = q->lrc[0]->ring.size / > > MAX_JOB_SIZE_BYTES; > > + params.hang_limit = XE_SCHED_HANG_LIMIT; > > + params.timeout = XE_SCHED_JOB_TIMEOUT; > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > + params.score = NULL; > > + params.name = q->hwe->name; > > + params.dev = gt_to_xe(q->gt)->drm.dev; > > + > > + err = drm_sched_init(&exl->sched, ¶ms); > > if (err) > > goto err_free; > > > > diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > index 50361b4638f9..2129fee83f25 100644 > > --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler > > *sched, > > atomic_t *score, const char *name, > > struct device *dev) > > { > > + struct drm_sched_init_params params; > > + > > sched->ops = xe_ops; > > INIT_LIST_HEAD(&sched->msgs); > > INIT_WORK(&sched->work_process_msg, > > xe_sched_process_msg_work); > > > > - return drm_sched_init(&sched->base, ops, submit_wq, 1, > > hw_submission, > > - hang_limit, timeout, timeout_wq, > > score, name, > > - dev); > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > + > > + params.ops = ops; > > + params.submit_wq = submit_wq; > > + params.num_rqs = 1; > > + params.credit_limit = hw_submission; > > + params.hang_limit = hang_limit; > > + params.timeout = timeout; > > + params.timeout_wq = timeout_wq; > > + params.score = score; > > + params.name = name; > > + params.dev = dev; > > + > > + return drm_sched_init(&sched->base, ¶ms); > > } > > > > void xe_sched_fini(struct xe_gpu_scheduler *sched) > > diff --git a/include/drm/gpu_scheduler.h > > b/include/drm/gpu_scheduler.h > > index 95e17504e46a..1a834ef43862 100644 > > --- a/include/drm/gpu_scheduler.h > > +++ b/include/drm/gpu_scheduler.h > > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > > struct device *dev; > > }; > > > > +/** > > + * struct drm_sched_init_params - parameters for initializing a > > DRM GPU scheduler > > + * > > + * @ops: backend operations provided by the driver > > + * @submit_wq: workqueue to use for submission. If NULL, an > > ordered wq is > > + * allocated and used > > + * @num_rqs: Number of run-queues. This is at most > > DRM_SCHED_PRIORITY_COUNT, > > + * as there's usually one run-queue per priority, but > > could be less. > > + * @credit_limit: the number of credits this scheduler can hold > > from all jobs > > + * @hang_limit: number of times to allow a job to hang before > > dropping it > > + * @timeout: timeout value in jiffies for the scheduler > > + * @timeout_wq: workqueue to use for timeout work. If NULL, the > > system_wq is > > + * used > > + * @score: optional score atomic shared with other schedulers > > + * @name: name used for debugging > > + * @dev: associated device. Used for debugging > > + */ > > +struct drm_sched_init_params { > > + const struct drm_sched_backend_ops *ops; > > + struct workqueue_struct *submit_wq; > > + struct workqueue_struct *timeout_wq; > > + u32 num_rqs, credit_limit; > > + unsigned int hang_limit; > > + long timeout; > > + atomic_t *score; > > + const char *name; > > + struct device *dev; > > +}; > > + > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > - const struct drm_sched_backend_ops *ops, > > - struct workqueue_struct *submit_wq, > > - u32 num_rqs, u32 credit_limit, unsigned int > > hang_limit, > > - long timeout, struct workqueue_struct > > *timeout_wq, > > - atomic_t *score, const char *name, struct > > device *dev); > > + const struct drm_sched_init_params *params); > > > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > > int drm_sched_job_init(struct drm_sched_job *job, >
On Wed, Jan 22, 2025 at 03:48:54PM +0100, Philipp Stanner wrote: > On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: > > Am 22.01.25 um 15:08 schrieb Philipp Stanner: > > > drm_sched_init() has a great many parameters and upcoming new > > > functionality for the scheduler might add even more. Generally, the > > > great number of parameters reduces readability and has already > > > caused > > > one missnaming in: > > > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > > nouveau_sched_init()"). > > > > > > Introduce a new struct for the scheduler init parameters and port > > > all > > > users. > > > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > > --- > > > Howdy, > > > > > > I have a patch-series in the pipe that will add a `flags` argument > > > to > > > drm_sched_init(). I thought it would be wise to first rework the > > > API as > > > detailed in this patch. It's really a lot of parameters by now, and > > > I > > > would expect that it might get more and more over the years for > > > special > > > use cases etc. > > > > > > Regards, > > > P. > > > --- > > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++- > > > ----- > > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > > include/drm/gpu_scheduler.h | 35 +++++- > > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > index cd4fac120834..c1f03eb5f5ea 100644 > > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > @@ -2821,6 +2821,9 @@ static int > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > { > > > long timeout; > > > int r, i; > > > + struct drm_sched_init_params params; > > > > Please keep the reverse xmas tree ordering for variable declaration. > > E.g. long lines first and variables like "i" and "r" last. > > Okay dokay > > > > > Apart from that looks like a good idea to me. > > +1. Looks like a good idea to me. Quite sure I have transposed arguments in the past and broken thing, this would be a way to avoid this. One bikeshed. s/drm_sched_init_params/drm_sched_init_args? No strong preference though. Matt > > > > > + > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > > > for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { > > > struct amdgpu_ring *ring = adev->rings[i]; > > > @@ -2844,12 +2847,18 @@ static int > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > break; > > > } > > > > > > - r = drm_sched_init(&ring->sched, > > > &amdgpu_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - ring->num_hw_submission, 0, > > > - timeout, adev->reset_domain- > > > >wq, > > > - ring->sched_score, ring->name, > > > - adev->dev); > > > + params.ops = &amdgpu_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = ring->num_hw_submission; > > > + params.hang_limit = 0; > > > > Could we please remove the hang limit as first step to get this awful > > feature deprecated? > > Remove it? From the struct you mean? > > We can mark it as deprecated in the docstring of the new struct. That's > what you mean, don't you? > > P. > > > > > Thanks, > > Christian. > > > > > + params.timeout = timeout; > > > + params.timeout_wq = adev->reset_domain->wq; > > > + params.score = ring->sched_score; > > > + params.name = ring->name; > > > + params.dev = adev->dev; > > > + > > > + r = drm_sched_init(&ring->sched, ¶ms); > > > if (r) { > > > DRM_ERROR("Failed to create scheduler on > > > ring %s.\n", > > > ring->name); > > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > index 5b67eda122db..7d8517f1963e 100644 > > > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct > > > etnaviv_gem_submit *submit) > > > int etnaviv_sched_init(struct etnaviv_gpu *gpu) > > > { > > > int ret; > > > + struct drm_sched_init_params params; > > > > > > - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, > > > NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - etnaviv_hw_jobs_limit, > > > etnaviv_job_hang_limit, > > > - msecs_to_jiffies(500), NULL, NULL, > > > - dev_name(gpu->dev), gpu->dev); > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > + params.ops = &etnaviv_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = etnaviv_hw_jobs_limit; > > > + params.hang_limit = etnaviv_job_hang_limit; > > > + params.timeout = msecs_to_jiffies(500); > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > + params.score = NULL; > > > + params.name = dev_name(gpu->dev); > > > + params.dev = gpu->dev; > > > + > > > + ret = drm_sched_init(&gpu->sched, ¶ms); > > > if (ret) > > > return ret; > > > > > > diff --git a/drivers/gpu/drm/imagination/pvr_queue.c > > > b/drivers/gpu/drm/imagination/pvr_queue.c > > > index c4f08432882b..03a2ce1a88e7 100644 > > > --- a/drivers/gpu/drm/imagination/pvr_queue.c > > > +++ b/drivers/gpu/drm/imagination/pvr_queue.c > > > @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct > > > pvr_context *ctx, > > > }; > > > struct pvr_device *pvr_dev = ctx->pvr_dev; > > > struct drm_gpu_scheduler *sched; > > > + struct drm_sched_init_params sched_params; > > > struct pvr_queue *queue; > > > int ctx_state_size, err; > > > void *cpu_map; > > > > > > + memset(&sched_params, 0, sizeof(struct > > > drm_sched_init_params)); > > > + > > > if (WARN_ON(type >= sizeof(props))) > > > return ERR_PTR(-EINVAL); > > > > > > @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct > > > pvr_context *ctx, > > > > > > queue->timeline_ufo.value = cpu_map; > > > > > > - err = drm_sched_init(&queue->scheduler, > > > - &pvr_queue_sched_ops, > > > - pvr_dev->sched_wq, 1, 64 * 1024, 1, > > > - msecs_to_jiffies(500), > > > - pvr_dev->sched_wq, NULL, "pvr-queue", > > > - pvr_dev->base.dev); > > > + sched_params.ops = &pvr_queue_sched_ops; > > > + sched_params.submit_wq = pvr_dev->sched_wq; > > > + sched_params.num_rqs = 1; > > > + sched_params.credit_limit = 64 * 1024; > > > + sched_params.hang_limit = 1; > > > + sched_params.timeout = msecs_to_jiffies(500); > > > + sched_params.timeout_wq = pvr_dev->sched_wq; > > > + sched_params.score = NULL; > > > + sched_params.name = "pvr-queue"; > > > + sched_params.dev = pvr_dev->base.dev; > > > + > > > + err = drm_sched_init(&queue->scheduler, &sched_params); > > > if (err) > > > goto err_release_ufo; > > > > > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > > > b/drivers/gpu/drm/lima/lima_sched.c > > > index b40c90e97d7e..a64c50fb6d1e 100644 > > > --- a/drivers/gpu/drm/lima/lima_sched.c > > > +++ b/drivers/gpu/drm/lima/lima_sched.c > > > @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct > > > work_struct *work) > > > > > > int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char > > > *name) > > > { > > > + struct drm_sched_init_params params; > > > unsigned int timeout = lima_sched_timeout_ms > 0 ? > > > lima_sched_timeout_ms : 10000; > > > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > 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, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - 1, > > > - lima_job_hang_limit, > > > - msecs_to_jiffies(timeout), NULL, > > > - NULL, name, pipe->ldev->dev); > > > + params.ops = &lima_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = 1; > > > + params.hang_limit = lima_job_hang_limit; > > > + params.timeout = msecs_to_jiffies(timeout); > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > + params.score = NULL; > > > + params.name = name; > > > + params.dev = pipe->ldev->dev; > > > + > > > + return drm_sched_init(&pipe->base, ¶ms); > > > } > > > > > > void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) > > > diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > index c803556a8f64..49a2c7422dc6 100644 > > > --- a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops > > > msm_sched_ops = { > > > struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, > > > int id, > > > void *memptrs, uint64_t memptrs_iova) > > > { > > > + struct drm_sched_init_params params; > > > struct msm_ringbuffer *ring; > > > - long sched_timeout; > > > char name[32]; > > > int ret; > > > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a > > > power of 2 */ > > > BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); > > > > > > @@ -95,13 +97,19 @@ struct msm_ringbuffer > > > *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > > > ring->memptrs = memptrs; > > > ring->memptrs_iova = memptrs_iova; > > > > > > - /* currently managing hangcheck ourselves: */ > > > - sched_timeout = MAX_SCHEDULE_TIMEOUT; > > > + params.ops = &msm_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = num_hw_submissions; > > > + params.hang_limit = 0; > > > + /* currently managing hangcheck ourselves: */ > > > + params.timeout = MAX_SCHEDULE_TIMEOUT; > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > + params.score = NULL; > > > + params.name = to_msm_bo(ring->bo)->name; > > > + params.dev = gpu->dev->dev; > > > > > > - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - num_hw_submissions, 0, sched_timeout, > > > - NULL, NULL, to_msm_bo(ring->bo)- > > > >name, gpu->dev->dev); > > > + ret = drm_sched_init(&ring->sched, ¶ms); > > > if (ret) { > > > goto fail; > > > } > > > diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > index 4412f2711fb5..f20c2e612750 100644 > > > --- a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched > > > *sched, struct nouveau_drm *drm, > > > { > > > struct drm_gpu_scheduler *drm_sched = &sched->base; > > > struct drm_sched_entity *entity = &sched->entity; > > > - const long timeout = > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > + struct drm_sched_init_params params; > > > int ret; > > > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > if (!wq) { > > > wq = alloc_workqueue("nouveau_sched_wq_%d", 0, > > > WQ_MAX_ACTIVE, > > > current->pid); > > > @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched > > > *sched, struct nouveau_drm *drm, > > > sched->wq = wq; > > > } > > > > > > - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, > > > - NOUVEAU_SCHED_PRIORITY_COUNT, > > > - credit_limit, 0, timeout, > > > - NULL, NULL, "nouveau_sched", drm- > > > >dev->dev); > > > + params.ops = &nouveau_sched_ops; > > > + params.submit_wq = wq; > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = credit_limit; > > > + params.hang_limit = 0; > > > + params.timeout = > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > + params.score = NULL; > > > + params.name = "nouveau_sched"; > > > + params.dev = drm->dev->dev; > > > + > > > + ret = drm_sched_init(drm_sched, ¶ms); > > > if (ret) > > > goto fail_wq; > > > > > > diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c > > > b/drivers/gpu/drm/panfrost/panfrost_job.c > > > index 9b8e82fb8bc4..6b509ff446b5 100644 > > > --- a/drivers/gpu/drm/panfrost/panfrost_job.c > > > +++ b/drivers/gpu/drm/panfrost/panfrost_job.c > > > @@ -836,10 +836,13 @@ static irqreturn_t > > > panfrost_job_irq_handler(int irq, void *data) > > > > > > int panfrost_job_init(struct panfrost_device *pfdev) > > > { > > > + struct drm_sched_init_params params; > > > struct panfrost_job_slot *js; > > > unsigned int nentries = 2; > > > int ret, j; > > > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > /* All GPUs have two entries per queue, but without > > > jobchain > > > * disambiguation stopping the right job in the close path > > > is tricky, > > > * so let's just advertise one entry in that case. > > > @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device > > > *pfdev) > > > if (!pfdev->reset.wq) > > > return -ENOMEM; > > > > > > + params.ops = &panfrost_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params.credit_limit = nentries; > > > + params.hang_limit = 0; > > > + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > > + params.timeout_wq = pfdev->reset.wq; > > > + params.score = NULL; > > > + params.name = "pan_js"; > > > + params.dev = pfdev->dev; > > > + > > > for (j = 0; j < NUM_JOB_SLOTS; j++) { > > > js->queue[j].fence_context = > > > dma_fence_context_alloc(1); > > > > > > - ret = drm_sched_init(&js->queue[j].sched, > > > - &panfrost_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - nentries, 0, > > > - > > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > > - pfdev->reset.wq, > > > - NULL, "pan_js", pfdev->dev); > > > + ret = drm_sched_init(&js->queue[j].sched, > > > ¶ms); > > > if (ret) { > > > dev_err(pfdev->dev, "Failed to create > > > scheduler: %d.", ret); > > > goto err_sched; > > > diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c > > > b/drivers/gpu/drm/panthor/panthor_mmu.c > > > index a49132f3778b..4362442cbfd8 100644 > > > --- a/drivers/gpu/drm/panthor/panthor_mmu.c > > > +++ b/drivers/gpu/drm/panthor/panthor_mmu.c > > > @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device > > > *ptdev, bool for_mcu, > > > u64 full_va_range = 1ull << va_bits; > > > struct drm_gem_object *dummy_gem; > > > struct drm_gpu_scheduler *sched; > > > + struct drm_sched_init_params sched_params; > > > struct io_pgtable_cfg pgtbl_cfg; > > > u64 mair, min_va, va_range; > > > struct panthor_vm *vm; > > > @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device > > > *ptdev, bool for_mcu, > > > goto err_free_vm; > > > } > > > > > > + memset(&sched_params, 0, sizeof(struct > > > drm_sched_init_params)); > > > + > > > mutex_init(&vm->heaps.lock); > > > vm->for_mcu = for_mcu; > > > vm->ptdev = ptdev; > > > @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device > > > *ptdev, bool for_mcu, > > > goto err_mm_takedown; > > > } > > > > > > + sched_params.ops = &panthor_vm_bind_ops; > > > + sched_params.submit_wq = ptdev->mmu->vm.wq; > > > + sched_params.num_rqs = 1; > > > + sched_params.credit_limit = 1; > > > + sched_params.hang_limit = 0; > > > /* Bind operations are synchronous for now, no timeout > > > needed. */ > > > - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, > > > ptdev->mmu->vm.wq, > > > - 1, 1, 0, > > > - MAX_SCHEDULE_TIMEOUT, NULL, NULL, > > > - "panthor-vm-bind", ptdev->base.dev); > > > + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; > > > + sched_params.timeout_wq = NULL; /* Use the system_wq. */ > > > + sched_params.score = NULL; > > > + sched_params.name = "panthor-vm-bind"; > > > + sched_params.dev = ptdev->base.dev; > > > + ret = drm_sched_init(&vm->sched, &sched_params); > > > if (ret) > > > goto err_free_io_pgtable; > > > > > > diff --git a/drivers/gpu/drm/panthor/panthor_sched.c > > > b/drivers/gpu/drm/panthor/panthor_sched.c > > > index ef4bec7ff9c7..a324346d302f 100644 > > > --- a/drivers/gpu/drm/panthor/panthor_sched.c > > > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group > > > *group, > > > const struct drm_panthor_queue_create *args) > > > { > > > struct drm_gpu_scheduler *drm_sched; > > > + struct drm_sched_init_params sched_params; > > > struct panthor_queue *queue; > > > int ret; > > > > > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group > > > *group, > > > if (!queue) > > > return ERR_PTR(-ENOMEM); > > > > > > + memset(&sched_params, 0, sizeof(struct > > > drm_sched_init_params)); > > > + > > > queue->fence_ctx.id = dma_fence_context_alloc(1); > > > spin_lock_init(&queue->fence_ctx.lock); > > > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group > > > *group, > > > if (ret) > > > goto err_free_queue; > > > > > > + sched_params.ops = &panthor_queue_sched_ops; > > > + sched_params.submit_wq = group->ptdev->scheduler->wq; > > > + sched_params.num_rqs = 1; > > > /* > > > - * Credit limit argument tells us the total number of > > > instructions > > > + * The credit limit argument tells us the total number of > > > instructions > > > * across all CS slots in the ringbuffer, with some jobs > > > requiring > > > * twice as many as others, depending on their profiling > > > status. > > > */ > > > - ret = drm_sched_init(&queue->scheduler, > > > &panthor_queue_sched_ops, > > > - group->ptdev->scheduler->wq, 1, > > > - args->ringbuf_size / sizeof(u64), > > > - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > > > - group->ptdev->reset.wq, > > > - NULL, "panthor-queue", group->ptdev- > > > >base.dev); > > > + sched_params.credit_limit = args->ringbuf_size / > > > sizeof(u64); > > > + sched_params.hang_limit = 0; > > > + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > > + sched_params.timeout_wq = group->ptdev->reset.wq; > > > + sched_params.score = NULL; > > > + sched_params.name = "panthor-queue"; > > > + sched_params.dev = group->ptdev->base.dev; > > > + > > > + ret = drm_sched_init(&queue->scheduler, &sched_params); > > > if (ret) > > > goto err_free_queue; > > > > > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > > > b/drivers/gpu/drm/scheduler/sched_main.c > > > index 57da84908752..27db748a5269 100644 > > > --- a/drivers/gpu/drm/scheduler/sched_main.c > > > +++ b/drivers/gpu/drm/scheduler/sched_main.c > > > @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct > > > work_struct *w) > > > * drm_sched_init - Init a gpu scheduler instance > > > * > > > * @sched: scheduler instance > > > - * @ops: backend operations for this scheduler > > > - * @submit_wq: workqueue to use for submission. If NULL, an > > > ordered wq is > > > - * allocated and used > > > - * @num_rqs: number of runqueues, one for each priority, up to > > > DRM_SCHED_PRIORITY_COUNT > > > - * @credit_limit: the number of credits this scheduler can hold > > > from all jobs > > > - * @hang_limit: number of times to allow a job to hang before > > > dropping it > > > - * @timeout: timeout value in jiffies for the scheduler > > > - * @timeout_wq: workqueue to use for timeout work. If NULL, the > > > system_wq is > > > - * used > > > - * @score: optional score atomic shared with other schedulers > > > - * @name: name used for debugging > > > - * @dev: target &struct device > > > + * @params: scheduler initialization parameters > > > * > > > * Return 0 on success, otherwise error code. > > > */ > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > - const struct drm_sched_backend_ops *ops, > > > - struct workqueue_struct *submit_wq, > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > hang_limit, > > > - long timeout, struct workqueue_struct > > > *timeout_wq, > > > - atomic_t *score, const char *name, struct > > > device *dev) > > > + const struct drm_sched_init_params *params) > > > { > > > int i; > > > > > > - sched->ops = ops; > > > - sched->credit_limit = credit_limit; > > > - sched->name = name; > > > - sched->timeout = timeout; > > > - sched->timeout_wq = timeout_wq ? : system_wq; > > > - sched->hang_limit = hang_limit; > > > - sched->score = score ? score : &sched->_score; > > > - sched->dev = dev; > > > + sched->ops = params->ops; > > > + sched->credit_limit = params->credit_limit; > > > + sched->name = params->name; > > > + sched->timeout = params->timeout; > > > + sched->timeout_wq = params->timeout_wq ? : system_wq; > > > + sched->hang_limit = params->hang_limit; > > > + sched->score = params->score ? params->score : &sched- > > > >_score; > > > + sched->dev = params->dev; > > > > > > - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > /* This is a gross violation--tell drivers what > > > the problem is. > > > */ > > > drm_err(sched, "%s: num_rqs cannot be greater than > > > DRM_SCHED_PRIORITY_COUNT\n", > > > @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler > > > *sched, > > > return 0; > > > } > > > > > > - if (submit_wq) { > > > - sched->submit_wq = submit_wq; > > > + if (params->submit_wq) { > > > + sched->submit_wq = params->submit_wq; > > > sched->own_submit_wq = false; > > > } else { > > > #ifdef CONFIG_LOCKDEP > > > - sched->submit_wq = > > > alloc_ordered_workqueue_lockdep_map(name, > > > - > > > WQ_MEM_RECLAIM, > > > - > > > &drm_sched_lockdep_map); > > > + sched->submit_wq = > > > alloc_ordered_workqueue_lockdep_map( > > > + params->name, > > > WQ_MEM_RECLAIM, > > > + &drm_sched_lockdep_map); > > > #else > > > - sched->submit_wq = alloc_ordered_workqueue(name, > > > WQ_MEM_RECLAIM); > > > + sched->submit_wq = alloc_ordered_workqueue(params- > > > >name, WQ_MEM_RECLAIM); > > > #endif > > > if (!sched->submit_wq) > > > return -ENOMEM; > > > @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler > > > *sched, > > > sched->own_submit_wq = true; > > > } > > > > > > - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched- > > > >sched_rq), > > > + sched->sched_rq = kmalloc_array(params->num_rqs, > > > sizeof(*sched->sched_rq), > > > GFP_KERNEL | __GFP_ZERO); > > > if (!sched->sched_rq) > > > goto Out_check_own; > > > - sched->num_rqs = num_rqs; > > > + sched->num_rqs = params->num_rqs; > > > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; > > > i++) { > > > sched->sched_rq[i] = kzalloc(sizeof(*sched- > > > >sched_rq[i]), GFP_KERNEL); > > > if (!sched->sched_rq[i]) > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > > b/drivers/gpu/drm/v3d/v3d_sched.c > > > index 99ac4995b5a1..716e6d074d87 100644 > > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops > > > v3d_cpu_sched_ops = { > > > .free_job = v3d_cpu_job_free > > > }; > > > > > > +/* > > > + * v3d's scheduler instances are all identical, except for ops and > > > name. > > > + */ > > > +static void > > > +v3d_common_sched_init(struct drm_sched_init_params *params, struct > > > device *dev) > > > +{ > > > + memset(params, 0, sizeof(struct drm_sched_init_params)); > > > + > > > + params->submit_wq = NULL; /* Use the system_wq. */ > > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params->credit_limit = 1; > > > + params->hang_limit = 0; > > > + params->timeout = msecs_to_jiffies(500); > > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > > + params->score = NULL; > > > + params->dev = dev; > > > +} > > > + > > > +static int > > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_bin_sched_ops; > > > + params.name = "v3d_bin"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_render_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_render_sched_ops; > > > + params.name = "v3d_render"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_tfu_sched_ops; > > > + params.name = "v3d_tfu"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_csd_sched_ops; > > > + params.name = "v3d_csd"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_cache_clean_sched_ops; > > > + params.name = "v3d_cache_clean"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_cpu_sched_ops; > > > + params.name = "v3d_cpu"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > ¶ms); > > > +} > > > + > > > int > > > v3d_sched_init(struct v3d_dev *v3d) > > > { > > > - int hw_jobs_limit = 1; > > > - int job_hang_limit = 0; > > > - int hang_limit_ms = 500; > > > int ret; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > - &v3d_bin_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_bin", v3d->drm.dev); > > > + ret = v3d_bin_sched_init(v3d); > > > if (ret) > > > return ret; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > - &v3d_render_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_render", v3d->drm.dev); > > > + ret = v3d_render_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > - &v3d_tfu_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_tfu", v3d->drm.dev); > > > + ret = v3d_tfu_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > if (v3d_has_csd(v3d)) { > > > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > - &v3d_csd_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, > > > job_hang_limit, > > > - > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > - NULL, "v3d_csd", v3d- > > > >drm.dev); > > > + ret = v3d_csd_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > - ret = drm_sched_init(&v3d- > > > >queue[V3D_CACHE_CLEAN].sched, > > > - &v3d_cache_clean_sched_ops, > > > NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, > > > job_hang_limit, > > > - > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > - NULL, "v3d_cache_clean", v3d- > > > >drm.dev); > > > + ret = v3d_cache_sched_init(v3d); > > > if (ret) > > > goto fail; > > > } > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > - &v3d_cpu_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - 1, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_cpu", v3d->drm.dev); > > > + ret = v3d_cpu_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > diff --git a/drivers/gpu/drm/xe/xe_execlist.c > > > b/drivers/gpu/drm/xe/xe_execlist.c > > > index a8c416a48812..7f29b7f04af4 100644 > > > --- a/drivers/gpu/drm/xe/xe_execlist.c > > > +++ b/drivers/gpu/drm/xe/xe_execlist.c > > > @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops > > > drm_sched_ops = { > > > static int execlist_exec_queue_init(struct xe_exec_queue *q) > > > { > > > struct drm_gpu_scheduler *sched; > > > + struct drm_sched_init_params params; > > > struct xe_execlist_exec_queue *exl; > > > struct xe_device *xe = gt_to_xe(q->gt); > > > int err; > > > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > xe_assert(xe, !xe_device_uc_enabled(xe)); > > > > > > drm_info(&xe->drm, "Enabling execlist submission (GuC > > > submission disabled)\n"); > > > @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct > > > xe_exec_queue *q) > > > > > > exl->q = q; > > > > > > - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, > > > - q->lrc[0]->ring.size / > > > MAX_JOB_SIZE_BYTES, > > > - XE_SCHED_HANG_LIMIT, > > > XE_SCHED_JOB_TIMEOUT, > > > - NULL, NULL, q->hwe->name, > > > - gt_to_xe(q->gt)->drm.dev); > > > + params.ops = &drm_sched_ops; > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > + params.num_rqs = 1; > > > + params.credit_limit = q->lrc[0]->ring.size / > > > MAX_JOB_SIZE_BYTES; > > > + params.hang_limit = XE_SCHED_HANG_LIMIT; > > > + params.timeout = XE_SCHED_JOB_TIMEOUT; > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > + params.score = NULL; > > > + params.name = q->hwe->name; > > > + params.dev = gt_to_xe(q->gt)->drm.dev; > > > + > > > + err = drm_sched_init(&exl->sched, ¶ms); > > > if (err) > > > goto err_free; > > > > > > diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > index 50361b4638f9..2129fee83f25 100644 > > > --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler > > > *sched, > > > atomic_t *score, const char *name, > > > struct device *dev) > > > { > > > + struct drm_sched_init_params params; > > > + > > > sched->ops = xe_ops; > > > INIT_LIST_HEAD(&sched->msgs); > > > INIT_WORK(&sched->work_process_msg, > > > xe_sched_process_msg_work); > > > > > > - return drm_sched_init(&sched->base, ops, submit_wq, 1, > > > hw_submission, > > > - hang_limit, timeout, timeout_wq, > > > score, name, > > > - dev); > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > + > > > + params.ops = ops; > > > + params.submit_wq = submit_wq; > > > + params.num_rqs = 1; > > > + params.credit_limit = hw_submission; > > > + params.hang_limit = hang_limit; > > > + params.timeout = timeout; > > > + params.timeout_wq = timeout_wq; > > > + params.score = score; > > > + params.name = name; > > > + params.dev = dev; > > > + > > > + return drm_sched_init(&sched->base, ¶ms); > > > } > > > > > > void xe_sched_fini(struct xe_gpu_scheduler *sched) > > > diff --git a/include/drm/gpu_scheduler.h > > > b/include/drm/gpu_scheduler.h > > > index 95e17504e46a..1a834ef43862 100644 > > > --- a/include/drm/gpu_scheduler.h > > > +++ b/include/drm/gpu_scheduler.h > > > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > > > struct device *dev; > > > }; > > > > > > +/** > > > + * struct drm_sched_init_params - parameters for initializing a > > > DRM GPU scheduler > > > + * > > > + * @ops: backend operations provided by the driver > > > + * @submit_wq: workqueue to use for submission. If NULL, an > > > ordered wq is > > > + * allocated and used > > > + * @num_rqs: Number of run-queues. This is at most > > > DRM_SCHED_PRIORITY_COUNT, > > > + * as there's usually one run-queue per priority, but > > > could be less. > > > + * @credit_limit: the number of credits this scheduler can hold > > > from all jobs > > > + * @hang_limit: number of times to allow a job to hang before > > > dropping it > > > + * @timeout: timeout value in jiffies for the scheduler > > > + * @timeout_wq: workqueue to use for timeout work. If NULL, the > > > system_wq is > > > + * used > > > + * @score: optional score atomic shared with other schedulers > > > + * @name: name used for debugging > > > + * @dev: associated device. Used for debugging > > > + */ > > > +struct drm_sched_init_params { > > > + const struct drm_sched_backend_ops *ops; > > > + struct workqueue_struct *submit_wq; > > > + struct workqueue_struct *timeout_wq; > > > + u32 num_rqs, credit_limit; > > > + unsigned int hang_limit; > > > + long timeout; > > > + atomic_t *score; > > > + const char *name; > > > + struct device *dev; > > > +}; > > > + > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > - const struct drm_sched_backend_ops *ops, > > > - struct workqueue_struct *submit_wq, > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > hang_limit, > > > - long timeout, struct workqueue_struct > > > *timeout_wq, > > > - atomic_t *score, const char *name, struct > > > device *dev); > > > + const struct drm_sched_init_params *params); > > > > > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > > > int drm_sched_job_init(struct drm_sched_job *job, > > >
Am 22.01.25 um 15:48 schrieb Philipp Stanner: > On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: >> Am 22.01.25 um 15:08 schrieb Philipp Stanner: >>> drm_sched_init() has a great many parameters and upcoming new >>> functionality for the scheduler might add even more. Generally, the >>> great number of parameters reduces readability and has already >>> caused >>> one missnaming in: >>> >>> commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in >>> nouveau_sched_init()"). >>> >>> Introduce a new struct for the scheduler init parameters and port >>> all >>> users. >>> >>> Signed-off-by: Philipp Stanner <phasta@kernel.org> >>> --- >>> Howdy, >>> >>> I have a patch-series in the pipe that will add a `flags` argument >>> to >>> drm_sched_init(). I thought it would be wise to first rework the >>> API as >>> detailed in this patch. It's really a lot of parameters by now, and >>> I >>> would expect that it might get more and more over the years for >>> special >>> use cases etc. >>> >>> Regards, >>> P. >>> --- >>> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- >>> drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- >>> drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- >>> drivers/gpu/drm/lima/lima_sched.c | 21 +++- >>> drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- >>> drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- >>> drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- >>> drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- >>> drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- >>> drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- >>> drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++- >>> ----- >>> drivers/gpu/drm/xe/xe_execlist.c | 20 ++- >>> drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- >>> include/drm/gpu_scheduler.h | 35 +++++- >>> 14 files changed, 311 insertions(+), 139 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>> index cd4fac120834..c1f03eb5f5ea 100644 >>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>> @@ -2821,6 +2821,9 @@ static int >>> amdgpu_device_init_schedulers(struct amdgpu_device *adev) >>> { >>> long timeout; >>> int r, i; >>> + struct drm_sched_init_params params; >> Please keep the reverse xmas tree ordering for variable declaration. >> E.g. long lines first and variables like "i" and "r" last. > Okay dokay > >> Apart from that looks like a good idea to me. >> >> >>> + >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> >>> for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { >>> struct amdgpu_ring *ring = adev->rings[i]; >>> @@ -2844,12 +2847,18 @@ static int >>> amdgpu_device_init_schedulers(struct amdgpu_device *adev) >>> break; >>> } >>> >>> - r = drm_sched_init(&ring->sched, >>> &amdgpu_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - ring->num_hw_submission, 0, >>> - timeout, adev->reset_domain- >>>> wq, >>> - ring->sched_score, ring->name, >>> - adev->dev); >>> + params.ops = &amdgpu_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = ring->num_hw_submission; >>> + params.hang_limit = 0; >> Could we please remove the hang limit as first step to get this awful >> feature deprecated? > Remove it? From the struct you mean? > > We can mark it as deprecated in the docstring of the new struct. That's > what you mean, don't you? No, the function using this parameter already deprecated. What I meant is to start to completely remove this feature. The hang_limit basically says how often the scheduler should try to run a job over and over again before giving up. And we already agreed that trying the same thing over and over again and expecting different results is the definition of insanity :) So my suggestion is to drop the parameter and drop the job as soon as it caused a timeout. Regards, Christian. > > P. > >> Thanks, >> Christian. >> >>> + params.timeout = timeout; >>> + params.timeout_wq = adev->reset_domain->wq; >>> + params.score = ring->sched_score; >>> + params.name = ring->name; >>> + params.dev = adev->dev; >>> + >>> + r = drm_sched_init(&ring->sched, ¶ms); >>> if (r) { >>> DRM_ERROR("Failed to create scheduler on >>> ring %s.\n", >>> ring->name); >>> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>> b/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>> index 5b67eda122db..7d8517f1963e 100644 >>> --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>> +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>> @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct >>> etnaviv_gem_submit *submit) >>> int etnaviv_sched_init(struct etnaviv_gpu *gpu) >>> { >>> int ret; >>> + struct drm_sched_init_params params; >>> >>> - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, >>> NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - etnaviv_hw_jobs_limit, >>> etnaviv_job_hang_limit, >>> - msecs_to_jiffies(500), NULL, NULL, >>> - dev_name(gpu->dev), gpu->dev); >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> + params.ops = &etnaviv_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = etnaviv_hw_jobs_limit; >>> + params.hang_limit = etnaviv_job_hang_limit; >>> + params.timeout = msecs_to_jiffies(500); >>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>> + params.score = NULL; >>> + params.name = dev_name(gpu->dev); >>> + params.dev = gpu->dev; >>> + >>> + ret = drm_sched_init(&gpu->sched, ¶ms); >>> if (ret) >>> return ret; >>> >>> diff --git a/drivers/gpu/drm/imagination/pvr_queue.c >>> b/drivers/gpu/drm/imagination/pvr_queue.c >>> index c4f08432882b..03a2ce1a88e7 100644 >>> --- a/drivers/gpu/drm/imagination/pvr_queue.c >>> +++ b/drivers/gpu/drm/imagination/pvr_queue.c >>> @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct >>> pvr_context *ctx, >>> }; >>> struct pvr_device *pvr_dev = ctx->pvr_dev; >>> struct drm_gpu_scheduler *sched; >>> + struct drm_sched_init_params sched_params; >>> struct pvr_queue *queue; >>> int ctx_state_size, err; >>> void *cpu_map; >>> >>> + memset(&sched_params, 0, sizeof(struct >>> drm_sched_init_params)); >>> + >>> if (WARN_ON(type >= sizeof(props))) >>> return ERR_PTR(-EINVAL); >>> >>> @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct >>> pvr_context *ctx, >>> >>> queue->timeline_ufo.value = cpu_map; >>> >>> - err = drm_sched_init(&queue->scheduler, >>> - &pvr_queue_sched_ops, >>> - pvr_dev->sched_wq, 1, 64 * 1024, 1, >>> - msecs_to_jiffies(500), >>> - pvr_dev->sched_wq, NULL, "pvr-queue", >>> - pvr_dev->base.dev); >>> + sched_params.ops = &pvr_queue_sched_ops; >>> + sched_params.submit_wq = pvr_dev->sched_wq; >>> + sched_params.num_rqs = 1; >>> + sched_params.credit_limit = 64 * 1024; >>> + sched_params.hang_limit = 1; >>> + sched_params.timeout = msecs_to_jiffies(500); >>> + sched_params.timeout_wq = pvr_dev->sched_wq; >>> + sched_params.score = NULL; >>> + sched_params.name = "pvr-queue"; >>> + sched_params.dev = pvr_dev->base.dev; >>> + >>> + err = drm_sched_init(&queue->scheduler, &sched_params); >>> if (err) >>> goto err_release_ufo; >>> >>> diff --git a/drivers/gpu/drm/lima/lima_sched.c >>> b/drivers/gpu/drm/lima/lima_sched.c >>> index b40c90e97d7e..a64c50fb6d1e 100644 >>> --- a/drivers/gpu/drm/lima/lima_sched.c >>> +++ b/drivers/gpu/drm/lima/lima_sched.c >>> @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct >>> work_struct *work) >>> >>> int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char >>> *name) >>> { >>> + struct drm_sched_init_params params; >>> unsigned int timeout = lima_sched_timeout_ms > 0 ? >>> lima_sched_timeout_ms : 10000; >>> >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> 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, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - 1, >>> - lima_job_hang_limit, >>> - msecs_to_jiffies(timeout), NULL, >>> - NULL, name, pipe->ldev->dev); >>> + params.ops = &lima_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = 1; >>> + params.hang_limit = lima_job_hang_limit; >>> + params.timeout = msecs_to_jiffies(timeout); >>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>> + params.score = NULL; >>> + params.name = name; >>> + params.dev = pipe->ldev->dev; >>> + >>> + return drm_sched_init(&pipe->base, ¶ms); >>> } >>> >>> void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) >>> diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c >>> b/drivers/gpu/drm/msm/msm_ringbuffer.c >>> index c803556a8f64..49a2c7422dc6 100644 >>> --- a/drivers/gpu/drm/msm/msm_ringbuffer.c >>> +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c >>> @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops >>> msm_sched_ops = { >>> struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, >>> int id, >>> void *memptrs, uint64_t memptrs_iova) >>> { >>> + struct drm_sched_init_params params; >>> struct msm_ringbuffer *ring; >>> - long sched_timeout; >>> char name[32]; >>> int ret; >>> >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a >>> power of 2 */ >>> BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); >>> >>> @@ -95,13 +97,19 @@ struct msm_ringbuffer >>> *msm_ringbuffer_new(struct msm_gpu *gpu, int id, >>> ring->memptrs = memptrs; >>> ring->memptrs_iova = memptrs_iova; >>> >>> - /* currently managing hangcheck ourselves: */ >>> - sched_timeout = MAX_SCHEDULE_TIMEOUT; >>> + params.ops = &msm_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = num_hw_submissions; >>> + params.hang_limit = 0; >>> + /* currently managing hangcheck ourselves: */ >>> + params.timeout = MAX_SCHEDULE_TIMEOUT; >>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>> + params.score = NULL; >>> + params.name = to_msm_bo(ring->bo)->name; >>> + params.dev = gpu->dev->dev; >>> >>> - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - num_hw_submissions, 0, sched_timeout, >>> - NULL, NULL, to_msm_bo(ring->bo)- >>>> name, gpu->dev->dev); >>> + ret = drm_sched_init(&ring->sched, ¶ms); >>> if (ret) { >>> goto fail; >>> } >>> diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c >>> b/drivers/gpu/drm/nouveau/nouveau_sched.c >>> index 4412f2711fb5..f20c2e612750 100644 >>> --- a/drivers/gpu/drm/nouveau/nouveau_sched.c >>> +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c >>> @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched >>> *sched, struct nouveau_drm *drm, >>> { >>> struct drm_gpu_scheduler *drm_sched = &sched->base; >>> struct drm_sched_entity *entity = &sched->entity; >>> - const long timeout = >>> msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); >>> + struct drm_sched_init_params params; >>> int ret; >>> >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> if (!wq) { >>> wq = alloc_workqueue("nouveau_sched_wq_%d", 0, >>> WQ_MAX_ACTIVE, >>> current->pid); >>> @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched >>> *sched, struct nouveau_drm *drm, >>> sched->wq = wq; >>> } >>> >>> - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, >>> - NOUVEAU_SCHED_PRIORITY_COUNT, >>> - credit_limit, 0, timeout, >>> - NULL, NULL, "nouveau_sched", drm- >>>> dev->dev); >>> + params.ops = &nouveau_sched_ops; >>> + params.submit_wq = wq; >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = credit_limit; >>> + params.hang_limit = 0; >>> + params.timeout = >>> msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); >>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>> + params.score = NULL; >>> + params.name = "nouveau_sched"; >>> + params.dev = drm->dev->dev; >>> + >>> + ret = drm_sched_init(drm_sched, ¶ms); >>> if (ret) >>> goto fail_wq; >>> >>> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c >>> b/drivers/gpu/drm/panfrost/panfrost_job.c >>> index 9b8e82fb8bc4..6b509ff446b5 100644 >>> --- a/drivers/gpu/drm/panfrost/panfrost_job.c >>> +++ b/drivers/gpu/drm/panfrost/panfrost_job.c >>> @@ -836,10 +836,13 @@ static irqreturn_t >>> panfrost_job_irq_handler(int irq, void *data) >>> >>> int panfrost_job_init(struct panfrost_device *pfdev) >>> { >>> + struct drm_sched_init_params params; >>> struct panfrost_job_slot *js; >>> unsigned int nentries = 2; >>> int ret, j; >>> >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> /* All GPUs have two entries per queue, but without >>> jobchain >>> * disambiguation stopping the right job in the close path >>> is tricky, >>> * so let's just advertise one entry in that case. >>> @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device >>> *pfdev) >>> if (!pfdev->reset.wq) >>> return -ENOMEM; >>> >>> + params.ops = &panfrost_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params.credit_limit = nentries; >>> + params.hang_limit = 0; >>> + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); >>> + params.timeout_wq = pfdev->reset.wq; >>> + params.score = NULL; >>> + params.name = "pan_js"; >>> + params.dev = pfdev->dev; >>> + >>> for (j = 0; j < NUM_JOB_SLOTS; j++) { >>> js->queue[j].fence_context = >>> dma_fence_context_alloc(1); >>> >>> - ret = drm_sched_init(&js->queue[j].sched, >>> - &panfrost_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - nentries, 0, >>> - >>> msecs_to_jiffies(JOB_TIMEOUT_MS), >>> - pfdev->reset.wq, >>> - NULL, "pan_js", pfdev->dev); >>> + ret = drm_sched_init(&js->queue[j].sched, >>> ¶ms); >>> if (ret) { >>> dev_err(pfdev->dev, "Failed to create >>> scheduler: %d.", ret); >>> goto err_sched; >>> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c >>> b/drivers/gpu/drm/panthor/panthor_mmu.c >>> index a49132f3778b..4362442cbfd8 100644 >>> --- a/drivers/gpu/drm/panthor/panthor_mmu.c >>> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c >>> @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device >>> *ptdev, bool for_mcu, >>> u64 full_va_range = 1ull << va_bits; >>> struct drm_gem_object *dummy_gem; >>> struct drm_gpu_scheduler *sched; >>> + struct drm_sched_init_params sched_params; >>> struct io_pgtable_cfg pgtbl_cfg; >>> u64 mair, min_va, va_range; >>> struct panthor_vm *vm; >>> @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device >>> *ptdev, bool for_mcu, >>> goto err_free_vm; >>> } >>> >>> + memset(&sched_params, 0, sizeof(struct >>> drm_sched_init_params)); >>> + >>> mutex_init(&vm->heaps.lock); >>> vm->for_mcu = for_mcu; >>> vm->ptdev = ptdev; >>> @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device >>> *ptdev, bool for_mcu, >>> goto err_mm_takedown; >>> } >>> >>> + sched_params.ops = &panthor_vm_bind_ops; >>> + sched_params.submit_wq = ptdev->mmu->vm.wq; >>> + sched_params.num_rqs = 1; >>> + sched_params.credit_limit = 1; >>> + sched_params.hang_limit = 0; >>> /* Bind operations are synchronous for now, no timeout >>> needed. */ >>> - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, >>> ptdev->mmu->vm.wq, >>> - 1, 1, 0, >>> - MAX_SCHEDULE_TIMEOUT, NULL, NULL, >>> - "panthor-vm-bind", ptdev->base.dev); >>> + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; >>> + sched_params.timeout_wq = NULL; /* Use the system_wq. */ >>> + sched_params.score = NULL; >>> + sched_params.name = "panthor-vm-bind"; >>> + sched_params.dev = ptdev->base.dev; >>> + ret = drm_sched_init(&vm->sched, &sched_params); >>> if (ret) >>> goto err_free_io_pgtable; >>> >>> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c >>> b/drivers/gpu/drm/panthor/panthor_sched.c >>> index ef4bec7ff9c7..a324346d302f 100644 >>> --- a/drivers/gpu/drm/panthor/panthor_sched.c >>> +++ b/drivers/gpu/drm/panthor/panthor_sched.c >>> @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group >>> *group, >>> const struct drm_panthor_queue_create *args) >>> { >>> struct drm_gpu_scheduler *drm_sched; >>> + struct drm_sched_init_params sched_params; >>> struct panthor_queue *queue; >>> int ret; >>> >>> @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group >>> *group, >>> if (!queue) >>> return ERR_PTR(-ENOMEM); >>> >>> + memset(&sched_params, 0, sizeof(struct >>> drm_sched_init_params)); >>> + >>> queue->fence_ctx.id = dma_fence_context_alloc(1); >>> spin_lock_init(&queue->fence_ctx.lock); >>> INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); >>> @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group >>> *group, >>> if (ret) >>> goto err_free_queue; >>> >>> + sched_params.ops = &panthor_queue_sched_ops; >>> + sched_params.submit_wq = group->ptdev->scheduler->wq; >>> + sched_params.num_rqs = 1; >>> /* >>> - * Credit limit argument tells us the total number of >>> instructions >>> + * The credit limit argument tells us the total number of >>> instructions >>> * across all CS slots in the ringbuffer, with some jobs >>> requiring >>> * twice as many as others, depending on their profiling >>> status. >>> */ >>> - ret = drm_sched_init(&queue->scheduler, >>> &panthor_queue_sched_ops, >>> - group->ptdev->scheduler->wq, 1, >>> - args->ringbuf_size / sizeof(u64), >>> - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), >>> - group->ptdev->reset.wq, >>> - NULL, "panthor-queue", group->ptdev- >>>> base.dev); >>> + sched_params.credit_limit = args->ringbuf_size / >>> sizeof(u64); >>> + sched_params.hang_limit = 0; >>> + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); >>> + sched_params.timeout_wq = group->ptdev->reset.wq; >>> + sched_params.score = NULL; >>> + sched_params.name = "panthor-queue"; >>> + sched_params.dev = group->ptdev->base.dev; >>> + >>> + ret = drm_sched_init(&queue->scheduler, &sched_params); >>> if (ret) >>> goto err_free_queue; >>> >>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c >>> b/drivers/gpu/drm/scheduler/sched_main.c >>> index 57da84908752..27db748a5269 100644 >>> --- a/drivers/gpu/drm/scheduler/sched_main.c >>> +++ b/drivers/gpu/drm/scheduler/sched_main.c >>> @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct >>> work_struct *w) >>> * drm_sched_init - Init a gpu scheduler instance >>> * >>> * @sched: scheduler instance >>> - * @ops: backend operations for this scheduler >>> - * @submit_wq: workqueue to use for submission. If NULL, an >>> ordered wq is >>> - * allocated and used >>> - * @num_rqs: number of runqueues, one for each priority, up to >>> DRM_SCHED_PRIORITY_COUNT >>> - * @credit_limit: the number of credits this scheduler can hold >>> from all jobs >>> - * @hang_limit: number of times to allow a job to hang before >>> dropping it >>> - * @timeout: timeout value in jiffies for the scheduler >>> - * @timeout_wq: workqueue to use for timeout work. If NULL, the >>> system_wq is >>> - * used >>> - * @score: optional score atomic shared with other schedulers >>> - * @name: name used for debugging >>> - * @dev: target &struct device >>> + * @params: scheduler initialization parameters >>> * >>> * Return 0 on success, otherwise error code. >>> */ >>> int drm_sched_init(struct drm_gpu_scheduler *sched, >>> - const struct drm_sched_backend_ops *ops, >>> - struct workqueue_struct *submit_wq, >>> - u32 num_rqs, u32 credit_limit, unsigned int >>> hang_limit, >>> - long timeout, struct workqueue_struct >>> *timeout_wq, >>> - atomic_t *score, const char *name, struct >>> device *dev) >>> + const struct drm_sched_init_params *params) >>> { >>> int i; >>> >>> - sched->ops = ops; >>> - sched->credit_limit = credit_limit; >>> - sched->name = name; >>> - sched->timeout = timeout; >>> - sched->timeout_wq = timeout_wq ? : system_wq; >>> - sched->hang_limit = hang_limit; >>> - sched->score = score ? score : &sched->_score; >>> - sched->dev = dev; >>> + sched->ops = params->ops; >>> + sched->credit_limit = params->credit_limit; >>> + sched->name = params->name; >>> + sched->timeout = params->timeout; >>> + sched->timeout_wq = params->timeout_wq ? : system_wq; >>> + sched->hang_limit = params->hang_limit; >>> + sched->score = params->score ? params->score : &sched- >>>> _score; >>> + sched->dev = params->dev; >>> >>> - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { >>> + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { >>> /* This is a gross violation--tell drivers what >>> the problem is. >>> */ >>> drm_err(sched, "%s: num_rqs cannot be greater than >>> DRM_SCHED_PRIORITY_COUNT\n", >>> @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler >>> *sched, >>> return 0; >>> } >>> >>> - if (submit_wq) { >>> - sched->submit_wq = submit_wq; >>> + if (params->submit_wq) { >>> + sched->submit_wq = params->submit_wq; >>> sched->own_submit_wq = false; >>> } else { >>> #ifdef CONFIG_LOCKDEP >>> - sched->submit_wq = >>> alloc_ordered_workqueue_lockdep_map(name, >>> - >>> WQ_MEM_RECLAIM, >>> - >>> &drm_sched_lockdep_map); >>> + sched->submit_wq = >>> alloc_ordered_workqueue_lockdep_map( >>> + params->name, >>> WQ_MEM_RECLAIM, >>> + &drm_sched_lockdep_map); >>> #else >>> - sched->submit_wq = alloc_ordered_workqueue(name, >>> WQ_MEM_RECLAIM); >>> + sched->submit_wq = alloc_ordered_workqueue(params- >>>> name, WQ_MEM_RECLAIM); >>> #endif >>> if (!sched->submit_wq) >>> return -ENOMEM; >>> @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler >>> *sched, >>> sched->own_submit_wq = true; >>> } >>> >>> - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched- >>>> sched_rq), >>> + sched->sched_rq = kmalloc_array(params->num_rqs, >>> sizeof(*sched->sched_rq), >>> GFP_KERNEL | __GFP_ZERO); >>> if (!sched->sched_rq) >>> goto Out_check_own; >>> - sched->num_rqs = num_rqs; >>> + sched->num_rqs = params->num_rqs; >>> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; >>> i++) { >>> sched->sched_rq[i] = kzalloc(sizeof(*sched- >>>> sched_rq[i]), GFP_KERNEL); >>> if (!sched->sched_rq[i]) >>> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c >>> b/drivers/gpu/drm/v3d/v3d_sched.c >>> index 99ac4995b5a1..716e6d074d87 100644 >>> --- a/drivers/gpu/drm/v3d/v3d_sched.c >>> +++ b/drivers/gpu/drm/v3d/v3d_sched.c >>> @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops >>> v3d_cpu_sched_ops = { >>> .free_job = v3d_cpu_job_free >>> }; >>> >>> +/* >>> + * v3d's scheduler instances are all identical, except for ops and >>> name. >>> + */ >>> +static void >>> +v3d_common_sched_init(struct drm_sched_init_params *params, struct >>> device *dev) >>> +{ >>> + memset(params, 0, sizeof(struct drm_sched_init_params)); >>> + >>> + params->submit_wq = NULL; /* Use the system_wq. */ >>> + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params->credit_limit = 1; >>> + params->hang_limit = 0; >>> + params->timeout = msecs_to_jiffies(500); >>> + params->timeout_wq = NULL; /* Use the system_wq. */ >>> + params->score = NULL; >>> + params->dev = dev; >>> +} >>> + >>> +static int >>> +v3d_bin_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_bin_sched_ops; >>> + params.name = "v3d_bin"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_BIN].sched, >>> ¶ms); >>> +} >>> + >>> +static int >>> +v3d_render_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_render_sched_ops; >>> + params.name = "v3d_render"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, >>> ¶ms); >>> +} >>> + >>> +static int >>> +v3d_tfu_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_tfu_sched_ops; >>> + params.name = "v3d_tfu"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_TFU].sched, >>> ¶ms); >>> +} >>> + >>> +static int >>> +v3d_csd_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_csd_sched_ops; >>> + params.name = "v3d_csd"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_CSD].sched, >>> ¶ms); >>> +} >>> + >>> +static int >>> +v3d_cache_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_cache_clean_sched_ops; >>> + params.name = "v3d_cache_clean"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, >>> ¶ms); >>> +} >>> + >>> +static int >>> +v3d_cpu_sched_init(struct v3d_dev *v3d) >>> +{ >>> + struct drm_sched_init_params params; >>> + >>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>> + params.ops = &v3d_cpu_sched_ops; >>> + params.name = "v3d_cpu"; >>> + >>> + return drm_sched_init(&v3d->queue[V3D_CPU].sched, >>> ¶ms); >>> +} >>> + >>> int >>> v3d_sched_init(struct v3d_dev *v3d) >>> { >>> - int hw_jobs_limit = 1; >>> - int job_hang_limit = 0; >>> - int hang_limit_ms = 500; >>> int ret; >>> >>> - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, >>> - &v3d_bin_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - hw_jobs_limit, job_hang_limit, >>> - msecs_to_jiffies(hang_limit_ms), >>> NULL, >>> - NULL, "v3d_bin", v3d->drm.dev); >>> + ret = v3d_bin_sched_init(v3d); >>> if (ret) >>> return ret; >>> >>> - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, >>> - &v3d_render_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - hw_jobs_limit, job_hang_limit, >>> - msecs_to_jiffies(hang_limit_ms), >>> NULL, >>> - NULL, "v3d_render", v3d->drm.dev); >>> + ret = v3d_render_sched_init(v3d); >>> if (ret) >>> goto fail; >>> >>> - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, >>> - &v3d_tfu_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - hw_jobs_limit, job_hang_limit, >>> - msecs_to_jiffies(hang_limit_ms), >>> NULL, >>> - NULL, "v3d_tfu", v3d->drm.dev); >>> + ret = v3d_tfu_sched_init(v3d); >>> if (ret) >>> goto fail; >>> >>> if (v3d_has_csd(v3d)) { >>> - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, >>> - &v3d_csd_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - hw_jobs_limit, >>> job_hang_limit, >>> - >>> msecs_to_jiffies(hang_limit_ms), NULL, >>> - NULL, "v3d_csd", v3d- >>>> drm.dev); >>> + ret = v3d_csd_sched_init(v3d); >>> if (ret) >>> goto fail; >>> >>> - ret = drm_sched_init(&v3d- >>>> queue[V3D_CACHE_CLEAN].sched, >>> - &v3d_cache_clean_sched_ops, >>> NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - hw_jobs_limit, >>> job_hang_limit, >>> - >>> msecs_to_jiffies(hang_limit_ms), NULL, >>> - NULL, "v3d_cache_clean", v3d- >>>> drm.dev); >>> + ret = v3d_cache_sched_init(v3d); >>> if (ret) >>> goto fail; >>> } >>> >>> - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, >>> - &v3d_cpu_sched_ops, NULL, >>> - DRM_SCHED_PRIORITY_COUNT, >>> - 1, job_hang_limit, >>> - msecs_to_jiffies(hang_limit_ms), >>> NULL, >>> - NULL, "v3d_cpu", v3d->drm.dev); >>> + ret = v3d_cpu_sched_init(v3d); >>> if (ret) >>> goto fail; >>> >>> diff --git a/drivers/gpu/drm/xe/xe_execlist.c >>> b/drivers/gpu/drm/xe/xe_execlist.c >>> index a8c416a48812..7f29b7f04af4 100644 >>> --- a/drivers/gpu/drm/xe/xe_execlist.c >>> +++ b/drivers/gpu/drm/xe/xe_execlist.c >>> @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops >>> drm_sched_ops = { >>> static int execlist_exec_queue_init(struct xe_exec_queue *q) >>> { >>> struct drm_gpu_scheduler *sched; >>> + struct drm_sched_init_params params; >>> struct xe_execlist_exec_queue *exl; >>> struct xe_device *xe = gt_to_xe(q->gt); >>> int err; >>> >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> xe_assert(xe, !xe_device_uc_enabled(xe)); >>> >>> drm_info(&xe->drm, "Enabling execlist submission (GuC >>> submission disabled)\n"); >>> @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct >>> xe_exec_queue *q) >>> >>> exl->q = q; >>> >>> - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, >>> - q->lrc[0]->ring.size / >>> MAX_JOB_SIZE_BYTES, >>> - XE_SCHED_HANG_LIMIT, >>> XE_SCHED_JOB_TIMEOUT, >>> - NULL, NULL, q->hwe->name, >>> - gt_to_xe(q->gt)->drm.dev); >>> + params.ops = &drm_sched_ops; >>> + params.submit_wq = NULL; /* Use the system_wq. */ >>> + params.num_rqs = 1; >>> + params.credit_limit = q->lrc[0]->ring.size / >>> MAX_JOB_SIZE_BYTES; >>> + params.hang_limit = XE_SCHED_HANG_LIMIT; >>> + params.timeout = XE_SCHED_JOB_TIMEOUT; >>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>> + params.score = NULL; >>> + params.name = q->hwe->name; >>> + params.dev = gt_to_xe(q->gt)->drm.dev; >>> + >>> + err = drm_sched_init(&exl->sched, ¶ms); >>> if (err) >>> goto err_free; >>> >>> diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>> b/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>> index 50361b4638f9..2129fee83f25 100644 >>> --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>> +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>> @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler >>> *sched, >>> atomic_t *score, const char *name, >>> struct device *dev) >>> { >>> + struct drm_sched_init_params params; >>> + >>> sched->ops = xe_ops; >>> INIT_LIST_HEAD(&sched->msgs); >>> INIT_WORK(&sched->work_process_msg, >>> xe_sched_process_msg_work); >>> >>> - return drm_sched_init(&sched->base, ops, submit_wq, 1, >>> hw_submission, >>> - hang_limit, timeout, timeout_wq, >>> score, name, >>> - dev); >>> + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); >>> + >>> + params.ops = ops; >>> + params.submit_wq = submit_wq; >>> + params.num_rqs = 1; >>> + params.credit_limit = hw_submission; >>> + params.hang_limit = hang_limit; >>> + params.timeout = timeout; >>> + params.timeout_wq = timeout_wq; >>> + params.score = score; >>> + params.name = name; >>> + params.dev = dev; >>> + >>> + return drm_sched_init(&sched->base, ¶ms); >>> } >>> >>> void xe_sched_fini(struct xe_gpu_scheduler *sched) >>> diff --git a/include/drm/gpu_scheduler.h >>> b/include/drm/gpu_scheduler.h >>> index 95e17504e46a..1a834ef43862 100644 >>> --- a/include/drm/gpu_scheduler.h >>> +++ b/include/drm/gpu_scheduler.h >>> @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { >>> struct device *dev; >>> }; >>> >>> +/** >>> + * struct drm_sched_init_params - parameters for initializing a >>> DRM GPU scheduler >>> + * >>> + * @ops: backend operations provided by the driver >>> + * @submit_wq: workqueue to use for submission. If NULL, an >>> ordered wq is >>> + * allocated and used >>> + * @num_rqs: Number of run-queues. This is at most >>> DRM_SCHED_PRIORITY_COUNT, >>> + * as there's usually one run-queue per priority, but >>> could be less. >>> + * @credit_limit: the number of credits this scheduler can hold >>> from all jobs >>> + * @hang_limit: number of times to allow a job to hang before >>> dropping it >>> + * @timeout: timeout value in jiffies for the scheduler >>> + * @timeout_wq: workqueue to use for timeout work. If NULL, the >>> system_wq is >>> + * used >>> + * @score: optional score atomic shared with other schedulers >>> + * @name: name used for debugging >>> + * @dev: associated device. Used for debugging >>> + */ >>> +struct drm_sched_init_params { >>> + const struct drm_sched_backend_ops *ops; >>> + struct workqueue_struct *submit_wq; >>> + struct workqueue_struct *timeout_wq; >>> + u32 num_rqs, credit_limit; >>> + unsigned int hang_limit; >>> + long timeout; >>> + atomic_t *score; >>> + const char *name; >>> + struct device *dev; >>> +}; >>> + >>> int drm_sched_init(struct drm_gpu_scheduler *sched, >>> - const struct drm_sched_backend_ops *ops, >>> - struct workqueue_struct *submit_wq, >>> - u32 num_rqs, u32 credit_limit, unsigned int >>> hang_limit, >>> - long timeout, struct workqueue_struct >>> *timeout_wq, >>> - atomic_t *score, const char *name, struct >>> device *dev); >>> + const struct drm_sched_init_params *params); >>> >>> void drm_sched_fini(struct drm_gpu_scheduler *sched); >>> int drm_sched_job_init(struct drm_sched_job *job,
On Wed, 2025-01-22 at 16:06 +0100, Christian König wrote: > Am 22.01.25 um 15:48 schrieb Philipp Stanner: > > On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: > > > Am 22.01.25 um 15:08 schrieb Philipp Stanner: > > > > drm_sched_init() has a great many parameters and upcoming new > > > > functionality for the scheduler might add even more. Generally, > > > > the > > > > great number of parameters reduces readability and has already > > > > caused > > > > one missnaming in: > > > > > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > > > nouveau_sched_init()"). > > > > > > > > Introduce a new struct for the scheduler init parameters and > > > > port > > > > all > > > > users. > > > > > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > > > --- > > > > Howdy, > > > > > > > > I have a patch-series in the pipe that will add a `flags` > > > > argument > > > > to > > > > drm_sched_init(). I thought it would be wise to first rework > > > > the > > > > API as > > > > detailed in this patch. It's really a lot of parameters by now, > > > > and > > > > I > > > > would expect that it might get more and more over the years for > > > > special > > > > use cases etc. > > > > > > > > Regards, > > > > P. > > > > --- > > > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > > > drivers/gpu/drm/v3d/v3d_sched.c | 135 > > > > +++++++++++++++- > > > > ----- > > > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > > > include/drm/gpu_scheduler.h | 35 +++++- > > > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > index cd4fac120834..c1f03eb5f5ea 100644 > > > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > @@ -2821,6 +2821,9 @@ static int > > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > > { > > > > long timeout; > > > > int r, i; > > > > + struct drm_sched_init_params params; > > > Please keep the reverse xmas tree ordering for variable > > > declaration. > > > E.g. long lines first and variables like "i" and "r" last. > > Okay dokay > > > > > Apart from that looks like a good idea to me. > > > > > > > > > > + > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > > > > > for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { > > > > struct amdgpu_ring *ring = adev->rings[i]; > > > > @@ -2844,12 +2847,18 @@ static int > > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > > break; > > > > } > > > > > > > > - r = drm_sched_init(&ring->sched, > > > > &amdgpu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - ring->num_hw_submission, 0, > > > > - timeout, adev- > > > > >reset_domain- > > > > > wq, > > > > - ring->sched_score, ring- > > > > >name, > > > > - adev->dev); > > > > + params.ops = &amdgpu_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. > > > > */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = ring->num_hw_submission; > > > > + params.hang_limit = 0; > > > Could we please remove the hang limit as first step to get this > > > awful > > > feature deprecated? > > Remove it? From the struct you mean? > > > > We can mark it as deprecated in the docstring of the new struct. > > That's > > what you mean, don't you? > > No, the function using this parameter already deprecated. What I > meant > is to start to completely remove this feature. > > The hang_limit basically says how often the scheduler should try to > run > a job over and over again before giving up. Agreed, it should be removed. But let me do that in a separate patch after this one is merged, and just hint at the deprecation in the arg in the struct for now; it's kind of unrelated to the init()-rework I'm doing here, ack? > > And we already agreed that trying the same thing over and over again > and > expecting different results is the definition of insanity :) I'll quote you (and Einstein) with that if I ever give a presentation about the scheduler ;p P. > > So my suggestion is to drop the parameter and drop the job as soon as > it > caused a timeout. > > Regards, > Christian. > > > > > P. > > > > > Thanks, > > > Christian. > > > > > > > + params.timeout = timeout; > > > > + params.timeout_wq = adev->reset_domain->wq; > > > > + params.score = ring->sched_score; > > > > + params.name = ring->name; > > > > + params.dev = adev->dev; > > > > + > > > > + r = drm_sched_init(&ring->sched, ¶ms); > > > > if (r) { > > > > DRM_ERROR("Failed to create scheduler > > > > on > > > > ring %s.\n", > > > > ring->name); > > > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > index 5b67eda122db..7d8517f1963e 100644 > > > > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct > > > > etnaviv_gem_submit *submit) > > > > int etnaviv_sched_init(struct etnaviv_gpu *gpu) > > > > { > > > > int ret; > > > > + struct drm_sched_init_params params; > > > > > > > > - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - etnaviv_hw_jobs_limit, > > > > etnaviv_job_hang_limit, > > > > - msecs_to_jiffies(500), NULL, > > > > NULL, > > > > - dev_name(gpu->dev), gpu->dev); > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > + params.ops = &etnaviv_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = etnaviv_hw_jobs_limit; > > > > + params.hang_limit = etnaviv_job_hang_limit; > > > > + params.timeout = msecs_to_jiffies(500); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = dev_name(gpu->dev); > > > > + params.dev = gpu->dev; > > > > + > > > > + ret = drm_sched_init(&gpu->sched, ¶ms); > > > > if (ret) > > > > return ret; > > > > > > > > diff --git a/drivers/gpu/drm/imagination/pvr_queue.c > > > > b/drivers/gpu/drm/imagination/pvr_queue.c > > > > index c4f08432882b..03a2ce1a88e7 100644 > > > > --- a/drivers/gpu/drm/imagination/pvr_queue.c > > > > +++ b/drivers/gpu/drm/imagination/pvr_queue.c > > > > @@ -1211,10 +1211,13 @@ struct pvr_queue > > > > *pvr_queue_create(struct > > > > pvr_context *ctx, > > > > }; > > > > struct pvr_device *pvr_dev = ctx->pvr_dev; > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct pvr_queue *queue; > > > > int ctx_state_size, err; > > > > void *cpu_map; > > > > > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > if (WARN_ON(type >= sizeof(props))) > > > > return ERR_PTR(-EINVAL); > > > > > > > > @@ -1282,12 +1285,18 @@ struct pvr_queue > > > > *pvr_queue_create(struct > > > > pvr_context *ctx, > > > > > > > > queue->timeline_ufo.value = cpu_map; > > > > > > > > - err = drm_sched_init(&queue->scheduler, > > > > - &pvr_queue_sched_ops, > > > > - pvr_dev->sched_wq, 1, 64 * 1024, > > > > 1, > > > > - msecs_to_jiffies(500), > > > > - pvr_dev->sched_wq, NULL, "pvr- > > > > queue", > > > > - pvr_dev->base.dev); > > > > + sched_params.ops = &pvr_queue_sched_ops; > > > > + sched_params.submit_wq = pvr_dev->sched_wq; > > > > + sched_params.num_rqs = 1; > > > > + sched_params.credit_limit = 64 * 1024; > > > > + sched_params.hang_limit = 1; > > > > + sched_params.timeout = msecs_to_jiffies(500); > > > > + sched_params.timeout_wq = pvr_dev->sched_wq; > > > > + sched_params.score = NULL; > > > > + sched_params.name = "pvr-queue"; > > > > + sched_params.dev = pvr_dev->base.dev; > > > > + > > > > + err = drm_sched_init(&queue->scheduler, > > > > &sched_params); > > > > if (err) > > > > goto err_release_ufo; > > > > > > > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > > > > b/drivers/gpu/drm/lima/lima_sched.c > > > > index b40c90e97d7e..a64c50fb6d1e 100644 > > > > --- a/drivers/gpu/drm/lima/lima_sched.c > > > > +++ b/drivers/gpu/drm/lima/lima_sched.c > > > > @@ -513,20 +513,29 @@ static void > > > > lima_sched_recover_work(struct > > > > work_struct *work) > > > > > > > > int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const > > > > char > > > > *name) > > > > { > > > > + struct drm_sched_init_params params; > > > > unsigned int timeout = lima_sched_timeout_ms > 0 ? > > > > lima_sched_timeout_ms : 10000; > > > > > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > 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, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - 1, > > > > - lima_job_hang_limit, > > > > - msecs_to_jiffies(timeout), NULL, > > > > - NULL, name, pipe->ldev->dev); > > > > + params.ops = &lima_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = 1; > > > > + params.hang_limit = lima_job_hang_limit; > > > > + params.timeout = msecs_to_jiffies(timeout); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = name; > > > > + params.dev = pipe->ldev->dev; > > > > + > > > > + return drm_sched_init(&pipe->base, ¶ms); > > > > } > > > > > > > > void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) > > > > diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > index c803556a8f64..49a2c7422dc6 100644 > > > > --- a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops > > > > msm_sched_ops = { > > > > struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu > > > > *gpu, > > > > int id, > > > > void *memptrs, uint64_t memptrs_iova) > > > > { > > > > + struct drm_sched_init_params params; > > > > struct msm_ringbuffer *ring; > > > > - long sched_timeout; > > > > char name[32]; > > > > int ret; > > > > > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is > > > > a > > > > power of 2 */ > > > > BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); > > > > > > > > @@ -95,13 +97,19 @@ struct msm_ringbuffer > > > > *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > > > > ring->memptrs = memptrs; > > > > ring->memptrs_iova = memptrs_iova; > > > > > > > > - /* currently managing hangcheck ourselves: */ > > > > - sched_timeout = MAX_SCHEDULE_TIMEOUT; > > > > + params.ops = &msm_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = num_hw_submissions; > > > > + params.hang_limit = 0; > > > > + /* currently managing hangcheck ourselves: */ > > > > + params.timeout = MAX_SCHEDULE_TIMEOUT; > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = to_msm_bo(ring->bo)->name; > > > > + params.dev = gpu->dev->dev; > > > > > > > > - ret = drm_sched_init(&ring->sched, &msm_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - num_hw_submissions, 0, > > > > sched_timeout, > > > > - NULL, NULL, to_msm_bo(ring->bo)- > > > > > name, gpu->dev->dev); > > > > + ret = drm_sched_init(&ring->sched, ¶ms); > > > > if (ret) { > > > > goto fail; > > > > } > > > > diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > index 4412f2711fb5..f20c2e612750 100644 > > > > --- a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched > > > > *sched, struct nouveau_drm *drm, > > > > { > > > > struct drm_gpu_scheduler *drm_sched = &sched->base; > > > > struct drm_sched_entity *entity = &sched->entity; > > > > - const long timeout = > > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > > + struct drm_sched_init_params params; > > > > int ret; > > > > > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > if (!wq) { > > > > wq = alloc_workqueue("nouveau_sched_wq_%d", 0, > > > > WQ_MAX_ACTIVE, > > > > current->pid); > > > > @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched > > > > *sched, struct nouveau_drm *drm, > > > > sched->wq = wq; > > > > } > > > > > > > > - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, > > > > wq, > > > > - NOUVEAU_SCHED_PRIORITY_COUNT, > > > > - credit_limit, 0, timeout, > > > > - NULL, NULL, "nouveau_sched", drm- > > > > > dev->dev); > > > > + params.ops = &nouveau_sched_ops; > > > > + params.submit_wq = wq; > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = credit_limit; > > > > + params.hang_limit = 0; > > > > + params.timeout = > > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = "nouveau_sched"; > > > > + params.dev = drm->dev->dev; > > > > + > > > > + ret = drm_sched_init(drm_sched, ¶ms); > > > > if (ret) > > > > goto fail_wq; > > > > > > > > diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c > > > > b/drivers/gpu/drm/panfrost/panfrost_job.c > > > > index 9b8e82fb8bc4..6b509ff446b5 100644 > > > > --- a/drivers/gpu/drm/panfrost/panfrost_job.c > > > > +++ b/drivers/gpu/drm/panfrost/panfrost_job.c > > > > @@ -836,10 +836,13 @@ static irqreturn_t > > > > panfrost_job_irq_handler(int irq, void *data) > > > > > > > > int panfrost_job_init(struct panfrost_device *pfdev) > > > > { > > > > + struct drm_sched_init_params params; > > > > struct panfrost_job_slot *js; > > > > unsigned int nentries = 2; > > > > int ret, j; > > > > > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > /* All GPUs have two entries per queue, but without > > > > jobchain > > > > * disambiguation stopping the right job in the close > > > > path > > > > is tricky, > > > > * so let's just advertise one entry in that case. > > > > @@ -872,16 +875,21 @@ int panfrost_job_init(struct > > > > panfrost_device > > > > *pfdev) > > > > if (!pfdev->reset.wq) > > > > return -ENOMEM; > > > > > > > > + params.ops = &panfrost_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = nentries; > > > > + params.hang_limit = 0; > > > > + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > > > + params.timeout_wq = pfdev->reset.wq; > > > > + params.score = NULL; > > > > + params.name = "pan_js"; > > > > + params.dev = pfdev->dev; > > > > + > > > > for (j = 0; j < NUM_JOB_SLOTS; j++) { > > > > js->queue[j].fence_context = > > > > dma_fence_context_alloc(1); > > > > > > > > - ret = drm_sched_init(&js->queue[j].sched, > > > > - &panfrost_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - nentries, 0, > > > > - > > > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > - pfdev->reset.wq, > > > > - NULL, "pan_js", pfdev- > > > > >dev); > > > > + ret = drm_sched_init(&js->queue[j].sched, > > > > ¶ms); > > > > if (ret) { > > > > dev_err(pfdev->dev, "Failed to create > > > > scheduler: %d.", ret); > > > > goto err_sched; > > > > diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c > > > > b/drivers/gpu/drm/panthor/panthor_mmu.c > > > > index a49132f3778b..4362442cbfd8 100644 > > > > --- a/drivers/gpu/drm/panthor/panthor_mmu.c > > > > +++ b/drivers/gpu/drm/panthor/panthor_mmu.c > > > > @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > u64 full_va_range = 1ull << va_bits; > > > > struct drm_gem_object *dummy_gem; > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct io_pgtable_cfg pgtbl_cfg; > > > > u64 mair, min_va, va_range; > > > > struct panthor_vm *vm; > > > > @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > goto err_free_vm; > > > > } > > > > > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > mutex_init(&vm->heaps.lock); > > > > vm->for_mcu = for_mcu; > > > > vm->ptdev = ptdev; > > > > @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > goto err_mm_takedown; > > > > } > > > > > > > > + sched_params.ops = &panthor_vm_bind_ops; > > > > + sched_params.submit_wq = ptdev->mmu->vm.wq; > > > > + sched_params.num_rqs = 1; > > > > + sched_params.credit_limit = 1; > > > > + sched_params.hang_limit = 0; > > > > /* Bind operations are synchronous for now, no timeout > > > > needed. */ > > > > - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, > > > > ptdev->mmu->vm.wq, > > > > - 1, 1, 0, > > > > - MAX_SCHEDULE_TIMEOUT, NULL, NULL, > > > > - "panthor-vm-bind", ptdev- > > > > >base.dev); > > > > + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; > > > > + sched_params.timeout_wq = NULL; /* Use the system_wq. > > > > */ > > > > + sched_params.score = NULL; > > > > + sched_params.name = "panthor-vm-bind"; > > > > + sched_params.dev = ptdev->base.dev; > > > > + ret = drm_sched_init(&vm->sched, &sched_params); > > > > if (ret) > > > > goto err_free_io_pgtable; > > > > > > > > diff --git a/drivers/gpu/drm/panthor/panthor_sched.c > > > > b/drivers/gpu/drm/panthor/panthor_sched.c > > > > index ef4bec7ff9c7..a324346d302f 100644 > > > > --- a/drivers/gpu/drm/panthor/panthor_sched.c > > > > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > > > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group > > > > *group, > > > > const struct drm_panthor_queue_create > > > > *args) > > > > { > > > > struct drm_gpu_scheduler *drm_sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct panthor_queue *queue; > > > > int ret; > > > > > > > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group > > > > *group, > > > > if (!queue) > > > > return ERR_PTR(-ENOMEM); > > > > > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > queue->fence_ctx.id = dma_fence_context_alloc(1); > > > > spin_lock_init(&queue->fence_ctx.lock); > > > > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > > > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group > > > > *group, > > > > if (ret) > > > > goto err_free_queue; > > > > > > > > + sched_params.ops = &panthor_queue_sched_ops; > > > > + sched_params.submit_wq = group->ptdev->scheduler->wq; > > > > + sched_params.num_rqs = 1; > > > > /* > > > > - * Credit limit argument tells us the total number of > > > > instructions > > > > + * The credit limit argument tells us the total number > > > > of > > > > instructions > > > > * across all CS slots in the ringbuffer, with some > > > > jobs > > > > requiring > > > > * twice as many as others, depending on their > > > > profiling > > > > status. > > > > */ > > > > - ret = drm_sched_init(&queue->scheduler, > > > > &panthor_queue_sched_ops, > > > > - group->ptdev->scheduler->wq, 1, > > > > - args->ringbuf_size / sizeof(u64), > > > > - 0, > > > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > - group->ptdev->reset.wq, > > > > - NULL, "panthor-queue", group- > > > > >ptdev- > > > > > base.dev); > > > > + sched_params.credit_limit = args->ringbuf_size / > > > > sizeof(u64); > > > > + sched_params.hang_limit = 0; > > > > + sched_params.timeout = > > > > msecs_to_jiffies(JOB_TIMEOUT_MS); > > > > + sched_params.timeout_wq = group->ptdev->reset.wq; > > > > + sched_params.score = NULL; > > > > + sched_params.name = "panthor-queue"; > > > > + sched_params.dev = group->ptdev->base.dev; > > > > + > > > > + ret = drm_sched_init(&queue->scheduler, > > > > &sched_params); > > > > if (ret) > > > > goto err_free_queue; > > > > > > > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > > > > b/drivers/gpu/drm/scheduler/sched_main.c > > > > index 57da84908752..27db748a5269 100644 > > > > --- a/drivers/gpu/drm/scheduler/sched_main.c > > > > +++ b/drivers/gpu/drm/scheduler/sched_main.c > > > > @@ -1240,40 +1240,25 @@ static void > > > > drm_sched_run_job_work(struct > > > > work_struct *w) > > > > * drm_sched_init - Init a gpu scheduler instance > > > > * > > > > * @sched: scheduler instance > > > > - * @ops: backend operations for this scheduler > > > > - * @submit_wq: workqueue to use for submission. If NULL, an > > > > ordered wq is > > > > - * allocated and used > > > > - * @num_rqs: number of runqueues, one for each priority, up to > > > > DRM_SCHED_PRIORITY_COUNT > > > > - * @credit_limit: the number of credits this scheduler can > > > > hold > > > > from all jobs > > > > - * @hang_limit: number of times to allow a job to hang before > > > > dropping it > > > > - * @timeout: timeout value in jiffies for the scheduler > > > > - * @timeout_wq: workqueue to use for timeout work. If NULL, > > > > the > > > > system_wq is > > > > - * used > > > > - * @score: optional score atomic shared with other schedulers > > > > - * @name: name used for debugging > > > > - * @dev: target &struct device > > > > + * @params: scheduler initialization parameters > > > > * > > > > * Return 0 on success, otherwise error code. > > > > */ > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > - const struct drm_sched_backend_ops *ops, > > > > - struct workqueue_struct *submit_wq, > > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > > hang_limit, > > > > - long timeout, struct workqueue_struct > > > > *timeout_wq, > > > > - atomic_t *score, const char *name, struct > > > > device *dev) > > > > + const struct drm_sched_init_params *params) > > > > { > > > > int i; > > > > > > > > - sched->ops = ops; > > > > - sched->credit_limit = credit_limit; > > > > - sched->name = name; > > > > - sched->timeout = timeout; > > > > - sched->timeout_wq = timeout_wq ? : system_wq; > > > > - sched->hang_limit = hang_limit; > > > > - sched->score = score ? score : &sched->_score; > > > > - sched->dev = dev; > > > > + sched->ops = params->ops; > > > > + sched->credit_limit = params->credit_limit; > > > > + sched->name = params->name; > > > > + sched->timeout = params->timeout; > > > > + sched->timeout_wq = params->timeout_wq ? : system_wq; > > > > + sched->hang_limit = params->hang_limit; > > > > + sched->score = params->score ? params->score : &sched- > > > > > _score; > > > > + sched->dev = params->dev; > > > > > > > > - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > > + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > > /* This is a gross violation--tell drivers > > > > what > > > > the problem is. > > > > */ > > > > drm_err(sched, "%s: num_rqs cannot be greater > > > > than > > > > DRM_SCHED_PRIORITY_COUNT\n", > > > > @@ -1288,16 +1273,16 @@ int drm_sched_init(struct > > > > drm_gpu_scheduler > > > > *sched, > > > > return 0; > > > > } > > > > > > > > - if (submit_wq) { > > > > - sched->submit_wq = submit_wq; > > > > + if (params->submit_wq) { > > > > + sched->submit_wq = params->submit_wq; > > > > sched->own_submit_wq = false; > > > > } else { > > > > #ifdef CONFIG_LOCKDEP > > > > - sched->submit_wq = > > > > alloc_ordered_workqueue_lockdep_map(name, > > > > - > > > > > > > > WQ_MEM_RECLAIM, > > > > - > > > > > > > > &drm_sched_lockdep_map); > > > > + sched->submit_wq = > > > > alloc_ordered_workqueue_lockdep_map( > > > > + params->name, > > > > WQ_MEM_RECLAIM, > > > > + &drm_sched_lockdep_map > > > > ); > > > > #else > > > > - sched->submit_wq = > > > > alloc_ordered_workqueue(name, > > > > WQ_MEM_RECLAIM); > > > > + sched->submit_wq = > > > > alloc_ordered_workqueue(params- > > > > > name, WQ_MEM_RECLAIM); > > > > #endif > > > > if (!sched->submit_wq) > > > > return -ENOMEM; > > > > @@ -1305,11 +1290,11 @@ int drm_sched_init(struct > > > > drm_gpu_scheduler > > > > *sched, > > > > sched->own_submit_wq = true; > > > > } > > > > > > > > - sched->sched_rq = kmalloc_array(num_rqs, > > > > sizeof(*sched- > > > > > sched_rq), > > > > + sched->sched_rq = kmalloc_array(params->num_rqs, > > > > sizeof(*sched->sched_rq), > > > > GFP_KERNEL | > > > > __GFP_ZERO); > > > > if (!sched->sched_rq) > > > > goto Out_check_own; > > > > - sched->num_rqs = num_rqs; > > > > + sched->num_rqs = params->num_rqs; > > > > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched- > > > > >num_rqs; > > > > i++) { > > > > sched->sched_rq[i] = kzalloc(sizeof(*sched- > > > > > sched_rq[i]), GFP_KERNEL); > > > > if (!sched->sched_rq[i]) > > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > > > b/drivers/gpu/drm/v3d/v3d_sched.c > > > > index 99ac4995b5a1..716e6d074d87 100644 > > > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > > > @@ -814,67 +814,124 @@ static const struct > > > > drm_sched_backend_ops > > > > v3d_cpu_sched_ops = { > > > > .free_job = v3d_cpu_job_free > > > > }; > > > > > > > > +/* > > > > + * v3d's scheduler instances are all identical, except for ops > > > > and > > > > name. > > > > + */ > > > > +static void > > > > +v3d_common_sched_init(struct drm_sched_init_params *params, > > > > struct > > > > device *dev) > > > > +{ > > > > + memset(params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > + params->submit_wq = NULL; /* Use the system_wq. */ > > > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params->credit_limit = 1; > > > > + params->hang_limit = 0; > > > > + params->timeout = msecs_to_jiffies(500); > > > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > > > + params->score = NULL; > > > > + params->dev = dev; > > > > +} > > > > + > > > > +static int > > > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_bin_sched_ops; > > > > + params.name = "v3d_bin"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_render_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_render_sched_ops; > > > > + params.name = "v3d_render"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_tfu_sched_ops; > > > > + params.name = "v3d_tfu"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_csd_sched_ops; > > > > + params.name = "v3d_csd"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_cache_clean_sched_ops; > > > > + params.name = "v3d_cache_clean"; > > > > + > > > > + return drm_sched_init(&v3d- > > > > >queue[V3D_CACHE_CLEAN].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_cpu_sched_ops; > > > > + params.name = "v3d_cpu"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > > ¶ms); > > > > +} > > > > + > > > > int > > > > v3d_sched_init(struct v3d_dev *v3d) > > > > { > > > > - int hw_jobs_limit = 1; > > > > - int job_hang_limit = 0; > > > > - int hang_limit_ms = 500; > > > > int ret; > > > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > > - &v3d_bin_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_bin", v3d->drm.dev); > > > > + ret = v3d_bin_sched_init(v3d); > > > > if (ret) > > > > return ret; > > > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > > - &v3d_render_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_render", v3d- > > > > >drm.dev); > > > > + ret = v3d_render_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > > - &v3d_tfu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_tfu", v3d->drm.dev); > > > > + ret = v3d_tfu_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > > > > > if (v3d_has_csd(v3d)) { > > > > - ret = drm_sched_init(&v3d- > > > > >queue[V3D_CSD].sched, > > > > - &v3d_csd_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, > > > > job_hang_limit, > > > > - > > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > > - NULL, "v3d_csd", v3d- > > > > > drm.dev); > > > > + ret = v3d_csd_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > > > > > - ret = drm_sched_init(&v3d- > > > > > queue[V3D_CACHE_CLEAN].sched, > > > > - > > > > &v3d_cache_clean_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, > > > > job_hang_limit, > > > > - > > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > > - NULL, "v3d_cache_clean", > > > > v3d- > > > > > drm.dev); > > > > + ret = v3d_cache_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > } > > > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > > - &v3d_cpu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - 1, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_cpu", v3d->drm.dev); > > > > + ret = v3d_cpu_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > > > > > diff --git a/drivers/gpu/drm/xe/xe_execlist.c > > > > b/drivers/gpu/drm/xe/xe_execlist.c > > > > index a8c416a48812..7f29b7f04af4 100644 > > > > --- a/drivers/gpu/drm/xe/xe_execlist.c > > > > +++ b/drivers/gpu/drm/xe/xe_execlist.c > > > > @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops > > > > drm_sched_ops = { > > > > static int execlist_exec_queue_init(struct xe_exec_queue *q) > > > > { > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params params; > > > > struct xe_execlist_exec_queue *exl; > > > > struct xe_device *xe = gt_to_xe(q->gt); > > > > int err; > > > > > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > xe_assert(xe, !xe_device_uc_enabled(xe)); > > > > > > > > drm_info(&xe->drm, "Enabling execlist submission (GuC > > > > submission disabled)\n"); > > > > @@ -346,11 +349,18 @@ static int > > > > execlist_exec_queue_init(struct > > > > xe_exec_queue *q) > > > > > > > > exl->q = q; > > > > > > > > - err = drm_sched_init(&exl->sched, &drm_sched_ops, > > > > NULL, 1, > > > > - q->lrc[0]->ring.size / > > > > MAX_JOB_SIZE_BYTES, > > > > - XE_SCHED_HANG_LIMIT, > > > > XE_SCHED_JOB_TIMEOUT, > > > > - NULL, NULL, q->hwe->name, > > > > - gt_to_xe(q->gt)->drm.dev); > > > > + params.ops = &drm_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = 1; > > > > + params.credit_limit = q->lrc[0]->ring.size / > > > > MAX_JOB_SIZE_BYTES; > > > > + params.hang_limit = XE_SCHED_HANG_LIMIT; > > > > + params.timeout = XE_SCHED_JOB_TIMEOUT; > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = q->hwe->name; > > > > + params.dev = gt_to_xe(q->gt)->drm.dev; > > > > + > > > > + err = drm_sched_init(&exl->sched, ¶ms); > > > > if (err) > > > > goto err_free; > > > > > > > > diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > index 50361b4638f9..2129fee83f25 100644 > > > > --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler > > > > *sched, > > > > atomic_t *score, const char *name, > > > > struct device *dev) > > > > { > > > > + struct drm_sched_init_params params; > > > > + > > > > sched->ops = xe_ops; > > > > INIT_LIST_HEAD(&sched->msgs); > > > > INIT_WORK(&sched->work_process_msg, > > > > xe_sched_process_msg_work); > > > > > > > > - return drm_sched_init(&sched->base, ops, submit_wq, 1, > > > > hw_submission, > > > > - hang_limit, timeout, timeout_wq, > > > > score, name, > > > > - dev); > > > > + memset(¶ms, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > + params.ops = ops; > > > > + params.submit_wq = submit_wq; > > > > + params.num_rqs = 1; > > > > + params.credit_limit = hw_submission; > > > > + params.hang_limit = hang_limit; > > > > + params.timeout = timeout; > > > > + params.timeout_wq = timeout_wq; > > > > + params.score = score; > > > > + params.name = name; > > > > + params.dev = dev; > > > > + > > > > + return drm_sched_init(&sched->base, ¶ms); > > > > } > > > > > > > > void xe_sched_fini(struct xe_gpu_scheduler *sched) > > > > diff --git a/include/drm/gpu_scheduler.h > > > > b/include/drm/gpu_scheduler.h > > > > index 95e17504e46a..1a834ef43862 100644 > > > > --- a/include/drm/gpu_scheduler.h > > > > +++ b/include/drm/gpu_scheduler.h > > > > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > > > > struct device *dev; > > > > }; > > > > > > > > +/** > > > > + * struct drm_sched_init_params - parameters for initializing > > > > a > > > > DRM GPU scheduler > > > > + * > > > > + * @ops: backend operations provided by the driver > > > > + * @submit_wq: workqueue to use for submission. If NULL, an > > > > ordered wq is > > > > + * allocated and used > > > > + * @num_rqs: Number of run-queues. This is at most > > > > DRM_SCHED_PRIORITY_COUNT, > > > > + * as there's usually one run-queue per priority, > > > > but > > > > could be less. > > > > + * @credit_limit: the number of credits this scheduler can > > > > hold > > > > from all jobs > > > > + * @hang_limit: number of times to allow a job to hang before > > > > dropping it > > > > + * @timeout: timeout value in jiffies for the scheduler > > > > + * @timeout_wq: workqueue to use for timeout work. If NULL, > > > > the > > > > system_wq is > > > > + * used > > > > + * @score: optional score atomic shared with other schedulers > > > > + * @name: name used for debugging > > > > + * @dev: associated device. Used for debugging > > > > + */ > > > > +struct drm_sched_init_params { > > > > + const struct drm_sched_backend_ops *ops; > > > > + struct workqueue_struct *submit_wq; > > > > + struct workqueue_struct *timeout_wq; > > > > + u32 num_rqs, credit_limit; > > > > + unsigned int hang_limit; > > > > + long timeout; > > > > + atomic_t *score; > > > > + const char *name; > > > > + struct device *dev; > > > > +}; > > > > + > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > - const struct drm_sched_backend_ops *ops, > > > > - struct workqueue_struct *submit_wq, > > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > > hang_limit, > > > > - long timeout, struct workqueue_struct > > > > *timeout_wq, > > > > - atomic_t *score, const char *name, struct > > > > device *dev); > > > > + const struct drm_sched_init_params *params); > > > > > > > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > > > > int drm_sched_job_init(struct drm_sched_job *job, >
On Wed, Jan 22, 2025 at 04:06:10PM +0100, Christian König wrote: > Am 22.01.25 um 15:48 schrieb Philipp Stanner: > > On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: > > > Am 22.01.25 um 15:08 schrieb Philipp Stanner: > > > > drm_sched_init() has a great many parameters and upcoming new > > > > functionality for the scheduler might add even more. Generally, the > > > > great number of parameters reduces readability and has already > > > > caused > > > > one missnaming in: > > > > > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > > > nouveau_sched_init()"). > > > > > > > > Introduce a new struct for the scheduler init parameters and port > > > > all > > > > users. > > > > > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > > > --- > > > > Howdy, > > > > > > > > I have a patch-series in the pipe that will add a `flags` argument > > > > to > > > > drm_sched_init(). I thought it would be wise to first rework the > > > > API as > > > > detailed in this patch. It's really a lot of parameters by now, and > > > > I > > > > would expect that it might get more and more over the years for > > > > special > > > > use cases etc. > > > > > > > > Regards, > > > > P. > > > > --- > > > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > > > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++- > > > > ----- > > > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > > > include/drm/gpu_scheduler.h | 35 +++++- > > > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > index cd4fac120834..c1f03eb5f5ea 100644 > > > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > > > > @@ -2821,6 +2821,9 @@ static int > > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > > { > > > > long timeout; > > > > int r, i; > > > > + struct drm_sched_init_params params; > > > Please keep the reverse xmas tree ordering for variable declaration. > > > E.g. long lines first and variables like "i" and "r" last. > > Okay dokay > > > > > Apart from that looks like a good idea to me. > > > > > > > > > > + > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { > > > > struct amdgpu_ring *ring = adev->rings[i]; > > > > @@ -2844,12 +2847,18 @@ static int > > > > amdgpu_device_init_schedulers(struct amdgpu_device *adev) > > > > break; > > > > } > > > > - r = drm_sched_init(&ring->sched, > > > > &amdgpu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - ring->num_hw_submission, 0, > > > > - timeout, adev->reset_domain- > > > > > wq, > > > > - ring->sched_score, ring->name, > > > > - adev->dev); > > > > + params.ops = &amdgpu_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = ring->num_hw_submission; > > > > + params.hang_limit = 0; > > > Could we please remove the hang limit as first step to get this awful > > > feature deprecated? > > Remove it? From the struct you mean? > > > > We can mark it as deprecated in the docstring of the new struct. That's > > what you mean, don't you? > > No, the function using this parameter already deprecated. What I meant is to > start to completely remove this feature. > > The hang_limit basically says how often the scheduler should try to run a > job over and over again before giving up. > > And we already agreed that trying the same thing over and over again and > expecting different results is the definition of insanity :) > > So my suggestion is to drop the parameter and drop the job as soon as it > caused a timeout. > In Xe we take this further, if a job hangs we ban the entire queue. So from our end hand limit is useless. Matt > Regards, > Christian. > > > > > P. > > > > > Thanks, > > > Christian. > > > > > > > + params.timeout = timeout; > > > > + params.timeout_wq = adev->reset_domain->wq; > > > > + params.score = ring->sched_score; > > > > + params.name = ring->name; > > > > + params.dev = adev->dev; > > > > + > > > > + r = drm_sched_init(&ring->sched, ¶ms); > > > > if (r) { > > > > DRM_ERROR("Failed to create scheduler on > > > > ring %s.\n", > > > > ring->name); > > > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > index 5b67eda122db..7d8517f1963e 100644 > > > > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > > > > @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct > > > > etnaviv_gem_submit *submit) > > > > int etnaviv_sched_init(struct etnaviv_gpu *gpu) > > > > { > > > > int ret; > > > > + struct drm_sched_init_params params; > > > > - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - etnaviv_hw_jobs_limit, > > > > etnaviv_job_hang_limit, > > > > - msecs_to_jiffies(500), NULL, NULL, > > > > - dev_name(gpu->dev), gpu->dev); > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > + params.ops = &etnaviv_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = etnaviv_hw_jobs_limit; > > > > + params.hang_limit = etnaviv_job_hang_limit; > > > > + params.timeout = msecs_to_jiffies(500); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = dev_name(gpu->dev); > > > > + params.dev = gpu->dev; > > > > + > > > > + ret = drm_sched_init(&gpu->sched, ¶ms); > > > > if (ret) > > > > return ret; > > > > diff --git a/drivers/gpu/drm/imagination/pvr_queue.c > > > > b/drivers/gpu/drm/imagination/pvr_queue.c > > > > index c4f08432882b..03a2ce1a88e7 100644 > > > > --- a/drivers/gpu/drm/imagination/pvr_queue.c > > > > +++ b/drivers/gpu/drm/imagination/pvr_queue.c > > > > @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct > > > > pvr_context *ctx, > > > > }; > > > > struct pvr_device *pvr_dev = ctx->pvr_dev; > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct pvr_queue *queue; > > > > int ctx_state_size, err; > > > > void *cpu_map; > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > if (WARN_ON(type >= sizeof(props))) > > > > return ERR_PTR(-EINVAL); > > > > @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct > > > > pvr_context *ctx, > > > > queue->timeline_ufo.value = cpu_map; > > > > - err = drm_sched_init(&queue->scheduler, > > > > - &pvr_queue_sched_ops, > > > > - pvr_dev->sched_wq, 1, 64 * 1024, 1, > > > > - msecs_to_jiffies(500), > > > > - pvr_dev->sched_wq, NULL, "pvr-queue", > > > > - pvr_dev->base.dev); > > > > + sched_params.ops = &pvr_queue_sched_ops; > > > > + sched_params.submit_wq = pvr_dev->sched_wq; > > > > + sched_params.num_rqs = 1; > > > > + sched_params.credit_limit = 64 * 1024; > > > > + sched_params.hang_limit = 1; > > > > + sched_params.timeout = msecs_to_jiffies(500); > > > > + sched_params.timeout_wq = pvr_dev->sched_wq; > > > > + sched_params.score = NULL; > > > > + sched_params.name = "pvr-queue"; > > > > + sched_params.dev = pvr_dev->base.dev; > > > > + > > > > + err = drm_sched_init(&queue->scheduler, &sched_params); > > > > if (err) > > > > goto err_release_ufo; > > > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > > > > b/drivers/gpu/drm/lima/lima_sched.c > > > > index b40c90e97d7e..a64c50fb6d1e 100644 > > > > --- a/drivers/gpu/drm/lima/lima_sched.c > > > > +++ b/drivers/gpu/drm/lima/lima_sched.c > > > > @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct > > > > work_struct *work) > > > > int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char > > > > *name) > > > > { > > > > + struct drm_sched_init_params params; > > > > unsigned int timeout = lima_sched_timeout_ms > 0 ? > > > > lima_sched_timeout_ms : 10000; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > 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, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - 1, > > > > - lima_job_hang_limit, > > > > - msecs_to_jiffies(timeout), NULL, > > > > - NULL, name, pipe->ldev->dev); > > > > + params.ops = &lima_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = 1; > > > > + params.hang_limit = lima_job_hang_limit; > > > > + params.timeout = msecs_to_jiffies(timeout); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = name; > > > > + params.dev = pipe->ldev->dev; > > > > + > > > > + return drm_sched_init(&pipe->base, ¶ms); > > > > } > > > > void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) > > > > diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > index c803556a8f64..49a2c7422dc6 100644 > > > > --- a/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c > > > > @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops > > > > msm_sched_ops = { > > > > struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, > > > > int id, > > > > void *memptrs, uint64_t memptrs_iova) > > > > { > > > > + struct drm_sched_init_params params; > > > > struct msm_ringbuffer *ring; > > > > - long sched_timeout; > > > > char name[32]; > > > > int ret; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a > > > > power of 2 */ > > > > BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); > > > > @@ -95,13 +97,19 @@ struct msm_ringbuffer > > > > *msm_ringbuffer_new(struct msm_gpu *gpu, int id, > > > > ring->memptrs = memptrs; > > > > ring->memptrs_iova = memptrs_iova; > > > > - /* currently managing hangcheck ourselves: */ > > > > - sched_timeout = MAX_SCHEDULE_TIMEOUT; > > > > + params.ops = &msm_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = num_hw_submissions; > > > > + params.hang_limit = 0; > > > > + /* currently managing hangcheck ourselves: */ > > > > + params.timeout = MAX_SCHEDULE_TIMEOUT; > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = to_msm_bo(ring->bo)->name; > > > > + params.dev = gpu->dev->dev; > > > > - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - num_hw_submissions, 0, sched_timeout, > > > > - NULL, NULL, to_msm_bo(ring->bo)- > > > > > name, gpu->dev->dev); > > > > + ret = drm_sched_init(&ring->sched, ¶ms); > > > > if (ret) { > > > > goto fail; > > > > } > > > > diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > index 4412f2711fb5..f20c2e612750 100644 > > > > --- a/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c > > > > @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched > > > > *sched, struct nouveau_drm *drm, > > > > { > > > > struct drm_gpu_scheduler *drm_sched = &sched->base; > > > > struct drm_sched_entity *entity = &sched->entity; > > > > - const long timeout = > > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > > + struct drm_sched_init_params params; > > > > int ret; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > if (!wq) { > > > > wq = alloc_workqueue("nouveau_sched_wq_%d", 0, > > > > WQ_MAX_ACTIVE, > > > > current->pid); > > > > @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched > > > > *sched, struct nouveau_drm *drm, > > > > sched->wq = wq; > > > > } > > > > - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, > > > > - NOUVEAU_SCHED_PRIORITY_COUNT, > > > > - credit_limit, 0, timeout, > > > > - NULL, NULL, "nouveau_sched", drm- > > > > > dev->dev); > > > > + params.ops = &nouveau_sched_ops; > > > > + params.submit_wq = wq; > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = credit_limit; > > > > + params.hang_limit = 0; > > > > + params.timeout = > > > > msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = "nouveau_sched"; > > > > + params.dev = drm->dev->dev; > > > > + > > > > + ret = drm_sched_init(drm_sched, ¶ms); > > > > if (ret) > > > > goto fail_wq; > > > > diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c > > > > b/drivers/gpu/drm/panfrost/panfrost_job.c > > > > index 9b8e82fb8bc4..6b509ff446b5 100644 > > > > --- a/drivers/gpu/drm/panfrost/panfrost_job.c > > > > +++ b/drivers/gpu/drm/panfrost/panfrost_job.c > > > > @@ -836,10 +836,13 @@ static irqreturn_t > > > > panfrost_job_irq_handler(int irq, void *data) > > > > int panfrost_job_init(struct panfrost_device *pfdev) > > > > { > > > > + struct drm_sched_init_params params; > > > > struct panfrost_job_slot *js; > > > > unsigned int nentries = 2; > > > > int ret, j; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > /* All GPUs have two entries per queue, but without > > > > jobchain > > > > * disambiguation stopping the right job in the close path > > > > is tricky, > > > > * so let's just advertise one entry in that case. > > > > @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device > > > > *pfdev) > > > > if (!pfdev->reset.wq) > > > > return -ENOMEM; > > > > + params.ops = &panfrost_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params.credit_limit = nentries; > > > > + params.hang_limit = 0; > > > > + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > > > + params.timeout_wq = pfdev->reset.wq; > > > > + params.score = NULL; > > > > + params.name = "pan_js"; > > > > + params.dev = pfdev->dev; > > > > + > > > > for (j = 0; j < NUM_JOB_SLOTS; j++) { > > > > js->queue[j].fence_context = > > > > dma_fence_context_alloc(1); > > > > - ret = drm_sched_init(&js->queue[j].sched, > > > > - &panfrost_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - nentries, 0, > > > > - > > > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > - pfdev->reset.wq, > > > > - NULL, "pan_js", pfdev->dev); > > > > + ret = drm_sched_init(&js->queue[j].sched, > > > > ¶ms); > > > > if (ret) { > > > > dev_err(pfdev->dev, "Failed to create > > > > scheduler: %d.", ret); > > > > goto err_sched; > > > > diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c > > > > b/drivers/gpu/drm/panthor/panthor_mmu.c > > > > index a49132f3778b..4362442cbfd8 100644 > > > > --- a/drivers/gpu/drm/panthor/panthor_mmu.c > > > > +++ b/drivers/gpu/drm/panthor/panthor_mmu.c > > > > @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > u64 full_va_range = 1ull << va_bits; > > > > struct drm_gem_object *dummy_gem; > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct io_pgtable_cfg pgtbl_cfg; > > > > u64 mair, min_va, va_range; > > > > struct panthor_vm *vm; > > > > @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > goto err_free_vm; > > > > } > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > mutex_init(&vm->heaps.lock); > > > > vm->for_mcu = for_mcu; > > > > vm->ptdev = ptdev; > > > > @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device > > > > *ptdev, bool for_mcu, > > > > goto err_mm_takedown; > > > > } > > > > + sched_params.ops = &panthor_vm_bind_ops; > > > > + sched_params.submit_wq = ptdev->mmu->vm.wq; > > > > + sched_params.num_rqs = 1; > > > > + sched_params.credit_limit = 1; > > > > + sched_params.hang_limit = 0; > > > > /* Bind operations are synchronous for now, no timeout > > > > needed. */ > > > > - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, > > > > ptdev->mmu->vm.wq, > > > > - 1, 1, 0, > > > > - MAX_SCHEDULE_TIMEOUT, NULL, NULL, > > > > - "panthor-vm-bind", ptdev->base.dev); > > > > + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; > > > > + sched_params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + sched_params.score = NULL; > > > > + sched_params.name = "panthor-vm-bind"; > > > > + sched_params.dev = ptdev->base.dev; > > > > + ret = drm_sched_init(&vm->sched, &sched_params); > > > > if (ret) > > > > goto err_free_io_pgtable; > > > > diff --git a/drivers/gpu/drm/panthor/panthor_sched.c > > > > b/drivers/gpu/drm/panthor/panthor_sched.c > > > > index ef4bec7ff9c7..a324346d302f 100644 > > > > --- a/drivers/gpu/drm/panthor/panthor_sched.c > > > > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > > > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group > > > > *group, > > > > const struct drm_panthor_queue_create *args) > > > > { > > > > struct drm_gpu_scheduler *drm_sched; > > > > + struct drm_sched_init_params sched_params; > > > > struct panthor_queue *queue; > > > > int ret; > > > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group > > > > *group, > > > > if (!queue) > > > > return ERR_PTR(-ENOMEM); > > > > + memset(&sched_params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > queue->fence_ctx.id = dma_fence_context_alloc(1); > > > > spin_lock_init(&queue->fence_ctx.lock); > > > > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > > > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group > > > > *group, > > > > if (ret) > > > > goto err_free_queue; > > > > + sched_params.ops = &panthor_queue_sched_ops; > > > > + sched_params.submit_wq = group->ptdev->scheduler->wq; > > > > + sched_params.num_rqs = 1; > > > > /* > > > > - * Credit limit argument tells us the total number of > > > > instructions > > > > + * The credit limit argument tells us the total number of > > > > instructions > > > > * across all CS slots in the ringbuffer, with some jobs > > > > requiring > > > > * twice as many as others, depending on their profiling > > > > status. > > > > */ > > > > - ret = drm_sched_init(&queue->scheduler, > > > > &panthor_queue_sched_ops, > > > > - group->ptdev->scheduler->wq, 1, > > > > - args->ringbuf_size / sizeof(u64), > > > > - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > - group->ptdev->reset.wq, > > > > - NULL, "panthor-queue", group->ptdev- > > > > > base.dev); > > > > + sched_params.credit_limit = args->ringbuf_size / > > > > sizeof(u64); > > > > + sched_params.hang_limit = 0; > > > > + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > > > + sched_params.timeout_wq = group->ptdev->reset.wq; > > > > + sched_params.score = NULL; > > > > + sched_params.name = "panthor-queue"; > > > > + sched_params.dev = group->ptdev->base.dev; > > > > + > > > > + ret = drm_sched_init(&queue->scheduler, &sched_params); > > > > if (ret) > > > > goto err_free_queue; > > > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c > > > > b/drivers/gpu/drm/scheduler/sched_main.c > > > > index 57da84908752..27db748a5269 100644 > > > > --- a/drivers/gpu/drm/scheduler/sched_main.c > > > > +++ b/drivers/gpu/drm/scheduler/sched_main.c > > > > @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct > > > > work_struct *w) > > > > * drm_sched_init - Init a gpu scheduler instance > > > > * > > > > * @sched: scheduler instance > > > > - * @ops: backend operations for this scheduler > > > > - * @submit_wq: workqueue to use for submission. If NULL, an > > > > ordered wq is > > > > - * allocated and used > > > > - * @num_rqs: number of runqueues, one for each priority, up to > > > > DRM_SCHED_PRIORITY_COUNT > > > > - * @credit_limit: the number of credits this scheduler can hold > > > > from all jobs > > > > - * @hang_limit: number of times to allow a job to hang before > > > > dropping it > > > > - * @timeout: timeout value in jiffies for the scheduler > > > > - * @timeout_wq: workqueue to use for timeout work. If NULL, the > > > > system_wq is > > > > - * used > > > > - * @score: optional score atomic shared with other schedulers > > > > - * @name: name used for debugging > > > > - * @dev: target &struct device > > > > + * @params: scheduler initialization parameters > > > > * > > > > * Return 0 on success, otherwise error code. > > > > */ > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > - const struct drm_sched_backend_ops *ops, > > > > - struct workqueue_struct *submit_wq, > > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > > hang_limit, > > > > - long timeout, struct workqueue_struct > > > > *timeout_wq, > > > > - atomic_t *score, const char *name, struct > > > > device *dev) > > > > + const struct drm_sched_init_params *params) > > > > { > > > > int i; > > > > - sched->ops = ops; > > > > - sched->credit_limit = credit_limit; > > > > - sched->name = name; > > > > - sched->timeout = timeout; > > > > - sched->timeout_wq = timeout_wq ? : system_wq; > > > > - sched->hang_limit = hang_limit; > > > > - sched->score = score ? score : &sched->_score; > > > > - sched->dev = dev; > > > > + sched->ops = params->ops; > > > > + sched->credit_limit = params->credit_limit; > > > > + sched->name = params->name; > > > > + sched->timeout = params->timeout; > > > > + sched->timeout_wq = params->timeout_wq ? : system_wq; > > > > + sched->hang_limit = params->hang_limit; > > > > + sched->score = params->score ? params->score : &sched- > > > > > _score; > > > > + sched->dev = params->dev; > > > > - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > > + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { > > > > /* This is a gross violation--tell drivers what > > > > the problem is. > > > > */ > > > > drm_err(sched, "%s: num_rqs cannot be greater than > > > > DRM_SCHED_PRIORITY_COUNT\n", > > > > @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler > > > > *sched, > > > > return 0; > > > > } > > > > - if (submit_wq) { > > > > - sched->submit_wq = submit_wq; > > > > + if (params->submit_wq) { > > > > + sched->submit_wq = params->submit_wq; > > > > sched->own_submit_wq = false; > > > > } else { > > > > #ifdef CONFIG_LOCKDEP > > > > - sched->submit_wq = > > > > alloc_ordered_workqueue_lockdep_map(name, > > > > - > > > > WQ_MEM_RECLAIM, > > > > - > > > > &drm_sched_lockdep_map); > > > > + sched->submit_wq = > > > > alloc_ordered_workqueue_lockdep_map( > > > > + params->name, > > > > WQ_MEM_RECLAIM, > > > > + &drm_sched_lockdep_map); > > > > #else > > > > - sched->submit_wq = alloc_ordered_workqueue(name, > > > > WQ_MEM_RECLAIM); > > > > + sched->submit_wq = alloc_ordered_workqueue(params- > > > > > name, WQ_MEM_RECLAIM); > > > > #endif > > > > if (!sched->submit_wq) > > > > return -ENOMEM; > > > > @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler > > > > *sched, > > > > sched->own_submit_wq = true; > > > > } > > > > - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched- > > > > > sched_rq), > > > > + sched->sched_rq = kmalloc_array(params->num_rqs, > > > > sizeof(*sched->sched_rq), > > > > GFP_KERNEL | __GFP_ZERO); > > > > if (!sched->sched_rq) > > > > goto Out_check_own; > > > > - sched->num_rqs = num_rqs; > > > > + sched->num_rqs = params->num_rqs; > > > > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; > > > > i++) { > > > > sched->sched_rq[i] = kzalloc(sizeof(*sched- > > > > > sched_rq[i]), GFP_KERNEL); > > > > if (!sched->sched_rq[i]) > > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > > > b/drivers/gpu/drm/v3d/v3d_sched.c > > > > index 99ac4995b5a1..716e6d074d87 100644 > > > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > > > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops > > > > v3d_cpu_sched_ops = { > > > > .free_job = v3d_cpu_job_free > > > > }; > > > > +/* > > > > + * v3d's scheduler instances are all identical, except for ops and > > > > name. > > > > + */ > > > > +static void > > > > +v3d_common_sched_init(struct drm_sched_init_params *params, struct > > > > device *dev) > > > > +{ > > > > + memset(params, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > + params->submit_wq = NULL; /* Use the system_wq. */ > > > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params->credit_limit = 1; > > > > + params->hang_limit = 0; > > > > + params->timeout = msecs_to_jiffies(500); > > > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > > > + params->score = NULL; > > > > + params->dev = dev; > > > > +} > > > > + > > > > +static int > > > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_bin_sched_ops; > > > > + params.name = "v3d_bin"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_render_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_render_sched_ops; > > > > + params.name = "v3d_render"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_tfu_sched_ops; > > > > + params.name = "v3d_tfu"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_csd_sched_ops; > > > > + params.name = "v3d_csd"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_cache_clean_sched_ops; > > > > + params.name = "v3d_cache_clean"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > > > > ¶ms); > > > > +} > > > > + > > > > +static int > > > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > > > +{ > > > > + struct drm_sched_init_params params; > > > > + > > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > > + params.ops = &v3d_cpu_sched_ops; > > > > + params.name = "v3d_cpu"; > > > > + > > > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > > ¶ms); > > > > +} > > > > + > > > > int > > > > v3d_sched_init(struct v3d_dev *v3d) > > > > { > > > > - int hw_jobs_limit = 1; > > > > - int job_hang_limit = 0; > > > > - int hang_limit_ms = 500; > > > > int ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > > - &v3d_bin_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_bin", v3d->drm.dev); > > > > + ret = v3d_bin_sched_init(v3d); > > > > if (ret) > > > > return ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > > - &v3d_render_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_render", v3d->drm.dev); > > > > + ret = v3d_render_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > > - &v3d_tfu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_tfu", v3d->drm.dev); > > > > + ret = v3d_tfu_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > if (v3d_has_csd(v3d)) { > > > > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > > - &v3d_csd_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, > > > > job_hang_limit, > > > > - > > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > > - NULL, "v3d_csd", v3d- > > > > > drm.dev); > > > > + ret = v3d_csd_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > - ret = drm_sched_init(&v3d- > > > > > queue[V3D_CACHE_CLEAN].sched, > > > > - &v3d_cache_clean_sched_ops, > > > > NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - hw_jobs_limit, > > > > job_hang_limit, > > > > - > > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > > - NULL, "v3d_cache_clean", v3d- > > > > > drm.dev); > > > > + ret = v3d_cache_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > } > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > > - &v3d_cpu_sched_ops, NULL, > > > > - DRM_SCHED_PRIORITY_COUNT, > > > > - 1, job_hang_limit, > > > > - msecs_to_jiffies(hang_limit_ms), > > > > NULL, > > > > - NULL, "v3d_cpu", v3d->drm.dev); > > > > + ret = v3d_cpu_sched_init(v3d); > > > > if (ret) > > > > goto fail; > > > > diff --git a/drivers/gpu/drm/xe/xe_execlist.c > > > > b/drivers/gpu/drm/xe/xe_execlist.c > > > > index a8c416a48812..7f29b7f04af4 100644 > > > > --- a/drivers/gpu/drm/xe/xe_execlist.c > > > > +++ b/drivers/gpu/drm/xe/xe_execlist.c > > > > @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops > > > > drm_sched_ops = { > > > > static int execlist_exec_queue_init(struct xe_exec_queue *q) > > > > { > > > > struct drm_gpu_scheduler *sched; > > > > + struct drm_sched_init_params params; > > > > struct xe_execlist_exec_queue *exl; > > > > struct xe_device *xe = gt_to_xe(q->gt); > > > > int err; > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > xe_assert(xe, !xe_device_uc_enabled(xe)); > > > > drm_info(&xe->drm, "Enabling execlist submission (GuC > > > > submission disabled)\n"); > > > > @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct > > > > xe_exec_queue *q) > > > > exl->q = q; > > > > - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, > > > > - q->lrc[0]->ring.size / > > > > MAX_JOB_SIZE_BYTES, > > > > - XE_SCHED_HANG_LIMIT, > > > > XE_SCHED_JOB_TIMEOUT, > > > > - NULL, NULL, q->hwe->name, > > > > - gt_to_xe(q->gt)->drm.dev); > > > > + params.ops = &drm_sched_ops; > > > > + params.submit_wq = NULL; /* Use the system_wq. */ > > > > + params.num_rqs = 1; > > > > + params.credit_limit = q->lrc[0]->ring.size / > > > > MAX_JOB_SIZE_BYTES; > > > > + params.hang_limit = XE_SCHED_HANG_LIMIT; > > > > + params.timeout = XE_SCHED_JOB_TIMEOUT; > > > > + params.timeout_wq = NULL; /* Use the system_wq. */ > > > > + params.score = NULL; > > > > + params.name = q->hwe->name; > > > > + params.dev = gt_to_xe(q->gt)->drm.dev; > > > > + > > > > + err = drm_sched_init(&exl->sched, ¶ms); > > > > if (err) > > > > goto err_free; > > > > diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > index 50361b4638f9..2129fee83f25 100644 > > > > --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c > > > > @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler > > > > *sched, > > > > atomic_t *score, const char *name, > > > > struct device *dev) > > > > { > > > > + struct drm_sched_init_params params; > > > > + > > > > sched->ops = xe_ops; > > > > INIT_LIST_HEAD(&sched->msgs); > > > > INIT_WORK(&sched->work_process_msg, > > > > xe_sched_process_msg_work); > > > > - return drm_sched_init(&sched->base, ops, submit_wq, 1, > > > > hw_submission, > > > > - hang_limit, timeout, timeout_wq, > > > > score, name, > > > > - dev); > > > > + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); > > > > + > > > > + params.ops = ops; > > > > + params.submit_wq = submit_wq; > > > > + params.num_rqs = 1; > > > > + params.credit_limit = hw_submission; > > > > + params.hang_limit = hang_limit; > > > > + params.timeout = timeout; > > > > + params.timeout_wq = timeout_wq; > > > > + params.score = score; > > > > + params.name = name; > > > > + params.dev = dev; > > > > + > > > > + return drm_sched_init(&sched->base, ¶ms); > > > > } > > > > void xe_sched_fini(struct xe_gpu_scheduler *sched) > > > > diff --git a/include/drm/gpu_scheduler.h > > > > b/include/drm/gpu_scheduler.h > > > > index 95e17504e46a..1a834ef43862 100644 > > > > --- a/include/drm/gpu_scheduler.h > > > > +++ b/include/drm/gpu_scheduler.h > > > > @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { > > > > struct device *dev; > > > > }; > > > > +/** > > > > + * struct drm_sched_init_params - parameters for initializing a > > > > DRM GPU scheduler > > > > + * > > > > + * @ops: backend operations provided by the driver > > > > + * @submit_wq: workqueue to use for submission. If NULL, an > > > > ordered wq is > > > > + * allocated and used > > > > + * @num_rqs: Number of run-queues. This is at most > > > > DRM_SCHED_PRIORITY_COUNT, > > > > + * as there's usually one run-queue per priority, but > > > > could be less. > > > > + * @credit_limit: the number of credits this scheduler can hold > > > > from all jobs > > > > + * @hang_limit: number of times to allow a job to hang before > > > > dropping it > > > > + * @timeout: timeout value in jiffies for the scheduler > > > > + * @timeout_wq: workqueue to use for timeout work. If NULL, the > > > > system_wq is > > > > + * used > > > > + * @score: optional score atomic shared with other schedulers > > > > + * @name: name used for debugging > > > > + * @dev: associated device. Used for debugging > > > > + */ > > > > +struct drm_sched_init_params { > > > > + const struct drm_sched_backend_ops *ops; > > > > + struct workqueue_struct *submit_wq; > > > > + struct workqueue_struct *timeout_wq; > > > > + u32 num_rqs, credit_limit; > > > > + unsigned int hang_limit; > > > > + long timeout; > > > > + atomic_t *score; > > > > + const char *name; > > > > + struct device *dev; > > > > +}; > > > > + > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > - const struct drm_sched_backend_ops *ops, > > > > - struct workqueue_struct *submit_wq, > > > > - u32 num_rqs, u32 credit_limit, unsigned int > > > > hang_limit, > > > > - long timeout, struct workqueue_struct > > > > *timeout_wq, > > > > - atomic_t *score, const char *name, struct > > > > device *dev); > > > > + const struct drm_sched_init_params *params); > > > > void drm_sched_fini(struct drm_gpu_scheduler *sched); > > > > int drm_sched_job_init(struct drm_sched_job *job, >
Am 22.01.25 um 16:23 schrieb Philipp Stanner: > On Wed, 2025-01-22 at 16:06 +0100, Christian König wrote: >> Am 22.01.25 um 15:48 schrieb Philipp Stanner: >>> On Wed, 2025-01-22 at 15:34 +0100, Christian König wrote: >>>> Am 22.01.25 um 15:08 schrieb Philipp Stanner: >>>>> drm_sched_init() has a great many parameters and upcoming new >>>>> functionality for the scheduler might add even more. Generally, >>>>> the >>>>> great number of parameters reduces readability and has already >>>>> caused >>>>> one missnaming in: >>>>> >>>>> commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in >>>>> nouveau_sched_init()"). >>>>> >>>>> Introduce a new struct for the scheduler init parameters and >>>>> port >>>>> all >>>>> users. >>>>> >>>>> Signed-off-by: Philipp Stanner <phasta@kernel.org> >>>>> --- >>>>> Howdy, >>>>> >>>>> I have a patch-series in the pipe that will add a `flags` >>>>> argument >>>>> to >>>>> drm_sched_init(). I thought it would be wise to first rework >>>>> the >>>>> API as >>>>> detailed in this patch. It's really a lot of parameters by now, >>>>> and >>>>> I >>>>> would expect that it might get more and more over the years for >>>>> special >>>>> use cases etc. >>>>> >>>>> Regards, >>>>> P. >>>>> --- >>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- >>>>> drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- >>>>> drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- >>>>> drivers/gpu/drm/lima/lima_sched.c | 21 +++- >>>>> drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- >>>>> drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- >>>>> drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- >>>>> drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- >>>>> drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- >>>>> drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- >>>>> drivers/gpu/drm/v3d/v3d_sched.c | 135 >>>>> +++++++++++++++- >>>>> ----- >>>>> drivers/gpu/drm/xe/xe_execlist.c | 20 ++- >>>>> drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- >>>>> include/drm/gpu_scheduler.h | 35 +++++- >>>>> 14 files changed, 311 insertions(+), 139 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>>>> index cd4fac120834..c1f03eb5f5ea 100644 >>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >>>>> @@ -2821,6 +2821,9 @@ static int >>>>> amdgpu_device_init_schedulers(struct amdgpu_device *adev) >>>>> { >>>>> long timeout; >>>>> int r, i; >>>>> + struct drm_sched_init_params params; >>>> Please keep the reverse xmas tree ordering for variable >>>> declaration. >>>> E.g. long lines first and variables like "i" and "r" last. >>> Okay dokay >>> >>>> Apart from that looks like a good idea to me. >>>> >>>> >>>>> + >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> >>>>> for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { >>>>> struct amdgpu_ring *ring = adev->rings[i]; >>>>> @@ -2844,12 +2847,18 @@ static int >>>>> amdgpu_device_init_schedulers(struct amdgpu_device *adev) >>>>> break; >>>>> } >>>>> >>>>> - r = drm_sched_init(&ring->sched, >>>>> &amdgpu_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - ring->num_hw_submission, 0, >>>>> - timeout, adev- >>>>>> reset_domain- >>>>>> wq, >>>>> - ring->sched_score, ring- >>>>>> name, >>>>> - adev->dev); >>>>> + params.ops = &amdgpu_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. >>>>> */ >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = ring->num_hw_submission; >>>>> + params.hang_limit = 0; >>>> Could we please remove the hang limit as first step to get this >>>> awful >>>> feature deprecated? >>> Remove it? From the struct you mean? >>> >>> We can mark it as deprecated in the docstring of the new struct. >>> That's >>> what you mean, don't you? >> No, the function using this parameter already deprecated. What I >> meant >> is to start to completely remove this feature. >> >> The hang_limit basically says how often the scheduler should try to >> run >> a job over and over again before giving up. > Agreed, it should be removed. > > But let me do that in a separate patch after this one is merged, and > just hint at the deprecation in the arg in the struct for now; it's > kind of unrelated to the init()-rework I'm doing here, ack? Works for me. Regards, Christian. > >> And we already agreed that trying the same thing over and over again >> and >> expecting different results is the definition of insanity :) > I'll quote you (and Einstein) with that if I ever give a presentation > about the scheduler ;p > > P. > >> So my suggestion is to drop the parameter and drop the job as soon as >> it >> caused a timeout. >> >> Regards, >> Christian. >> >>> P. >>> >>>> Thanks, >>>> Christian. >>>> >>>>> + params.timeout = timeout; >>>>> + params.timeout_wq = adev->reset_domain->wq; >>>>> + params.score = ring->sched_score; >>>>> + params.name = ring->name; >>>>> + params.dev = adev->dev; >>>>> + >>>>> + r = drm_sched_init(&ring->sched, ¶ms); >>>>> if (r) { >>>>> DRM_ERROR("Failed to create scheduler >>>>> on >>>>> ring %s.\n", >>>>> ring->name); >>>>> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>>>> b/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>>>> index 5b67eda122db..7d8517f1963e 100644 >>>>> --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>>>> +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c >>>>> @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct >>>>> etnaviv_gem_submit *submit) >>>>> int etnaviv_sched_init(struct etnaviv_gpu *gpu) >>>>> { >>>>> int ret; >>>>> + struct drm_sched_init_params params; >>>>> >>>>> - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, >>>>> NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - etnaviv_hw_jobs_limit, >>>>> etnaviv_job_hang_limit, >>>>> - msecs_to_jiffies(500), NULL, >>>>> NULL, >>>>> - dev_name(gpu->dev), gpu->dev); >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> + params.ops = &etnaviv_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. */ >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = etnaviv_hw_jobs_limit; >>>>> + params.hang_limit = etnaviv_job_hang_limit; >>>>> + params.timeout = msecs_to_jiffies(500); >>>>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params.score = NULL; >>>>> + params.name = dev_name(gpu->dev); >>>>> + params.dev = gpu->dev; >>>>> + >>>>> + ret = drm_sched_init(&gpu->sched, ¶ms); >>>>> if (ret) >>>>> return ret; >>>>> >>>>> diff --git a/drivers/gpu/drm/imagination/pvr_queue.c >>>>> b/drivers/gpu/drm/imagination/pvr_queue.c >>>>> index c4f08432882b..03a2ce1a88e7 100644 >>>>> --- a/drivers/gpu/drm/imagination/pvr_queue.c >>>>> +++ b/drivers/gpu/drm/imagination/pvr_queue.c >>>>> @@ -1211,10 +1211,13 @@ struct pvr_queue >>>>> *pvr_queue_create(struct >>>>> pvr_context *ctx, >>>>> }; >>>>> struct pvr_device *pvr_dev = ctx->pvr_dev; >>>>> struct drm_gpu_scheduler *sched; >>>>> + struct drm_sched_init_params sched_params; >>>>> struct pvr_queue *queue; >>>>> int ctx_state_size, err; >>>>> void *cpu_map; >>>>> >>>>> + memset(&sched_params, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> if (WARN_ON(type >= sizeof(props))) >>>>> return ERR_PTR(-EINVAL); >>>>> >>>>> @@ -1282,12 +1285,18 @@ struct pvr_queue >>>>> *pvr_queue_create(struct >>>>> pvr_context *ctx, >>>>> >>>>> queue->timeline_ufo.value = cpu_map; >>>>> >>>>> - err = drm_sched_init(&queue->scheduler, >>>>> - &pvr_queue_sched_ops, >>>>> - pvr_dev->sched_wq, 1, 64 * 1024, >>>>> 1, >>>>> - msecs_to_jiffies(500), >>>>> - pvr_dev->sched_wq, NULL, "pvr- >>>>> queue", >>>>> - pvr_dev->base.dev); >>>>> + sched_params.ops = &pvr_queue_sched_ops; >>>>> + sched_params.submit_wq = pvr_dev->sched_wq; >>>>> + sched_params.num_rqs = 1; >>>>> + sched_params.credit_limit = 64 * 1024; >>>>> + sched_params.hang_limit = 1; >>>>> + sched_params.timeout = msecs_to_jiffies(500); >>>>> + sched_params.timeout_wq = pvr_dev->sched_wq; >>>>> + sched_params.score = NULL; >>>>> + sched_params.name = "pvr-queue"; >>>>> + sched_params.dev = pvr_dev->base.dev; >>>>> + >>>>> + err = drm_sched_init(&queue->scheduler, >>>>> &sched_params); >>>>> if (err) >>>>> goto err_release_ufo; >>>>> >>>>> diff --git a/drivers/gpu/drm/lima/lima_sched.c >>>>> b/drivers/gpu/drm/lima/lima_sched.c >>>>> index b40c90e97d7e..a64c50fb6d1e 100644 >>>>> --- a/drivers/gpu/drm/lima/lima_sched.c >>>>> +++ b/drivers/gpu/drm/lima/lima_sched.c >>>>> @@ -513,20 +513,29 @@ static void >>>>> lima_sched_recover_work(struct >>>>> work_struct *work) >>>>> >>>>> int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const >>>>> char >>>>> *name) >>>>> { >>>>> + struct drm_sched_init_params params; >>>>> unsigned int timeout = lima_sched_timeout_ms > 0 ? >>>>> lima_sched_timeout_ms : 10000; >>>>> >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> 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, >>>>> NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - 1, >>>>> - lima_job_hang_limit, >>>>> - msecs_to_jiffies(timeout), NULL, >>>>> - NULL, name, pipe->ldev->dev); >>>>> + params.ops = &lima_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. */ >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = 1; >>>>> + params.hang_limit = lima_job_hang_limit; >>>>> + params.timeout = msecs_to_jiffies(timeout); >>>>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params.score = NULL; >>>>> + params.name = name; >>>>> + params.dev = pipe->ldev->dev; >>>>> + >>>>> + return drm_sched_init(&pipe->base, ¶ms); >>>>> } >>>>> >>>>> void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) >>>>> diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c >>>>> b/drivers/gpu/drm/msm/msm_ringbuffer.c >>>>> index c803556a8f64..49a2c7422dc6 100644 >>>>> --- a/drivers/gpu/drm/msm/msm_ringbuffer.c >>>>> +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c >>>>> @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops >>>>> msm_sched_ops = { >>>>> struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu >>>>> *gpu, >>>>> int id, >>>>> void *memptrs, uint64_t memptrs_iova) >>>>> { >>>>> + struct drm_sched_init_params params; >>>>> struct msm_ringbuffer *ring; >>>>> - long sched_timeout; >>>>> char name[32]; >>>>> int ret; >>>>> >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is >>>>> a >>>>> power of 2 */ >>>>> BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); >>>>> >>>>> @@ -95,13 +97,19 @@ struct msm_ringbuffer >>>>> *msm_ringbuffer_new(struct msm_gpu *gpu, int id, >>>>> ring->memptrs = memptrs; >>>>> ring->memptrs_iova = memptrs_iova; >>>>> >>>>> - /* currently managing hangcheck ourselves: */ >>>>> - sched_timeout = MAX_SCHEDULE_TIMEOUT; >>>>> + params.ops = &msm_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. */ >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = num_hw_submissions; >>>>> + params.hang_limit = 0; >>>>> + /* currently managing hangcheck ourselves: */ >>>>> + params.timeout = MAX_SCHEDULE_TIMEOUT; >>>>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params.score = NULL; >>>>> + params.name = to_msm_bo(ring->bo)->name; >>>>> + params.dev = gpu->dev->dev; >>>>> >>>>> - ret = drm_sched_init(&ring->sched, &msm_sched_ops, >>>>> NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - num_hw_submissions, 0, >>>>> sched_timeout, >>>>> - NULL, NULL, to_msm_bo(ring->bo)- >>>>>> name, gpu->dev->dev); >>>>> + ret = drm_sched_init(&ring->sched, ¶ms); >>>>> if (ret) { >>>>> goto fail; >>>>> } >>>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c >>>>> b/drivers/gpu/drm/nouveau/nouveau_sched.c >>>>> index 4412f2711fb5..f20c2e612750 100644 >>>>> --- a/drivers/gpu/drm/nouveau/nouveau_sched.c >>>>> +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c >>>>> @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched >>>>> *sched, struct nouveau_drm *drm, >>>>> { >>>>> struct drm_gpu_scheduler *drm_sched = &sched->base; >>>>> struct drm_sched_entity *entity = &sched->entity; >>>>> - const long timeout = >>>>> msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); >>>>> + struct drm_sched_init_params params; >>>>> int ret; >>>>> >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> if (!wq) { >>>>> wq = alloc_workqueue("nouveau_sched_wq_%d", 0, >>>>> WQ_MAX_ACTIVE, >>>>> current->pid); >>>>> @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched >>>>> *sched, struct nouveau_drm *drm, >>>>> sched->wq = wq; >>>>> } >>>>> >>>>> - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, >>>>> wq, >>>>> - NOUVEAU_SCHED_PRIORITY_COUNT, >>>>> - credit_limit, 0, timeout, >>>>> - NULL, NULL, "nouveau_sched", drm- >>>>>> dev->dev); >>>>> + params.ops = &nouveau_sched_ops; >>>>> + params.submit_wq = wq; >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = credit_limit; >>>>> + params.hang_limit = 0; >>>>> + params.timeout = >>>>> msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); >>>>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params.score = NULL; >>>>> + params.name = "nouveau_sched"; >>>>> + params.dev = drm->dev->dev; >>>>> + >>>>> + ret = drm_sched_init(drm_sched, ¶ms); >>>>> if (ret) >>>>> goto fail_wq; >>>>> >>>>> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c >>>>> b/drivers/gpu/drm/panfrost/panfrost_job.c >>>>> index 9b8e82fb8bc4..6b509ff446b5 100644 >>>>> --- a/drivers/gpu/drm/panfrost/panfrost_job.c >>>>> +++ b/drivers/gpu/drm/panfrost/panfrost_job.c >>>>> @@ -836,10 +836,13 @@ static irqreturn_t >>>>> panfrost_job_irq_handler(int irq, void *data) >>>>> >>>>> int panfrost_job_init(struct panfrost_device *pfdev) >>>>> { >>>>> + struct drm_sched_init_params params; >>>>> struct panfrost_job_slot *js; >>>>> unsigned int nentries = 2; >>>>> int ret, j; >>>>> >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> /* All GPUs have two entries per queue, but without >>>>> jobchain >>>>> * disambiguation stopping the right job in the close >>>>> path >>>>> is tricky, >>>>> * so let's just advertise one entry in that case. >>>>> @@ -872,16 +875,21 @@ int panfrost_job_init(struct >>>>> panfrost_device >>>>> *pfdev) >>>>> if (!pfdev->reset.wq) >>>>> return -ENOMEM; >>>>> >>>>> + params.ops = &panfrost_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. */ >>>>> + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params.credit_limit = nentries; >>>>> + params.hang_limit = 0; >>>>> + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); >>>>> + params.timeout_wq = pfdev->reset.wq; >>>>> + params.score = NULL; >>>>> + params.name = "pan_js"; >>>>> + params.dev = pfdev->dev; >>>>> + >>>>> for (j = 0; j < NUM_JOB_SLOTS; j++) { >>>>> js->queue[j].fence_context = >>>>> dma_fence_context_alloc(1); >>>>> >>>>> - ret = drm_sched_init(&js->queue[j].sched, >>>>> - &panfrost_sched_ops, >>>>> NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - nentries, 0, >>>>> - >>>>> msecs_to_jiffies(JOB_TIMEOUT_MS), >>>>> - pfdev->reset.wq, >>>>> - NULL, "pan_js", pfdev- >>>>>> dev); >>>>> + ret = drm_sched_init(&js->queue[j].sched, >>>>> ¶ms); >>>>> if (ret) { >>>>> dev_err(pfdev->dev, "Failed to create >>>>> scheduler: %d.", ret); >>>>> goto err_sched; >>>>> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c >>>>> b/drivers/gpu/drm/panthor/panthor_mmu.c >>>>> index a49132f3778b..4362442cbfd8 100644 >>>>> --- a/drivers/gpu/drm/panthor/panthor_mmu.c >>>>> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c >>>>> @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device >>>>> *ptdev, bool for_mcu, >>>>> u64 full_va_range = 1ull << va_bits; >>>>> struct drm_gem_object *dummy_gem; >>>>> struct drm_gpu_scheduler *sched; >>>>> + struct drm_sched_init_params sched_params; >>>>> struct io_pgtable_cfg pgtbl_cfg; >>>>> u64 mair, min_va, va_range; >>>>> struct panthor_vm *vm; >>>>> @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device >>>>> *ptdev, bool for_mcu, >>>>> goto err_free_vm; >>>>> } >>>>> >>>>> + memset(&sched_params, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> mutex_init(&vm->heaps.lock); >>>>> vm->for_mcu = for_mcu; >>>>> vm->ptdev = ptdev; >>>>> @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device >>>>> *ptdev, bool for_mcu, >>>>> goto err_mm_takedown; >>>>> } >>>>> >>>>> + sched_params.ops = &panthor_vm_bind_ops; >>>>> + sched_params.submit_wq = ptdev->mmu->vm.wq; >>>>> + sched_params.num_rqs = 1; >>>>> + sched_params.credit_limit = 1; >>>>> + sched_params.hang_limit = 0; >>>>> /* Bind operations are synchronous for now, no timeout >>>>> needed. */ >>>>> - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, >>>>> ptdev->mmu->vm.wq, >>>>> - 1, 1, 0, >>>>> - MAX_SCHEDULE_TIMEOUT, NULL, NULL, >>>>> - "panthor-vm-bind", ptdev- >>>>>> base.dev); >>>>> + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; >>>>> + sched_params.timeout_wq = NULL; /* Use the system_wq. >>>>> */ >>>>> + sched_params.score = NULL; >>>>> + sched_params.name = "panthor-vm-bind"; >>>>> + sched_params.dev = ptdev->base.dev; >>>>> + ret = drm_sched_init(&vm->sched, &sched_params); >>>>> if (ret) >>>>> goto err_free_io_pgtable; >>>>> >>>>> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c >>>>> b/drivers/gpu/drm/panthor/panthor_sched.c >>>>> index ef4bec7ff9c7..a324346d302f 100644 >>>>> --- a/drivers/gpu/drm/panthor/panthor_sched.c >>>>> +++ b/drivers/gpu/drm/panthor/panthor_sched.c >>>>> @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group >>>>> *group, >>>>> const struct drm_panthor_queue_create >>>>> *args) >>>>> { >>>>> struct drm_gpu_scheduler *drm_sched; >>>>> + struct drm_sched_init_params sched_params; >>>>> struct panthor_queue *queue; >>>>> int ret; >>>>> >>>>> @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group >>>>> *group, >>>>> if (!queue) >>>>> return ERR_PTR(-ENOMEM); >>>>> >>>>> + memset(&sched_params, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> queue->fence_ctx.id = dma_fence_context_alloc(1); >>>>> spin_lock_init(&queue->fence_ctx.lock); >>>>> INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); >>>>> @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group >>>>> *group, >>>>> if (ret) >>>>> goto err_free_queue; >>>>> >>>>> + sched_params.ops = &panthor_queue_sched_ops; >>>>> + sched_params.submit_wq = group->ptdev->scheduler->wq; >>>>> + sched_params.num_rqs = 1; >>>>> /* >>>>> - * Credit limit argument tells us the total number of >>>>> instructions >>>>> + * The credit limit argument tells us the total number >>>>> of >>>>> instructions >>>>> * across all CS slots in the ringbuffer, with some >>>>> jobs >>>>> requiring >>>>> * twice as many as others, depending on their >>>>> profiling >>>>> status. >>>>> */ >>>>> - ret = drm_sched_init(&queue->scheduler, >>>>> &panthor_queue_sched_ops, >>>>> - group->ptdev->scheduler->wq, 1, >>>>> - args->ringbuf_size / sizeof(u64), >>>>> - 0, >>>>> msecs_to_jiffies(JOB_TIMEOUT_MS), >>>>> - group->ptdev->reset.wq, >>>>> - NULL, "panthor-queue", group- >>>>>> ptdev- >>>>>> base.dev); >>>>> + sched_params.credit_limit = args->ringbuf_size / >>>>> sizeof(u64); >>>>> + sched_params.hang_limit = 0; >>>>> + sched_params.timeout = >>>>> msecs_to_jiffies(JOB_TIMEOUT_MS); >>>>> + sched_params.timeout_wq = group->ptdev->reset.wq; >>>>> + sched_params.score = NULL; >>>>> + sched_params.name = "panthor-queue"; >>>>> + sched_params.dev = group->ptdev->base.dev; >>>>> + >>>>> + ret = drm_sched_init(&queue->scheduler, >>>>> &sched_params); >>>>> if (ret) >>>>> goto err_free_queue; >>>>> >>>>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c >>>>> b/drivers/gpu/drm/scheduler/sched_main.c >>>>> index 57da84908752..27db748a5269 100644 >>>>> --- a/drivers/gpu/drm/scheduler/sched_main.c >>>>> +++ b/drivers/gpu/drm/scheduler/sched_main.c >>>>> @@ -1240,40 +1240,25 @@ static void >>>>> drm_sched_run_job_work(struct >>>>> work_struct *w) >>>>> * drm_sched_init - Init a gpu scheduler instance >>>>> * >>>>> * @sched: scheduler instance >>>>> - * @ops: backend operations for this scheduler >>>>> - * @submit_wq: workqueue to use for submission. If NULL, an >>>>> ordered wq is >>>>> - * allocated and used >>>>> - * @num_rqs: number of runqueues, one for each priority, up to >>>>> DRM_SCHED_PRIORITY_COUNT >>>>> - * @credit_limit: the number of credits this scheduler can >>>>> hold >>>>> from all jobs >>>>> - * @hang_limit: number of times to allow a job to hang before >>>>> dropping it >>>>> - * @timeout: timeout value in jiffies for the scheduler >>>>> - * @timeout_wq: workqueue to use for timeout work. If NULL, >>>>> the >>>>> system_wq is >>>>> - * used >>>>> - * @score: optional score atomic shared with other schedulers >>>>> - * @name: name used for debugging >>>>> - * @dev: target &struct device >>>>> + * @params: scheduler initialization parameters >>>>> * >>>>> * Return 0 on success, otherwise error code. >>>>> */ >>>>> int drm_sched_init(struct drm_gpu_scheduler *sched, >>>>> - const struct drm_sched_backend_ops *ops, >>>>> - struct workqueue_struct *submit_wq, >>>>> - u32 num_rqs, u32 credit_limit, unsigned int >>>>> hang_limit, >>>>> - long timeout, struct workqueue_struct >>>>> *timeout_wq, >>>>> - atomic_t *score, const char *name, struct >>>>> device *dev) >>>>> + const struct drm_sched_init_params *params) >>>>> { >>>>> int i; >>>>> >>>>> - sched->ops = ops; >>>>> - sched->credit_limit = credit_limit; >>>>> - sched->name = name; >>>>> - sched->timeout = timeout; >>>>> - sched->timeout_wq = timeout_wq ? : system_wq; >>>>> - sched->hang_limit = hang_limit; >>>>> - sched->score = score ? score : &sched->_score; >>>>> - sched->dev = dev; >>>>> + sched->ops = params->ops; >>>>> + sched->credit_limit = params->credit_limit; >>>>> + sched->name = params->name; >>>>> + sched->timeout = params->timeout; >>>>> + sched->timeout_wq = params->timeout_wq ? : system_wq; >>>>> + sched->hang_limit = params->hang_limit; >>>>> + sched->score = params->score ? params->score : &sched- >>>>>> _score; >>>>> + sched->dev = params->dev; >>>>> >>>>> - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { >>>>> + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { >>>>> /* This is a gross violation--tell drivers >>>>> what >>>>> the problem is. >>>>> */ >>>>> drm_err(sched, "%s: num_rqs cannot be greater >>>>> than >>>>> DRM_SCHED_PRIORITY_COUNT\n", >>>>> @@ -1288,16 +1273,16 @@ int drm_sched_init(struct >>>>> drm_gpu_scheduler >>>>> *sched, >>>>> return 0; >>>>> } >>>>> >>>>> - if (submit_wq) { >>>>> - sched->submit_wq = submit_wq; >>>>> + if (params->submit_wq) { >>>>> + sched->submit_wq = params->submit_wq; >>>>> sched->own_submit_wq = false; >>>>> } else { >>>>> #ifdef CONFIG_LOCKDEP >>>>> - sched->submit_wq = >>>>> alloc_ordered_workqueue_lockdep_map(name, >>>>> - >>>>> >>>>> WQ_MEM_RECLAIM, >>>>> - >>>>> >>>>> &drm_sched_lockdep_map); >>>>> + sched->submit_wq = >>>>> alloc_ordered_workqueue_lockdep_map( >>>>> + params->name, >>>>> WQ_MEM_RECLAIM, >>>>> + &drm_sched_lockdep_map >>>>> ); >>>>> #else >>>>> - sched->submit_wq = >>>>> alloc_ordered_workqueue(name, >>>>> WQ_MEM_RECLAIM); >>>>> + sched->submit_wq = >>>>> alloc_ordered_workqueue(params- >>>>>> name, WQ_MEM_RECLAIM); >>>>> #endif >>>>> if (!sched->submit_wq) >>>>> return -ENOMEM; >>>>> @@ -1305,11 +1290,11 @@ int drm_sched_init(struct >>>>> drm_gpu_scheduler >>>>> *sched, >>>>> sched->own_submit_wq = true; >>>>> } >>>>> >>>>> - sched->sched_rq = kmalloc_array(num_rqs, >>>>> sizeof(*sched- >>>>>> sched_rq), >>>>> + sched->sched_rq = kmalloc_array(params->num_rqs, >>>>> sizeof(*sched->sched_rq), >>>>> GFP_KERNEL | >>>>> __GFP_ZERO); >>>>> if (!sched->sched_rq) >>>>> goto Out_check_own; >>>>> - sched->num_rqs = num_rqs; >>>>> + sched->num_rqs = params->num_rqs; >>>>> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched- >>>>>> num_rqs; >>>>> i++) { >>>>> sched->sched_rq[i] = kzalloc(sizeof(*sched- >>>>>> sched_rq[i]), GFP_KERNEL); >>>>> if (!sched->sched_rq[i]) >>>>> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c >>>>> b/drivers/gpu/drm/v3d/v3d_sched.c >>>>> index 99ac4995b5a1..716e6d074d87 100644 >>>>> --- a/drivers/gpu/drm/v3d/v3d_sched.c >>>>> +++ b/drivers/gpu/drm/v3d/v3d_sched.c >>>>> @@ -814,67 +814,124 @@ static const struct >>>>> drm_sched_backend_ops >>>>> v3d_cpu_sched_ops = { >>>>> .free_job = v3d_cpu_job_free >>>>> }; >>>>> >>>>> +/* >>>>> + * v3d's scheduler instances are all identical, except for ops >>>>> and >>>>> name. >>>>> + */ >>>>> +static void >>>>> +v3d_common_sched_init(struct drm_sched_init_params *params, >>>>> struct >>>>> device *dev) >>>>> +{ >>>>> + memset(params, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> + params->submit_wq = NULL; /* Use the system_wq. */ >>>>> + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params->credit_limit = 1; >>>>> + params->hang_limit = 0; >>>>> + params->timeout = msecs_to_jiffies(500); >>>>> + params->timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params->score = NULL; >>>>> + params->dev = dev; >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_bin_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_bin_sched_ops; >>>>> + params.name = "v3d_bin"; >>>>> + >>>>> + return drm_sched_init(&v3d->queue[V3D_BIN].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_render_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_render_sched_ops; >>>>> + params.name = "v3d_render"; >>>>> + >>>>> + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_tfu_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_tfu_sched_ops; >>>>> + params.name = "v3d_tfu"; >>>>> + >>>>> + return drm_sched_init(&v3d->queue[V3D_TFU].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_csd_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_csd_sched_ops; >>>>> + params.name = "v3d_csd"; >>>>> + >>>>> + return drm_sched_init(&v3d->queue[V3D_CSD].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_cache_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_cache_clean_sched_ops; >>>>> + params.name = "v3d_cache_clean"; >>>>> + >>>>> + return drm_sched_init(&v3d- >>>>>> queue[V3D_CACHE_CLEAN].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> +static int >>>>> +v3d_cpu_sched_init(struct v3d_dev *v3d) >>>>> +{ >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> + v3d_common_sched_init(¶ms, v3d->drm.dev); >>>>> + params.ops = &v3d_cpu_sched_ops; >>>>> + params.name = "v3d_cpu"; >>>>> + >>>>> + return drm_sched_init(&v3d->queue[V3D_CPU].sched, >>>>> ¶ms); >>>>> +} >>>>> + >>>>> int >>>>> v3d_sched_init(struct v3d_dev *v3d) >>>>> { >>>>> - int hw_jobs_limit = 1; >>>>> - int job_hang_limit = 0; >>>>> - int hang_limit_ms = 500; >>>>> int ret; >>>>> >>>>> - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, >>>>> - &v3d_bin_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - hw_jobs_limit, job_hang_limit, >>>>> - msecs_to_jiffies(hang_limit_ms), >>>>> NULL, >>>>> - NULL, "v3d_bin", v3d->drm.dev); >>>>> + ret = v3d_bin_sched_init(v3d); >>>>> if (ret) >>>>> return ret; >>>>> >>>>> - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, >>>>> - &v3d_render_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - hw_jobs_limit, job_hang_limit, >>>>> - msecs_to_jiffies(hang_limit_ms), >>>>> NULL, >>>>> - NULL, "v3d_render", v3d- >>>>>> drm.dev); >>>>> + ret = v3d_render_sched_init(v3d); >>>>> if (ret) >>>>> goto fail; >>>>> >>>>> - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, >>>>> - &v3d_tfu_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - hw_jobs_limit, job_hang_limit, >>>>> - msecs_to_jiffies(hang_limit_ms), >>>>> NULL, >>>>> - NULL, "v3d_tfu", v3d->drm.dev); >>>>> + ret = v3d_tfu_sched_init(v3d); >>>>> if (ret) >>>>> goto fail; >>>>> >>>>> if (v3d_has_csd(v3d)) { >>>>> - ret = drm_sched_init(&v3d- >>>>>> queue[V3D_CSD].sched, >>>>> - &v3d_csd_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - hw_jobs_limit, >>>>> job_hang_limit, >>>>> - >>>>> msecs_to_jiffies(hang_limit_ms), NULL, >>>>> - NULL, "v3d_csd", v3d- >>>>>> drm.dev); >>>>> + ret = v3d_csd_sched_init(v3d); >>>>> if (ret) >>>>> goto fail; >>>>> >>>>> - ret = drm_sched_init(&v3d- >>>>>> queue[V3D_CACHE_CLEAN].sched, >>>>> - >>>>> &v3d_cache_clean_sched_ops, >>>>> NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - hw_jobs_limit, >>>>> job_hang_limit, >>>>> - >>>>> msecs_to_jiffies(hang_limit_ms), NULL, >>>>> - NULL, "v3d_cache_clean", >>>>> v3d- >>>>>> drm.dev); >>>>> + ret = v3d_cache_sched_init(v3d); >>>>> if (ret) >>>>> goto fail; >>>>> } >>>>> >>>>> - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, >>>>> - &v3d_cpu_sched_ops, NULL, >>>>> - DRM_SCHED_PRIORITY_COUNT, >>>>> - 1, job_hang_limit, >>>>> - msecs_to_jiffies(hang_limit_ms), >>>>> NULL, >>>>> - NULL, "v3d_cpu", v3d->drm.dev); >>>>> + ret = v3d_cpu_sched_init(v3d); >>>>> if (ret) >>>>> goto fail; >>>>> >>>>> diff --git a/drivers/gpu/drm/xe/xe_execlist.c >>>>> b/drivers/gpu/drm/xe/xe_execlist.c >>>>> index a8c416a48812..7f29b7f04af4 100644 >>>>> --- a/drivers/gpu/drm/xe/xe_execlist.c >>>>> +++ b/drivers/gpu/drm/xe/xe_execlist.c >>>>> @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops >>>>> drm_sched_ops = { >>>>> static int execlist_exec_queue_init(struct xe_exec_queue *q) >>>>> { >>>>> struct drm_gpu_scheduler *sched; >>>>> + struct drm_sched_init_params params; >>>>> struct xe_execlist_exec_queue *exl; >>>>> struct xe_device *xe = gt_to_xe(q->gt); >>>>> int err; >>>>> >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> xe_assert(xe, !xe_device_uc_enabled(xe)); >>>>> >>>>> drm_info(&xe->drm, "Enabling execlist submission (GuC >>>>> submission disabled)\n"); >>>>> @@ -346,11 +349,18 @@ static int >>>>> execlist_exec_queue_init(struct >>>>> xe_exec_queue *q) >>>>> >>>>> exl->q = q; >>>>> >>>>> - err = drm_sched_init(&exl->sched, &drm_sched_ops, >>>>> NULL, 1, >>>>> - q->lrc[0]->ring.size / >>>>> MAX_JOB_SIZE_BYTES, >>>>> - XE_SCHED_HANG_LIMIT, >>>>> XE_SCHED_JOB_TIMEOUT, >>>>> - NULL, NULL, q->hwe->name, >>>>> - gt_to_xe(q->gt)->drm.dev); >>>>> + params.ops = &drm_sched_ops; >>>>> + params.submit_wq = NULL; /* Use the system_wq. */ >>>>> + params.num_rqs = 1; >>>>> + params.credit_limit = q->lrc[0]->ring.size / >>>>> MAX_JOB_SIZE_BYTES; >>>>> + params.hang_limit = XE_SCHED_HANG_LIMIT; >>>>> + params.timeout = XE_SCHED_JOB_TIMEOUT; >>>>> + params.timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params.score = NULL; >>>>> + params.name = q->hwe->name; >>>>> + params.dev = gt_to_xe(q->gt)->drm.dev; >>>>> + >>>>> + err = drm_sched_init(&exl->sched, ¶ms); >>>>> if (err) >>>>> goto err_free; >>>>> >>>>> diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>>>> b/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>>>> index 50361b4638f9..2129fee83f25 100644 >>>>> --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>>>> +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c >>>>> @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler >>>>> *sched, >>>>> atomic_t *score, const char *name, >>>>> struct device *dev) >>>>> { >>>>> + struct drm_sched_init_params params; >>>>> + >>>>> sched->ops = xe_ops; >>>>> INIT_LIST_HEAD(&sched->msgs); >>>>> INIT_WORK(&sched->work_process_msg, >>>>> xe_sched_process_msg_work); >>>>> >>>>> - return drm_sched_init(&sched->base, ops, submit_wq, 1, >>>>> hw_submission, >>>>> - hang_limit, timeout, timeout_wq, >>>>> score, name, >>>>> - dev); >>>>> + memset(¶ms, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> + params.ops = ops; >>>>> + params.submit_wq = submit_wq; >>>>> + params.num_rqs = 1; >>>>> + params.credit_limit = hw_submission; >>>>> + params.hang_limit = hang_limit; >>>>> + params.timeout = timeout; >>>>> + params.timeout_wq = timeout_wq; >>>>> + params.score = score; >>>>> + params.name = name; >>>>> + params.dev = dev; >>>>> + >>>>> + return drm_sched_init(&sched->base, ¶ms); >>>>> } >>>>> >>>>> void xe_sched_fini(struct xe_gpu_scheduler *sched) >>>>> diff --git a/include/drm/gpu_scheduler.h >>>>> b/include/drm/gpu_scheduler.h >>>>> index 95e17504e46a..1a834ef43862 100644 >>>>> --- a/include/drm/gpu_scheduler.h >>>>> +++ b/include/drm/gpu_scheduler.h >>>>> @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { >>>>> struct device *dev; >>>>> }; >>>>> >>>>> +/** >>>>> + * struct drm_sched_init_params - parameters for initializing >>>>> a >>>>> DRM GPU scheduler >>>>> + * >>>>> + * @ops: backend operations provided by the driver >>>>> + * @submit_wq: workqueue to use for submission. If NULL, an >>>>> ordered wq is >>>>> + * allocated and used >>>>> + * @num_rqs: Number of run-queues. This is at most >>>>> DRM_SCHED_PRIORITY_COUNT, >>>>> + * as there's usually one run-queue per priority, >>>>> but >>>>> could be less. >>>>> + * @credit_limit: the number of credits this scheduler can >>>>> hold >>>>> from all jobs >>>>> + * @hang_limit: number of times to allow a job to hang before >>>>> dropping it >>>>> + * @timeout: timeout value in jiffies for the scheduler >>>>> + * @timeout_wq: workqueue to use for timeout work. If NULL, >>>>> the >>>>> system_wq is >>>>> + * used >>>>> + * @score: optional score atomic shared with other schedulers >>>>> + * @name: name used for debugging >>>>> + * @dev: associated device. Used for debugging >>>>> + */ >>>>> +struct drm_sched_init_params { >>>>> + const struct drm_sched_backend_ops *ops; >>>>> + struct workqueue_struct *submit_wq; >>>>> + struct workqueue_struct *timeout_wq; >>>>> + u32 num_rqs, credit_limit; >>>>> + unsigned int hang_limit; >>>>> + long timeout; >>>>> + atomic_t *score; >>>>> + const char *name; >>>>> + struct device *dev; >>>>> +}; >>>>> + >>>>> int drm_sched_init(struct drm_gpu_scheduler *sched, >>>>> - const struct drm_sched_backend_ops *ops, >>>>> - struct workqueue_struct *submit_wq, >>>>> - u32 num_rqs, u32 credit_limit, unsigned int >>>>> hang_limit, >>>>> - long timeout, struct workqueue_struct >>>>> *timeout_wq, >>>>> - atomic_t *score, const char *name, struct >>>>> device *dev); >>>>> + const struct drm_sched_init_params *params); >>>>> >>>>> void drm_sched_fini(struct drm_gpu_scheduler *sched); >>>>> int drm_sched_job_init(struct drm_sched_job *job,
On Wed, 22 Jan 2025 15:08:20 +0100 Philipp Stanner <phasta@kernel.org> wrote: > --- a/drivers/gpu/drm/panthor/panthor_sched.c > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, > const struct drm_panthor_queue_create *args) > { > struct drm_gpu_scheduler *drm_sched; > + struct drm_sched_init_params sched_params; nit: Could we use a struct initializer instead of a memset(0)+field-assignment? struct drm_sched_init_params sched_params = { .ops = &panthor_queue_sched_ops, .submit_wq = group->ptdev->scheduler->wq, .num_rqs = 1, .credit_limit = args->ringbuf_size / sizeof(u64), .hang_limit = 0, .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), .timeout_wq = group->ptdev->reset.wq, .name = "panthor-queue", .dev = group->ptdev->base.dev, }; The same comment applies the panfrost changes BTW. > struct panthor_queue *queue; > int ret; > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, > if (!queue) > return ERR_PTR(-ENOMEM); > > + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > + > queue->fence_ctx.id = dma_fence_context_alloc(1); > spin_lock_init(&queue->fence_ctx.lock); > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, > if (ret) > goto err_free_queue; > > + sched_params.ops = &panthor_queue_sched_ops; > + sched_params.submit_wq = group->ptdev->scheduler->wq; > + sched_params.num_rqs = 1; > /* > - * Credit limit argument tells us the total number of instructions > + * The credit limit argument tells us the total number of instructions > * across all CS slots in the ringbuffer, with some jobs requiring > * twice as many as others, depending on their profiling status. > */ > - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, > - group->ptdev->scheduler->wq, 1, > - args->ringbuf_size / sizeof(u64), > - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > - group->ptdev->reset.wq, > - NULL, "panthor-queue", group->ptdev->base.dev); > + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); > + sched_params.hang_limit = 0; > + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > + sched_params.timeout_wq = group->ptdev->reset.wq; > + sched_params.score = NULL; > + sched_params.name = "panthor-queue"; > + sched_params.dev = group->ptdev->base.dev; > + > + ret = drm_sched_init(&queue->scheduler, &sched_params); > if (ret) > goto err_free_queue;
On 22/01/2025 15:51, Boris Brezillon wrote: > On Wed, 22 Jan 2025 15:08:20 +0100 > Philipp Stanner <phasta@kernel.org> wrote: > >> --- a/drivers/gpu/drm/panthor/panthor_sched.c >> +++ b/drivers/gpu/drm/panthor/panthor_sched.c >> @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, >> const struct drm_panthor_queue_create *args) >> { >> struct drm_gpu_scheduler *drm_sched; >> + struct drm_sched_init_params sched_params; > > nit: Could we use a struct initializer instead of a > memset(0)+field-assignment? > > struct drm_sched_init_params sched_params = { > .ops = &panthor_queue_sched_ops, > .submit_wq = group->ptdev->scheduler->wq, > .num_rqs = 1, > .credit_limit = args->ringbuf_size / sizeof(u64), > .hang_limit = 0, > .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), > .timeout_wq = group->ptdev->reset.wq, > .name = "panthor-queue", > .dev = group->ptdev->base.dev, > }; +1 on this as a general approach for the whole series. And I'd drop the explicit zeros and NULLs. Memsets could then go too. Regards, Tvrtko > > The same comment applies the panfrost changes BTW. > >> struct panthor_queue *queue; >> int ret; >> >> @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, >> if (!queue) >> return ERR_PTR(-ENOMEM); >> >> + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); >> + >> queue->fence_ctx.id = dma_fence_context_alloc(1); >> spin_lock_init(&queue->fence_ctx.lock); >> INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); >> @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, >> if (ret) >> goto err_free_queue; >> >> + sched_params.ops = &panthor_queue_sched_ops; >> + sched_params.submit_wq = group->ptdev->scheduler->wq; >> + sched_params.num_rqs = 1; >> /* >> - * Credit limit argument tells us the total number of instructions >> + * The credit limit argument tells us the total number of instructions >> * across all CS slots in the ringbuffer, with some jobs requiring >> * twice as many as others, depending on their profiling status. >> */ >> - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, >> - group->ptdev->scheduler->wq, 1, >> - args->ringbuf_size / sizeof(u64), >> - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), >> - group->ptdev->reset.wq, >> - NULL, "panthor-queue", group->ptdev->base.dev); >> + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); >> + sched_params.hang_limit = 0; >> + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); >> + sched_params.timeout_wq = group->ptdev->reset.wq; >> + sched_params.score = NULL; >> + sched_params.name = "panthor-queue"; >> + sched_params.dev = group->ptdev->base.dev; >> + >> + ret = drm_sched_init(&queue->scheduler, &sched_params); >> if (ret) >> goto err_free_queue;
On Wed, 22 Jan 2025 16:14:59 +0000 Tvrtko Ursulin <tursulin@ursulin.net> wrote: > On 22/01/2025 15:51, Boris Brezillon wrote: > > On Wed, 22 Jan 2025 15:08:20 +0100 > > Philipp Stanner <phasta@kernel.org> wrote: > > > >> --- a/drivers/gpu/drm/panthor/panthor_sched.c > >> +++ b/drivers/gpu/drm/panthor/panthor_sched.c > >> @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, > >> const struct drm_panthor_queue_create *args) > >> { > >> struct drm_gpu_scheduler *drm_sched; > >> + struct drm_sched_init_params sched_params; > > > > nit: Could we use a struct initializer instead of a > > memset(0)+field-assignment? > > > > struct drm_sched_init_params sched_params = { Actually, you can even make it const if it's not modified after the declaration. > > .ops = &panthor_queue_sched_ops, > > .submit_wq = group->ptdev->scheduler->wq, > > .num_rqs = 1, > > .credit_limit = args->ringbuf_size / sizeof(u64), > > .hang_limit = 0, > > .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), > > .timeout_wq = group->ptdev->reset.wq, > > .name = "panthor-queue", > > .dev = group->ptdev->base.dev, > > }; > > +1 on this as a general approach for the whole series. And I'd drop the > explicit zeros and NULLs. Memsets could then go too. > > Regards, > > Tvrtko > > > > > The same comment applies the panfrost changes BTW. > > > >> struct panthor_queue *queue; > >> int ret; > >> > >> @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, > >> if (!queue) > >> return ERR_PTR(-ENOMEM); > >> > >> + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > >> + > >> queue->fence_ctx.id = dma_fence_context_alloc(1); > >> spin_lock_init(&queue->fence_ctx.lock); > >> INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > >> @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, > >> if (ret) > >> goto err_free_queue; > >> > >> + sched_params.ops = &panthor_queue_sched_ops; > >> + sched_params.submit_wq = group->ptdev->scheduler->wq; > >> + sched_params.num_rqs = 1; > >> /* > >> - * Credit limit argument tells us the total number of instructions > >> + * The credit limit argument tells us the total number of instructions > >> * across all CS slots in the ringbuffer, with some jobs requiring > >> * twice as many as others, depending on their profiling status. > >> */ > >> - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, > >> - group->ptdev->scheduler->wq, 1, > >> - args->ringbuf_size / sizeof(u64), > >> - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > >> - group->ptdev->reset.wq, > >> - NULL, "panthor-queue", group->ptdev->base.dev); > >> + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); > >> + sched_params.hang_limit = 0; > >> + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > >> + sched_params.timeout_wq = group->ptdev->reset.wq; > >> + sched_params.score = NULL; > >> + sched_params.name = "panthor-queue"; > >> + sched_params.dev = group->ptdev->base.dev; > >> + > >> + ret = drm_sched_init(&queue->scheduler, &sched_params); > >> if (ret) > >> goto err_free_queue;
On Wed, 22 Jan 2025 15:08:20 +0100 Philipp Stanner <phasta@kernel.org> wrote: > int drm_sched_init(struct drm_gpu_scheduler *sched, > - const struct drm_sched_backend_ops *ops, > - struct workqueue_struct *submit_wq, > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > - long timeout, struct workqueue_struct *timeout_wq, > - atomic_t *score, const char *name, struct device *dev); > + const struct drm_sched_init_params *params); Another nit: indenting is messed up here.
Hi Philipp, On 22/01/25 11:08, Philipp Stanner wrote: > drm_sched_init() has a great many parameters and upcoming new > functionality for the scheduler might add even more. Generally, the > great number of parameters reduces readability and has already caused > one missnaming in: > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in nouveau_sched_init()"). > > Introduce a new struct for the scheduler init parameters and port all > users. > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > --- > Howdy, > > I have a patch-series in the pipe that will add a `flags` argument to > drm_sched_init(). I thought it would be wise to first rework the API as > detailed in this patch. It's really a lot of parameters by now, and I > would expect that it might get more and more over the years for special > use cases etc. > > Regards, > P. > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++------ > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > include/drm/gpu_scheduler.h | 35 +++++- > 14 files changed, 311 insertions(+), 139 deletions(-) > [...] > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c > index 99ac4995b5a1..716e6d074d87 100644 > --- a/drivers/gpu/drm/v3d/v3d_sched.c > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { > .free_job = v3d_cpu_job_free > }; > > +/* > + * v3d's scheduler instances are all identical, except for ops and name. > + */ > +static void > +v3d_common_sched_init(struct drm_sched_init_params *params, struct device *dev) > +{ > + memset(params, 0, sizeof(struct drm_sched_init_params)); > + > + params->submit_wq = NULL; /* Use the system_wq. */ > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > + params->credit_limit = 1; > + params->hang_limit = 0; > + params->timeout = msecs_to_jiffies(500); > + params->timeout_wq = NULL; /* Use the system_wq. */ > + params->score = NULL; > + params->dev = dev; > +} Could we use only one function that takes struct v3d_dev *v3d, enum v3d_queue, and sched_ops as arguments (instead of one function per queue)? You can get the name of the scheduler by concatenating "v3d_" to the return of v3d_queue_to_string(). I believe it would make the code much simpler. Best Regards, - Maíra > + > +static int > +v3d_bin_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_bin_sched_ops; > + params.name = "v3d_bin"; > + > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, ¶ms); > +} > + > +static int > +v3d_render_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_render_sched_ops; > + params.name = "v3d_render"; > + > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, ¶ms); > +} > + > +static int > +v3d_tfu_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_tfu_sched_ops; > + params.name = "v3d_tfu"; > + > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, ¶ms); > +} > + > +static int > +v3d_csd_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_csd_sched_ops; > + params.name = "v3d_csd"; > + > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, ¶ms); > +} > + > +static int > +v3d_cache_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_cache_clean_sched_ops; > + params.name = "v3d_cache_clean"; > + > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, ¶ms); > +} > + > +static int > +v3d_cpu_sched_init(struct v3d_dev *v3d) > +{ > + struct drm_sched_init_params params; > + > + v3d_common_sched_init(¶ms, v3d->drm.dev); > + params.ops = &v3d_cpu_sched_ops; > + params.name = "v3d_cpu"; > + > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, ¶ms); > +} > + > int > v3d_sched_init(struct v3d_dev *v3d) > { > - int hw_jobs_limit = 1; > - int job_hang_limit = 0; > - int hang_limit_ms = 500; > int ret; > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > - &v3d_bin_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_bin", v3d->drm.dev); > + ret = v3d_bin_sched_init(v3d); > if (ret) > return ret; > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > - &v3d_render_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_render", v3d->drm.dev); > + ret = v3d_render_sched_init(v3d); > if (ret) > goto fail; > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > - &v3d_tfu_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_tfu", v3d->drm.dev); > + ret = v3d_tfu_sched_init(v3d); > if (ret) > goto fail; > > if (v3d_has_csd(v3d)) { > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > - &v3d_csd_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_csd", v3d->drm.dev); > + ret = v3d_csd_sched_init(v3d); > if (ret) > goto fail; > > - ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > - &v3d_cache_clean_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_cache_clean", v3d->drm.dev); > + ret = v3d_cache_sched_init(v3d); > if (ret) > goto fail; > } > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > - &v3d_cpu_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - 1, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_cpu", v3d->drm.dev); > + ret = v3d_cpu_sched_init(v3d); > if (ret) > goto fail; >
On Wed, Jan 22, 2025 at 06:04:58PM +0100, Boris Brezillon wrote: > On Wed, 22 Jan 2025 16:14:59 +0000 > Tvrtko Ursulin <tursulin@ursulin.net> wrote: > > > On 22/01/2025 15:51, Boris Brezillon wrote: > > > On Wed, 22 Jan 2025 15:08:20 +0100 > > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > >> --- a/drivers/gpu/drm/panthor/panthor_sched.c > > >> +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > >> @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, > > >> const struct drm_panthor_queue_create *args) > > >> { > > >> struct drm_gpu_scheduler *drm_sched; > > >> + struct drm_sched_init_params sched_params; > > > > > > nit: Could we use a struct initializer instead of a > > > memset(0)+field-assignment? > > > > > > struct drm_sched_init_params sched_params = { > > Actually, you can even make it const if it's not modified after the > declaration. > > > > .ops = &panthor_queue_sched_ops, > > > .submit_wq = group->ptdev->scheduler->wq, > > > .num_rqs = 1, > > > .credit_limit = args->ringbuf_size / sizeof(u64), > > > .hang_limit = 0, > > > .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), > > > .timeout_wq = group->ptdev->reset.wq, > > > .name = "panthor-queue", > > > .dev = group->ptdev->base.dev, > > > }; > > +2 Matt > > +1 on this as a general approach for the whole series. And I'd drop the > > explicit zeros and NULLs. Memsets could then go too. > > > > Regards, > > > > Tvrtko > > > > > > > > The same comment applies the panfrost changes BTW. > > > > > >> struct panthor_queue *queue; > > >> int ret; > > >> > > >> @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, > > >> if (!queue) > > >> return ERR_PTR(-ENOMEM); > > >> > > >> + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); > > >> + > > >> queue->fence_ctx.id = dma_fence_context_alloc(1); > > >> spin_lock_init(&queue->fence_ctx.lock); > > >> INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > >> @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, > > >> if (ret) > > >> goto err_free_queue; > > >> > > >> + sched_params.ops = &panthor_queue_sched_ops; > > >> + sched_params.submit_wq = group->ptdev->scheduler->wq; > > >> + sched_params.num_rqs = 1; > > >> /* > > >> - * Credit limit argument tells us the total number of instructions > > >> + * The credit limit argument tells us the total number of instructions > > >> * across all CS slots in the ringbuffer, with some jobs requiring > > >> * twice as many as others, depending on their profiling status. > > >> */ > > >> - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, > > >> - group->ptdev->scheduler->wq, 1, > > >> - args->ringbuf_size / sizeof(u64), > > >> - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), > > >> - group->ptdev->reset.wq, > > >> - NULL, "panthor-queue", group->ptdev->base.dev); > > >> + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); > > >> + sched_params.hang_limit = 0; > > >> + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); > > >> + sched_params.timeout_wq = group->ptdev->reset.wq; > > >> + sched_params.score = NULL; > > >> + sched_params.name = "panthor-queue"; > > >> + sched_params.dev = group->ptdev->base.dev; > > >> + > > >> + ret = drm_sched_init(&queue->scheduler, &sched_params); > > >> if (ret) > > >> goto err_free_queue; >
On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: > On Wed, 22 Jan 2025 15:08:20 +0100 > Philipp Stanner <phasta@kernel.org> wrote: > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > - const struct drm_sched_backend_ops *ops, > > - struct workqueue_struct *submit_wq, > > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > > - long timeout, struct workqueue_struct *timeout_wq, > > - atomic_t *score, const char *name, struct device *dev); > > + const struct drm_sched_init_params *params); > > > Another nit: indenting is messed up here. That was done on purpose. I never got why so many like to intend to the opening brackets, because: 1. The kernel coding guide line does not demand it 2. It mixes tabs with spaces 3. It doesn't create an identical level of intendation 4. It wastes huge amount of space and does not solve the problem of long names, but might even make it worse: https://elixir.bootlin.com/linux/v6.13- rc3/source/drivers/gpu/drm/scheduler/sched_main.c#L1296
On Wed, 2025-01-22 at 20:37 -0800, Matthew Brost wrote: > On Wed, Jan 22, 2025 at 06:04:58PM +0100, Boris Brezillon wrote: > > On Wed, 22 Jan 2025 16:14:59 +0000 > > Tvrtko Ursulin <tursulin@ursulin.net> wrote: > > > > > On 22/01/2025 15:51, Boris Brezillon wrote: > > > > On Wed, 22 Jan 2025 15:08:20 +0100 > > > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > > > > > --- a/drivers/gpu/drm/panthor/panthor_sched.c > > > > > +++ b/drivers/gpu/drm/panthor/panthor_sched.c > > > > > @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group > > > > > *group, > > > > > const struct drm_panthor_queue_create > > > > > *args) > > > > > { > > > > > struct drm_gpu_scheduler *drm_sched; > > > > > + struct drm_sched_init_params sched_params; > > > > > > > > nit: Could we use a struct initializer instead of a > > > > memset(0)+field-assignment? > > > > > > > > struct drm_sched_init_params sched_params = { > > > > Actually, you can even make it const if it's not modified after the > > declaration. > > > > > > .ops = &panthor_queue_sched_ops, > > > > .submit_wq = group->ptdev->scheduler->wq, > > > > .num_rqs = 1, > > > > .credit_limit = args->ringbuf_size / > > > > sizeof(u64), > > > > .hang_limit = 0, > > > > .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > .timeout_wq = group->ptdev->reset.wq, > > > > .name = "panthor-queue", > > > > .dev = group->ptdev->base.dev, > > > > }; > > > > > +2 Yup, getting rid of memset() similar to Danilo's suggestion is surely a good idea. I personally don't like mixing initialization and declaration when possible (readability), but having it const is probably a good argument. P. > > Matt > > > > +1 on this as a general approach for the whole series. And I'd > > > drop the > > > explicit zeros and NULLs. Memsets could then go too. > > > > > > Regards, > > > > > > Tvrtko > > > > > > > > > > > The same comment applies the panfrost changes BTW. > > > > > > > > > struct panthor_queue *queue; > > > > > int ret; > > > > > > > > > > @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group > > > > > *group, > > > > > if (!queue) > > > > > return ERR_PTR(-ENOMEM); > > > > > > > > > > + memset(&sched_params, 0, sizeof(struct > > > > > drm_sched_init_params)); > > > > > + > > > > > queue->fence_ctx.id = dma_fence_context_alloc(1); > > > > > spin_lock_init(&queue->fence_ctx.lock); > > > > > INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); > > > > > @@ -3341,17 +3344,23 @@ group_create_queue(struct > > > > > panthor_group *group, > > > > > if (ret) > > > > > goto err_free_queue; > > > > > > > > > > + sched_params.ops = &panthor_queue_sched_ops; > > > > > + sched_params.submit_wq = group->ptdev->scheduler- > > > > > >wq; > > > > > + sched_params.num_rqs = 1; > > > > > /* > > > > > - * Credit limit argument tells us the total number > > > > > of instructions > > > > > + * The credit limit argument tells us the total > > > > > number of instructions > > > > > * across all CS slots in the ringbuffer, with some > > > > > jobs requiring > > > > > * twice as many as others, depending on their > > > > > profiling status. > > > > > */ > > > > > - ret = drm_sched_init(&queue->scheduler, > > > > > &panthor_queue_sched_ops, > > > > > - group->ptdev->scheduler->wq, 1, > > > > > - args->ringbuf_size / > > > > > sizeof(u64), > > > > > - 0, > > > > > msecs_to_jiffies(JOB_TIMEOUT_MS), > > > > > - group->ptdev->reset.wq, > > > > > - NULL, "panthor-queue", group- > > > > > >ptdev->base.dev); > > > > > + sched_params.credit_limit = args->ringbuf_size / > > > > > sizeof(u64); > > > > > + sched_params.hang_limit = 0; > > > > > + sched_params.timeout = > > > > > msecs_to_jiffies(JOB_TIMEOUT_MS); > > > > > + sched_params.timeout_wq = group->ptdev->reset.wq; > > > > > + sched_params.score = NULL; > > > > > + sched_params.name = "panthor-queue"; > > > > > + sched_params.dev = group->ptdev->base.dev; > > > > > + > > > > > + ret = drm_sched_init(&queue->scheduler, > > > > > &sched_params); > > > > > if (ret) > > > > > goto err_free_queue; > >
On Wed, 2025-01-22 at 19:07 -0300, Maíra Canal wrote: > Hi Philipp, > > On 22/01/25 11:08, Philipp Stanner wrote: > > drm_sched_init() has a great many parameters and upcoming new > > functionality for the scheduler might add even more. Generally, the > > great number of parameters reduces readability and has already > > caused > > one missnaming in: > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > nouveau_sched_init()"). > > > > Introduce a new struct for the scheduler init parameters and port > > all > > users. > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > --- > > Howdy, > > > > I have a patch-series in the pipe that will add a `flags` argument > > to > > drm_sched_init(). I thought it would be wise to first rework the > > API as > > detailed in this patch. It's really a lot of parameters by now, and > > I > > would expect that it might get more and more over the years for > > special > > use cases etc. > > > > Regards, > > P. > > --- > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++- > > ----- > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > include/drm/gpu_scheduler.h | 35 +++++- > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > [...] > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > b/drivers/gpu/drm/v3d/v3d_sched.c > > index 99ac4995b5a1..716e6d074d87 100644 > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops > > v3d_cpu_sched_ops = { > > .free_job = v3d_cpu_job_free > > }; > > > > +/* > > + * v3d's scheduler instances are all identical, except for ops and > > name. > > + */ > > +static void > > +v3d_common_sched_init(struct drm_sched_init_params *params, struct > > device *dev) > > +{ > > + memset(params, 0, sizeof(struct drm_sched_init_params)); > > + > > + params->submit_wq = NULL; /* Use the system_wq. */ > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > + params->credit_limit = 1; > > + params->hang_limit = 0; > > + params->timeout = msecs_to_jiffies(500); > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > + params->score = NULL; > > + params->dev = dev; > > +} > > Could we use only one function that takes struct v3d_dev *v3d, enum > v3d_queue, and sched_ops as arguments (instead of one function per > queue)? You can get the name of the scheduler by concatenating "v3d_" > to > the return of v3d_queue_to_string(). > > I believe it would make the code much simpler. Hello, so just to get that right: You'd like to have one universal function that switch-cases over an enum, sets the ops and creates the name with string concatenation? I'm not convinced that this is simpler than a few small functions, but it's not my component, so… Whatever we'll do will be simpler than the existing code, though. Right now no reader can see at first glance whether all those schedulers are identically parametrized or not. P. > > Best Regards, > - Maíra > > > + > > +static int > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_bin_sched_ops; > > + params.name = "v3d_bin"; > > + > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_render_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_render_sched_ops; > > + params.name = "v3d_render"; > > + > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_tfu_sched_ops; > > + params.name = "v3d_tfu"; > > + > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_csd_sched_ops; > > + params.name = "v3d_csd"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_cache_clean_sched_ops; > > + params.name = "v3d_cache_clean"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, > > ¶ms); > > +} > > + > > +static int > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > +{ > > + struct drm_sched_init_params params; > > + > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > + params.ops = &v3d_cpu_sched_ops; > > + params.name = "v3d_cpu"; > > + > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > ¶ms); > > +} > > + > > int > > v3d_sched_init(struct v3d_dev *v3d) > > { > > - int hw_jobs_limit = 1; > > - int job_hang_limit = 0; > > - int hang_limit_ms = 500; > > int ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > - &v3d_bin_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_bin", v3d->drm.dev); > > + ret = v3d_bin_sched_init(v3d); > > if (ret) > > return ret; > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > - &v3d_render_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_render", v3d->drm.dev); > > + ret = v3d_render_sched_init(v3d); > > if (ret) > > goto fail; > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > - &v3d_tfu_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_tfu", v3d->drm.dev); > > + ret = v3d_tfu_sched_init(v3d); > > if (ret) > > goto fail; > > > > if (v3d_has_csd(v3d)) { > > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > > - &v3d_csd_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, > > job_hang_limit, > > - > > msecs_to_jiffies(hang_limit_ms), NULL, > > - NULL, "v3d_csd", v3d- > > >drm.dev); > > + ret = v3d_csd_sched_init(v3d); > > if (ret) > > goto fail; > > > > - ret = drm_sched_init(&v3d- > > >queue[V3D_CACHE_CLEAN].sched, > > - &v3d_cache_clean_sched_ops, > > NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - hw_jobs_limit, > > job_hang_limit, > > - > > msecs_to_jiffies(hang_limit_ms), NULL, > > - NULL, "v3d_cache_clean", v3d- > > >drm.dev); > > + ret = v3d_cache_sched_init(v3d); > > if (ret) > > goto fail; > > } > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > - &v3d_cpu_sched_ops, NULL, > > - DRM_SCHED_PRIORITY_COUNT, > > - 1, job_hang_limit, > > - msecs_to_jiffies(hang_limit_ms), > > NULL, > > - NULL, "v3d_cpu", v3d->drm.dev); > > + ret = v3d_cpu_sched_init(v3d); > > if (ret) > > goto fail; > > >
On Thu, 23 Jan 2025 08:33:01 +0100 Philipp Stanner <phasta@mailbox.org> wrote: > On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: > > On Wed, 22 Jan 2025 15:08:20 +0100 > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > - const struct drm_sched_backend_ops *ops, > > > - struct workqueue_struct *submit_wq, > > > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > > > - long timeout, struct workqueue_struct *timeout_wq, > > > - atomic_t *score, const char *name, struct device *dev); > > > + const struct drm_sched_init_params *params); > > > > > > Another nit: indenting is messed up here. > > That was done on purpose. > > I never got why so many like to intend to the opening brackets, > because: > 1. The kernel coding guide line does not demand it > 2. It mixes tabs with spaces > 3. It doesn't create an identical level of intendation > 4. It wastes huge amount of space and does not solve the problem of > long names, but might even make it worse: > https://elixir.bootlin.com/linux/v6.13- > rc3/source/drivers/gpu/drm/scheduler/sched_main.c#L1296 It's mostly a matter of keeping things consistent in a code base. I don't really have strong opinions when it comes to coding style, but I always try to follow the rules in place in the file/subsystem/project I'm contributing to, and clearly the pattern in this file is to align the extra lines of arguments on the first argument...
On Thu, 2025-01-23 at 09:10 +0100, Philipp Stanner wrote: > On Wed, 2025-01-22 at 19:07 -0300, Maíra Canal wrote: > > Hi Philipp, > > > > On 22/01/25 11:08, Philipp Stanner wrote: > > > drm_sched_init() has a great many parameters and upcoming new > > > functionality for the scheduler might add even more. Generally, > > > the > > > great number of parameters reduces readability and has already > > > caused > > > one missnaming in: > > > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > > nouveau_sched_init()"). > > > > > > Introduce a new struct for the scheduler init parameters and port > > > all > > > users. > > > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > > --- > > > Howdy, > > > > > > I have a patch-series in the pipe that will add a `flags` > > > argument > > > to > > > drm_sched_init(). I thought it would be wise to first rework the > > > API as > > > detailed in this patch. It's really a lot of parameters by now, > > > and > > > I > > > would expect that it might get more and more over the years for > > > special > > > use cases etc. > > > > > > Regards, > > > P. > > > --- > > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- > > > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- > > > drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- > > > drivers/gpu/drm/lima/lima_sched.c | 21 +++- > > > drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- > > > drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- > > > drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- > > > drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- > > > drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- > > > drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- > > > drivers/gpu/drm/v3d/v3d_sched.c | 135 > > > +++++++++++++++- > > > ----- > > > drivers/gpu/drm/xe/xe_execlist.c | 20 ++- > > > drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- > > > include/drm/gpu_scheduler.h | 35 +++++- > > > 14 files changed, 311 insertions(+), 139 deletions(-) > > > > > > > [...] > > > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > > b/drivers/gpu/drm/v3d/v3d_sched.c > > > index 99ac4995b5a1..716e6d074d87 100644 > > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > > @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops > > > v3d_cpu_sched_ops = { > > > .free_job = v3d_cpu_job_free > > > }; > > > > > > +/* > > > + * v3d's scheduler instances are all identical, except for ops > > > and > > > name. > > > + */ > > > +static void > > > +v3d_common_sched_init(struct drm_sched_init_params *params, > > > struct > > > device *dev) > > > +{ > > > + memset(params, 0, sizeof(struct drm_sched_init_params)); > > > + > > > + params->submit_wq = NULL; /* Use the system_wq. */ > > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > + params->credit_limit = 1; > > > + params->hang_limit = 0; > > > + params->timeout = msecs_to_jiffies(500); > > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > > + params->score = NULL; > > > + params->dev = dev; > > > +} > > > > Could we use only one function that takes struct v3d_dev *v3d, enum > > v3d_queue, and sched_ops as arguments (instead of one function per > > queue)? You can get the name of the scheduler by concatenating > > "v3d_" > > to > > the return of v3d_queue_to_string(). > > > > I believe it would make the code much simpler. > > Hello, > > so just to get that right: > You'd like to have one universal function that switch-cases over an > enum, sets the ops and creates the name with string concatenation? Oh, and here's another issue: The @name string has life time issues to take into account. It must live as long as the scheduler instance. In your mind, where should the memory for the strings your concatenating be and how should their life time be managed? Currently they're in the TEXT segment, which is fine P. > > I'm not convinced that this is simpler than a few small functions, > but > it's not my component, so… > > Whatever we'll do will be simpler than the existing code, though. > Right > now no reader can see at first glance whether all those schedulers > are > identically parametrized or not. > > P. > > > > > > Best Regards, > > - Maíra > > > > > + > > > +static int > > > +v3d_bin_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_bin_sched_ops; > > > + params.name = "v3d_bin"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_render_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_render_sched_ops; > > > + params.name = "v3d_render"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_tfu_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_tfu_sched_ops; > > > + params.name = "v3d_tfu"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_csd_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_csd_sched_ops; > > > + params.name = "v3d_csd"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_cache_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_cache_clean_sched_ops; > > > + params.name = "v3d_cache_clean"; > > > + > > > + return drm_sched_init(&v3d- > > > >queue[V3D_CACHE_CLEAN].sched, > > > ¶ms); > > > +} > > > + > > > +static int > > > +v3d_cpu_sched_init(struct v3d_dev *v3d) > > > +{ > > > + struct drm_sched_init_params params; > > > + > > > + v3d_common_sched_init(¶ms, v3d->drm.dev); > > > + params.ops = &v3d_cpu_sched_ops; > > > + params.name = "v3d_cpu"; > > > + > > > + return drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > ¶ms); > > > +} > > > + > > > int > > > v3d_sched_init(struct v3d_dev *v3d) > > > { > > > - int hw_jobs_limit = 1; > > > - int job_hang_limit = 0; > > > - int hang_limit_ms = 500; > > > int ret; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > > > - &v3d_bin_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_bin", v3d->drm.dev); > > > + ret = v3d_bin_sched_init(v3d); > > > if (ret) > > > return ret; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > > > - &v3d_render_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_render", v3d->drm.dev); > > > + ret = v3d_render_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, > > > - &v3d_tfu_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_tfu", v3d->drm.dev); > > > + ret = v3d_tfu_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > if (v3d_has_csd(v3d)) { > > > - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, > > > - &v3d_csd_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, > > > job_hang_limit, > > > - > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > - NULL, "v3d_csd", v3d- > > > > drm.dev); > > > + ret = v3d_csd_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > > - ret = drm_sched_init(&v3d- > > > > queue[V3D_CACHE_CLEAN].sched, > > > - &v3d_cache_clean_sched_ops, > > > NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - hw_jobs_limit, > > > job_hang_limit, > > > - > > > msecs_to_jiffies(hang_limit_ms), NULL, > > > - NULL, "v3d_cache_clean", > > > v3d- > > > > drm.dev); > > > + ret = v3d_cache_sched_init(v3d); > > > if (ret) > > > goto fail; > > > } > > > > > > - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, > > > - &v3d_cpu_sched_ops, NULL, > > > - DRM_SCHED_PRIORITY_COUNT, > > > - 1, job_hang_limit, > > > - msecs_to_jiffies(hang_limit_ms), > > > NULL, > > > - NULL, "v3d_cpu", v3d->drm.dev); > > > + ret = v3d_cpu_sched_init(v3d); > > > if (ret) > > > goto fail; > > > > > >
On Thu, Jan 23, 2025 at 08:33:01AM +0100, Philipp Stanner wrote: > On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: > > On Wed, 22 Jan 2025 15:08:20 +0100 > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > - const struct drm_sched_backend_ops *ops, > > > - struct workqueue_struct *submit_wq, > > > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > > > - long timeout, struct workqueue_struct *timeout_wq, > > > - atomic_t *score, const char *name, struct device *dev); > > > + const struct drm_sched_init_params *params); > > > > > > Another nit: indenting is messed up here. > > That was done on purpose. Let's not change this convention, it's used all over the kernel tree, including the GPU scheduler. People are used to read code that is formatted this way, plus the attempt of changing it will make code formatting inconsistent.
On Thu, 2025-01-23 at 10:29 +0100, Danilo Krummrich wrote: > On Thu, Jan 23, 2025 at 08:33:01AM +0100, Philipp Stanner wrote: > > On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: > > > On Wed, 22 Jan 2025 15:08:20 +0100 > > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > - const struct drm_sched_backend_ops *ops, > > > > - struct workqueue_struct *submit_wq, > > > > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > > > > - long timeout, struct workqueue_struct *timeout_wq, > > > > - atomic_t *score, const char *name, struct device *dev); > > > > + const struct drm_sched_init_params *params); > > > > > > > > > Another nit: indenting is messed up here. > > > > That was done on purpose. > > Let's not change this convention, it's used all over the kernel tree, > including > the GPU scheduler. People are used to read code that is formatted > this way, plus > the attempt of changing it will make code formatting inconsistent. Both the tree and this file are already inconsistent in regards to this. Anyways, what is your proposed solution to ridiculous nonsense like this? https://elixir.bootlin.com/linux/v6.13-rc3/source/drivers/gpu/drm/scheduler/sched_main.c#L1296
On Thu, Jan 23, 2025 at 10:35:43AM +0100, Philipp Stanner wrote: > On Thu, 2025-01-23 at 10:29 +0100, Danilo Krummrich wrote: > > On Thu, Jan 23, 2025 at 08:33:01AM +0100, Philipp Stanner wrote: > > > On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: > > > > On Wed, 22 Jan 2025 15:08:20 +0100 > > > > Philipp Stanner <phasta@kernel.org> wrote: > > > > > > > > > int drm_sched_init(struct drm_gpu_scheduler *sched, > > > > > - const struct drm_sched_backend_ops *ops, > > > > > - struct workqueue_struct *submit_wq, > > > > > - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, > > > > > - long timeout, struct workqueue_struct *timeout_wq, > > > > > - atomic_t *score, const char *name, struct device *dev); > > > > > + const struct drm_sched_init_params *params); > > > > > > > > > > > > Another nit: indenting is messed up here. > > > > > > That was done on purpose. > > > > Let's not change this convention, it's used all over the kernel tree, > > including > > the GPU scheduler. People are used to read code that is formatted > > this way, plus > > the attempt of changing it will make code formatting inconsistent. > > Both the tree and this file are already inconsistent in regards to > this. That's not really a good argument to make it more inconsistent, is it? > > Anyways, what is your proposed solution to ridiculous nonsense like > this? > > https://elixir.bootlin.com/linux/v6.13-rc3/source/drivers/gpu/drm/scheduler/sched_main.c#L1296 I don't think this one needs a solution. The kernel picked a convention long ago, which also has downsides. If it gets too bad, we can deviate from conventions at any point of time; for the thing that otherwise would be bad, but we shouldn't do it in general.
On 23/01/2025 09:35, Philipp Stanner wrote: > On Thu, 2025-01-23 at 10:29 +0100, Danilo Krummrich wrote: >> On Thu, Jan 23, 2025 at 08:33:01AM +0100, Philipp Stanner wrote: >>> On Wed, 2025-01-22 at 18:16 +0100, Boris Brezillon wrote: >>>> On Wed, 22 Jan 2025 15:08:20 +0100 >>>> Philipp Stanner <phasta@kernel.org> wrote: >>>> >>>>> int drm_sched_init(struct drm_gpu_scheduler *sched, >>>>> - const struct drm_sched_backend_ops *ops, >>>>> - struct workqueue_struct *submit_wq, >>>>> - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, >>>>> - long timeout, struct workqueue_struct *timeout_wq, >>>>> - atomic_t *score, const char *name, struct device *dev); >>>>> + const struct drm_sched_init_params *params); >>>> >>>> >>>> Another nit: indenting is messed up here. >>> >>> That was done on purpose. >> >> Let's not change this convention, it's used all over the kernel tree, >> including >> the GPU scheduler. People are used to read code that is formatted >> this way, plus >> the attempt of changing it will make code formatting inconsistent. > > Both the tree and this file are already inconsistent in regards to > this. > > Anyways, what is your proposed solution to ridiculous nonsense like > this? > > https://elixir.bootlin.com/linux/v6.13-rc3/source/drivers/gpu/drm/scheduler/sched_main.c#L1296 Apologies for budging in. Sometimes breaking 80 cols is unavoidable, or perhaps something like the below would be a bit easier on the eyes? Although it still breaks 80 columns, just a bit less. diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 06b06987129d..3f7e97b240d1 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1287,22 +1287,18 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, return 0; } - if (submit_wq) { - sched->submit_wq = submit_wq; - sched->own_submit_wq = false; - } else { -#ifdef CONFIG_LOCKDEP - sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name, - WQ_MEM_RECLAIM, - &drm_sched_lockdep_map); -#else - sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM); -#endif - if (!sched->submit_wq) - return -ENOMEM; + own_wq = !!submit_wq; + if (!submit_wq && IS_ENABLED(CONFIG_LOCKDEP)) + submit_wq = alloc_ordered_workqueue_lockdep_map(name, + WQ_MEM_RECLAIM, + &drm_sched_lockdep_map); + else if (!submit_wq) + submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM); + if (!submit_wq) + return -ENOMEM; - sched->own_submit_wq = true; - } + sched->submit_wq = submit_wq; + sched->own_submit_wq = own_wq; sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq), GFP_KERNEL | __GFP_ZERO); Could bring it under 80 by renaming drm_sched_lockdep_map to something shorter. Which should be fine since it is local to the file. Regards, Tvrtko
Hi Philipp, On 23/01/25 05:10, Philipp Stanner wrote: > On Wed, 2025-01-22 at 19:07 -0300, Maíra Canal wrote: >> Hi Philipp, >> >> On 22/01/25 11:08, Philipp Stanner wrote: >>> drm_sched_init() has a great many parameters and upcoming new >>> functionality for the scheduler might add even more. Generally, the >>> great number of parameters reduces readability and has already >>> caused >>> one missnaming in: >>> >>> commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in >>> nouveau_sched_init()"). >>> >>> Introduce a new struct for the scheduler init parameters and port >>> all >>> users. >>> >>> Signed-off-by: Philipp Stanner <phasta@kernel.org> [...] >> >>> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c >>> b/drivers/gpu/drm/v3d/v3d_sched.c >>> index 99ac4995b5a1..716e6d074d87 100644 >>> --- a/drivers/gpu/drm/v3d/v3d_sched.c >>> +++ b/drivers/gpu/drm/v3d/v3d_sched.c >>> @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops >>> v3d_cpu_sched_ops = { >>> .free_job = v3d_cpu_job_free >>> }; >>> >>> +/* >>> + * v3d's scheduler instances are all identical, except for ops and >>> name. >>> + */ >>> +static void >>> +v3d_common_sched_init(struct drm_sched_init_params *params, struct >>> device *dev) >>> +{ >>> + memset(params, 0, sizeof(struct drm_sched_init_params)); >>> + >>> + params->submit_wq = NULL; /* Use the system_wq. */ >>> + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; >>> + params->credit_limit = 1; >>> + params->hang_limit = 0; >>> + params->timeout = msecs_to_jiffies(500); >>> + params->timeout_wq = NULL; /* Use the system_wq. */ >>> + params->score = NULL; >>> + params->dev = dev; >>> +} >> >> Could we use only one function that takes struct v3d_dev *v3d, enum >> v3d_queue, and sched_ops as arguments (instead of one function per >> queue)? You can get the name of the scheduler by concatenating "v3d_" >> to >> the return of v3d_queue_to_string(). >> >> I believe it would make the code much simpler. > > Hello, > > so just to get that right: > You'd like to have one universal function that switch-cases over an > enum, sets the ops and creates the name with string concatenation? > > I'm not convinced that this is simpler than a few small functions, but > it's not my component, so… > > Whatever we'll do will be simpler than the existing code, though. Right > now no reader can see at first glance whether all those schedulers are > identically parametrized or not. > This is my proposal (just a quick draft, please check if it compiles): diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 961465128d80..7cc45a0c6ca0 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -820,67 +820,62 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { .free_job = v3d_cpu_job_free }; +static int +v3d_sched_queue_init(struct v3d_dev *v3d, enum v3d_queue queue, + const struct drm_sched_backend_ops *ops, const char *name) +{ + struct drm_sched_init_params params = { + .submit_wq = NULL, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = 1, + .hang_limit = 0, + .timeout = msecs_to_jiffies(500), + .timeout_wq = NULL, + .score = NULL, + .dev = v3d->drm.dev, + }; + + params.ops = ops; + params.name = name; + + return drm_sched_init(&v3d->queue[queue].sched, ¶ms); +} + int v3d_sched_init(struct v3d_dev *v3d) { - int hw_jobs_limit = 1; - int job_hang_limit = 0; - int hang_limit_ms = 500; int ret; - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, - &v3d_bin_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_bin", v3d->drm.dev); + ret = v3d_sched_queue_init(v3d, V3D_BIN, &v3d_bin_sched_ops, + "v3d_bin"); if (ret) return ret; - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, - &v3d_render_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_render", v3d->drm.dev); + ret = v3d_sched_queue_init(v3d, V3D_RENDER, &v3d_render_sched_ops, + "v3d_render"); if (ret) goto fail; [...] At least for me, this looks much simpler than one function for each V3D queue. Best Regards, - Maíra > P. > > >> >> Best Regards, >> - Maíra >>
On Thu, 2025-01-23 at 08:10 -0300, Maíra Canal wrote: > Hi Philipp, > > On 23/01/25 05:10, Philipp Stanner wrote: > > On Wed, 2025-01-22 at 19:07 -0300, Maíra Canal wrote: > > > Hi Philipp, > > > > > > On 22/01/25 11:08, Philipp Stanner wrote: > > > > drm_sched_init() has a great many parameters and upcoming new > > > > functionality for the scheduler might add even more. Generally, > > > > the > > > > great number of parameters reduces readability and has already > > > > caused > > > > one missnaming in: > > > > > > > > commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in > > > > nouveau_sched_init()"). > > > > > > > > Introduce a new struct for the scheduler init parameters and > > > > port > > > > all > > > > users. > > > > > > > > Signed-off-by: Philipp Stanner <phasta@kernel.org> > > [...] > > > > > > > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > > > > b/drivers/gpu/drm/v3d/v3d_sched.c > > > > index 99ac4995b5a1..716e6d074d87 100644 > > > > --- a/drivers/gpu/drm/v3d/v3d_sched.c > > > > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > > > > @@ -814,67 +814,124 @@ static const struct > > > > drm_sched_backend_ops > > > > v3d_cpu_sched_ops = { > > > > .free_job = v3d_cpu_job_free > > > > }; > > > > > > > > +/* > > > > + * v3d's scheduler instances are all identical, except for ops > > > > and > > > > name. > > > > + */ > > > > +static void > > > > +v3d_common_sched_init(struct drm_sched_init_params *params, > > > > struct > > > > device *dev) > > > > +{ > > > > + memset(params, 0, sizeof(struct > > > > drm_sched_init_params)); > > > > + > > > > + params->submit_wq = NULL; /* Use the system_wq. */ > > > > + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; > > > > + params->credit_limit = 1; > > > > + params->hang_limit = 0; > > > > + params->timeout = msecs_to_jiffies(500); > > > > + params->timeout_wq = NULL; /* Use the system_wq. */ > > > > + params->score = NULL; > > > > + params->dev = dev; > > > > +} > > > > > > Could we use only one function that takes struct v3d_dev *v3d, > > > enum > > > v3d_queue, and sched_ops as arguments (instead of one function > > > per > > > queue)? You can get the name of the scheduler by concatenating > > > "v3d_" > > > to > > > the return of v3d_queue_to_string(). > > > > > > I believe it would make the code much simpler. > > > > Hello, > > > > so just to get that right: > > You'd like to have one universal function that switch-cases over an > > enum, sets the ops and creates the name with string concatenation? > > > > I'm not convinced that this is simpler than a few small functions, > > but > > it's not my component, so… > > > > Whatever we'll do will be simpler than the existing code, though. > > Right > > now no reader can see at first glance whether all those schedulers > > are > > identically parametrized or not. > > > > This is my proposal (just a quick draft, please check if it > compiles): > > diff --git a/drivers/gpu/drm/v3d/v3d_sched.c > b/drivers/gpu/drm/v3d/v3d_sched.c > index 961465128d80..7cc45a0c6ca0 100644 > --- a/drivers/gpu/drm/v3d/v3d_sched.c > +++ b/drivers/gpu/drm/v3d/v3d_sched.c > @@ -820,67 +820,62 @@ static const struct drm_sched_backend_ops > v3d_cpu_sched_ops = { > .free_job = v3d_cpu_job_free > }; > > +static int > +v3d_sched_queue_init(struct v3d_dev *v3d, enum v3d_queue queue, > + const struct drm_sched_backend_ops *ops, const Is it a queue, though? How about _v3d_sched_init()? P. > char > *name) > +{ > + struct drm_sched_init_params params = { > + .submit_wq = NULL, > + .num_rqs = DRM_SCHED_PRIORITY_COUNT, > + .credit_limit = 1, > + .hang_limit = 0, > + .timeout = msecs_to_jiffies(500), > + .timeout_wq = NULL, > + .score = NULL, > + .dev = v3d->drm.dev, > + }; > + > + params.ops = ops; > + params.name = name; > + > + return drm_sched_init(&v3d->queue[queue].sched, ¶ms); > +} > + > int > v3d_sched_init(struct v3d_dev *v3d) > { > - int hw_jobs_limit = 1; > - int job_hang_limit = 0; > - int hang_limit_ms = 500; > int ret; > > - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, > - &v3d_bin_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_bin", v3d->drm.dev); > + ret = v3d_sched_queue_init(v3d, V3D_BIN, &v3d_bin_sched_ops, > + "v3d_bin"); > if (ret) > return ret; > > - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, > - &v3d_render_sched_ops, NULL, > - DRM_SCHED_PRIORITY_COUNT, > - hw_jobs_limit, job_hang_limit, > - msecs_to_jiffies(hang_limit_ms), NULL, > - NULL, "v3d_render", v3d->drm.dev); > + ret = v3d_sched_queue_init(v3d, V3D_RENDER, > &v3d_render_sched_ops, > + "v3d_render"); > if (ret) > goto fail; > > [...] > > At least for me, this looks much simpler than one function for each > V3D queue. > > Best Regards, > - Maíra > > > P. > > > > > > > > > > Best Regards, > > > - Maíra > > > >
Hi Philipp, On 23/01/25 09:13, Philipp Stanner wrote: > On Thu, 2025-01-23 at 08:10 -0300, Maíra Canal wrote: >> Hi Philipp, >> >> On 23/01/25 05:10, Philipp Stanner wrote: >>> On Wed, 2025-01-22 at 19:07 -0300, Maíra Canal wrote: >>>> Hi Philipp, >>>> >>>> On 22/01/25 11:08, Philipp Stanner wrote: >>>>> drm_sched_init() has a great many parameters and upcoming new >>>>> functionality for the scheduler might add even more. Generally, >>>>> the >>>>> great number of parameters reduces readability and has already >>>>> caused >>>>> one missnaming in: >>>>> >>>>> commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in >>>>> nouveau_sched_init()"). >>>>> >>>>> Introduce a new struct for the scheduler init parameters and >>>>> port >>>>> all >>>>> users. >>>>> >>>>> Signed-off-by: Philipp Stanner <phasta@kernel.org> >> >> [...] >> >>>> >>>>> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c >>>>> b/drivers/gpu/drm/v3d/v3d_sched.c >>>>> index 99ac4995b5a1..716e6d074d87 100644 >>>>> --- a/drivers/gpu/drm/v3d/v3d_sched.c >>>>> +++ b/drivers/gpu/drm/v3d/v3d_sched.c >>>>> @@ -814,67 +814,124 @@ static const struct >>>>> drm_sched_backend_ops >>>>> v3d_cpu_sched_ops = { >>>>> .free_job = v3d_cpu_job_free >>>>> }; >>>>> >>>>> +/* >>>>> + * v3d's scheduler instances are all identical, except for ops >>>>> and >>>>> name. >>>>> + */ >>>>> +static void >>>>> +v3d_common_sched_init(struct drm_sched_init_params *params, >>>>> struct >>>>> device *dev) >>>>> +{ >>>>> + memset(params, 0, sizeof(struct >>>>> drm_sched_init_params)); >>>>> + >>>>> + params->submit_wq = NULL; /* Use the system_wq. */ >>>>> + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; >>>>> + params->credit_limit = 1; >>>>> + params->hang_limit = 0; >>>>> + params->timeout = msecs_to_jiffies(500); >>>>> + params->timeout_wq = NULL; /* Use the system_wq. */ >>>>> + params->score = NULL; >>>>> + params->dev = dev; >>>>> +} >>>> >>>> Could we use only one function that takes struct v3d_dev *v3d, >>>> enum >>>> v3d_queue, and sched_ops as arguments (instead of one function >>>> per >>>> queue)? You can get the name of the scheduler by concatenating >>>> "v3d_" >>>> to >>>> the return of v3d_queue_to_string(). >>>> >>>> I believe it would make the code much simpler. >>> >>> Hello, >>> >>> so just to get that right: >>> You'd like to have one universal function that switch-cases over an >>> enum, sets the ops and creates the name with string concatenation? >>> >>> I'm not convinced that this is simpler than a few small functions, >>> but >>> it's not my component, so… >>> >>> Whatever we'll do will be simpler than the existing code, though. >>> Right >>> now no reader can see at first glance whether all those schedulers >>> are >>> identically parametrized or not. >>> >> >> This is my proposal (just a quick draft, please check if it >> compiles): >> >> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c >> b/drivers/gpu/drm/v3d/v3d_sched.c >> index 961465128d80..7cc45a0c6ca0 100644 >> --- a/drivers/gpu/drm/v3d/v3d_sched.c >> +++ b/drivers/gpu/drm/v3d/v3d_sched.c >> @@ -820,67 +820,62 @@ static const struct drm_sched_backend_ops >> v3d_cpu_sched_ops = { >> .free_job = v3d_cpu_job_free >> }; >> >> +static int >> +v3d_sched_queue_init(struct v3d_dev *v3d, enum v3d_queue queue, >> + const struct drm_sched_backend_ops *ops, const > > Is it a queue, though? In V3D, we use the abstraction of a queue for everything related to job submission. For each queue, we have a scheduler instance, a different IOCTL and such. The queues work independently and the synchronization between them can be done through syncobjs. > > How about _v3d_sched_init()? > I'd prefer if you use a function name related to "queue", as it would make more sense semantically. Best Regards, - Maíra > P. > >> char >> *name) >> +{ >> + struct drm_sched_init_params params = { >> + .submit_wq = NULL, >> + .num_rqs = DRM_SCHED_PRIORITY_COUNT, >> + .credit_limit = 1, >> + .hang_limit = 0, >> + .timeout = msecs_to_jiffies(500), >> + .timeout_wq = NULL, >> + .score = NULL, >> + .dev = v3d->drm.dev, >> + }; >> + >> + params.ops = ops; >> + params.name = name; >> + >> + return drm_sched_init(&v3d->queue[queue].sched, ¶ms); >> +} >> + >> int >> v3d_sched_init(struct v3d_dev *v3d) >> { >> - int hw_jobs_limit = 1; >> - int job_hang_limit = 0; >> - int hang_limit_ms = 500; >> int ret; >> >> - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, >> - &v3d_bin_sched_ops, NULL, >> - DRM_SCHED_PRIORITY_COUNT, >> - hw_jobs_limit, job_hang_limit, >> - msecs_to_jiffies(hang_limit_ms), NULL, >> - NULL, "v3d_bin", v3d->drm.dev); >> + ret = v3d_sched_queue_init(v3d, V3D_BIN, &v3d_bin_sched_ops, >> + "v3d_bin"); >> if (ret) >> return ret; >> >> - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, >> - &v3d_render_sched_ops, NULL, >> - DRM_SCHED_PRIORITY_COUNT, >> - hw_jobs_limit, job_hang_limit, >> - msecs_to_jiffies(hang_limit_ms), NULL, >> - NULL, "v3d_render", v3d->drm.dev); >> + ret = v3d_sched_queue_init(v3d, V3D_RENDER, >> &v3d_render_sched_ops, >> + "v3d_render"); >> if (ret) >> goto fail; >> >> [...] >> >> At least for me, this looks much simpler than one function for each >> V3D queue. >> >> Best Regards, >> - Maíra >> >>> P. >>> >>> >>>> >>>> Best Regards, >>>> - Maíra >>>> >> >
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index cd4fac120834..c1f03eb5f5ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2821,6 +2821,9 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) { long timeout; int r, i; + struct drm_sched_init_params params; + + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i]; @@ -2844,12 +2847,18 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) break; } - r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - ring->num_hw_submission, 0, - timeout, adev->reset_domain->wq, - ring->sched_score, ring->name, - adev->dev); + params.ops = &amdgpu_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = ring->num_hw_submission; + params.hang_limit = 0; + params.timeout = timeout; + params.timeout_wq = adev->reset_domain->wq; + params.score = ring->sched_score; + params.name = ring->name; + params.dev = adev->dev; + + r = drm_sched_init(&ring->sched, ¶ms); if (r) { DRM_ERROR("Failed to create scheduler on ring %s.\n", ring->name); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 5b67eda122db..7d8517f1963e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -145,12 +145,22 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit) int etnaviv_sched_init(struct etnaviv_gpu *gpu) { int ret; + struct drm_sched_init_params params; - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - etnaviv_hw_jobs_limit, etnaviv_job_hang_limit, - msecs_to_jiffies(500), NULL, NULL, - dev_name(gpu->dev), gpu->dev); + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + + params.ops = &etnaviv_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = etnaviv_hw_jobs_limit; + params.hang_limit = etnaviv_job_hang_limit; + params.timeout = msecs_to_jiffies(500); + params.timeout_wq = NULL; /* Use the system_wq. */ + params.score = NULL; + params.name = dev_name(gpu->dev); + params.dev = gpu->dev; + + ret = drm_sched_init(&gpu->sched, ¶ms); if (ret) return ret; diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c index c4f08432882b..03a2ce1a88e7 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.c +++ b/drivers/gpu/drm/imagination/pvr_queue.c @@ -1211,10 +1211,13 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, }; struct pvr_device *pvr_dev = ctx->pvr_dev; struct drm_gpu_scheduler *sched; + struct drm_sched_init_params sched_params; struct pvr_queue *queue; int ctx_state_size, err; void *cpu_map; + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); + if (WARN_ON(type >= sizeof(props))) return ERR_PTR(-EINVAL); @@ -1282,12 +1285,18 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, queue->timeline_ufo.value = cpu_map; - err = drm_sched_init(&queue->scheduler, - &pvr_queue_sched_ops, - pvr_dev->sched_wq, 1, 64 * 1024, 1, - msecs_to_jiffies(500), - pvr_dev->sched_wq, NULL, "pvr-queue", - pvr_dev->base.dev); + sched_params.ops = &pvr_queue_sched_ops; + sched_params.submit_wq = pvr_dev->sched_wq; + sched_params.num_rqs = 1; + sched_params.credit_limit = 64 * 1024; + sched_params.hang_limit = 1; + sched_params.timeout = msecs_to_jiffies(500); + sched_params.timeout_wq = pvr_dev->sched_wq; + sched_params.score = NULL; + sched_params.name = "pvr-queue"; + sched_params.dev = pvr_dev->base.dev; + + err = drm_sched_init(&queue->scheduler, &sched_params); if (err) goto err_release_ufo; diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index b40c90e97d7e..a64c50fb6d1e 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -513,20 +513,29 @@ static void lima_sched_recover_work(struct work_struct *work) int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) { + struct drm_sched_init_params params; unsigned int timeout = lima_sched_timeout_ms > 0 ? lima_sched_timeout_ms : 10000; + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + 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, NULL, - DRM_SCHED_PRIORITY_COUNT, - 1, - lima_job_hang_limit, - msecs_to_jiffies(timeout), NULL, - NULL, name, pipe->ldev->dev); + params.ops = &lima_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = 1; + params.hang_limit = lima_job_hang_limit; + params.timeout = msecs_to_jiffies(timeout); + params.timeout_wq = NULL; /* Use the system_wq. */ + params.score = NULL; + params.name = name; + params.dev = pipe->ldev->dev; + + return drm_sched_init(&pipe->base, ¶ms); } void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index c803556a8f64..49a2c7422dc6 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -59,11 +59,13 @@ static const struct drm_sched_backend_ops msm_sched_ops = { struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, void *memptrs, uint64_t memptrs_iova) { + struct drm_sched_init_params params; struct msm_ringbuffer *ring; - long sched_timeout; char name[32]; int ret; + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */ BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); @@ -95,13 +97,19 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->memptrs = memptrs; ring->memptrs_iova = memptrs_iova; - /* currently managing hangcheck ourselves: */ - sched_timeout = MAX_SCHEDULE_TIMEOUT; + params.ops = &msm_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = num_hw_submissions; + params.hang_limit = 0; + /* currently managing hangcheck ourselves: */ + params.timeout = MAX_SCHEDULE_TIMEOUT; + params.timeout_wq = NULL; /* Use the system_wq. */ + params.score = NULL; + params.name = to_msm_bo(ring->bo)->name; + params.dev = gpu->dev->dev; - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - num_hw_submissions, 0, sched_timeout, - NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); + ret = drm_sched_init(&ring->sched, ¶ms); if (ret) { goto fail; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c index 4412f2711fb5..f20c2e612750 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.c +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -404,9 +404,11 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, { struct drm_gpu_scheduler *drm_sched = &sched->base; struct drm_sched_entity *entity = &sched->entity; - const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + struct drm_sched_init_params params; int ret; + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + if (!wq) { wq = alloc_workqueue("nouveau_sched_wq_%d", 0, WQ_MAX_ACTIVE, current->pid); @@ -416,10 +418,18 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, sched->wq = wq; } - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, - NOUVEAU_SCHED_PRIORITY_COUNT, - credit_limit, 0, timeout, - NULL, NULL, "nouveau_sched", drm->dev->dev); + params.ops = &nouveau_sched_ops; + params.submit_wq = wq; + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = credit_limit; + params.hang_limit = 0; + params.timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + params.timeout_wq = NULL; /* Use the system_wq. */ + params.score = NULL; + params.name = "nouveau_sched"; + params.dev = drm->dev->dev; + + ret = drm_sched_init(drm_sched, ¶ms); if (ret) goto fail_wq; diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 9b8e82fb8bc4..6b509ff446b5 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -836,10 +836,13 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) int panfrost_job_init(struct panfrost_device *pfdev) { + struct drm_sched_init_params params; struct panfrost_job_slot *js; unsigned int nentries = 2; int ret, j; + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + /* All GPUs have two entries per queue, but without jobchain * disambiguation stopping the right job in the close path is tricky, * so let's just advertise one entry in that case. @@ -872,16 +875,21 @@ int panfrost_job_init(struct panfrost_device *pfdev) if (!pfdev->reset.wq) return -ENOMEM; + params.ops = &panfrost_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = DRM_SCHED_PRIORITY_COUNT; + params.credit_limit = nentries; + params.hang_limit = 0; + params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); + params.timeout_wq = pfdev->reset.wq; + params.score = NULL; + params.name = "pan_js"; + params.dev = pfdev->dev; + for (j = 0; j < NUM_JOB_SLOTS; j++) { js->queue[j].fence_context = dma_fence_context_alloc(1); - ret = drm_sched_init(&js->queue[j].sched, - &panfrost_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - nentries, 0, - msecs_to_jiffies(JOB_TIMEOUT_MS), - pfdev->reset.wq, - NULL, "pan_js", pfdev->dev); + ret = drm_sched_init(&js->queue[j].sched, ¶ms); if (ret) { dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret); goto err_sched; diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index a49132f3778b..4362442cbfd8 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -2268,6 +2268,7 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, u64 full_va_range = 1ull << va_bits; struct drm_gem_object *dummy_gem; struct drm_gpu_scheduler *sched; + struct drm_sched_init_params sched_params; struct io_pgtable_cfg pgtbl_cfg; u64 mair, min_va, va_range; struct panthor_vm *vm; @@ -2284,6 +2285,8 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, goto err_free_vm; } + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); + mutex_init(&vm->heaps.lock); vm->for_mcu = for_mcu; vm->ptdev = ptdev; @@ -2325,11 +2328,18 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, goto err_mm_takedown; } + sched_params.ops = &panthor_vm_bind_ops; + sched_params.submit_wq = ptdev->mmu->vm.wq; + sched_params.num_rqs = 1; + sched_params.credit_limit = 1; + sched_params.hang_limit = 0; /* Bind operations are synchronous for now, no timeout needed. */ - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq, - 1, 1, 0, - MAX_SCHEDULE_TIMEOUT, NULL, NULL, - "panthor-vm-bind", ptdev->base.dev); + sched_params.timeout = MAX_SCHEDULE_TIMEOUT; + sched_params.timeout_wq = NULL; /* Use the system_wq. */ + sched_params.score = NULL; + sched_params.name = "panthor-vm-bind"; + sched_params.dev = ptdev->base.dev; + ret = drm_sched_init(&vm->sched, &sched_params); if (ret) goto err_free_io_pgtable; diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index ef4bec7ff9c7..a324346d302f 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -3272,6 +3272,7 @@ group_create_queue(struct panthor_group *group, const struct drm_panthor_queue_create *args) { struct drm_gpu_scheduler *drm_sched; + struct drm_sched_init_params sched_params; struct panthor_queue *queue; int ret; @@ -3289,6 +3290,8 @@ group_create_queue(struct panthor_group *group, if (!queue) return ERR_PTR(-ENOMEM); + memset(&sched_params, 0, sizeof(struct drm_sched_init_params)); + queue->fence_ctx.id = dma_fence_context_alloc(1); spin_lock_init(&queue->fence_ctx.lock); INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); @@ -3341,17 +3344,23 @@ group_create_queue(struct panthor_group *group, if (ret) goto err_free_queue; + sched_params.ops = &panthor_queue_sched_ops; + sched_params.submit_wq = group->ptdev->scheduler->wq; + sched_params.num_rqs = 1; /* - * Credit limit argument tells us the total number of instructions + * The credit limit argument tells us the total number of instructions * across all CS slots in the ringbuffer, with some jobs requiring * twice as many as others, depending on their profiling status. */ - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, - group->ptdev->scheduler->wq, 1, - args->ringbuf_size / sizeof(u64), - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), - group->ptdev->reset.wq, - NULL, "panthor-queue", group->ptdev->base.dev); + sched_params.credit_limit = args->ringbuf_size / sizeof(u64); + sched_params.hang_limit = 0; + sched_params.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS); + sched_params.timeout_wq = group->ptdev->reset.wq; + sched_params.score = NULL; + sched_params.name = "panthor-queue"; + sched_params.dev = group->ptdev->base.dev; + + ret = drm_sched_init(&queue->scheduler, &sched_params); if (ret) goto err_free_queue; diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 57da84908752..27db748a5269 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1240,40 +1240,25 @@ static void drm_sched_run_job_work(struct work_struct *w) * drm_sched_init - Init a gpu scheduler instance * * @sched: scheduler instance - * @ops: backend operations for this scheduler - * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is - * allocated and used - * @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT - * @credit_limit: the number of credits this scheduler can hold from all jobs - * @hang_limit: number of times to allow a job to hang before dropping it - * @timeout: timeout value in jiffies for the scheduler - * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is - * used - * @score: optional score atomic shared with other schedulers - * @name: name used for debugging - * @dev: target &struct device + * @params: scheduler initialization parameters * * Return 0 on success, otherwise error code. */ int drm_sched_init(struct drm_gpu_scheduler *sched, - const struct drm_sched_backend_ops *ops, - struct workqueue_struct *submit_wq, - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, - long timeout, struct workqueue_struct *timeout_wq, - atomic_t *score, const char *name, struct device *dev) + const struct drm_sched_init_params *params) { int i; - sched->ops = ops; - sched->credit_limit = credit_limit; - sched->name = name; - sched->timeout = timeout; - sched->timeout_wq = timeout_wq ? : system_wq; - sched->hang_limit = hang_limit; - sched->score = score ? score : &sched->_score; - sched->dev = dev; + sched->ops = params->ops; + sched->credit_limit = params->credit_limit; + sched->name = params->name; + sched->timeout = params->timeout; + sched->timeout_wq = params->timeout_wq ? : system_wq; + sched->hang_limit = params->hang_limit; + sched->score = params->score ? params->score : &sched->_score; + sched->dev = params->dev; - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { + if (params->num_rqs > DRM_SCHED_PRIORITY_COUNT) { /* This is a gross violation--tell drivers what the problem is. */ drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n", @@ -1288,16 +1273,16 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, return 0; } - if (submit_wq) { - sched->submit_wq = submit_wq; + if (params->submit_wq) { + sched->submit_wq = params->submit_wq; sched->own_submit_wq = false; } else { #ifdef CONFIG_LOCKDEP - sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name, - WQ_MEM_RECLAIM, - &drm_sched_lockdep_map); + sched->submit_wq = alloc_ordered_workqueue_lockdep_map( + params->name, WQ_MEM_RECLAIM, + &drm_sched_lockdep_map); #else - sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM); + sched->submit_wq = alloc_ordered_workqueue(params->name, WQ_MEM_RECLAIM); #endif if (!sched->submit_wq) return -ENOMEM; @@ -1305,11 +1290,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, sched->own_submit_wq = true; } - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq), + sched->sched_rq = kmalloc_array(params->num_rqs, sizeof(*sched->sched_rq), GFP_KERNEL | __GFP_ZERO); if (!sched->sched_rq) goto Out_check_own; - sched->num_rqs = num_rqs; + sched->num_rqs = params->num_rqs; for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL); if (!sched->sched_rq[i]) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 99ac4995b5a1..716e6d074d87 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -814,67 +814,124 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { .free_job = v3d_cpu_job_free }; +/* + * v3d's scheduler instances are all identical, except for ops and name. + */ +static void +v3d_common_sched_init(struct drm_sched_init_params *params, struct device *dev) +{ + memset(params, 0, sizeof(struct drm_sched_init_params)); + + params->submit_wq = NULL; /* Use the system_wq. */ + params->num_rqs = DRM_SCHED_PRIORITY_COUNT; + params->credit_limit = 1; + params->hang_limit = 0; + params->timeout = msecs_to_jiffies(500); + params->timeout_wq = NULL; /* Use the system_wq. */ + params->score = NULL; + params->dev = dev; +} + +static int +v3d_bin_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_bin_sched_ops; + params.name = "v3d_bin"; + + return drm_sched_init(&v3d->queue[V3D_BIN].sched, ¶ms); +} + +static int +v3d_render_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_render_sched_ops; + params.name = "v3d_render"; + + return drm_sched_init(&v3d->queue[V3D_RENDER].sched, ¶ms); +} + +static int +v3d_tfu_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_tfu_sched_ops; + params.name = "v3d_tfu"; + + return drm_sched_init(&v3d->queue[V3D_TFU].sched, ¶ms); +} + +static int +v3d_csd_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_csd_sched_ops; + params.name = "v3d_csd"; + + return drm_sched_init(&v3d->queue[V3D_CSD].sched, ¶ms); +} + +static int +v3d_cache_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_cache_clean_sched_ops; + params.name = "v3d_cache_clean"; + + return drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, ¶ms); +} + +static int +v3d_cpu_sched_init(struct v3d_dev *v3d) +{ + struct drm_sched_init_params params; + + v3d_common_sched_init(¶ms, v3d->drm.dev); + params.ops = &v3d_cpu_sched_ops; + params.name = "v3d_cpu"; + + return drm_sched_init(&v3d->queue[V3D_CPU].sched, ¶ms); +} + int v3d_sched_init(struct v3d_dev *v3d) { - int hw_jobs_limit = 1; - int job_hang_limit = 0; - int hang_limit_ms = 500; int ret; - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, - &v3d_bin_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_bin", v3d->drm.dev); + ret = v3d_bin_sched_init(v3d); if (ret) return ret; - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, - &v3d_render_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_render", v3d->drm.dev); + ret = v3d_render_sched_init(v3d); if (ret) goto fail; - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, - &v3d_tfu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_tfu", v3d->drm.dev); + ret = v3d_tfu_sched_init(v3d); if (ret) goto fail; if (v3d_has_csd(v3d)) { - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, - &v3d_csd_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_csd", v3d->drm.dev); + ret = v3d_csd_sched_init(v3d); if (ret) goto fail; - ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, - &v3d_cache_clean_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_cache_clean", v3d->drm.dev); + ret = v3d_cache_sched_init(v3d); if (ret) goto fail; } - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, - &v3d_cpu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - 1, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_cpu", v3d->drm.dev); + ret = v3d_cpu_sched_init(v3d); if (ret) goto fail; diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index a8c416a48812..7f29b7f04af4 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -332,10 +332,13 @@ static const struct drm_sched_backend_ops drm_sched_ops = { static int execlist_exec_queue_init(struct xe_exec_queue *q) { struct drm_gpu_scheduler *sched; + struct drm_sched_init_params params; struct xe_execlist_exec_queue *exl; struct xe_device *xe = gt_to_xe(q->gt); int err; + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + xe_assert(xe, !xe_device_uc_enabled(xe)); drm_info(&xe->drm, "Enabling execlist submission (GuC submission disabled)\n"); @@ -346,11 +349,18 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q) exl->q = q; - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, - q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, - XE_SCHED_HANG_LIMIT, XE_SCHED_JOB_TIMEOUT, - NULL, NULL, q->hwe->name, - gt_to_xe(q->gt)->drm.dev); + params.ops = &drm_sched_ops; + params.submit_wq = NULL; /* Use the system_wq. */ + params.num_rqs = 1; + params.credit_limit = q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES; + params.hang_limit = XE_SCHED_HANG_LIMIT; + params.timeout = XE_SCHED_JOB_TIMEOUT; + params.timeout_wq = NULL; /* Use the system_wq. */ + params.score = NULL; + params.name = q->hwe->name; + params.dev = gt_to_xe(q->gt)->drm.dev; + + err = drm_sched_init(&exl->sched, ¶ms); if (err) goto err_free; diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c b/drivers/gpu/drm/xe/xe_gpu_scheduler.c index 50361b4638f9..2129fee83f25 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c @@ -63,13 +63,26 @@ int xe_sched_init(struct xe_gpu_scheduler *sched, atomic_t *score, const char *name, struct device *dev) { + struct drm_sched_init_params params; + sched->ops = xe_ops; INIT_LIST_HEAD(&sched->msgs); INIT_WORK(&sched->work_process_msg, xe_sched_process_msg_work); - return drm_sched_init(&sched->base, ops, submit_wq, 1, hw_submission, - hang_limit, timeout, timeout_wq, score, name, - dev); + memset(¶ms, 0, sizeof(struct drm_sched_init_params)); + + params.ops = ops; + params.submit_wq = submit_wq; + params.num_rqs = 1; + params.credit_limit = hw_submission; + params.hang_limit = hang_limit; + params.timeout = timeout; + params.timeout_wq = timeout_wq; + params.score = score; + params.name = name; + params.dev = dev; + + return drm_sched_init(&sched->base, ¶ms); } void xe_sched_fini(struct xe_gpu_scheduler *sched) diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 95e17504e46a..1a834ef43862 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -553,12 +553,37 @@ struct drm_gpu_scheduler { struct device *dev; }; +/** + * struct drm_sched_init_params - parameters for initializing a DRM GPU scheduler + * + * @ops: backend operations provided by the driver + * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is + * allocated and used + * @num_rqs: Number of run-queues. This is at most DRM_SCHED_PRIORITY_COUNT, + * as there's usually one run-queue per priority, but could be less. + * @credit_limit: the number of credits this scheduler can hold from all jobs + * @hang_limit: number of times to allow a job to hang before dropping it + * @timeout: timeout value in jiffies for the scheduler + * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is + * used + * @score: optional score atomic shared with other schedulers + * @name: name used for debugging + * @dev: associated device. Used for debugging + */ +struct drm_sched_init_params { + const struct drm_sched_backend_ops *ops; + struct workqueue_struct *submit_wq; + struct workqueue_struct *timeout_wq; + u32 num_rqs, credit_limit; + unsigned int hang_limit; + long timeout; + atomic_t *score; + const char *name; + struct device *dev; +}; + int drm_sched_init(struct drm_gpu_scheduler *sched, - const struct drm_sched_backend_ops *ops, - struct workqueue_struct *submit_wq, - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, - long timeout, struct workqueue_struct *timeout_wq, - atomic_t *score, const char *name, struct device *dev); + const struct drm_sched_init_params *params); void drm_sched_fini(struct drm_gpu_scheduler *sched); int drm_sched_job_init(struct drm_sched_job *job,
drm_sched_init() has a great many parameters and upcoming new functionality for the scheduler might add even more. Generally, the great number of parameters reduces readability and has already caused one missnaming in: commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in nouveau_sched_init()"). Introduce a new struct for the scheduler init parameters and port all users. Signed-off-by: Philipp Stanner <phasta@kernel.org> --- Howdy, I have a patch-series in the pipe that will add a `flags` argument to drm_sched_init(). I thought it would be wise to first rework the API as detailed in this patch. It's really a lot of parameters by now, and I would expect that it might get more and more over the years for special use cases etc. Regards, P. --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 +++- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 ++- drivers/gpu/drm/imagination/pvr_queue.c | 21 +++- drivers/gpu/drm/lima/lima_sched.c | 21 +++- drivers/gpu/drm/msm/msm_ringbuffer.c | 22 ++-- drivers/gpu/drm/nouveau/nouveau_sched.c | 20 ++- drivers/gpu/drm/panfrost/panfrost_job.c | 22 ++-- drivers/gpu/drm/panthor/panthor_mmu.c | 18 ++- drivers/gpu/drm/panthor/panthor_sched.c | 23 ++-- drivers/gpu/drm/scheduler/sched_main.c | 53 +++----- drivers/gpu/drm/v3d/v3d_sched.c | 135 +++++++++++++++------ drivers/gpu/drm/xe/xe_execlist.c | 20 ++- drivers/gpu/drm/xe/xe_gpu_scheduler.c | 19 ++- include/drm/gpu_scheduler.h | 35 +++++- 14 files changed, 311 insertions(+), 139 deletions(-)