Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f97647f authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: Delay firmware unload during session close



Video driver loads and unloads firmware at the start
and end of each session. Firmware download takes up
to 100 msec. When there are many b2b video sessions
e.g. thumbnail generation, this is an unnecessary
overhead. To overcome this problem, video driver will
unload the firmware 10 secs after the session is closed.
If a new session starts during this period, it will not
be required to download the firmware again.

Change-Id: Ia515c3ed89c75ea9e43852958d1cbb2d77fe4c51
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent 2049a6cf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -335,6 +335,7 @@ static int msm_vidc_initialize_core(struct platform_device *pdev,
		init_completion(&core->completions[i]);
	}

	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
	return rc;
}

+56 −25
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <soc/qcom/subsystem_restart.h>
#include <asm/div64.h>
#include "msm_vidc_common.h"
@@ -2220,6 +2219,7 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
			goto fail_load_fw;
		}
		core->state = VIDC_CORE_LOADED;
		dprintk(VIDC_DBG, "Firmware downloaded\n");
	}
	mutex_unlock(&core->lock);

@@ -2257,7 +2257,6 @@ fail_vote_bus:

static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct msm_vidc_core *core;
	struct hfi_device *hdev;

@@ -2281,35 +2280,22 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)

	mutex_lock(&core->lock);
	if (list_empty(&core->instances)) {
		if (core->state > VIDC_CORE_INIT) {
			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;
			}
		}
		cancel_delayed_work(&core->fw_unload_work);

		core->state = VIDC_CORE_UNINIT;

		call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
		msm_comm_unvote_buses(core);
		/*
		* Delay unloading of firmware for 10 sec. This is useful
		* in avoiding firmware download delays in cases where we
		* 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:
	change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
exit:
	mutex_unlock(&core->lock);
	return rc;
	return 0;
}

int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
@@ -4490,3 +4476,48 @@ int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
	return msm_smem_get_domain_partition(inst->mem_client, flags,
			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);
}
+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <soc/qcom/ocmem.h>
@@ -275,6 +276,7 @@ struct msm_vidc_core {
	u32 enc_codec_supported;
	u32 dec_codec_supported;
	struct msm_vidc_idle_stats idle_stats;
	struct delayed_work fw_unload_work;
};

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);
int msm_smem_get_domain_partition(void *clt, u32 flags, enum hal_buffer
		buffer_type, int *domain_num, int *partition_num);
void msm_vidc_fw_unload_handler(struct work_struct *work);
#endif