diff options
Diffstat (limited to 'drivers/gpu/drm/msm')
| -rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_device.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu_devfreq.c | 21 | 
10 files changed, 70 insertions, 11 deletions
| diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 51b83776951b..17cfad6424db 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1560,6 +1560,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)  		for (i = 0; i < gpu->nr_rings; i++)  			a6xx_gpu->shadow[i] = 0; +	gpu->suspend_count++; +  	return 0;  } diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 93005839b5da..fb261930ad1c 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -608,9 +608,27 @@ static int adreno_resume(struct device *dev)  	return gpu->funcs->pm_resume(gpu);  } +static int active_submits(struct msm_gpu *gpu) +{ +	int active_submits; +	mutex_lock(&gpu->active_lock); +	active_submits = gpu->active_submits; +	mutex_unlock(&gpu->active_lock); +	return active_submits; +} +  static int adreno_suspend(struct device *dev)  {  	struct msm_gpu *gpu = dev_to_gpu(dev); +	int remaining; + +	remaining = wait_event_timeout(gpu->retire_event, +				       active_submits(gpu) == 0, +				       msecs_to_jiffies(1000)); +	if (remaining == 0) { +		dev_err(dev, "Timeout waiting for GPU to suspend\n"); +		return -EBUSY; +	}  	return gpu->funcs->pm_suspend(gpu);  } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index a98e964c3b6f..355894a3b48c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -26,9 +26,16 @@ static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,  		struct dpu_hw_pcc_cfg *cfg)  { -	u32 base = ctx->cap->sblk->pcc.base; +	u32 base; -	if (!ctx || !base) { +	if (!ctx) { +		DRM_ERROR("invalid ctx %pK\n", ctx); +		return; +	} + +	base = ctx->cap->sblk->pcc.base; + +	if (!base) {  		DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);  		return;  	} diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 052548883d27..0fe02529b5e7 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -40,7 +40,12 @@ static int dsi_get_phy(struct msm_dsi *msm_dsi)  	of_node_put(phy_node); -	if (!phy_pdev || !msm_dsi->phy) { +	if (!phy_pdev) { +		DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__); +		return -EPROBE_DEFER; +	} +	if (!msm_dsi->phy) { +		put_device(&phy_pdev->dev);  		DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__);  		return -EPROBE_DEFER;  	} diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index c2ed177717c7..2027b38617ab 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -808,12 +808,14 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy,  			struct msm_dsi_phy_clk_request *clk_req,  			struct msm_dsi_phy_shared_timings *shared_timings)  { -	struct device *dev = &phy->pdev->dev; +	struct device *dev;  	int ret;  	if (!phy || !phy->cfg->ops.enable)  		return -EINVAL; +	dev = &phy->pdev->dev; +  	ret = dsi_phy_enable_resource(phy);  	if (ret) {  		DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n", diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 3acdeae25caf..719720709e9e 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -97,10 +97,15 @@ static int msm_hdmi_get_phy(struct hdmi *hdmi)  	of_node_put(phy_node); -	if (!phy_pdev || !hdmi->phy) { +	if (!phy_pdev) {  		DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");  		return -EPROBE_DEFER;  	} +	if (!hdmi->phy) { +		DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n"); +		put_device(&phy_pdev->dev); +		return -EPROBE_DEFER; +	}  	hdmi->phy_dev = get_device(&phy_pdev->dev); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index ad35a5d94053..555666e3f960 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -461,7 +461,7 @@ static int msm_init_vram(struct drm_device *dev)  		of_node_put(node);  		if (ret)  			return ret; -		size = r.end - r.start; +		size = r.end - r.start + 1;  		DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start);  		/* if we have no IOMMU, then we need to use carveout allocator. @@ -510,7 +510,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)  	struct msm_drm_private *priv = dev_get_drvdata(dev);  	struct drm_device *ddev;  	struct msm_kms *kms; -	struct msm_mdss *mdss;  	int ret, i;  	ddev = drm_dev_alloc(drv, dev); @@ -521,8 +520,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)  	ddev->dev_private = priv;  	priv->dev = ddev; -	mdss = priv->mdss; -  	priv->wq = alloc_ordered_workqueue("msm", 0);  	priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 0f78c2615272..2c1049c0ea14 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -703,6 +703,8 @@ static void retire_submits(struct msm_gpu *gpu)  			}  		}  	} + +	wake_up_all(&gpu->retire_event);  }  static void retire_worker(struct kthread_work *work) @@ -848,6 +850,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	INIT_LIST_HEAD(&gpu->active_list);  	mutex_init(&gpu->active_lock);  	mutex_init(&gpu->lock); +	init_waitqueue_head(&gpu->retire_event);  	kthread_init_work(&gpu->retire_work, retire_worker);  	kthread_init_work(&gpu->recover_work, recover_worker);  	kthread_init_work(&gpu->fault_work, fault_worker); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 445c6bfd4b6b..92aa1e9196c6 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -230,6 +230,9 @@ struct msm_gpu {  	/* work for handling GPU recovery: */  	struct kthread_work recover_work; +	/** retire_event: notified when submits are retired: */ +	wait_queue_head_t retire_event; +  	/* work for handling active-list retiring: */  	struct kthread_work retire_work; diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 62405e980925..9bf319be11f6 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -133,6 +133,18 @@ void msm_devfreq_init(struct msm_gpu *gpu)  			      CLOCK_MONOTONIC, HRTIMER_MODE_REL);  } +static void cancel_idle_work(struct msm_gpu_devfreq *df) +{ +	hrtimer_cancel(&df->idle_work.timer); +	kthread_cancel_work_sync(&df->idle_work.work); +} + +static void cancel_boost_work(struct msm_gpu_devfreq *df) +{ +	hrtimer_cancel(&df->boost_work.timer); +	kthread_cancel_work_sync(&df->boost_work.work); +} +  void msm_devfreq_cleanup(struct msm_gpu *gpu)  {  	struct msm_gpu_devfreq *df = &gpu->devfreq; @@ -152,7 +164,12 @@ void msm_devfreq_resume(struct msm_gpu *gpu)  void msm_devfreq_suspend(struct msm_gpu *gpu)  { -	devfreq_suspend_device(gpu->devfreq.devfreq); +	struct msm_gpu_devfreq *df = &gpu->devfreq; + +	devfreq_suspend_device(df->devfreq); + +	cancel_idle_work(df); +	cancel_boost_work(df);  }  static void msm_devfreq_boost_work(struct kthread_work *work) @@ -196,7 +213,7 @@ void msm_devfreq_active(struct msm_gpu *gpu)  	/*  	 * Cancel any pending transition to idle frequency:  	 */ -	hrtimer_cancel(&df->idle_work.timer); +	cancel_idle_work(df);  	idle_time = ktime_to_ms(ktime_sub(ktime_get(), df->idle_time)); |