[PATCH v2] [media] dvb-frontends/stv0910: prevent consecutive mutex_unlock()'s

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Daniel Scheller <d.scheller@xxxxxxx>

When calling gate_ctrl() with enable=0 if previously the mutex wasn't
locked (ie. on enable=1 failure and subdrivers not handling this properly,
or by otherwise badly behaving drivers), the i2c_lock could be unlocked
consecutively which isn't allowed. Prevent this by checking the lock
state, and actually call mutex_unlock() only when certain the lock
is actually held.

Signed-off-by: Daniel Scheller <d.scheller@xxxxxxx>
Tested-by: Jasmin Jessich <jasmin@xxxxxx>
Cc: Ralph Metzler <rjkm@xxxxxxxxxxxxxx>
---
Changes from v1 to v2:
 - use mutex_is_locked() instead of tracking the lock state in a separate
   variable
 - print message to KERN_DEBUG after a double unlock was prevented

 drivers/media/dvb-frontends/stv0910.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c
index 73f6df0abbfe..5d0146782488 100644
--- a/drivers/media/dvb-frontends/stv0910.c
+++ b/drivers/media/dvb-frontends/stv0910.c
@@ -1240,8 +1240,17 @@ static int gate_ctrl(struct dvb_frontend *fe, int enable)
 
 	if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT :
 		      RSTV0910_P1_I2CRPT, i2crpt) < 0) {
-		/* don't hold the I2C bus lock on failure */
-		mutex_unlock(&state->base->i2c_lock);
+		/*
+		 * don't hold the I2C bus lock on failure while preventing
+		 * consecutive and disallowed calls to mutex_unlock()
+		 */
+		if (mutex_is_locked(&state->base->i2c_lock))
+			mutex_unlock(&state->base->i2c_lock);
+		else
+			dev_dbg(&state->base->i2c->dev,
+				"%s(): prevented consecutive mutex_unlock\n",
+				__func__);
+
 		dev_err(&state->base->i2c->dev,
 			"%s() write_reg failure (enable=%d)\n",
 			__func__, enable);
@@ -1250,8 +1259,15 @@ static int gate_ctrl(struct dvb_frontend *fe, int enable)
 
 	state->i2crpt = i2crpt;
 
-	if (!enable)
-		mutex_unlock(&state->base->i2c_lock);
+	if (!enable) {
+		if (mutex_is_locked(&state->base->i2c_lock))
+			mutex_unlock(&state->base->i2c_lock);
+		else
+			dev_dbg(&state->base->i2c->dev,
+				"%s(): prevented consecutive mutex_unlock\n",
+				__func__);
+	}
+
 	return 0;
 }
 
-- 
2.13.6




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux