aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-06-30 08:08:54 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-30 13:26:06 -0400
commit61a96113de51e1f8f43ac98cbeadb54e60045905 (patch)
tree16eb4f6fbf3d2d65074d08d71d9d22e90e57a826 /drivers/media/common
parent704a28e88ab6c9cfe393ae626b612cab8b46028e (diff)
[media] tuner-xc2028: use request_firmware_nowait()
Change the firmware logic to use request_firmware_nowait(), and to preserve the loaded firmwares in memory, to reduce the risk of troubles with buggy userspace apps. With this change, while the firmware is being loaded, the driver will return -EAGAIN to any calls. If, for some reason, firmware failed to be loaded from userspace, it will return -ENODEV. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c178
1 files changed, 129 insertions, 49 deletions
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index b5ee3ebfcfca..9638a69f36b2 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -90,11 +90,22 @@ struct firmware_properties {
90 int scode_nr; 90 int scode_nr;
91}; 91};
92 92
93enum xc2028_state {
94 XC2028_NO_FIRMWARE = 0,
95 XC2028_WAITING_FIRMWARE,
96 XC2028_ACTIVE,
97 XC2028_SLEEP,
98 XC2028_NODEV,
99};
100
93struct xc2028_data { 101struct xc2028_data {
94 struct list_head hybrid_tuner_instance_list; 102 struct list_head hybrid_tuner_instance_list;
95 struct tuner_i2c_props i2c_props; 103 struct tuner_i2c_props i2c_props;
96 __u32 frequency; 104 __u32 frequency;
97 105
106 enum xc2028_state state;
107 const char *fname;
108
98 struct firmware_description *firm; 109 struct firmware_description *firm;
99 int firm_size; 110 int firm_size;
100 __u16 firm_version; 111 __u16 firm_version;
@@ -255,6 +266,21 @@ static v4l2_std_id parse_audio_std_option(void)
255 return 0; 266 return 0;
256} 267}
257 268
269static int check_device_status(struct xc2028_data *priv)
270{
271 switch (priv->state) {
272 case XC2028_NO_FIRMWARE:
273 case XC2028_WAITING_FIRMWARE:
274 return -EAGAIN;
275 case XC2028_ACTIVE:
276 case XC2028_SLEEP:
277 return 0;
278 case XC2028_NODEV:
279 return -ENODEV;
280 }
281 return 0;
282}
283
258static void free_firmware(struct xc2028_data *priv) 284static void free_firmware(struct xc2028_data *priv)
259{ 285{
260 int i; 286 int i;
@@ -270,45 +296,28 @@ static void free_firmware(struct xc2028_data *priv)
270 296
271 priv->firm = NULL; 297 priv->firm = NULL;
272 priv->firm_size = 0; 298 priv->firm_size = 0;
299 priv->state = XC2028_NO_FIRMWARE;
273 300
274 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); 301 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
275} 302}
276 303
277static int load_all_firmwares(struct dvb_frontend *fe) 304static int load_all_firmwares(struct dvb_frontend *fe,
305 const struct firmware *fw)
278{ 306{
279 struct xc2028_data *priv = fe->tuner_priv; 307 struct xc2028_data *priv = fe->tuner_priv;
280 const struct firmware *fw = NULL;
281 const unsigned char *p, *endp; 308 const unsigned char *p, *endp;
282 int rc = 0; 309 int rc = 0;
283 int n, n_array; 310 int n, n_array;
284 char name[33]; 311 char name[33];
285 char *fname;
286 312
287 tuner_dbg("%s called\n", __func__); 313 tuner_dbg("%s called\n", __func__);
288 314
289 if (!firmware_name[0])
290 fname = priv->ctrl.fname;
291 else
292 fname = firmware_name;
293
294 tuner_dbg("Reading firmware %s\n", fname);
295 rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
296 if (rc < 0) {
297 if (rc == -ENOENT)
298 tuner_err("Error: firmware %s not found.\n",
299 fname);
300 else
301 tuner_err("Error %d while requesting firmware %s \n",
302 rc, fname);
303
304 return rc;
305 }
306 p = fw->data; 315 p = fw->data;
307 endp = p + fw->size; 316 endp = p + fw->size;
308 317
309 if (fw->size < sizeof(name) - 1 + 2 + 2) { 318 if (fw->size < sizeof(name) - 1 + 2 + 2) {
310 tuner_err("Error: firmware file %s has invalid size!\n", 319 tuner_err("Error: firmware file %s has invalid size!\n",
311 fname); 320 priv->fname);
312 goto corrupt; 321 goto corrupt;
313 } 322 }
314 323
@@ -323,7 +332,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
323 p += 2; 332 p += 2;
324 333
325 tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", 334 tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
326 n_array, fname, name, 335 n_array, priv->fname, name,
327 priv->firm_version >> 8, priv->firm_version & 0xff); 336 priv->firm_version >> 8, priv->firm_version & 0xff);
328 337
329 priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL); 338 priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
@@ -417,9 +426,10 @@ err:
417 free_firmware(priv); 426 free_firmware(priv);
418 427
419done: 428done:
420 release_firmware(fw);
421 if (rc == 0) 429 if (rc == 0)
422 tuner_dbg("Firmware files loaded.\n"); 430 tuner_dbg("Firmware files loaded.\n");
431 else
432 priv->state = XC2028_NODEV;
423 433
424 return rc; 434 return rc;
425} 435}
@@ -707,22 +717,15 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
707{ 717{
708 struct xc2028_data *priv = fe->tuner_priv; 718 struct xc2028_data *priv = fe->tuner_priv;
709 struct firmware_properties new_fw; 719 struct firmware_properties new_fw;
710 int rc = 0, retry_count = 0; 720 int rc, retry_count = 0;
711 u16 version, hwmodel; 721 u16 version, hwmodel;
712 v4l2_std_id std0; 722 v4l2_std_id std0;
713 723
714 tuner_dbg("%s called\n", __func__); 724 tuner_dbg("%s called\n", __func__);
715 725
716 if (!priv->firm) { 726 rc = check_device_status(priv);
717 if (!priv->ctrl.fname) { 727 if (rc < 0)
718 tuner_info("xc2028/3028 firmware name not set!\n"); 728 return rc;
719 return -EINVAL;
720 }
721
722 rc = load_all_firmwares(fe);
723 if (rc < 0)
724 return rc;
725 }
726 729
727 if (priv->ctrl.mts && !(type & FM)) 730 if (priv->ctrl.mts && !(type & FM))
728 type |= MTS; 731 type |= MTS;
@@ -749,9 +752,13 @@ retry:
749 printk("scode_nr %d\n", new_fw.scode_nr); 752 printk("scode_nr %d\n", new_fw.scode_nr);
750 } 753 }
751 754
752 /* No need to reload base firmware if it matches */ 755 /*
753 if (((BASE | new_fw.type) & BASE_TYPES) == 756 * No need to reload base firmware if it matches and if the tuner
754 (priv->cur_fw.type & BASE_TYPES)) { 757 * is not at sleep mode
758 */
759 if ((priv->state = XC2028_ACTIVE) &&
760 (((BASE | new_fw.type) & BASE_TYPES) ==
761 (priv->cur_fw.type & BASE_TYPES))) {
755 tuner_dbg("BASE firmware not changed.\n"); 762 tuner_dbg("BASE firmware not changed.\n");
756 goto skip_base; 763 goto skip_base;
757 } 764 }
@@ -872,10 +879,13 @@ read_not_reliable:
872 * 2. Tell whether BASE firmware was just changed the next time through. 879 * 2. Tell whether BASE firmware was just changed the next time through.
873 */ 880 */
874 priv->cur_fw.type |= BASE; 881 priv->cur_fw.type |= BASE;
882 priv->state = XC2028_ACTIVE;
875 883
876 return 0; 884 return 0;
877 885
878fail: 886fail:
887 priv->state = XC2028_SLEEP;
888
879 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); 889 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
880 if (retry_count < 8) { 890 if (retry_count < 8) {
881 msleep(50); 891 msleep(50);
@@ -897,6 +907,10 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
897 907
898 tuner_dbg("%s called\n", __func__); 908 tuner_dbg("%s called\n", __func__);
899 909
910 rc = check_device_status(priv);
911 if (rc < 0)
912 return rc;
913
900 mutex_lock(&priv->lock); 914 mutex_lock(&priv->lock);
901 915
902 /* Sync Lock Indicator */ 916 /* Sync Lock Indicator */
@@ -1111,11 +1125,16 @@ static int xc2028_set_params(struct dvb_frontend *fe)
1111 u32 delsys = c->delivery_system; 1125 u32 delsys = c->delivery_system;
1112 u32 bw = c->bandwidth_hz; 1126 u32 bw = c->bandwidth_hz;
1113 struct xc2028_data *priv = fe->tuner_priv; 1127 struct xc2028_data *priv = fe->tuner_priv;
1114 unsigned int type=0; 1128 int rc;
1129 unsigned int type = 0;
1115 u16 demod = 0; 1130 u16 demod = 0;
1116 1131
1117 tuner_dbg("%s called\n", __func__); 1132 tuner_dbg("%s called\n", __func__);
1118 1133
1134 rc = check_device_status(priv);
1135 if (rc < 0)
1136 return rc;
1137
1119 switch (delsys) { 1138 switch (delsys) {
1120 case SYS_DVBT: 1139 case SYS_DVBT:
1121 case SYS_DVBT2: 1140 case SYS_DVBT2:
@@ -1201,7 +1220,11 @@ static int xc2028_set_params(struct dvb_frontend *fe)
1201static int xc2028_sleep(struct dvb_frontend *fe) 1220static int xc2028_sleep(struct dvb_frontend *fe)
1202{ 1221{
1203 struct xc2028_data *priv = fe->tuner_priv; 1222 struct xc2028_data *priv = fe->tuner_priv;
1204 int rc = 0; 1223 int rc;
1224
1225 rc = check_device_status(priv);
1226 if (rc < 0)
1227 return rc;
1205 1228
1206 /* Avoid firmware reload on slow devices or if PM disabled */ 1229 /* Avoid firmware reload on slow devices or if PM disabled */
1207 if (no_poweroff || priv->ctrl.disable_power_mgmt) 1230 if (no_poweroff || priv->ctrl.disable_power_mgmt)
@@ -1220,7 +1243,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
1220 else 1243 else
1221 rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00}); 1244 rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
1222 1245
1223 priv->cur_fw.type = 0; /* need firmware reload */ 1246 priv->state = XC2028_SLEEP;
1224 1247
1225 mutex_unlock(&priv->lock); 1248 mutex_unlock(&priv->lock);
1226 1249
@@ -1237,8 +1260,9 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
1237 1260
1238 /* only perform final cleanup if this is the last instance */ 1261 /* only perform final cleanup if this is the last instance */
1239 if (hybrid_tuner_report_instance_count(priv) == 1) { 1262 if (hybrid_tuner_report_instance_count(priv) == 1) {
1240 kfree(priv->ctrl.fname);
1241 free_firmware(priv); 1263 free_firmware(priv);
1264 kfree(priv->ctrl.fname);
1265 priv->ctrl.fname = NULL;
1242 } 1266 }
1243 1267
1244 if (priv) 1268 if (priv)
@@ -1254,14 +1278,42 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
1254static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) 1278static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
1255{ 1279{
1256 struct xc2028_data *priv = fe->tuner_priv; 1280 struct xc2028_data *priv = fe->tuner_priv;
1281 int rc;
1257 1282
1258 tuner_dbg("%s called\n", __func__); 1283 tuner_dbg("%s called\n", __func__);
1259 1284
1285 rc = check_device_status(priv);
1286 if (rc < 0)
1287 return rc;
1288
1260 *frequency = priv->frequency; 1289 *frequency = priv->frequency;
1261 1290
1262 return 0; 1291 return 0;
1263} 1292}
1264 1293
1294static void load_firmware_cb(const struct firmware *fw,
1295 void *context)
1296{
1297 struct dvb_frontend *fe = context;
1298 struct xc2028_data *priv = fe->tuner_priv;
1299 int rc;
1300
1301 tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
1302 if (!fw) {
1303 tuner_err("Could not load firmware %s.\n", priv->fname);
1304 priv->state = XC2028_NODEV;
1305 return;
1306 }
1307
1308 rc = load_all_firmwares(fe, fw);
1309
1310 release_firmware(fw);
1311
1312 if (rc < 0)
1313 return;
1314 priv->state = XC2028_SLEEP;
1315}
1316
1265static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) 1317static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
1266{ 1318{
1267 struct xc2028_data *priv = fe->tuner_priv; 1319 struct xc2028_data *priv = fe->tuner_priv;
@@ -1272,21 +1324,49 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
1272 1324
1273 mutex_lock(&priv->lock); 1325 mutex_lock(&priv->lock);
1274 1326
1327 /*
1328 * Copy the config data.
1329 * For the firmware name, keep a local copy of the string,
1330 * in order to avoid troubles during device release.
1331 */
1332 if (priv->ctrl.fname)
1333 kfree(priv->ctrl.fname);
1275 memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); 1334 memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
1276 if (priv->ctrl.max_len < 9)
1277 priv->ctrl.max_len = 13;
1278
1279 if (p->fname) { 1335 if (p->fname) {
1280 if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
1281 kfree(priv->ctrl.fname);
1282 free_firmware(priv);
1283 }
1284
1285 priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); 1336 priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
1286 if (priv->ctrl.fname == NULL) 1337 if (priv->ctrl.fname == NULL)
1287 rc = -ENOMEM; 1338 rc = -ENOMEM;
1288 } 1339 }
1289 1340
1341 /*
1342 * If firmware name changed, frees firmware. As free_firmware will
1343 * reset the status to NO_FIRMWARE, this forces a new request_firmware
1344 */
1345 if (!firmware_name[0] && p->fname &&
1346 priv->fname && strcmp(p->fname, priv->fname))
1347 free_firmware(priv);
1348
1349 if (priv->ctrl.max_len < 9)
1350 priv->ctrl.max_len = 13;
1351
1352 if (priv->state == XC2028_NO_FIRMWARE) {
1353 if (!firmware_name[0])
1354 priv->fname = priv->ctrl.fname;
1355 else
1356 priv->fname = firmware_name;
1357
1358 rc = request_firmware_nowait(THIS_MODULE, 1,
1359 priv->fname,
1360 priv->i2c_props.adap->dev.parent,
1361 GFP_KERNEL,
1362 fe, load_firmware_cb);
1363 if (rc < 0) {
1364 tuner_err("Failed to request firmware %s\n",
1365 priv->fname);
1366 priv->state = XC2028_NODEV;
1367 }
1368 priv->state = XC2028_WAITING_FIRMWARE;
1369 }
1290 mutex_unlock(&priv->lock); 1370 mutex_unlock(&priv->lock);
1291 1371
1292 return rc; 1372 return rc;