diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-30 09:36:32 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-30 14:52:54 -0400 |
commit | 2621c0b3224633393ef9e24c3ac9de2770b3750c (patch) | |
tree | b7254b22ec1127581b7bc3e6f0e68ef8b617f801 /drivers/media/tuners/xc5000.c | |
parent | 2fcfd317f66c6e6cf0e05351e7641898d767dfa4 (diff) |
[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.
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/tuners/xc5000.c')
-rw-r--r-- | drivers/media/tuners/xc5000.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index ab7d444bcdcc..460df44aa1ad 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c | |||
@@ -1101,16 +1101,17 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) | |||
1101 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) | 1101 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) |
1102 | { | 1102 | { |
1103 | struct xc5000_priv *priv = fe->tuner_priv; | 1103 | struct xc5000_priv *priv = fe->tuner_priv; |
1104 | int ret = 0; | 1104 | int ret, i; |
1105 | u16 pll_lock_status; | 1105 | u16 pll_lock_status; |
1106 | u16 fw_ck; | 1106 | u16 fw_ck; |
1107 | 1107 | ||
1108 | cancel_delayed_work(&priv->timer_sleep); | 1108 | cancel_delayed_work(&priv->timer_sleep); |
1109 | 1109 | ||
1110 | if (force || xc5000_is_firmware_loaded(fe) != 0) { | 1110 | if (!force && xc5000_is_firmware_loaded(fe) == 0) |
1111 | 1111 | return 0; | |
1112 | fw_retry: | ||
1113 | 1112 | ||
1113 | /* Try up to 5 times to load firmware */ | ||
1114 | for (i = 0; i < 5; i++) { | ||
1114 | ret = xc5000_fwupload(fe); | 1115 | ret = xc5000_fwupload(fe); |
1115 | if (ret != 0) | 1116 | if (ret != 0) |
1116 | return ret; | 1117 | return ret; |
@@ -1118,25 +1119,25 @@ fw_retry: | |||
1118 | msleep(20); | 1119 | msleep(20); |
1119 | 1120 | ||
1120 | if (priv->fw_checksum_supported) { | 1121 | if (priv->fw_checksum_supported) { |
1121 | if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck) | 1122 | if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)) { |
1122 | != 0) { | ||
1123 | dprintk(1, "%s() FW checksum reading failed.\n", | 1123 | dprintk(1, "%s() FW checksum reading failed.\n", |
1124 | __func__); | 1124 | __func__); |
1125 | goto fw_retry; | 1125 | continue; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | if (fw_ck == 0) { | 1128 | if (!fw_ck) { |
1129 | dprintk(1, "%s() FW checksum failed = 0x%04x\n", | 1129 | dprintk(1, "%s() FW checksum failed = 0x%04x\n", |
1130 | __func__, fw_ck); | 1130 | __func__, fw_ck); |
1131 | goto fw_retry; | 1131 | continue; |
1132 | } | 1132 | } |
1133 | } | 1133 | } |
1134 | 1134 | ||
1135 | /* Start the tuner self-calibration process */ | 1135 | /* Start the tuner self-calibration process */ |
1136 | ret |= xc_initialize(priv); | 1136 | ret = xc_initialize(priv); |
1137 | 1137 | if (ret) { | |
1138 | if (ret != 0) | 1138 | dprintk(1, "Can't request Self-callibration. Reloading firmware\n"); |
1139 | goto fw_retry; | 1139 | continue; |
1140 | } | ||
1140 | 1141 | ||
1141 | /* Wait for calibration to complete. | 1142 | /* Wait for calibration to complete. |
1142 | * We could continue but XC5000 will clock stretch subsequent | 1143 | * We could continue but XC5000 will clock stretch subsequent |
@@ -1146,15 +1147,15 @@ fw_retry: | |||
1146 | msleep(100); | 1147 | msleep(100); |
1147 | 1148 | ||
1148 | if (priv->init_status_supported) { | 1149 | if (priv->init_status_supported) { |
1149 | if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) { | 1150 | if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck)) { |
1150 | dprintk(1, "%s() FW failed reading init status.\n", | 1151 | dprintk(1, "%s() FW failed reading init status.\n", |
1151 | __func__); | 1152 | __func__); |
1152 | goto fw_retry; | 1153 | continue; |
1153 | } | 1154 | } |
1154 | 1155 | ||
1155 | if (fw_ck == 0) { | 1156 | if (!fw_ck) { |
1156 | dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck); | 1157 | dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck); |
1157 | goto fw_retry; | 1158 | continue; |
1158 | } | 1159 | } |
1159 | } | 1160 | } |
1160 | 1161 | ||
@@ -1164,12 +1165,13 @@ fw_retry: | |||
1164 | if (pll_lock_status > 63) { | 1165 | if (pll_lock_status > 63) { |
1165 | /* PLL is unlocked, force reload of the firmware */ | 1166 | /* PLL is unlocked, force reload of the firmware */ |
1166 | printk(KERN_ERR "xc5000: PLL not running after fwload.\n"); | 1167 | printk(KERN_ERR "xc5000: PLL not running after fwload.\n"); |
1167 | goto fw_retry; | 1168 | continue; |
1168 | } | 1169 | } |
1169 | } | 1170 | } |
1170 | 1171 | ||
1171 | /* Default to "CABLE" mode */ | 1172 | /* Default to "CABLE" mode */ |
1172 | ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); | 1173 | ret = xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); |
1174 | break; | ||
1173 | } | 1175 | } |
1174 | 1176 | ||
1175 | return ret; | 1177 | return ret; |