summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c23
3 files changed, 22 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 2771d155587a..9facd4b6ffd9 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -86,6 +86,7 @@ struct msm_gem_submit {
struct list_head bo_list;
struct ww_acquire_ctx ticket;
struct fence *fence;
+ struct pid *pid; /* submitting process */
bool valid; /* true if no cmdstream patching needed */
unsigned int nr_cmds;
unsigned int nr_bos;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 711a658cf1ea..a9a001150b9e 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -45,6 +45,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
submit->dev = dev;
submit->gpu = gpu;
+ submit->pid = get_pid(task_pid(current));
/* initially, until copy_from_user() and bo lookup succeeds: */
submit->nr_bos = 0;
@@ -60,6 +61,7 @@ void msm_gem_submit_free(struct msm_gem_submit *submit)
{
fence_put(submit->fence);
list_del(&submit->node);
+ put_pid(submit->pid);
kfree(submit);
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 5aed93a87e4c..36ed53e661fe 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -272,16 +272,30 @@ 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;
+ struct msm_gem_submit *submit;
uint32_t fence = gpu->funcs->last_fence(gpu);
- dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
-
msm_update_fence(gpu->fctx, fence + 1);
mutex_lock(&dev->struct_mutex);
- if (msm_gpu_active(gpu)) {
- struct msm_gem_submit *submit;
+ dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
+ list_for_each_entry(submit, &gpu->submit_list, node) {
+ if (submit->fence->seqno == (fence + 1)) {
+ struct task_struct *task;
+
+ rcu_read_lock();
+ task = pid_task(submit->pid, PIDTYPE_PID);
+ if (task) {
+ dev_err(dev->dev, "%s: offending task: %s\n",
+ gpu->name, task->comm);
+ }
+ rcu_read_unlock();
+ break;
+ }
+ }
+
+ if (msm_gpu_active(gpu)) {
/* retire completed submits, plus the one that hung: */
retire_submits(gpu);
@@ -293,6 +307,7 @@ static void recover_worker(struct work_struct *work)
gpu->funcs->submit(gpu, submit, NULL);
}
}
+
mutex_unlock(&dev->struct_mutex);
msm_gpu_retire(gpu);