aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-xc2028.c
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 04:06:08 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:26 -0500
commit06fd82dc7bdc6045bf8d6c1438d2a33ffb1cf337 (patch)
treef48a2b413ab38ca51cd1db2dc72b93f2f4e093a5 /drivers/media/video/tuner-xc2028.c
parentb32f9fb962d593e3c5a61092a79434714f405ef5 (diff)
V4L/DVB (6638): xc2028: firmware loading cleanup
Hold the private lock over set_config and set priv->firm_size to 0 after a failed firmware load to prevent firmware accidentally being freed on us. Clean up the firmware load/error messages somewhat and rename priv->version to priv->firm_version to make it clear which "version" it is. Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r--drivers/media/video/tuner-xc2028.c82
1 files changed, 38 insertions, 44 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
index 7e558decad84..7c86971a8d64 100644
--- a/drivers/media/video/tuner-xc2028.c
+++ b/drivers/media/video/tuner-xc2028.c
@@ -65,8 +65,7 @@ struct xc2028_data {
65 65
66 struct firmware_description *firm; 66 struct firmware_description *firm;
67 int firm_size; 67 int firm_size;
68 68 __u16 firm_version;
69 __u16 version;
70 69
71 struct xc2028_ctrl ctrl; 70 struct xc2028_ctrl ctrl;
72 71
@@ -237,6 +236,7 @@ static void free_firmware(struct xc2028_data *priv)
237 kfree(priv->firm); 236 kfree(priv->firm);
238 237
239 priv->firm = NULL; 238 priv->firm = NULL;
239 priv->firm_size = 0;
240 priv->need_load_generic = 1; 240 priv->need_load_generic = 1;
241} 241}
242 242
@@ -251,7 +251,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
251 251
252 tuner_dbg("%s called\n", __FUNCTION__); 252 tuner_dbg("%s called\n", __FUNCTION__);
253 253
254 tuner_info("Reading firmware %s\n", priv->ctrl.fname); 254 tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
255 rc = request_firmware(&fw, priv->ctrl.fname, 255 rc = request_firmware(&fw, priv->ctrl.fname,
256 &priv->i2c_props.adap->dev); 256 &priv->i2c_props.adap->dev);
257 if (rc < 0) { 257 if (rc < 0) {
@@ -267,40 +267,34 @@ static int load_all_firmwares(struct dvb_frontend *fe)
267 p = fw->data; 267 p = fw->data;
268 endp = p + fw->size; 268 endp = p + fw->size;
269 269
270 if (fw->size < sizeof(name) - 1 + 2) { 270 if (fw->size < sizeof(name) - 1 + 2 + 2) {
271 tuner_err("Error: firmware size is zero!\n"); 271 tuner_err("Error: firmware file %s has invalid size!\n",
272 rc = -EINVAL; 272 priv->ctrl.fname);
273 goto done; 273 goto corrupt;
274 } 274 }
275 275
276 memcpy(name, p, sizeof(name) - 1); 276 memcpy(name, p, sizeof(name) - 1);
277 name[sizeof(name) - 1] = 0; 277 name[sizeof(name) - 1] = 0;
278 p += sizeof(name) - 1; 278 p += sizeof(name) - 1;
279 279
280 priv->version = le16_to_cpu(*(__u16 *) p); 280 priv->firm_version = le16_to_cpu(*(__u16 *) p);
281 p += 2; 281 p += 2;
282 282
283 tuner_info("Firmware: %s, ver %d.%d\n", name,
284 priv->version >> 8, priv->version & 0xff);
285
286 if (p + 2 > endp)
287 goto corrupt;
288
289 n_array = le16_to_cpu(*(__u16 *) p); 283 n_array = le16_to_cpu(*(__u16 *) p);
290 p += 2; 284 p += 2;
291 285
292 tuner_info("There are %d firmwares at %s\n", 286 tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
293 n_array, priv->ctrl.fname); 287 n_array, priv->ctrl.fname, name,
288 priv->firm_version >> 8, priv->firm_version & 0xff);
294 289
295 priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL); 290 priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
296 291 if (priv->firm == NULL) {
297 if (!fw) { 292 tuner_err("Not enough memory to load firmware file.\n");
298 tuner_err("Not enough memory for reading firmware.\n");
299 rc = -ENOMEM; 293 rc = -ENOMEM;
300 goto done; 294 goto err;
301 } 295 }
302
303 priv->firm_size = n_array; 296 priv->firm_size = n_array;
297
304 n = -1; 298 n = -1;
305 while (p < endp) { 299 while (p < endp) {
306 __u32 type, size; 300 __u32 type, size;
@@ -308,7 +302,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
308 302
309 n++; 303 n++;
310 if (n >= n_array) { 304 if (n >= n_array) {
311 tuner_err("Too much firmwares at the file\n"); 305 tuner_err("More firmware images in file than "
306 "were expected!\n");
312 goto corrupt; 307 goto corrupt;
313 } 308 }
314 309
@@ -338,15 +333,17 @@ static int load_all_firmwares(struct dvb_frontend *fe)
338 } 333 }
339 334
340 priv->firm[n].ptr = kzalloc(size, GFP_KERNEL); 335 priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
341 if (!priv->firm[n].ptr) { 336 if (priv->firm[n].ptr == NULL) {
342 tuner_err("Not enough memory.\n"); 337 tuner_err("Not enough memory to load firmware file.\n");
343 rc = -ENOMEM; 338 rc = -ENOMEM;
344 goto err; 339 goto err;
345 } 340 }
346 tuner_info("Reading firmware type "); 341 tuner_dbg("Reading firmware type ");
347 dump_firm_type(type); 342 if (debug) {
348 printk("(%x), id %llx, size=%d.\n", 343 dump_firm_type(type);
349 type, (unsigned long long)id, size); 344 printk("(%x), id %llx, size=%d.\n",
345 type, (unsigned long long)id, size);
346 }
350 347
351 memcpy(priv->firm[n].ptr, p, size); 348 memcpy(priv->firm[n].ptr, p, size);
352 priv->firm[n].type = type; 349 priv->firm[n].type = type;
@@ -368,13 +365,13 @@ corrupt:
368 tuner_err("Error: firmware file is corrupted!\n"); 365 tuner_err("Error: firmware file is corrupted!\n");
369 366
370err: 367err:
371 tuner_info("Releasing loaded firmware file.\n"); 368 tuner_info("Releasing partially loaded firmware file.\n");
372
373 free_firmware(priv); 369 free_firmware(priv);
374 370
375done: 371done:
376 release_firmware(fw); 372 release_firmware(fw);
377 tuner_dbg("Firmware files loaded.\n"); 373 if (rc == 0)
374 tuner_dbg("Firmware files loaded.\n");
378 375
379 return rc; 376 return rc;
380} 377}
@@ -442,11 +439,6 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
442 printk("(%x), id %016llx.\n", type, (unsigned long long)*id); 439 printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
443 440
444 p = priv->firm[pos].ptr; 441 p = priv->firm[pos].ptr;
445
446 if (!p) {
447 tuner_err("Firmware pointer were freed!");
448 return -EINVAL;
449 }
450 endp = p + priv->firm[pos].size; 442 endp = p + priv->firm[pos].size;
451 443
452 while (p < endp) { 444 while (p < endp) {
@@ -546,15 +538,10 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
546 538
547 p = priv->firm[pos].ptr; 539 p = priv->firm[pos].ptr;
548 540
549 if (!p) {
550 tuner_err("Firmware pointer were freed!");
551 return -EINVAL;
552 }
553
554 if ((priv->firm[pos].size != 12 * 16) || (scode >= 16)) 541 if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
555 return -EINVAL; 542 return -EINVAL;
556 543
557 if (priv->version < 0x0202) 544 if (priv->firm_version < 0x0202)
558 rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00}); 545 rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
559 else 546 else
560 rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00}); 547 rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
@@ -783,7 +770,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
783 770
784 /* CMD= Set frequency */ 771 /* CMD= Set frequency */
785 772
786 if (priv->version < 0x0202) 773 if (priv->firm_version < 0x0202)
787 rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00}); 774 rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
788 else 775 else
789 rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00}); 776 rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
@@ -868,6 +855,7 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
868 855
869 free_firmware(priv); 856 free_firmware(priv);
870 kfree(priv); 857 kfree(priv);
858 fe->tuner_priv = NULL;
871 } 859 }
872 860
873 mutex_unlock(&xc2028_list_mutex); 861 mutex_unlock(&xc2028_list_mutex);
@@ -893,14 +881,18 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
893 881
894 tuner_dbg("%s called\n", __FUNCTION__); 882 tuner_dbg("%s called\n", __FUNCTION__);
895 883
884 mutex_lock(&priv->lock);
885
896 priv->ctrl.type = p->type; 886 priv->ctrl.type = p->type;
897 887
898 if (p->fname) { 888 if (p->fname) {
899 kfree(priv->ctrl.fname); 889 kfree(priv->ctrl.fname);
900 890
901 priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL); 891 priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL);
902 if (!priv->ctrl.fname) 892 if (priv->ctrl.fname == NULL) {
893 mutex_unlock(&priv->lock);
903 return -ENOMEM; 894 return -ENOMEM;
895 }
904 896
905 free_firmware(priv); 897 free_firmware(priv);
906 strcpy(priv->ctrl.fname, p->fname); 898 strcpy(priv->ctrl.fname, p->fname);
@@ -909,6 +901,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
909 if (p->max_len > 0) 901 if (p->max_len > 0)
910 priv->max_len = p->max_len; 902 priv->max_len = p->max_len;
911 903
904 mutex_unlock(&priv->lock);
905
912 return 0; 906 return 0;
913} 907}
914 908