diff options
| -rw-r--r-- | drivers/media/tuners/tuner-xc2028.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 317ef63ee789..8d96a22647b3 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c | |||
| @@ -281,6 +281,14 @@ static void free_firmware(struct xc2028_data *priv) | |||
| 281 | int i; | 281 | int i; |
| 282 | tuner_dbg("%s called\n", __func__); | 282 | tuner_dbg("%s called\n", __func__); |
| 283 | 283 | ||
| 284 | /* free allocated f/w string */ | ||
| 285 | if (priv->fname != firmware_name) | ||
| 286 | kfree(priv->fname); | ||
| 287 | priv->fname = NULL; | ||
| 288 | |||
| 289 | priv->state = XC2028_NO_FIRMWARE; | ||
| 290 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
| 291 | |||
| 284 | if (!priv->firm) | 292 | if (!priv->firm) |
| 285 | return; | 293 | return; |
| 286 | 294 | ||
| @@ -291,9 +299,6 @@ static void free_firmware(struct xc2028_data *priv) | |||
| 291 | 299 | ||
| 292 | priv->firm = NULL; | 300 | priv->firm = NULL; |
| 293 | priv->firm_size = 0; | 301 | priv->firm_size = 0; |
| 294 | priv->state = XC2028_NO_FIRMWARE; | ||
| 295 | |||
| 296 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
| 297 | } | 302 | } |
| 298 | 303 | ||
| 299 | static int load_all_firmwares(struct dvb_frontend *fe, | 304 | static int load_all_firmwares(struct dvb_frontend *fe, |
| @@ -884,9 +889,8 @@ read_not_reliable: | |||
| 884 | return 0; | 889 | return 0; |
| 885 | 890 | ||
| 886 | fail: | 891 | fail: |
| 887 | priv->state = XC2028_NO_FIRMWARE; | 892 | free_firmware(priv); |
| 888 | 893 | ||
| 889 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
| 890 | if (retry_count < 8) { | 894 | if (retry_count < 8) { |
| 891 | msleep(50); | 895 | msleep(50); |
| 892 | retry_count++; | 896 | retry_count++; |
| @@ -1332,11 +1336,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) | |||
| 1332 | mutex_lock(&xc2028_list_mutex); | 1336 | mutex_lock(&xc2028_list_mutex); |
| 1333 | 1337 | ||
| 1334 | /* only perform final cleanup if this is the last instance */ | 1338 | /* only perform final cleanup if this is the last instance */ |
| 1335 | if (hybrid_tuner_report_instance_count(priv) == 1) { | 1339 | if (hybrid_tuner_report_instance_count(priv) == 1) |
| 1336 | free_firmware(priv); | 1340 | free_firmware(priv); |
| 1337 | kfree(priv->ctrl.fname); | ||
| 1338 | priv->ctrl.fname = NULL; | ||
| 1339 | } | ||
| 1340 | 1341 | ||
| 1341 | if (priv) | 1342 | if (priv) |
| 1342 | hybrid_tuner_release_state(priv); | 1343 | hybrid_tuner_release_state(priv); |
| @@ -1399,19 +1400,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) | |||
| 1399 | 1400 | ||
| 1400 | /* | 1401 | /* |
| 1401 | * Copy the config data. | 1402 | * Copy the config data. |
| 1402 | * For the firmware name, keep a local copy of the string, | ||
| 1403 | * in order to avoid troubles during device release. | ||
| 1404 | */ | 1403 | */ |
| 1405 | kfree(priv->ctrl.fname); | ||
| 1406 | priv->ctrl.fname = NULL; | ||
| 1407 | memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); | 1404 | memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); |
| 1408 | if (p->fname) { | ||
| 1409 | priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); | ||
| 1410 | if (priv->ctrl.fname == NULL) { | ||
| 1411 | rc = -ENOMEM; | ||
| 1412 | goto unlock; | ||
| 1413 | } | ||
| 1414 | } | ||
| 1415 | 1405 | ||
| 1416 | /* | 1406 | /* |
| 1417 | * If firmware name changed, frees firmware. As free_firmware will | 1407 | * If firmware name changed, frees firmware. As free_firmware will |
| @@ -1426,10 +1416,15 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) | |||
| 1426 | 1416 | ||
| 1427 | if (priv->state == XC2028_NO_FIRMWARE) { | 1417 | if (priv->state == XC2028_NO_FIRMWARE) { |
| 1428 | if (!firmware_name[0]) | 1418 | if (!firmware_name[0]) |
| 1429 | priv->fname = priv->ctrl.fname; | 1419 | priv->fname = kstrdup(p->fname, GFP_KERNEL); |
| 1430 | else | 1420 | else |
| 1431 | priv->fname = firmware_name; | 1421 | priv->fname = firmware_name; |
| 1432 | 1422 | ||
| 1423 | if (!priv->fname) { | ||
| 1424 | rc = -ENOMEM; | ||
| 1425 | goto unlock; | ||
| 1426 | } | ||
| 1427 | |||
| 1433 | rc = request_firmware_nowait(THIS_MODULE, 1, | 1428 | rc = request_firmware_nowait(THIS_MODULE, 1, |
| 1434 | priv->fname, | 1429 | priv->fname, |
| 1435 | priv->i2c_props.adap->dev.parent, | 1430 | priv->i2c_props.adap->dev.parent, |
