diff options
author | Istvan Varga <istvan_v@mailbox.hu> | 2011-06-03 11:23:33 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:52:34 -0400 |
commit | 5614942bb06f5620d0d6eb67bc0268c76c5dd921 (patch) | |
tree | 044e35ce245775eeac12e25d4c04cab828010355 /drivers/media/common/tuners/xc4000.c | |
parent | f0ef7c88ca919912011593d2392a59c2fde04748 (diff) |
[media] xc4000: added mutex
This patch adds a mutex to xc4000_priv, to protect the driver
from being accessed by multiple processes at the same time.
Signed-off-by: Istvan Varga <istvan_v@mailbox.hu>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common/tuners/xc4000.c')
-rw-r--r-- | drivers/media/common/tuners/xc4000.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c index 307a8745e06e..be43a6dfac6c 100644 --- a/drivers/media/common/tuners/xc4000.c +++ b/drivers/media/common/tuners/xc4000.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/dvb/frontend.h> | 29 | #include <linux/dvb/frontend.h> |
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/mutex.h> | ||
31 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
32 | 33 | ||
33 | #include "dvb_frontend.h" | 34 | #include "dvb_frontend.h" |
@@ -90,6 +91,7 @@ struct xc4000_priv { | |||
90 | struct firmware_properties cur_fw; | 91 | struct firmware_properties cur_fw; |
91 | __u16 hwmodel; | 92 | __u16 hwmodel; |
92 | __u16 hwvers; | 93 | __u16 hwvers; |
94 | struct mutex lock; | ||
93 | }; | 95 | }; |
94 | 96 | ||
95 | /* Misc Defines */ | 97 | /* Misc Defines */ |
@@ -1145,10 +1147,12 @@ static int xc4000_set_params(struct dvb_frontend *fe, | |||
1145 | { | 1147 | { |
1146 | struct xc4000_priv *priv = fe->tuner_priv; | 1148 | struct xc4000_priv *priv = fe->tuner_priv; |
1147 | unsigned int type; | 1149 | unsigned int type; |
1148 | int ret; | 1150 | int ret = -EREMOTEIO; |
1149 | 1151 | ||
1150 | dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); | 1152 | dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); |
1151 | 1153 | ||
1154 | mutex_lock(&priv->lock); | ||
1155 | |||
1152 | if (fe->ops.info.type == FE_ATSC) { | 1156 | if (fe->ops.info.type == FE_ATSC) { |
1153 | dprintk(1, "%s() ATSC\n", __func__); | 1157 | dprintk(1, "%s() ATSC\n", __func__); |
1154 | switch (params->u.vsb.modulation) { | 1158 | switch (params->u.vsb.modulation) { |
@@ -1172,7 +1176,8 @@ static int xc4000_set_params(struct dvb_frontend *fe, | |||
1172 | type = DTV6; | 1176 | type = DTV6; |
1173 | break; | 1177 | break; |
1174 | default: | 1178 | default: |
1175 | return -EINVAL; | 1179 | ret = -EINVAL; |
1180 | goto fail; | ||
1176 | } | 1181 | } |
1177 | } else if (fe->ops.info.type == FE_OFDM) { | 1182 | } else if (fe->ops.info.type == FE_OFDM) { |
1178 | dprintk(1, "%s() OFDM\n", __func__); | 1183 | dprintk(1, "%s() OFDM\n", __func__); |
@@ -1208,28 +1213,29 @@ static int xc4000_set_params(struct dvb_frontend *fe, | |||
1208 | break; | 1213 | break; |
1209 | default: | 1214 | default: |
1210 | printk(KERN_ERR "xc4000 bandwidth not set!\n"); | 1215 | printk(KERN_ERR "xc4000 bandwidth not set!\n"); |
1211 | return -EINVAL; | 1216 | ret = -EINVAL; |
1217 | goto fail; | ||
1212 | } | 1218 | } |
1213 | priv->rf_mode = XC_RF_MODE_AIR; | 1219 | priv->rf_mode = XC_RF_MODE_AIR; |
1214 | } else { | 1220 | } else { |
1215 | printk(KERN_ERR "xc4000 modulation type not supported!\n"); | 1221 | printk(KERN_ERR "xc4000 modulation type not supported!\n"); |
1216 | return -EINVAL; | 1222 | ret = -EINVAL; |
1223 | goto fail; | ||
1217 | } | 1224 | } |
1218 | 1225 | ||
1219 | dprintk(1, "%s() frequency=%d (compensated)\n", | 1226 | dprintk(1, "%s() frequency=%d (compensated)\n", |
1220 | __func__, priv->freq_hz); | 1227 | __func__, priv->freq_hz); |
1221 | 1228 | ||
1222 | /* Make sure the correct firmware type is loaded */ | 1229 | /* Make sure the correct firmware type is loaded */ |
1223 | if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS) { | 1230 | if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS) |
1224 | return -EREMOTEIO; | 1231 | goto fail; |
1225 | } | ||
1226 | 1232 | ||
1227 | ret = xc_SetSignalSource(priv, priv->rf_mode); | 1233 | ret = xc_SetSignalSource(priv, priv->rf_mode); |
1228 | if (ret != XC_RESULT_SUCCESS) { | 1234 | if (ret != XC_RESULT_SUCCESS) { |
1229 | printk(KERN_ERR | 1235 | printk(KERN_ERR |
1230 | "xc4000: xc_SetSignalSource(%d) failed\n", | 1236 | "xc4000: xc_SetSignalSource(%d) failed\n", |
1231 | priv->rf_mode); | 1237 | priv->rf_mode); |
1232 | return -EREMOTEIO; | 1238 | goto fail; |
1233 | } | 1239 | } |
1234 | 1240 | ||
1235 | ret = xc_SetTVStandard(priv, | 1241 | ret = xc_SetTVStandard(priv, |
@@ -1237,33 +1243,32 @@ static int xc4000_set_params(struct dvb_frontend *fe, | |||
1237 | XC4000_Standard[priv->video_standard].AudioMode); | 1243 | XC4000_Standard[priv->video_standard].AudioMode); |
1238 | if (ret != XC_RESULT_SUCCESS) { | 1244 | if (ret != XC_RESULT_SUCCESS) { |
1239 | printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); | 1245 | printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); |
1240 | return -EREMOTEIO; | 1246 | goto fail; |
1241 | } | ||
1242 | #ifdef DJH_DEBUG | ||
1243 | ret = xc_set_IF_frequency(priv, priv->if_khz); | ||
1244 | if (ret != XC_RESULT_SUCCESS) { | ||
1245 | printk(KERN_ERR "xc4000: xc_Set_IF_frequency(%d) failed\n", | ||
1246 | priv->if_khz); | ||
1247 | return -EIO; | ||
1248 | } | 1247 | } |
1249 | #endif | ||
1250 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); | 1248 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); |
1251 | 1249 | ||
1252 | if (debug) | 1250 | if (debug) |
1253 | xc_debug_dump(priv); | 1251 | xc_debug_dump(priv); |
1254 | 1252 | ||
1255 | return 0; | 1253 | ret = 0; |
1254 | |||
1255 | fail: | ||
1256 | mutex_unlock(&priv->lock); | ||
1257 | |||
1258 | return ret; | ||
1256 | } | 1259 | } |
1257 | 1260 | ||
1258 | static int xc4000_set_analog_params(struct dvb_frontend *fe, | 1261 | static int xc4000_set_analog_params(struct dvb_frontend *fe, |
1259 | struct analog_parameters *params) | 1262 | struct analog_parameters *params) |
1260 | { | 1263 | { |
1261 | struct xc4000_priv *priv = fe->tuner_priv; | 1264 | struct xc4000_priv *priv = fe->tuner_priv; |
1262 | int ret; | 1265 | int ret = -EREMOTEIO; |
1263 | 1266 | ||
1264 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", | 1267 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", |
1265 | __func__, params->frequency); | 1268 | __func__, params->frequency); |
1266 | 1269 | ||
1270 | mutex_lock(&priv->lock); | ||
1271 | |||
1267 | /* Fix me: it could be air. */ | 1272 | /* Fix me: it could be air. */ |
1268 | priv->rf_mode = params->mode; | 1273 | priv->rf_mode = params->mode; |
1269 | if (params->mode > XC_RF_MODE_CABLE) | 1274 | if (params->mode > XC_RF_MODE_CABLE) |
@@ -1318,16 +1323,15 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe, | |||
1318 | tune_channel: | 1323 | tune_channel: |
1319 | 1324 | ||
1320 | /* FIXME - firmware type not being set properly */ | 1325 | /* FIXME - firmware type not being set properly */ |
1321 | if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) { | 1326 | if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) |
1322 | return -EREMOTEIO; | 1327 | goto fail; |
1323 | } | ||
1324 | 1328 | ||
1325 | ret = xc_SetSignalSource(priv, priv->rf_mode); | 1329 | ret = xc_SetSignalSource(priv, priv->rf_mode); |
1326 | if (ret != XC_RESULT_SUCCESS) { | 1330 | if (ret != XC_RESULT_SUCCESS) { |
1327 | printk(KERN_ERR | 1331 | printk(KERN_ERR |
1328 | "xc4000: xc_SetSignalSource(%d) failed\n", | 1332 | "xc4000: xc_SetSignalSource(%d) failed\n", |
1329 | priv->rf_mode); | 1333 | priv->rf_mode); |
1330 | return -EREMOTEIO; | 1334 | goto fail; |
1331 | } | 1335 | } |
1332 | 1336 | ||
1333 | ret = xc_SetTVStandard(priv, | 1337 | ret = xc_SetTVStandard(priv, |
@@ -1335,7 +1339,7 @@ tune_channel: | |||
1335 | XC4000_Standard[priv->video_standard].AudioMode); | 1339 | XC4000_Standard[priv->video_standard].AudioMode); |
1336 | if (ret != XC_RESULT_SUCCESS) { | 1340 | if (ret != XC_RESULT_SUCCESS) { |
1337 | printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); | 1341 | printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); |
1338 | return -EREMOTEIO; | 1342 | goto fail; |
1339 | } | 1343 | } |
1340 | 1344 | ||
1341 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); | 1345 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); |
@@ -1343,7 +1347,12 @@ tune_channel: | |||
1343 | if (debug) | 1347 | if (debug) |
1344 | xc_debug_dump(priv); | 1348 | xc_debug_dump(priv); |
1345 | 1349 | ||
1346 | return 0; | 1350 | ret = 0; |
1351 | |||
1352 | fail: | ||
1353 | mutex_unlock(&priv->lock); | ||
1354 | |||
1355 | return ret; | ||
1347 | } | 1356 | } |
1348 | 1357 | ||
1349 | static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) | 1358 | static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) |
@@ -1368,8 +1377,12 @@ static int xc4000_get_status(struct dvb_frontend *fe, u32 *status) | |||
1368 | struct xc4000_priv *priv = fe->tuner_priv; | 1377 | struct xc4000_priv *priv = fe->tuner_priv; |
1369 | u16 lock_status = 0; | 1378 | u16 lock_status = 0; |
1370 | 1379 | ||
1380 | mutex_lock(&priv->lock); | ||
1381 | |||
1371 | xc_get_lock_status(priv, &lock_status); | 1382 | xc_get_lock_status(priv, &lock_status); |
1372 | 1383 | ||
1384 | mutex_unlock(&priv->lock); | ||
1385 | |||
1373 | dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); | 1386 | dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); |
1374 | 1387 | ||
1375 | *status = lock_status; | 1388 | *status = lock_status; |
@@ -1386,9 +1399,13 @@ static int xc4000_sleep(struct dvb_frontend *fe) | |||
1386 | static int xc4000_init(struct dvb_frontend *fe) | 1399 | static int xc4000_init(struct dvb_frontend *fe) |
1387 | { | 1400 | { |
1388 | struct xc4000_priv *priv = fe->tuner_priv; | 1401 | struct xc4000_priv *priv = fe->tuner_priv; |
1402 | int ret; | ||
1389 | dprintk(1, "%s()\n", __func__); | 1403 | dprintk(1, "%s()\n", __func__); |
1390 | 1404 | ||
1391 | if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) { | 1405 | mutex_lock(&priv->lock); |
1406 | ret = check_firmware(fe, DTV8, 0, priv->if_khz); | ||
1407 | mutex_unlock(&priv->lock); | ||
1408 | if (ret != XC_RESULT_SUCCESS) { | ||
1392 | printk(KERN_ERR "xc4000: Unable to initialise tuner\n"); | 1409 | printk(KERN_ERR "xc4000: Unable to initialise tuner\n"); |
1393 | return -EREMOTEIO; | 1410 | return -EREMOTEIO; |
1394 | } | 1411 | } |
@@ -1460,6 +1477,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe, | |||
1460 | case 1: | 1477 | case 1: |
1461 | /* new tuner instance */ | 1478 | /* new tuner instance */ |
1462 | priv->bandwidth = BANDWIDTH_6_MHZ; | 1479 | priv->bandwidth = BANDWIDTH_6_MHZ; |
1480 | mutex_init(&priv->lock); | ||
1463 | fe->tuner_priv = priv; | 1481 | fe->tuner_priv = priv; |
1464 | break; | 1482 | break; |
1465 | default: | 1483 | default: |
@@ -1511,7 +1529,9 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe, | |||
1511 | 1529 | ||
1512 | /* FIXME: For now, load the firmware at startup. We will remove this | 1530 | /* FIXME: For now, load the firmware at startup. We will remove this |
1513 | before the code goes to production... */ | 1531 | before the code goes to production... */ |
1532 | mutex_lock(&priv->lock); | ||
1514 | check_firmware(fe, DTV8, 0, priv->if_khz); | 1533 | check_firmware(fe, DTV8, 0, priv->if_khz); |
1534 | mutex_unlock(&priv->lock); | ||
1515 | 1535 | ||
1516 | return fe; | 1536 | return fe; |
1517 | fail: | 1537 | fail: |