Merge "msm: vidc: Delay firmware unload during session close"

This commit is contained in:
Linux Build Service Account 2014-07-16 03:59:36 -07:00 committed by Gerrit - the friendly Code Review server
commit 2914c1526d
3 changed files with 60 additions and 25 deletions

View file

@ -335,6 +335,7 @@ static int msm_vidc_initialize_core(struct platform_device *pdev,
init_completion(&core->completions[i]); init_completion(&core->completions[i]);
} }
INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
return rc; return rc;
} }

View file

@ -15,7 +15,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/workqueue.h>
#include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_restart.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "msm_vidc_common.h" #include "msm_vidc_common.h"
@ -2244,6 +2243,7 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
goto fail_load_fw; goto fail_load_fw;
} }
core->state = VIDC_CORE_LOADED; core->state = VIDC_CORE_LOADED;
dprintk(VIDC_DBG, "Firmware downloaded\n");
} }
mutex_unlock(&core->lock); mutex_unlock(&core->lock);
@ -2281,7 +2281,6 @@ fail_vote_bus:
static int msm_vidc_deinit_core(struct msm_vidc_inst *inst) static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
{ {
int rc = 0;
struct msm_vidc_core *core; struct msm_vidc_core *core;
struct hfi_device *hdev; struct hfi_device *hdev;
@ -2305,35 +2304,22 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
mutex_lock(&core->lock); mutex_lock(&core->lock);
if (list_empty(&core->instances)) { if (list_empty(&core->instances)) {
if (core->state > VIDC_CORE_INIT) { cancel_delayed_work(&core->fw_unload_work);
if (core->resources.ocmem_size) {
if (inst->state != MSM_VIDC_CORE_INVALID)
msm_comm_unset_ocmem(core);
call_hfi_op(hdev, free_ocmem,
hdev->hfi_device_data);
}
dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
rc = call_hfi_op(hdev, core_release,
hdev->hfi_device_data);
if (rc) {
dprintk(VIDC_ERR,
"Failed to release core, id = %d\n",
core->id);
goto exit;
}
}
core->state = VIDC_CORE_UNINIT; /*
* Delay unloading of firmware for 10 sec. This is useful
call_hfi_op(hdev, unload_fw, hdev->hfi_device_data); * in avoiding firmware download delays in cases where we
msm_comm_unvote_buses(core); * will have a burst of back to back video playback sessions
* e.g. thumbnail generation.
*/
schedule_delayed_work(&core->fw_unload_work,
msecs_to_jiffies(10000));
} }
core_already_uninited: core_already_uninited:
change_inst_state(inst, MSM_VIDC_CORE_UNINIT); change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
exit:
mutex_unlock(&core->lock); mutex_unlock(&core->lock);
return rc; return 0;
} }
int msm_comm_force_cleanup(struct msm_vidc_inst *inst) int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
@ -4541,3 +4527,48 @@ int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
return msm_smem_get_domain_partition(inst->mem_client, flags, return msm_smem_get_domain_partition(inst->mem_client, flags,
buffer_type, domain_num, partition_num); buffer_type, domain_num, partition_num);
} }
void msm_vidc_fw_unload_handler(struct work_struct *work)
{
struct msm_vidc_core *core = NULL;
struct hfi_device *hdev = NULL;
int rc = 0;
core = container_of(work, struct msm_vidc_core, fw_unload_work.work);
if (!core || !core->device) {
dprintk(VIDC_ERR, "%s - invalid work or core handle\n",
__func__);
return;
}
hdev = core->device;
mutex_lock(&core->lock);
if (list_empty(&core->instances) &&
core->state != VIDC_CORE_UNINIT) {
if (core->state > VIDC_CORE_INIT) {
if (core->resources.ocmem_size) {
if (core->state != VIDC_CORE_INVALID)
msm_comm_unset_ocmem(core);
call_hfi_op(hdev, free_ocmem,
hdev->hfi_device_data);
}
dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
rc = call_hfi_op(hdev, core_release,
hdev->hfi_device_data);
if (rc) {
dprintk(VIDC_ERR,
"Failed to release core, id = %d\n",
core->id);
return;
}
}
core->state = VIDC_CORE_UNINIT;
call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
dprintk(VIDC_DBG, "Firmware unloaded\n");
msm_comm_unvote_buses(core);
}
mutex_unlock(&core->lock);
}

View file

@ -20,6 +20,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/msm-bus.h> #include <linux/msm-bus.h>
#include <linux/msm-bus-board.h> #include <linux/msm-bus-board.h>
#include <soc/qcom/ocmem.h> #include <soc/qcom/ocmem.h>
@ -275,6 +276,7 @@ struct msm_vidc_core {
u32 enc_codec_supported; u32 enc_codec_supported;
u32 dec_codec_supported; u32 dec_codec_supported;
struct msm_vidc_idle_stats idle_stats; struct msm_vidc_idle_stats idle_stats;
struct delayed_work fw_unload_work;
}; };
struct msm_vidc_inst { struct msm_vidc_inst {
@ -391,4 +393,5 @@ struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
enum hal_buffer buffer_type); enum hal_buffer buffer_type);
int msm_smem_get_domain_partition(void *clt, u32 flags, enum hal_buffer int msm_smem_get_domain_partition(void *clt, u32 flags, enum hal_buffer
buffer_type, int *domain_num, int *partition_num); buffer_type, int *domain_num, int *partition_num);
void msm_vidc_fw_unload_handler(struct work_struct *work);
#endif #endif