diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2013-09-16 12:52:37 +0200 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2013-09-17 08:45:21 +0200 |
commit | 67cc74905799e26d884894d1d29807cdb7a49166 (patch) | |
tree | 154d7249154ff3940ff673a231d3fa25ffe4557b /drivers/gpu/drm | |
parent | 5c5c7a90f086aac3f514f80c34e44f80fc32047f (diff) | |
download | linux-67cc74905799e26d884894d1d29807cdb7a49166.tar.gz linux-67cc74905799e26d884894d1d29807cdb7a49166.tar.xz |
WIP: push down hangcheck into adreno_gpu
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.h | 11 |
6 files changed, 74 insertions, 71 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 2483a6b9225f..386993aec7e2 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -379,8 +379,8 @@ static const struct adreno_gpu_funcs funcs = { #endif }; -struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, - struct adreno_gem *gem) +struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, struct adreno_gem *gem, + struct workqueue_struct *wq) { struct adreno_gpu *adreno_gpu = NULL; struct msm_gpu *gpu; @@ -414,7 +414,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, gpu->fast_rate, gpu->slow_rate, gpu->bus_freq); ret = adreno_gpu_init(dev, pdev, adreno_gpu, - &funcs, gem, config->rev); + &funcs, gem, wq, config->rev); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index c0bf75b47ef6..5e10446f7798 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -60,6 +60,50 @@ const char *adreno_get_name(struct adreno_gpu *gpu) return gpu->info->name; } +/* + * Hangcheck detection for locked gpu: + */ + +static void recover_worker(struct work_struct *work) +{ + struct adreno_gpu *gpu = container_of(work, struct adreno_gpu, recover_work); + struct drm_device *dev = gpu->drm; + + dev_err(dev->dev, "%s: hangcheck recover!\n", adreno_get_name(gpu)); + + mutex_lock(&dev->struct_mutex); + gpu->funcs->recover(gpu); + mutex_unlock(&dev->struct_mutex); + + gpu->gem->gem_retire(gpu->gem->priv); +} + +static void hangcheck_timer_reset(struct adreno_gpu *gpu) +{ + DBG("%s", adreno_get_name(gpu)); + mod_timer(&gpu->hangcheck_timer, + round_jiffies_up(jiffies + DRM_MSM_HANGCHECK_JIFFIES)); +} + +static void hangcheck_handler(unsigned long data) +{ + struct adreno_gpu *gpu = (struct adreno_gpu *)data; + uint32_t fence = gpu->funcs->last_fence(gpu); + + if (fence != gpu->hangcheck_fence) { + /* some progress has been made.. ya! */ + gpu->hangcheck_fence = fence; + } else if (fence < gpu->submitted_fence) { + /* no progress and not done.. hung! */ + gpu->hangcheck_fence = fence; + queue_work(gpu->shared_wq, &gpu->recover_work); + } + + /* if still more pending work, reset the hangcheck timer: */ + if (gpu->submitted_fence > gpu->hangcheck_fence) + hangcheck_timer_reset(gpu); +} + int adreno_get_param(struct adreno_gpu *gpu, uint32_t param, uint64_t *value) { switch (param) { @@ -120,7 +164,7 @@ void adreno_recover(struct adreno_gpu *gpu) gpu->rb->cur = gpu->rb->start; /* reset completed fence seqno, just discard anything pending: */ - gpu->memptrs->fence = gpu->base.submitted_fence; + gpu->memptrs->fence = gpu->submitted_fence; gpu->funcs->pm_resume(gpu); ret = gpu->funcs->hw_init(gpu); @@ -196,6 +240,9 @@ int adreno_submit(struct adreno_gpu *gpu, struct adreno_submit *submit, gpu->funcs->flush(gpu); + gpu->submitted_fence = submit->fence; + hangcheck_timer_reset(gpu); + return 0; } @@ -238,7 +285,7 @@ void adreno_show(struct adreno_gpu *gpu, struct seq_file *m) gpu->rev.patchid); seq_printf(m, "fence: %d/%d\n", gpu->memptrs->fence, - gpu->base.submitted_fence); + gpu->submitted_fence); seq_printf(m, "rptr: %d\n", gpu->memptrs->rptr); seq_printf(m, "wptr: %d\n", gpu->memptrs->wptr); seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb)); @@ -268,7 +315,8 @@ static inline bool _rev_match(uint8_t entry, uint8_t id) int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, - struct adreno_gem *gem, struct adreno_rev rev) + struct adreno_gem *gem, struct workqueue_struct *wq, + struct adreno_rev rev) { int i, ret; @@ -297,6 +345,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->drm = drm; gpu->funcs = funcs; gpu->gem = gem; + gpu->shared_wq = wq; gpu->rev = rev; /* XXX: urgh - pointers to self are fun! */ @@ -368,6 +417,10 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, return ret; } + INIT_WORK(&gpu->recover_work, recover_worker); + setup_timer(&gpu->hangcheck_timer, hangcheck_handler, + (unsigned long)gpu); + return 0; } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 8d7f26e7d950..a7fe0e5e0c62 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -54,6 +54,7 @@ struct adreno_gpu { uint32_t revn; /* numeric revision name */ const struct adreno_gpu_funcs *funcs; struct adreno_gem *gem; + struct workqueue_struct *shared_wq; /* firmware: */ const struct firmware *pm4, *pfp; @@ -65,10 +66,19 @@ struct adreno_gpu { struct drm_gem_object *memptrs_bo; uint32_t memptrs_iova; + uint32_t submitted_fence; + struct adreno_ringbuffer *rb; uint32_t rb_iova; struct adreno_context *lastctx; + + /* Hang Detction: */ +#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */ +#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD) + struct timer_list hangcheck_timer; + uint32_t hangcheck_fence; + struct work_struct recover_work; }; #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base) @@ -115,7 +125,8 @@ void adreno_wait_ring(struct adreno_gpu *gpu, uint32_t ndwords); int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, - struct adreno_gem *gem, struct adreno_rev rev); + struct adreno_gem *gem, struct workqueue_struct *wq, + struct adreno_rev rev); void adreno_gpu_cleanup(struct adreno_gpu *gpu); static inline void gpu_write(struct adreno_gpu *gpu, u32 reg, u32 data) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 9f3c45c95f13..a4db194c57e9 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -315,7 +315,7 @@ static void load_gpu(struct drm_device *dev) return; mutex_lock(&dev->struct_mutex); - gpu = a3xx_gpu_init(dev, &msm_gem_funcs); + gpu = a3xx_gpu_init(dev, &msm_gem_funcs, priv->wq); if (IS_ERR(gpu)) { dev_warn(dev->dev, "failed to load a3xx gpu\n"); gpu = NULL; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 96214168c91c..a18646503ecc 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -203,52 +203,6 @@ int msm_gpu_pm_suspend(struct adreno_gpu *gpu) } /* - * Hangcheck detection for locked gpu: - */ - -static void recover_worker(struct work_struct *work) -{ - struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); - struct drm_device *dev = gpu->dev; - - dev_err(dev->dev, "%s: hangcheck recover!\n", - adreno_get_name(gpu->gpu)); - - mutex_lock(&dev->struct_mutex); - gpu->funcs->recover(gpu->gpu); - mutex_unlock(&dev->struct_mutex); - - msm_gpu_retire(gpu); -} - -static void hangcheck_timer_reset(struct msm_gpu *gpu) -{ - DBG("%s", adreno_get_name(gpu->gpu)); - mod_timer(&gpu->hangcheck_timer, - round_jiffies_up(jiffies + DRM_MSM_HANGCHECK_JIFFIES)); -} - -static void hangcheck_handler(unsigned long data) -{ - struct msm_gpu *gpu = (struct msm_gpu *)data; - uint32_t fence = gpu->funcs->last_fence(gpu->gpu); - - if (fence != gpu->hangcheck_fence) { - /* some progress has been made.. ya! */ - gpu->hangcheck_fence = fence; - } else if (fence < gpu->submitted_fence) { - /* no progress and not done.. hung! */ - struct msm_drm_private *priv = gpu->dev->dev_private; - gpu->hangcheck_fence = fence; - queue_work(priv->wq, &gpu->recover_work); - } - - /* if still more pending work, reset the hangcheck timer: */ - if (gpu->submitted_fence > gpu->hangcheck_fence) - hangcheck_timer_reset(gpu); -} - -/* * Cmdstream submission/retirement: */ @@ -300,8 +254,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, submit->base.fence = ++priv->next_fence; - gpu->submitted_fence = submit->base.fence; - ret = gpu->funcs->submit(gpu->gpu, &submit->base, &filp->ctx); for (i = 0; i < submit->nr_bos; i++) { @@ -323,7 +275,7 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, msm_gem_move_to_active(&msm_obj->base, gpu, submit->base.fence); } - hangcheck_timer_reset(gpu); + mutex_unlock(&dev->struct_mutex); return ret; @@ -354,10 +306,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, INIT_LIST_HEAD(&gpu->active_list); INIT_WORK(&gpu->retire_work, retire_worker); - INIT_WORK(&gpu->recover_work, recover_worker); - - setup_timer(&gpu->hangcheck_timer, hangcheck_handler, - (unsigned long)gpu); BUG_ON(ARRAY_SIZE(clk_names) != ARRAY_SIZE(gpu->grp_clks)); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 2dc686e05c54..35e45b865e44 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -46,8 +46,6 @@ struct msm_gpu { /* list of GEM active objects: */ struct list_head active_list; - uint32_t submitted_fence; - /* worker for handling active-list retiring: */ struct work_struct retire_work; @@ -62,13 +60,6 @@ struct msm_gpu { struct clk *ebi1_clk, *grp_clks[5]; uint32_t fast_rate, slow_rate, bus_freq; uint32_t bsc; - - /* Hang Detction: */ -#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */ -#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD) - struct timer_list hangcheck_timer; - uint32_t hangcheck_fence; - struct work_struct recover_work; }; int msm_gpu_pm_suspend(struct adreno_gpu *gpu); @@ -85,7 +76,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, void msm_gpu_cleanup(struct msm_gpu *gpu); struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, - struct adreno_gem *gem); + struct adreno_gem *gem, struct workqueue_struct *wq); void __init a3xx_register(void); void __exit a3xx_unregister(void); |