diff options
author | Alexey Khoroshilov <khoroshilov@ispras.ru> | 2012-03-06 15:08:29 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-19 13:36:24 -0400 |
commit | f3033aecf2341a4e2669c63ed78a190a1c3e7a3a (patch) | |
tree | 922c9e4476283fb1eb346c12bd9b0ee8be556a8a /drivers/media/dvb/frontends/dib9000.c | |
parent | 9bb24a7e49c33c16c4d9d7d3496f46626e573d02 (diff) |
[media] dib9000: implement error handling for DibAcquireLock
DibAcquireLock() is implemented as mutex_lock_interruptible()
but the driver does not handle unsuccessful locking.
As a result it may lead to unlock of an unheld mutex.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends/dib9000.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib9000.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c index d96b6a1e65d9..80848b4c15d4 100644 --- a/drivers/media/dvb/frontends/dib9000.c +++ b/drivers/media/dvb/frontends/dib9000.c | |||
@@ -33,7 +33,7 @@ struct i2c_device { | |||
33 | 33 | ||
34 | /* lock */ | 34 | /* lock */ |
35 | #define DIB_LOCK struct mutex | 35 | #define DIB_LOCK struct mutex |
36 | #define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0) | 36 | #define DibAcquireLock(lock) mutex_lock_interruptible(lock) |
37 | #define DibReleaseLock(lock) mutex_unlock(lock) | 37 | #define DibReleaseLock(lock) mutex_unlock(lock) |
38 | #define DibInitLock(lock) mutex_init(lock) | 38 | #define DibInitLock(lock) mutex_init(lock) |
39 | #define DibFreeLock(lock) | 39 | #define DibFreeLock(lock) |
@@ -446,7 +446,10 @@ static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u1 | |||
446 | if (!state->platform.risc.fw_is_running) | 446 | if (!state->platform.risc.fw_is_running) |
447 | return -EIO; | 447 | return -EIO; |
448 | 448 | ||
449 | DibAcquireLock(&state->platform.risc.mem_lock); | 449 | if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { |
450 | dprintk("could not get the lock"); | ||
451 | return -EINTR; | ||
452 | } | ||
450 | dib9000_risc_mem_setup(state, cmd | 0x80); | 453 | dib9000_risc_mem_setup(state, cmd | 0x80); |
451 | dib9000_risc_mem_read_chunks(state, b, len); | 454 | dib9000_risc_mem_read_chunks(state, b, len); |
452 | DibReleaseLock(&state->platform.risc.mem_lock); | 455 | DibReleaseLock(&state->platform.risc.mem_lock); |
@@ -459,7 +462,10 @@ static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 | |||
459 | if (!state->platform.risc.fw_is_running) | 462 | if (!state->platform.risc.fw_is_running) |
460 | return -EIO; | 463 | return -EIO; |
461 | 464 | ||
462 | DibAcquireLock(&state->platform.risc.mem_lock); | 465 | if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { |
466 | dprintk("could not get the lock"); | ||
467 | return -EINTR; | ||
468 | } | ||
463 | dib9000_risc_mem_setup(state, cmd); | 469 | dib9000_risc_mem_setup(state, cmd); |
464 | dib9000_risc_mem_write_chunks(state, b, m->size); | 470 | dib9000_risc_mem_write_chunks(state, b, m->size); |
465 | DibReleaseLock(&state->platform.risc.mem_lock); | 471 | DibReleaseLock(&state->platform.risc.mem_lock); |
@@ -531,7 +537,10 @@ static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, | |||
531 | if (!state->platform.risc.fw_is_running) | 537 | if (!state->platform.risc.fw_is_running) |
532 | return -EINVAL; | 538 | return -EINVAL; |
533 | 539 | ||
534 | DibAcquireLock(&state->platform.risc.mbx_if_lock); | 540 | if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { |
541 | dprintk("could not get the lock"); | ||
542 | return -EINTR; | ||
543 | } | ||
535 | tmp = MAX_MAILBOX_TRY; | 544 | tmp = MAX_MAILBOX_TRY; |
536 | do { | 545 | do { |
537 | size = dib9000_read_word_attr(state, 1043, attr) & 0xff; | 546 | size = dib9000_read_word_attr(state, 1043, attr) & 0xff; |
@@ -593,7 +602,10 @@ static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, | |||
593 | if (!state->platform.risc.fw_is_running) | 602 | if (!state->platform.risc.fw_is_running) |
594 | return 0; | 603 | return 0; |
595 | 604 | ||
596 | DibAcquireLock(&state->platform.risc.mbx_if_lock); | 605 | if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { |
606 | dprintk("could not get the lock"); | ||
607 | return 0; | ||
608 | } | ||
597 | if (risc_id == 1) | 609 | if (risc_id == 1) |
598 | mc_base = 16; | 610 | mc_base = 16; |
599 | else | 611 | else |
@@ -701,7 +713,10 @@ static int dib9000_mbx_process(struct dib9000_state *state, u16 attr) | |||
701 | if (!state->platform.risc.fw_is_running) | 713 | if (!state->platform.risc.fw_is_running) |
702 | return -1; | 714 | return -1; |
703 | 715 | ||
704 | DibAcquireLock(&state->platform.risc.mbx_lock); | 716 | if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) { |
717 | dprintk("could not get the lock"); | ||
718 | return -1; | ||
719 | } | ||
705 | 720 | ||
706 | if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ | 721 | if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ |
707 | ret = dib9000_mbx_fetch_to_cache(state, attr); | 722 | ret = dib9000_mbx_fetch_to_cache(state, attr); |
@@ -1178,7 +1193,10 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe) | |||
1178 | struct dibDVBTChannel *ch; | 1193 | struct dibDVBTChannel *ch; |
1179 | int ret = 0; | 1194 | int ret = 0; |
1180 | 1195 | ||
1181 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 1196 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { |
1197 | dprintk("could not get the lock"); | ||
1198 | return -EINTR; | ||
1199 | } | ||
1182 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { | 1200 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { |
1183 | ret = -EIO; | 1201 | ret = -EIO; |
1184 | goto error; | 1202 | goto error; |
@@ -1660,7 +1678,10 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2 | |||
1660 | p[12] = 0; | 1678 | p[12] = 0; |
1661 | } | 1679 | } |
1662 | 1680 | ||
1663 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 1681 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { |
1682 | dprintk("could not get the lock"); | ||
1683 | return 0; | ||
1684 | } | ||
1664 | 1685 | ||
1665 | dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); | 1686 | dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); |
1666 | 1687 | ||
@@ -1768,7 +1789,10 @@ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | |||
1768 | return 0; | 1789 | return 0; |
1769 | } | 1790 | } |
1770 | 1791 | ||
1771 | DibAcquireLock(&state->demod_lock); | 1792 | if (DibAcquireLock(&state->demod_lock) < 0) { |
1793 | dprintk("could not get the lock"); | ||
1794 | return -EINTR; | ||
1795 | } | ||
1772 | 1796 | ||
1773 | val = dib9000_read_word(state, 294 + 1) & 0xffef; | 1797 | val = dib9000_read_word(state, 294 + 1) & 0xffef; |
1774 | val |= (onoff & 0x1) << 4; | 1798 | val |= (onoff & 0x1) << 4; |
@@ -1800,7 +1824,10 @@ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | |||
1800 | return 0; | 1824 | return 0; |
1801 | } | 1825 | } |
1802 | 1826 | ||
1803 | DibAcquireLock(&state->demod_lock); | 1827 | if (DibAcquireLock(&state->demod_lock) < 0) { |
1828 | dprintk("could not get the lock"); | ||
1829 | return -EINTR; | ||
1830 | } | ||
1804 | dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); | 1831 | dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); |
1805 | ret = dib9000_write_word(state, 300 + 1 + id, | 1832 | ret = dib9000_write_word(state, 300 + 1 + id, |
1806 | onoff ? (1 << 13) | pid : 0); | 1833 | onoff ? (1 << 13) | pid : 0); |
@@ -1848,7 +1875,10 @@ static int dib9000_sleep(struct dvb_frontend *fe) | |||
1848 | u8 index_frontend; | 1875 | u8 index_frontend; |
1849 | int ret = 0; | 1876 | int ret = 0; |
1850 | 1877 | ||
1851 | DibAcquireLock(&state->demod_lock); | 1878 | if (DibAcquireLock(&state->demod_lock) < 0) { |
1879 | dprintk("could not get the lock"); | ||
1880 | return -EINTR; | ||
1881 | } | ||
1852 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 1882 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
1853 | ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); | 1883 | ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); |
1854 | if (ret < 0) | 1884 | if (ret < 0) |
@@ -1874,8 +1904,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) | |||
1874 | fe_status_t stat; | 1904 | fe_status_t stat; |
1875 | int ret = 0; | 1905 | int ret = 0; |
1876 | 1906 | ||
1877 | if (state->get_frontend_internal == 0) | 1907 | if (state->get_frontend_internal == 0) { |
1878 | DibAcquireLock(&state->demod_lock); | 1908 | if (DibAcquireLock(&state->demod_lock) < 0) { |
1909 | dprintk("could not get the lock"); | ||
1910 | return -EINTR; | ||
1911 | } | ||
1912 | } | ||
1879 | 1913 | ||
1880 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 1914 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
1881 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); | 1915 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); |
@@ -1978,7 +2012,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe) | |||
1978 | } | 2012 | } |
1979 | 2013 | ||
1980 | state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ | 2014 | state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ |
1981 | DibAcquireLock(&state->demod_lock); | 2015 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2016 | dprintk("could not get the lock"); | ||
2017 | return 0; | ||
2018 | } | ||
1982 | 2019 | ||
1983 | fe->dtv_property_cache.delivery_system = SYS_DVBT; | 2020 | fe->dtv_property_cache.delivery_system = SYS_DVBT; |
1984 | 2021 | ||
@@ -2138,7 +2175,10 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | |||
2138 | u8 index_frontend; | 2175 | u8 index_frontend; |
2139 | u16 lock = 0, lock_slave = 0; | 2176 | u16 lock = 0, lock_slave = 0; |
2140 | 2177 | ||
2141 | DibAcquireLock(&state->demod_lock); | 2178 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2179 | dprintk("could not get the lock"); | ||
2180 | return -EINTR; | ||
2181 | } | ||
2142 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | 2182 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) |
2143 | lock_slave |= dib9000_read_lock(state->fe[index_frontend]); | 2183 | lock_slave |= dib9000_read_lock(state->fe[index_frontend]); |
2144 | 2184 | ||
@@ -2168,8 +2208,15 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) | |||
2168 | u16 *c; | 2208 | u16 *c; |
2169 | int ret = 0; | 2209 | int ret = 0; |
2170 | 2210 | ||
2171 | DibAcquireLock(&state->demod_lock); | 2211 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2172 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2212 | dprintk("could not get the lock"); |
2213 | return -EINTR; | ||
2214 | } | ||
2215 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { | ||
2216 | dprintk("could not get the lock"); | ||
2217 | ret = -EINTR; | ||
2218 | goto error; | ||
2219 | } | ||
2173 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { | 2220 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { |
2174 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2221 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
2175 | ret = -EIO; | 2222 | ret = -EIO; |
@@ -2196,7 +2243,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
2196 | u16 val; | 2243 | u16 val; |
2197 | int ret = 0; | 2244 | int ret = 0; |
2198 | 2245 | ||
2199 | DibAcquireLock(&state->demod_lock); | 2246 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2247 | dprintk("could not get the lock"); | ||
2248 | return -EINTR; | ||
2249 | } | ||
2200 | *strength = 0; | 2250 | *strength = 0; |
2201 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 2251 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
2202 | state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); | 2252 | state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); |
@@ -2206,7 +2256,11 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
2206 | *strength += val; | 2256 | *strength += val; |
2207 | } | 2257 | } |
2208 | 2258 | ||
2209 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2259 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { |
2260 | dprintk("could not get the lock"); | ||
2261 | ret = -EINTR; | ||
2262 | goto error; | ||
2263 | } | ||
2210 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { | 2264 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { |
2211 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2265 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
2212 | ret = -EIO; | 2266 | ret = -EIO; |
@@ -2233,10 +2287,13 @@ static u32 dib9000_get_snr(struct dvb_frontend *fe) | |||
2233 | u32 n, s, exp; | 2287 | u32 n, s, exp; |
2234 | u16 val; | 2288 | u16 val; |
2235 | 2289 | ||
2236 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2290 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { |
2291 | dprintk("could not get the lock"); | ||
2292 | return 0; | ||
2293 | } | ||
2237 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { | 2294 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { |
2238 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2295 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
2239 | return -EIO; | 2296 | return 0; |
2240 | } | 2297 | } |
2241 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); | 2298 | dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); |
2242 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2299 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
@@ -2269,7 +2326,10 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) | |||
2269 | u8 index_frontend; | 2326 | u8 index_frontend; |
2270 | u32 snr_master; | 2327 | u32 snr_master; |
2271 | 2328 | ||
2272 | DibAcquireLock(&state->demod_lock); | 2329 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2330 | dprintk("could not get the lock"); | ||
2331 | return -EINTR; | ||
2332 | } | ||
2273 | snr_master = dib9000_get_snr(fe); | 2333 | snr_master = dib9000_get_snr(fe); |
2274 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | 2334 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) |
2275 | snr_master += dib9000_get_snr(state->fe[index_frontend]); | 2335 | snr_master += dib9000_get_snr(state->fe[index_frontend]); |
@@ -2291,8 +2351,15 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | |||
2291 | u16 *c = (u16 *)state->i2c_read_buffer; | 2351 | u16 *c = (u16 *)state->i2c_read_buffer; |
2292 | int ret = 0; | 2352 | int ret = 0; |
2293 | 2353 | ||
2294 | DibAcquireLock(&state->demod_lock); | 2354 | if (DibAcquireLock(&state->demod_lock) < 0) { |
2295 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); | 2355 | dprintk("could not get the lock"); |
2356 | return -EINTR; | ||
2357 | } | ||
2358 | if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { | ||
2359 | dprintk("could not get the lock"); | ||
2360 | ret = -EINTR; | ||
2361 | goto error; | ||
2362 | } | ||
2296 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { | 2363 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { |
2297 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); | 2364 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
2298 | ret = -EIO; | 2365 | ret = -EIO; |