diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 52 | 
1 files changed, 48 insertions, 4 deletions
| diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4a0dce587745..8f70d9248ac5 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -24,7 +24,7 @@   * Power Management:   */ -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING  #include <mach/board.h>  static void bs_init(struct msm_gpu *gpu)  { @@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu)   * Hangcheck detection for locked gpu:   */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence); +  static void recover_worker(struct work_struct *work)  {  	struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); @@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work)  	mutex_lock(&dev->struct_mutex);  	if (msm_gpu_active(gpu)) { +		struct msm_gem_submit *submit; +		uint32_t fence = gpu->funcs->last_fence(gpu); + +		/* retire completed submits, plus the one that hung: */ +		retire_submits(gpu, fence + 1); +  		inactive_cancel(gpu);  		gpu->funcs->recover(gpu); + +		/* replay the remaining submits after the one that hung: */ +		list_for_each_entry(submit, &gpu->submit_list, node) { +			gpu->funcs->submit(gpu, submit, NULL); +		}  	}  	mutex_unlock(&dev->struct_mutex); @@ -418,6 +431,27 @@ out:   * Cmdstream submission/retirement:   */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence) +{ +	struct drm_device *dev = gpu->dev; + +	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + +	while (!list_empty(&gpu->submit_list)) { +		struct msm_gem_submit *submit; + +		submit = list_first_entry(&gpu->submit_list, +				struct msm_gem_submit, node); + +		if (submit->fence <= fence) { +			list_del(&submit->node); +			kfree(submit); +		} else { +			break; +		} +	} +} +  static void retire_worker(struct work_struct *work)  {  	struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work); @@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work)  	mutex_lock(&dev->struct_mutex); +	retire_submits(gpu, fence); +  	while (!list_empty(&gpu->active_list)) {  		struct msm_gem_object *obj; @@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,  	struct msm_drm_private *priv = dev->dev_private;  	int i, ret; +	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); +  	submit->fence = ++priv->next_fence;  	gpu->submitted_fence = submit->fence;  	inactive_cancel(gpu); +	list_add_tail(&submit->node, &gpu->submit_list); +  	msm_rd_dump_submit(submit);  	gpu->submitted_fence = submit->fence;  	update_sw_cntrs(gpu); -	ret = gpu->funcs->submit(gpu, submit, ctx); -	priv->lastctx = ctx; -  	for (i = 0; i < submit->nr_bos; i++) {  		struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,  		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)  			msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);  	} + +	ret = gpu->funcs->submit(gpu, submit, ctx); +	priv->lastctx = ctx; +  	hangcheck_timer_reset(gpu);  	return ret; @@ -522,6 +563,7 @@ static irqreturn_t irq_handler(int irq, void *data)  static const char *clk_names[] = {  		"src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk", +		"alt_mem_iface_clk",  };  int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, @@ -544,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	INIT_WORK(&gpu->inactive_work, inactive_worker);  	INIT_WORK(&gpu->recover_work, recover_worker); +	INIT_LIST_HEAD(&gpu->submit_list); +  	setup_timer(&gpu->inactive_timer, inactive_handler,  			(unsigned long)gpu);  	setup_timer(&gpu->hangcheck_timer, hangcheck_handler, | 
