summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-30 10:36:32 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-30 16:18:04 -0300
commit50b96a77aab97e745f9bb8bb283933903234cf4d (patch)
tree0dce967396597ecd47d28f4a6b3597e4e0966486
parentbeb867e3a78022979857812d76f4c0c6292834c9 (diff)
downloadlinux-3.10-50b96a77aab97e745f9bb8bb283933903234cf4d.tar.gz
linux-3.10-50b96a77aab97e745f9bb8bb283933903234cf4d.tar.bz2
linux-3.10-50b96a77aab97e745f9bb8bb283933903234cf4d.zip
upstream: [media] xc5000: Don't try forever to load the firmware
With the current code, if something bad happens during the firmware init process, the device will keep trying forever, and removing it would cause an OOPS. Instead, try only a limited amount of time. If not, fails. Backports http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/?id=2621c0b32246 Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/tuners/xc5000.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c
index f183bec0f80..18f95a31cf6 100644
--- a/drivers/media/tuners/xc5000.c
+++ b/drivers/media/tuners/xc5000.c
@@ -1099,16 +1099,17 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
{
struct xc5000_priv *priv = fe->tuner_priv;
- int ret = 0;
+ int ret, i;
u16 pll_lock_status;
u16 fw_ck;
cancel_delayed_work(&priv->timer_sleep);
- if (force || xc5000_is_firmware_loaded(fe) != 0) {
-
-fw_retry:
+ if (!force && xc5000_is_firmware_loaded(fe) == 0)
+ return 0;
+ /* Try up to 5 times to load firmware */
+ for (i = 0; i < 5; i++) {
ret = xc5000_fwupload(fe);
if (ret != 0)
return ret;
@@ -1116,25 +1117,25 @@ fw_retry:
msleep(20);
if (priv->fw_checksum_supported) {
- if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
- != 0) {
+ if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)) {
dprintk(1, "%s() FW checksum reading failed.\n",
__func__);
- goto fw_retry;
+ continue;
}
- if (fw_ck == 0) {
+ if (!fw_ck) {
dprintk(1, "%s() FW checksum failed = 0x%04x\n",
__func__, fw_ck);
- goto fw_retry;
+ continue;
}
}
/* Start the tuner self-calibration process */
- ret |= xc_initialize(priv);
-
- if (ret != 0)
- goto fw_retry;
+ ret = xc_initialize(priv);
+ if (ret) {
+ dprintk(1, "Can't request Self-callibration. Reloading firmware\n");
+ continue;
+ }
/* Wait for calibration to complete.
* We could continue but XC5000 will clock stretch subsequent
@@ -1144,15 +1145,15 @@ fw_retry:
msleep(100);
if (priv->init_status_supported) {
- if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) {
+ if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck)) {
dprintk(1, "%s() FW failed reading init status.\n",
__func__);
- goto fw_retry;
+ continue;
}
- if (fw_ck == 0) {
+ if (!fw_ck) {
dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
- goto fw_retry;
+ continue;
}
}
@@ -1162,12 +1163,13 @@ fw_retry:
if (pll_lock_status > 63) {
/* PLL is unlocked, force reload of the firmware */
printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
- goto fw_retry;
+ continue;
}
}
/* Default to "CABLE" mode */
- ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+ ret = xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+ break;
}
return ret;