aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-06-21 08:36:38 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-29 18:03:56 -0400
commit177bc7dade38b5bd02dbcd008f92135b2c7a92b6 (patch)
tree7d7992fad74944f5d479193abea666e39338b439 /drivers/media/dvb
parentb37d2a3a75cb0e72e18c29336cb2095b63dabfc8 (diff)
[media] drxk: change it to use request_firmware_nowait()
The firmware blob may not be available when the driver probes. Instead of blocking the whole kernel use request_firmware_nowait() and continue without firmware. This shouldn't be that bad on drx-k devices, as they all seem to have an internal firmware. So, only the firmware update will take a little longer to happen. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.c109
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.h3
2 files changed, 72 insertions, 40 deletions
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index 60b868faeac..4cb8d1e83fb 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -5968,29 +5968,9 @@ error:
5968 return status; 5968 return status;
5969} 5969}
5970 5970
5971static int load_microcode(struct drxk_state *state, const char *mc_name)
5972{
5973 const struct firmware *fw = NULL;
5974 int err = 0;
5975
5976 dprintk(1, "\n");
5977
5978 err = request_firmware(&fw, mc_name, state->i2c->dev.parent);
5979 if (err < 0) {
5980 printk(KERN_ERR
5981 "drxk: Could not load firmware file %s.\n", mc_name);
5982 printk(KERN_INFO
5983 "drxk: Copy %s to your hotplug directory!\n", mc_name);
5984 return err;
5985 }
5986 err = DownloadMicrocode(state, fw->data, fw->size);
5987 release_firmware(fw);
5988 return err;
5989}
5990
5991static int init_drxk(struct drxk_state *state) 5971static int init_drxk(struct drxk_state *state)
5992{ 5972{
5993 int status = 0; 5973 int status = 0, n = 0;
5994 enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; 5974 enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
5995 u16 driverVersion; 5975 u16 driverVersion;
5996 5976
@@ -6073,8 +6053,12 @@ static int init_drxk(struct drxk_state *state)
6073 if (status < 0) 6053 if (status < 0)
6074 goto error; 6054 goto error;
6075 6055
6076 if (state->microcode_name) 6056 if (state->fw) {
6077 load_microcode(state, state->microcode_name); 6057 status = DownloadMicrocode(state, state->fw->data,
6058 state->fw->size);
6059 if (status < 0)
6060 goto error;
6061 }
6078 6062
6079 /* disable token-ring bus through OFDM block for possible ucode upload */ 6063 /* disable token-ring bus through OFDM block for possible ucode upload */
6080 status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); 6064 status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
@@ -6167,6 +6151,20 @@ static int init_drxk(struct drxk_state *state)
6167 state->m_DrxkState = DRXK_POWERED_DOWN; 6151 state->m_DrxkState = DRXK_POWERED_DOWN;
6168 } else 6152 } else
6169 state->m_DrxkState = DRXK_STOPPED; 6153 state->m_DrxkState = DRXK_STOPPED;
6154
6155 /* Initialize the supported delivery systems */
6156 n = 0;
6157 if (state->m_hasDVBC) {
6158 state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
6159 state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
6160 strlcat(state->frontend.ops.info.name, " DVB-C",
6161 sizeof(state->frontend.ops.info.name));
6162 }
6163 if (state->m_hasDVBT) {
6164 state->frontend.ops.delsys[n++] = SYS_DVBT;
6165 strlcat(state->frontend.ops.info.name, " DVB-T",
6166 sizeof(state->frontend.ops.info.name));
6167 }
6170 } 6168 }
6171error: 6169error:
6172 if (status < 0) 6170 if (status < 0)
@@ -6175,11 +6173,44 @@ error:
6175 return status; 6173 return status;
6176} 6174}
6177 6175
6176static void load_firmware_cb(const struct firmware *fw,
6177 void *context)
6178{
6179 struct drxk_state *state = context;
6180
6181 if (!fw) {
6182 printk(KERN_ERR
6183 "drxk: Could not load firmware file %s.\n",
6184 state->microcode_name);
6185 printk(KERN_INFO
6186 "drxk: Copy %s to your hotplug directory!\n",
6187 state->microcode_name);
6188 state->microcode_name = NULL;
6189
6190 /*
6191 * As firmware is now load asynchronous, it is not possible
6192 * anymore to fail at frontend attach. We might silently
6193 * return here, and hope that the driver won't crash.
6194 * We might also change all DVB callbacks to return -ENODEV
6195 * if the device is not initialized.
6196 * As the DRX-K devices have their own internal firmware,
6197 * let's just hope that it will match a firmware revision
6198 * compatible with this driver and proceed.
6199 */
6200 }
6201 state->fw = fw;
6202
6203 init_drxk(state);
6204}
6205
6178static void drxk_release(struct dvb_frontend *fe) 6206static void drxk_release(struct dvb_frontend *fe)
6179{ 6207{
6180 struct drxk_state *state = fe->demodulator_priv; 6208 struct drxk_state *state = fe->demodulator_priv;
6181 6209
6182 dprintk(1, "\n"); 6210 dprintk(1, "\n");
6211 if (state->fw)
6212 release_firmware(state->fw);
6213
6183 kfree(state); 6214 kfree(state);
6184} 6215}
6185 6216
@@ -6371,10 +6402,9 @@ static struct dvb_frontend_ops drxk_ops = {
6371struct dvb_frontend *drxk_attach(const struct drxk_config *config, 6402struct dvb_frontend *drxk_attach(const struct drxk_config *config,
6372 struct i2c_adapter *i2c) 6403 struct i2c_adapter *i2c)
6373{ 6404{
6374 int n;
6375
6376 struct drxk_state *state = NULL; 6405 struct drxk_state *state = NULL;
6377 u8 adr = config->adr; 6406 u8 adr = config->adr;
6407 int status;
6378 6408
6379 dprintk(1, "\n"); 6409 dprintk(1, "\n");
6380 state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL); 6410 state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
@@ -6425,22 +6455,21 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
6425 state->frontend.demodulator_priv = state; 6455 state->frontend.demodulator_priv = state;
6426 6456
6427 init_state(state); 6457 init_state(state);
6428 if (init_drxk(state) < 0)
6429 goto error;
6430 6458
6431 /* Initialize the supported delivery systems */ 6459 /* Load firmware and initialize DRX-K */
6432 n = 0; 6460 if (state->microcode_name) {
6433 if (state->m_hasDVBC) { 6461 status = request_firmware_nowait(THIS_MODULE, 1,
6434 state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; 6462 state->microcode_name,
6435 state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; 6463 state->i2c->dev.parent,
6436 strlcat(state->frontend.ops.info.name, " DVB-C", 6464 GFP_KERNEL,
6437 sizeof(state->frontend.ops.info.name)); 6465 state, load_firmware_cb);
6438 } 6466 if (status < 0) {
6439 if (state->m_hasDVBT) { 6467 printk(KERN_ERR
6440 state->frontend.ops.delsys[n++] = SYS_DVBT; 6468 "drxk: failed to request a firmware\n");
6441 strlcat(state->frontend.ops.info.name, " DVB-T", 6469 return NULL;
6442 sizeof(state->frontend.ops.info.name)); 6470 }
6443 } 6471 } else if (init_drxk(state) < 0)
6472 goto error;
6444 6473
6445 printk(KERN_INFO "drxk: frontend initialized.\n"); 6474 printk(KERN_INFO "drxk: frontend initialized.\n");
6446 return &state->frontend; 6475 return &state->frontend;
diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h
index 4bbf841de83..36677cdc01d 100644
--- a/drivers/media/dvb/frontends/drxk_hard.h
+++ b/drivers/media/dvb/frontends/drxk_hard.h
@@ -338,7 +338,10 @@ struct drxk_state {
338 bool antenna_dvbt; 338 bool antenna_dvbt;
339 u16 antenna_gpio; 339 u16 antenna_gpio;
340 340
341 /* Firmware */
341 const char *microcode_name; 342 const char *microcode_name;
343 struct completion fw_wait_load;
344 const struct firmware *fw;
342}; 345};
343 346
344#define NEVER_LOCK 0 347#define NEVER_LOCK 0