summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/etnaviv/etnaviv_sched.c
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2017-12-06 10:53:27 +0100
committerLucas Stach <l.stach@pengutronix.de>2018-02-12 16:31:01 +0100
commit6d7a20c0776036115c6e22bc673d645d524c4b8a (patch)
tree133109c3465b8db06286f8c7a24a24e6e291c3e7 /drivers/gpu/drm/etnaviv/etnaviv_sched.c
parente0580254ae5c70f9fad3e24c20b92287ad817d8e (diff)
downloadlinux-6d7a20c0776036115c6e22bc673d645d524c4b8a.tar.gz
linux-6d7a20c0776036115c6e22bc673d645d524c4b8a.tar.xz
drm/etnaviv: replace hangcheck with scheduler timeout
This replaces the etnaviv internal hangcheck logic with the job timeout handling provided by the DRM scheduler. This simplifies the driver further and allows to replay jobs after a GPU reset, so only minimal state is lost. This introduces a user-visible change in that we don't allow jobs to run indefinitely as long as they make progress anymore, as this introduces quality of service issues when multiple processes are using the GPU. Userspace is now responsible to flush jobs in a way that the finish in a reasonable time, where reasonable is currently defined as less than 500ms. 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.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 26e139786c7a..3e334735ac17 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -14,24 +14,19 @@
* 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_dump.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
+#include "etnaviv_sched.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)
{
@@ -86,34 +81,38 @@ struct dma_fence *etnaviv_sched_dependency(struct drm_sched_job *sched_job,
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);
+ struct dma_fence *fence = NULL;
- fence = etnaviv_gpu_submit(submit);
- if (!fence) {
- etnaviv_submit_put(submit);
- return NULL;
- }
+ if (likely(!sched_job->s_fence->finished.error))
+ fence = etnaviv_gpu_submit(submit);
+ else
+ dev_dbg(submit->gpu->dev, "skipping bad job\n");
return fence;
}
static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
{
- /* this replaces the hangcheck */
+ struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
+ struct etnaviv_gpu *gpu = submit->gpu;
+
+ /* block scheduler */
+ kthread_park(gpu->sched.thread);
+ drm_sched_hw_job_reset(&gpu->sched, sched_job);
+
+ /* get the GPU back into the init state */
+ etnaviv_core_dump(gpu);
+ etnaviv_gpu_recover_hang(gpu);
+
+ /* restart scheduler after GPU is usable again */
+ drm_sched_job_recovery(&gpu->sched);
+ kthread_unpark(gpu->sched.thread);
}
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);
}