diff mbox

[3/3] drm/tilcdc: Add mutex to protect crtc enable and disable routines

Message ID e8921dc7096d0b9b336e9a1956d3d634801e56ac.1473148345.git.jsarha@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jyri Sarha Sept. 6, 2016, 8:19 a.m. UTC
Add mutex to protect crtc enable and disable routines. The
tilcdc_crtc_disable() function waits for frame done interrupt, the
internal data will get out of sync, should another enable arrive while
waiting for the interrupt.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Tomi Valkeinen Sept. 6, 2016, 9:30 a.m. UTC | #1
On 06/09/16 11:19, Jyri Sarha wrote:
> Add mutex to protect crtc enable and disable routines. The
> tilcdc_crtc_disable() function waits for frame done interrupt, the
> internal data will get out of sync, should another enable arrive while
> waiting for the interrupt.

Why doesn't the per-crtc modeset lock work for this?

 Tomi
Jyri Sarha Sept. 6, 2016, 12:09 p.m. UTC | #2
On 09/06/16 12:30, Tomi Valkeinen wrote:
> On 06/09/16 11:19, Jyri Sarha wrote:
>> Add mutex to protect crtc enable and disable routines. The
>> tilcdc_crtc_disable() function waits for frame done interrupt, the
>> internal data will get out of sync, should another enable arrive while
>> waiting for the interrupt.
> 
> Why doesn't the per-crtc modeset lock work for this?
> 

I am not worried about DRM enabling and disabling the crtc, it should
take the locks it needs on its own, and AFAIU the driver should not try
take the same locks again.

The purpose of these locks is to protect underneath workings the LCDC
driver reacting to something happening outside the DRM, like CPU
frequency change or module unloading.

I considered dropping this patch already last night (it was my first
attempt to fix the race, and it worked too), but then decided to put it
under review just for the sake of argument ;).

All in all it should be enough to take all the necessary DRM locks when
fiddling with lcdc hw and not to implement any extra layers of locking.

I'll drop this patch.

BR,
Jyri
diff mbox

Patch

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index f9e3da9..ac0a63e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -31,6 +31,7 @@  struct tilcdc_crtc {
 	const struct tilcdc_panel_info *info;
 	struct drm_pending_vblank_event *event;
 	bool enabled;
+	struct mutex enable_lock;
 	wait_queue_head_t frame_done_wq;
 	bool frame_done;
 	spinlock_t irq_lock;
@@ -153,8 +154,10 @@  static void tilcdc_crtc_enable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 
+	mutex_lock(&tilcdc_crtc->enable_lock);
+
 	if (tilcdc_crtc->enabled)
-		return;
+		goto out;
 
 	pm_runtime_get_sync(dev->dev);
 
@@ -169,6 +172,8 @@  static void tilcdc_crtc_enable(struct drm_crtc *crtc)
 	drm_crtc_vblank_on(crtc);
 
 	tilcdc_crtc->enabled = true;
+out:
+	mutex_unlock(&tilcdc_crtc->enable_lock);
 }
 
 void tilcdc_crtc_disable(struct drm_crtc *crtc)
@@ -177,8 +182,10 @@  void tilcdc_crtc_disable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_drm_private *priv = dev->dev_private;
 
+	mutex_lock(&tilcdc_crtc->enable_lock);
+
 	if (!tilcdc_crtc->enabled)
-		return;
+		goto out;
 
 	tilcdc_crtc->frame_done = false;
 	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
@@ -218,6 +225,8 @@  void tilcdc_crtc_disable(struct drm_crtc *crtc)
 	tilcdc_crtc->last_vblank = ktime_set(0, 0);
 
 	tilcdc_crtc->enabled = false;
+out:
+	mutex_unlock(&tilcdc_crtc->enable_lock);
 }
 
 static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
@@ -819,6 +828,8 @@  struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 	drm_flip_work_init(&tilcdc_crtc->unref_work,
 			"unref", unref_worker);
 
+	mutex_init(&tilcdc_crtc->enable_lock);
+
 	spin_lock_init(&tilcdc_crtc->irq_lock);
 	INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);