summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2013-09-16 12:52:37 +0200
committerLucas Stach <l.stach@pengutronix.de>2013-09-17 08:45:21 +0200
commit67cc74905799e26d884894d1d29807cdb7a49166 (patch)
tree154d7249154ff3940ff673a231d3fa25ffe4557b
parent5c5c7a90f086aac3f514f80c34e44f80fc32047f (diff)
downloadlinux-67cc74905799e26d884894d1d29807cdb7a49166.tar.gz
WIP: push down hangcheck into adreno_gpu
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c59
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h13
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c54
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h11
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 2483a6b..386993ae 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 c0bf75b..5e10446 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 8d7f26e..a7fe0e5 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 9f3c45c..a4db194 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 9621416..a186465 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 2dc686e..35e45b8 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);