diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c index 09d0ef4984d3..db9a4b3a7113 100644 --- a/drivers/staging/media/go7007/go7007-driver.c +++ b/drivers/staging/media/go7007/go7007-driver.c @@ -95,34 +95,34 @@ static int go7007_load_encoder(struct go7007 *go) int fw_len, rv = 0; u16 intr_val, intr_data; - if (request_firmware(&fw_entry, fw_name, go->dev)) { - v4l2_err(go, "unable to load firmware from file " - "\"%s\"\n", fw_name); - return -1; - } - if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { - v4l2_err(go, "file \"%s\" does not appear to be " - "go7007 firmware\n", fw_name); + if (go->boot_fw == NULL) { + if (request_firmware(&fw_entry, fw_name, go->dev)) { + v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name); + return -1; + } + if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { + v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name); + release_firmware(fw_entry); + return -1; + } + fw_len = fw_entry->size - 16; + bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL); + if (bounce == NULL) { + v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len); + release_firmware(fw_entry); + return -1; + } release_firmware(fw_entry); - return -1; + go->boot_fw_len = fw_len; + go->boot_fw = bounce; } - fw_len = fw_entry->size - 16; - bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL); - if (bounce == NULL) { - v4l2_err(go, "unable to allocate %d bytes for " - "firmware transfer\n", fw_len); - release_firmware(fw_entry); - return -1; - } - release_firmware(fw_entry); if (go7007_interface_reset(go) < 0 || - go7007_send_firmware(go, bounce, fw_len) < 0 || - go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || + go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 || + go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || (intr_val & ~0x1) != 0x5a5a) { v4l2_err(go, "error transferring firmware\n"); rv = -1; } - kfree(bounce); return rv; } @@ -675,6 +675,7 @@ void go7007_remove(struct go7007 *go) if (go->audio_enabled) go7007_snd_remove(go); + kfree(go->boot_fw); go7007_v4l2_remove(go); } EXPORT_SYMBOL(go7007_remove); diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h index daae6ddc4689..d390120e4db4 100644 --- a/drivers/staging/media/go7007/go7007-priv.h +++ b/drivers/staging/media/go7007/go7007-priv.h @@ -178,6 +178,8 @@ struct go7007 { int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ char name[64]; struct video_device *video_dev; + void *boot_fw; + unsigned boot_fw_len; struct v4l2_device v4l2_dev; int ref_count; enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;