diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2017-12-04 18:41:58 +0100 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2018-02-12 16:30:59 +0100 |
commit | e93b6deeb45a781489f4ceaa97f9545a3cbebb81 (patch) | |
tree | 82b760c0285f254b0fa73999f9da3230cdad2266 /drivers/gpu/drm/etnaviv/etnaviv_sched.c | |
parent | drm/etnaviv: track fences by IDR instead of seqno (diff) | |
download | linux-e93b6deeb45a781489f4ceaa97f9545a3cbebb81.tar.xz linux-e93b6deeb45a781489f4ceaa97f9545a3cbebb81.zip |
drm/etnaviv: hook up DRM GPU scheduler
This hooks in the DRM GPU scheduler. No improvement yet, as all the
dependency handling is still done in etnaviv_gem_submit. This just
replaces the actual GPU submit by passing through the scheduler.
Allows to get rid of the retire worker, as this is now driven by the
scheduler.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_sched.c')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_sched.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c new file mode 100644 index 000000000000..143c3eca80b0 --- /dev/null +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2017 Etnaviv Project + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <drm/gpu_scheduler.h> +#include <linux/kthread.h> + +#include "etnaviv_drv.h" +#include "etnaviv_gem.h" +#include "etnaviv_gpu.h" + +static int etnaviv_job_hang_limit = 0; +module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444); +static int etnaviv_hw_jobs_limit = 2; +module_param_named(hw_job_limit, etnaviv_hw_jobs_limit, int , 0444); + +static inline +struct etnaviv_gem_submit *to_etnaviv_submit(struct drm_sched_job *sched_job) +{ + return container_of(sched_job, struct etnaviv_gem_submit, sched_job); +} + +struct dma_fence *etnaviv_sched_dependency(struct drm_sched_job *sched_job, + struct drm_sched_entity *entity) +{ + return NULL; +} + +struct dma_fence *etnaviv_sched_run_job(struct drm_sched_job *sched_job) +{ + struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); + struct dma_fence *fence; + + mutex_lock(&submit->gpu->lock); + list_add_tail(&submit->node, &submit->gpu->active_submit_list); + mutex_unlock(&submit->gpu->lock); + + fence = etnaviv_gpu_submit(submit); + if (!fence) { + etnaviv_submit_put(submit); + return NULL; + } + + return fence; +} + +static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) +{ + /* this replaces the hangcheck */ +} + +static void etnaviv_sched_free_job(struct drm_sched_job *sched_job) +{ + struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); + + mutex_lock(&submit->gpu->lock); + list_del(&submit->node); + mutex_unlock(&submit->gpu->lock); + + etnaviv_submit_put(submit); +} + +static const struct drm_sched_backend_ops etnaviv_sched_ops = { + .dependency = etnaviv_sched_dependency, + .run_job = etnaviv_sched_run_job, + .timedout_job = etnaviv_sched_timedout_job, + .free_job = etnaviv_sched_free_job, +}; + +int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity, + struct etnaviv_gem_submit *submit) +{ + int ret; + + ret = drm_sched_job_init(&submit->sched_job, &submit->gpu->sched, + sched_entity, submit->cmdbuf.ctx); + if (ret) + return ret; + + submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished); + mutex_lock(&submit->gpu->fence_idr_lock); + submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr, + submit->out_fence, 0, + INT_MAX, GFP_KERNEL); + mutex_unlock(&submit->gpu->fence_idr_lock); + if (submit->out_fence_id < 0) + return -ENOMEM; + + /* the scheduler holds on to the job now */ + kref_get(&submit->refcount); + + drm_sched_entity_push_job(&submit->sched_job, sched_entity); + + return 0; +} + +int etnaviv_sched_init(struct etnaviv_gpu *gpu) +{ + int ret; + + ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, + etnaviv_hw_jobs_limit, etnaviv_job_hang_limit, + msecs_to_jiffies(500), dev_name(gpu->dev)); + if (ret) + return ret; + + return 0; +} + +void etnaviv_sched_fini(struct etnaviv_gpu *gpu) +{ + drm_sched_fini(&gpu->sched); +} |