diff options
author | Alexey Khoroshilov <khoroshilov@ispras.ru> | 2013-02-19 12:58:53 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-14 10:40:32 -0400 |
commit | c67d2f074073b39e5eba84e852c894c22057d159 (patch) | |
tree | 8d8e857a7be4cd7382569495d84c324a2d93c2c4 /drivers/media/dvb-frontends/stv090x.c | |
parent | a9fc36afc074db2d5995136b50b018c2ca77f48f (diff) |
[media] stv090x: do not unlock unheld mutex in stv090x_sleep()
goto err and goto err_gateoff before mutex_lock(&state->internal->demod_lock)
lead to unlock of unheld mutex in stv090x_sleep().
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Cc: Manu Abraham <abraham.manu@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-frontends/stv090x.c')
-rw-r--r-- | drivers/media/dvb-frontends/stv090x.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index f36eeefb76a6..56d470ad5a82 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c | |||
@@ -3906,12 +3906,12 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3906 | reg = stv090x_read_reg(state, STV090x_TSTTNR1); | 3906 | reg = stv090x_read_reg(state, STV090x_TSTTNR1); |
3907 | STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0); | 3907 | STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0); |
3908 | if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) | 3908 | if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) |
3909 | goto err; | 3909 | goto err_unlock; |
3910 | /* power off DiSEqC 1 */ | 3910 | /* power off DiSEqC 1 */ |
3911 | reg = stv090x_read_reg(state, STV090x_TSTTNR2); | 3911 | reg = stv090x_read_reg(state, STV090x_TSTTNR2); |
3912 | STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0); | 3912 | STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0); |
3913 | if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0) | 3913 | if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0) |
3914 | goto err; | 3914 | goto err_unlock; |
3915 | 3915 | ||
3916 | /* check whether path 2 is already sleeping, that is when | 3916 | /* check whether path 2 is already sleeping, that is when |
3917 | ADC2 is off */ | 3917 | ADC2 is off */ |
@@ -3930,7 +3930,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3930 | if (full_standby) | 3930 | if (full_standby) |
3931 | STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); | 3931 | STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); |
3932 | if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) | 3932 | if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) |
3933 | goto err; | 3933 | goto err_unlock; |
3934 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); | 3934 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); |
3935 | /* sampling 1 clock */ | 3935 | /* sampling 1 clock */ |
3936 | STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1); | 3936 | STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1); |
@@ -3941,7 +3941,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3941 | if (full_standby) | 3941 | if (full_standby) |
3942 | STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); | 3942 | STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); |
3943 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) | 3943 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) |
3944 | goto err; | 3944 | goto err_unlock; |
3945 | break; | 3945 | break; |
3946 | 3946 | ||
3947 | case STV090x_DEMODULATOR_1: | 3947 | case STV090x_DEMODULATOR_1: |
@@ -3949,12 +3949,12 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3949 | reg = stv090x_read_reg(state, STV090x_TSTTNR3); | 3949 | reg = stv090x_read_reg(state, STV090x_TSTTNR3); |
3950 | STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0); | 3950 | STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0); |
3951 | if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) | 3951 | if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) |
3952 | goto err; | 3952 | goto err_unlock; |
3953 | /* power off DiSEqC 2 */ | 3953 | /* power off DiSEqC 2 */ |
3954 | reg = stv090x_read_reg(state, STV090x_TSTTNR4); | 3954 | reg = stv090x_read_reg(state, STV090x_TSTTNR4); |
3955 | STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0); | 3955 | STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0); |
3956 | if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0) | 3956 | if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0) |
3957 | goto err; | 3957 | goto err_unlock; |
3958 | 3958 | ||
3959 | /* check whether path 1 is already sleeping, that is when | 3959 | /* check whether path 1 is already sleeping, that is when |
3960 | ADC1 is off */ | 3960 | ADC1 is off */ |
@@ -3973,7 +3973,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3973 | if (full_standby) | 3973 | if (full_standby) |
3974 | STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); | 3974 | STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); |
3975 | if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) | 3975 | if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) |
3976 | goto err; | 3976 | goto err_unlock; |
3977 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); | 3977 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); |
3978 | /* sampling 2 clock */ | 3978 | /* sampling 2 clock */ |
3979 | STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1); | 3979 | STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1); |
@@ -3984,7 +3984,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3984 | if (full_standby) | 3984 | if (full_standby) |
3985 | STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); | 3985 | STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); |
3986 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) | 3986 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) |
3987 | goto err; | 3987 | goto err_unlock; |
3988 | break; | 3988 | break; |
3989 | 3989 | ||
3990 | default: | 3990 | default: |
@@ -3997,7 +3997,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3997 | reg = stv090x_read_reg(state, STV090x_SYNTCTRL); | 3997 | reg = stv090x_read_reg(state, STV090x_SYNTCTRL); |
3998 | STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); | 3998 | STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); |
3999 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) | 3999 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) |
4000 | goto err; | 4000 | goto err_unlock; |
4001 | } | 4001 | } |
4002 | 4002 | ||
4003 | mutex_unlock(&state->internal->demod_lock); | 4003 | mutex_unlock(&state->internal->demod_lock); |
@@ -4005,8 +4005,10 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
4005 | 4005 | ||
4006 | err_gateoff: | 4006 | err_gateoff: |
4007 | stv090x_i2c_gate_ctrl(state, 0); | 4007 | stv090x_i2c_gate_ctrl(state, 0); |
4008 | err: | 4008 | goto err; |
4009 | err_unlock: | ||
4009 | mutex_unlock(&state->internal->demod_lock); | 4010 | mutex_unlock(&state->internal->demod_lock); |
4011 | err: | ||
4010 | dprintk(FE_ERROR, 1, "I/O error"); | 4012 | dprintk(FE_ERROR, 1, "I/O error"); |
4011 | return -1; | 4013 | return -1; |
4012 | } | 4014 | } |