提交 5614942b 编写于 作者: I Istvan Varga 提交者: Mauro Carvalho Chehab

[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: NIstvan Varga <istvan_v@mailbox.hu>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 f0ef7c88
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
...@@ -90,6 +91,7 @@ struct xc4000_priv { ...@@ -90,6 +91,7 @@ struct xc4000_priv {
struct firmware_properties cur_fw; struct firmware_properties cur_fw;
__u16 hwmodel; __u16 hwmodel;
__u16 hwvers; __u16 hwvers;
struct mutex lock;
}; };
/* Misc Defines */ /* Misc Defines */
...@@ -1145,10 +1147,12 @@ static int xc4000_set_params(struct dvb_frontend *fe, ...@@ -1145,10 +1147,12 @@ static int xc4000_set_params(struct dvb_frontend *fe,
{ {
struct xc4000_priv *priv = fe->tuner_priv; struct xc4000_priv *priv = fe->tuner_priv;
unsigned int type; unsigned int type;
int ret; int ret = -EREMOTEIO;
dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
mutex_lock(&priv->lock);
if (fe->ops.info.type == FE_ATSC) { if (fe->ops.info.type == FE_ATSC) {
dprintk(1, "%s() ATSC\n", __func__); dprintk(1, "%s() ATSC\n", __func__);
switch (params->u.vsb.modulation) { switch (params->u.vsb.modulation) {
...@@ -1172,7 +1176,8 @@ static int xc4000_set_params(struct dvb_frontend *fe, ...@@ -1172,7 +1176,8 @@ static int xc4000_set_params(struct dvb_frontend *fe,
type = DTV6; type = DTV6;
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
goto fail;
} }
} else if (fe->ops.info.type == FE_OFDM) { } else if (fe->ops.info.type == FE_OFDM) {
dprintk(1, "%s() OFDM\n", __func__); dprintk(1, "%s() OFDM\n", __func__);
...@@ -1208,28 +1213,29 @@ static int xc4000_set_params(struct dvb_frontend *fe, ...@@ -1208,28 +1213,29 @@ static int xc4000_set_params(struct dvb_frontend *fe,
break; break;
default: default:
printk(KERN_ERR "xc4000 bandwidth not set!\n"); printk(KERN_ERR "xc4000 bandwidth not set!\n");
return -EINVAL; ret = -EINVAL;
goto fail;
} }
priv->rf_mode = XC_RF_MODE_AIR; priv->rf_mode = XC_RF_MODE_AIR;
} else { } else {
printk(KERN_ERR "xc4000 modulation type not supported!\n"); printk(KERN_ERR "xc4000 modulation type not supported!\n");
return -EINVAL; ret = -EINVAL;
goto fail;
} }
dprintk(1, "%s() frequency=%d (compensated)\n", dprintk(1, "%s() frequency=%d (compensated)\n",
__func__, priv->freq_hz); __func__, priv->freq_hz);
/* Make sure the correct firmware type is loaded */ /* Make sure the correct firmware type is loaded */
if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS) { if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS)
return -EREMOTEIO; goto fail;
}
ret = xc_SetSignalSource(priv, priv->rf_mode); ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) { if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR printk(KERN_ERR
"xc4000: xc_SetSignalSource(%d) failed\n", "xc4000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode); priv->rf_mode);
return -EREMOTEIO; goto fail;
} }
ret = xc_SetTVStandard(priv, ret = xc_SetTVStandard(priv,
...@@ -1237,33 +1243,32 @@ static int xc4000_set_params(struct dvb_frontend *fe, ...@@ -1237,33 +1243,32 @@ static int xc4000_set_params(struct dvb_frontend *fe,
XC4000_Standard[priv->video_standard].AudioMode); XC4000_Standard[priv->video_standard].AudioMode);
if (ret != XC_RESULT_SUCCESS) { if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
return -EREMOTEIO; goto fail;
}
#ifdef DJH_DEBUG
ret = xc_set_IF_frequency(priv, priv->if_khz);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc4000: xc_Set_IF_frequency(%d) failed\n",
priv->if_khz);
return -EIO;
} }
#endif
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
if (debug) if (debug)
xc_debug_dump(priv); xc_debug_dump(priv);
return 0; ret = 0;
fail:
mutex_unlock(&priv->lock);
return ret;
} }
static int xc4000_set_analog_params(struct dvb_frontend *fe, static int xc4000_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params) struct analog_parameters *params)
{ {
struct xc4000_priv *priv = fe->tuner_priv; struct xc4000_priv *priv = fe->tuner_priv;
int ret; int ret = -EREMOTEIO;
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
__func__, params->frequency); __func__, params->frequency);
mutex_lock(&priv->lock);
/* Fix me: it could be air. */ /* Fix me: it could be air. */
priv->rf_mode = params->mode; priv->rf_mode = params->mode;
if (params->mode > XC_RF_MODE_CABLE) if (params->mode > XC_RF_MODE_CABLE)
...@@ -1318,16 +1323,15 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe, ...@@ -1318,16 +1323,15 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe,
tune_channel: tune_channel:
/* FIXME - firmware type not being set properly */ /* FIXME - firmware type not being set properly */
if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) { if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS)
return -EREMOTEIO; goto fail;
}
ret = xc_SetSignalSource(priv, priv->rf_mode); ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) { if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR printk(KERN_ERR
"xc4000: xc_SetSignalSource(%d) failed\n", "xc4000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode); priv->rf_mode);
return -EREMOTEIO; goto fail;
} }
ret = xc_SetTVStandard(priv, ret = xc_SetTVStandard(priv,
...@@ -1335,7 +1339,7 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe, ...@@ -1335,7 +1339,7 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe,
XC4000_Standard[priv->video_standard].AudioMode); XC4000_Standard[priv->video_standard].AudioMode);
if (ret != XC_RESULT_SUCCESS) { if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n"); printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
return -EREMOTEIO; goto fail;
} }
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
...@@ -1343,7 +1347,12 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe, ...@@ -1343,7 +1347,12 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe,
if (debug) if (debug)
xc_debug_dump(priv); xc_debug_dump(priv);
return 0; ret = 0;
fail:
mutex_unlock(&priv->lock);
return ret;
} }
static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) 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,8 +1377,12 @@ static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
struct xc4000_priv *priv = fe->tuner_priv; struct xc4000_priv *priv = fe->tuner_priv;
u16 lock_status = 0; u16 lock_status = 0;
mutex_lock(&priv->lock);
xc_get_lock_status(priv, &lock_status); xc_get_lock_status(priv, &lock_status);
mutex_unlock(&priv->lock);
dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
*status = lock_status; *status = lock_status;
...@@ -1386,9 +1399,13 @@ static int xc4000_sleep(struct dvb_frontend *fe) ...@@ -1386,9 +1399,13 @@ static int xc4000_sleep(struct dvb_frontend *fe)
static int xc4000_init(struct dvb_frontend *fe) static int xc4000_init(struct dvb_frontend *fe)
{ {
struct xc4000_priv *priv = fe->tuner_priv; struct xc4000_priv *priv = fe->tuner_priv;
int ret;
dprintk(1, "%s()\n", __func__); dprintk(1, "%s()\n", __func__);
if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) { mutex_lock(&priv->lock);
ret = check_firmware(fe, DTV8, 0, priv->if_khz);
mutex_unlock(&priv->lock);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc4000: Unable to initialise tuner\n"); printk(KERN_ERR "xc4000: Unable to initialise tuner\n");
return -EREMOTEIO; return -EREMOTEIO;
} }
...@@ -1460,6 +1477,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe, ...@@ -1460,6 +1477,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
case 1: case 1:
/* new tuner instance */ /* new tuner instance */
priv->bandwidth = BANDWIDTH_6_MHZ; priv->bandwidth = BANDWIDTH_6_MHZ;
mutex_init(&priv->lock);
fe->tuner_priv = priv; fe->tuner_priv = priv;
break; break;
default: default:
...@@ -1511,7 +1529,9 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe, ...@@ -1511,7 +1529,9 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
/* FIXME: For now, load the firmware at startup. We will remove this /* FIXME: For now, load the firmware at startup. We will remove this
before the code goes to production... */ before the code goes to production... */
mutex_lock(&priv->lock);
check_firmware(fe, DTV8, 0, priv->if_khz); check_firmware(fe, DTV8, 0, priv->if_khz);
mutex_unlock(&priv->lock);
return fe; return fe;
fail: fail:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册