Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: dvb-frontends/stv0910: release lock on gate_ctrl() failure

Whenever write_reg() fails to open/close the demod's I2C gate, release the
lock to avoid deadlocking situations. If I2c gate open failed, there's no
need to hold a lock, and if close fails, the mutex_unlock() at the end of
the function is never reached, leaving the mutex_lock in locked state,
which in turn will cause potential for deadlocks. Thus, release the lock
on failure.

While we're touching gate_ctrl(), add some explanation about the need for
locking and the shared I2C bus/gate.

Cc: Julia Lawall <julia.lawall@lip6.fr>
Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Daniel Scheller and committed by
Mauro Carvalho Chehab
6b852620 e59eb4ad

+20 -5
+20 -5
drivers/media/dvb-frontends/stv0910.c
··· 1221 1221 struct stv *state = fe->demodulator_priv; 1222 1222 u8 i2crpt = state->i2crpt & ~0x86; 1223 1223 1224 - if (enable) 1225 - mutex_lock(&state->base->i2c_lock); 1224 + /* 1225 + * mutex_lock note: Concurrent I2C gate bus accesses must be 1226 + * prevented (STV0910 = dual demod on a single IC with a single I2C 1227 + * gate/bus, and two tuners attached), similar to most (if not all) 1228 + * other I2C host interfaces/busses. 1229 + * 1230 + * enable=1 (open I2C gate) will grab the lock 1231 + * enable=0 (close I2C gate) releases the lock 1232 + */ 1226 1233 1227 - if (enable) 1234 + if (enable) { 1235 + mutex_lock(&state->base->i2c_lock); 1228 1236 i2crpt |= 0x80; 1229 - else 1237 + } else { 1230 1238 i2crpt |= 0x02; 1239 + } 1231 1240 1232 1241 if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : 1233 - RSTV0910_P1_I2CRPT, i2crpt) < 0) 1242 + RSTV0910_P1_I2CRPT, i2crpt) < 0) { 1243 + /* don't hold the I2C bus lock on failure */ 1244 + mutex_unlock(&state->base->i2c_lock); 1245 + dev_err(&state->base->i2c->dev, 1246 + "%s() write_reg failure (enable=%d)\n", 1247 + __func__, enable); 1234 1248 return -EIO; 1249 + } 1235 1250 1236 1251 state->i2crpt = i2crpt; 1237 1252