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

Commit dbb89d61 authored by Govindaraj Rajagopal's avatar Govindaraj Rajagopal
Browse files

msm: vidc: keep memory_size_limit check for new session



do not allow to open new session, if total video consumed
memory is beyond allowed memory_size_max_limit for video.

Change-Id: I6bfade01f99bae24691254744adf7ce38de51fdd
Signed-off-by: default avatarGovindaraj Rajagopal <grajagop@codeaurora.org>
parent 21b5e42b
Loading
Loading
Loading
Loading
+15 −1
Original line number Original line Diff line number Diff line
@@ -800,8 +800,15 @@ static inline int start_streaming(struct msm_vidc_inst *inst)


	b.buffer_type = HFI_BUFFER_OUTPUT;
	b.buffer_type = HFI_BUFFER_OUTPUT;
	if (inst->session_type == MSM_VIDC_DECODER &&
	if (inst->session_type == MSM_VIDC_DECODER &&
		is_secondary_output_mode(inst))
		is_secondary_output_mode(inst)) {
		b.buffer_type = HFI_BUFFER_OUTPUT2;
		b.buffer_type = HFI_BUFFER_OUTPUT2;
		rc = msm_comm_update_dpb_bufreqs(inst);
		if (rc) {
			s_vpr_e(inst->sid,
				"%s: set dpb bufreq failed\n", __func__);
			goto fail_start;
		}
	}


	/* Check if current session is under HW capability */
	/* Check if current session is under HW capability */
	rc = msm_vidc_check_session_supported(inst);
	rc = msm_vidc_check_session_supported(inst);
@@ -840,6 +847,13 @@ static inline int start_streaming(struct msm_vidc_inst *inst)


	rc = msm_comm_try_get_bufreqs(inst);
	rc = msm_comm_try_get_bufreqs(inst);


	rc = msm_comm_check_memory_supported(inst);
	if (rc) {
		s_vpr_e(inst->sid,
			"Memory not sufficient to proceed current session\n");
		goto fail_start;
	}

	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	b.buffer_size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
	b.buffer_size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
	rc = call_hfi_op(hdev, session_set_property,
	rc = call_hfi_op(hdev, session_set_property,
+287 −32
Original line number Original line Diff line number Diff line
@@ -3214,6 +3214,185 @@ static int msm_comm_session_init(int flipped_state,
	return rc;
	return rc;
}
}


int msm_comm_update_dpb_bufreqs(struct msm_vidc_inst *inst)
{
	struct hal_buffer_requirements *req = NULL;
	struct msm_vidc_format *fmt;
	struct v4l2_format *f;
	u32 i, hfi_fmt, rc = 0;

	if (!inst) {
		d_vpr_e("%s: invalid parameters\n", __func__);
		return -EINVAL;
	}

	if (msm_comm_get_stream_output_mode(inst) !=
		HAL_VIDEO_DECODER_SECONDARY)
		return 0;

	for (i = 0; i < HAL_BUFFER_MAX; i++) {
		if (inst->buff_req.buffer[i].buffer_type == HAL_BUFFER_OUTPUT) {
			req = &inst->buff_req.buffer[i];
			break;
		}
	}

	if (!req) {
		s_vpr_e(inst->sid, "%s: req not found\n", __func__);
		return -EINVAL;
	}

	fmt = &inst->fmts[OUTPUT_PORT];
	/* For DPB buffers, Always use min count */
	req->buffer_count_actual = fmt->count_min;

	hfi_fmt = msm_comm_convert_color_fmt(inst->clk_data.dpb_fourcc,
					inst->sid);
	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	req->buffer_size = VENUS_BUFFER_SIZE(hfi_fmt, f->fmt.pix_mp.width,
			f->fmt.pix_mp.height);

	return rc;
}

static int msm_comm_get_dpb_bufreqs(struct msm_vidc_inst *inst,
	struct hal_buffer_requirements *req)
{
	struct hal_buffer_requirements *dpb = NULL;
	u32 i;

	if (!inst || !req) {
		d_vpr_e("%s: invalid parameters\n", __func__);
		return -EINVAL;
	}

	if (msm_comm_get_stream_output_mode(inst) !=
		HAL_VIDEO_DECODER_SECONDARY)
		return 0;

	for (i = 0; i < HAL_BUFFER_MAX; i++) {
		if (inst->buff_req.buffer[i].buffer_type == HAL_BUFFER_OUTPUT) {
			dpb = &inst->buff_req.buffer[i];
			break;
		}
	}

	if (!dpb) {
		s_vpr_e(inst->sid, "%s: req not found\n", __func__);
		return -EINVAL;
	}

	memcpy(req, dpb, sizeof(struct hal_buffer_requirements));

	return 0;
}

static void msm_comm_print_mem_usage(struct msm_vidc_core *core)
{
	struct msm_vidc_inst *inst;
	struct msm_vidc_format *inp_f, *out_f;
	u32 dpb_cnt, dpb_size, i = 0, rc = 0;
	struct v4l2_pix_format_mplane *iplane, *oplane;
	u32 sz_i, sz_i_e, sz_o, sz_o_e, sz_s, sz_s1, sz_s2, sz_p, sz_p1, sz_r;
	u32 cnt_i, cnt_o, cnt_s, cnt_s1, cnt_s2, cnt_p, cnt_p1, cnt_r;
	u64 total;

	d_vpr_e("Running instances - mem breakup:\n");
	d_vpr_e(
		"%4s|%4s|%24s|%24s|%24s|%24s|%24s|%10s|%10s|%10s|%10s|%10s|%10s|%10s\n",
		"w", "h", "in", "extra_in", "out", "extra_out",
		"out2", "scratch", "scratch_1", "scratch_2",
		"persist", "persist_1", "recon", "total_kb");
	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		dpb_cnt = dpb_size = total = 0;
		sz_s = sz_s1 = sz_s2 = sz_p = sz_p1 = sz_r = 0;
		cnt_s = cnt_s1 = cnt_s2 = cnt_p = cnt_p1 = cnt_r = 0;

		inp_f = &inst->fmts[INPUT_PORT];
		out_f = &inst->fmts[OUTPUT_PORT];
		iplane = &inp_f->v4l2_fmt.fmt.pix_mp;
		oplane = &out_f->v4l2_fmt.fmt.pix_mp;

		if (msm_comm_get_stream_output_mode(inst) ==
			HAL_VIDEO_DECODER_SECONDARY) {
			struct hal_buffer_requirements dpb = {0};

			rc = msm_comm_get_dpb_bufreqs(inst, &dpb);
			if (rc) {
				s_vpr_e(inst->sid,
					"%s: get dpb bufreq failed\n",
					__func__);
				goto error;
			}
			dpb_cnt = dpb.buffer_count_actual;
			dpb_size = dpb.buffer_size;
		}
		for (i = 0; i < HAL_BUFFER_MAX; i++) {
			struct hal_buffer_requirements *req;

			req = &inst->buff_req.buffer[i];
			switch (req->buffer_type) {
			case HAL_BUFFER_INTERNAL_SCRATCH:
				sz_s  = req->buffer_size;
				cnt_s = req->buffer_count_actual;
				break;
			case HAL_BUFFER_INTERNAL_SCRATCH_1:
				sz_s1  = req->buffer_size;
				cnt_s1 = req->buffer_count_actual;
				break;
			case HAL_BUFFER_INTERNAL_SCRATCH_2:
				sz_s2  = req->buffer_size;
				cnt_s2 = req->buffer_count_actual;
				break;
			case HAL_BUFFER_INTERNAL_PERSIST:
				sz_p  = req->buffer_size;
				cnt_p = req->buffer_count_actual;
				break;
			case HAL_BUFFER_INTERNAL_PERSIST_1:
				sz_p1  = req->buffer_size;
				cnt_p1 = req->buffer_count_actual;
				break;
			case HAL_BUFFER_INTERNAL_RECON:
				sz_r  = req->buffer_size;
				cnt_r = req->buffer_count_actual;
				break;
			default:
				break;
			}
		}
		sz_i = iplane->plane_fmt[0].sizeimage;
		sz_i_e = iplane->plane_fmt[1].sizeimage;
		cnt_i = inp_f->count_actual;

		sz_o = oplane->plane_fmt[0].sizeimage;
		sz_o_e = oplane->plane_fmt[1].sizeimage;
		cnt_o = out_f->count_actual;

		total = sz_i * cnt_i + sz_i_e * cnt_i + sz_o * cnt_o +
			sz_o_e * cnt_o + dpb_cnt * dpb_size + sz_s * cnt_s +
			sz_s1 * cnt_s1 + sz_s2 * cnt_s2 + sz_p * cnt_p +
			sz_p1 * cnt_p1 + sz_r * cnt_r;
		total = total >> 10;

		s_vpr_e(inst->sid,
			"%4d|%4d|%11u(%8ux%2u)|%11u(%8ux%2u)|%11u(%8ux%2u)|%11u(%8ux%2u)|%11u(%8ux%2u)|%10u|%10u|%10u|%10u|%10u|%10u|%10llu\n",
			max(iplane->width, oplane->width),
			max(iplane->height, oplane->height),
			sz_i * cnt_i, sz_i, cnt_i,
			sz_i_e * cnt_i, sz_i_e, cnt_i,
			sz_o * cnt_o, sz_o, cnt_o,
			sz_o_e * cnt_o, sz_o_e, cnt_o,
			dpb_size * dpb_cnt, dpb_size, dpb_cnt,
			sz_s * cnt_s, sz_s1 * cnt_s1,
			sz_s2 * cnt_s2, sz_p * cnt_p, sz_p1 * cnt_p1,
			sz_r * cnt_r, total);
	}
error:
	mutex_unlock(&core->lock);

}

static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
{
{
	struct msm_vidc_inst *temp;
	struct msm_vidc_inst *temp;
@@ -3589,27 +3768,26 @@ static int set_dpb_only_buffers(struct msm_vidc_inst *inst,
{
{
	int rc = 0;
	int rc = 0;
	struct internal_buf *binfo = NULL;
	struct internal_buf *binfo = NULL;
	u32 smem_flags = SMEM_UNCACHED, buffer_size, num_buffers, hfi_fmt;
	u32 smem_flags = SMEM_UNCACHED, buffer_size = 0, num_buffers = 0;
	struct msm_vidc_format *fmt;
	unsigned int i;
	unsigned int i;
	struct hfi_device *hdev;
	struct hfi_device *hdev;
	struct hfi_buffer_size_minimum b;
	struct hfi_buffer_size_minimum b;
	struct v4l2_format *f;
	struct v4l2_format *f;
	struct hal_buffer_requirements dpb = {0};


	hdev = inst->core->device;
	hdev = inst->core->device;


	fmt = &inst->fmts[OUTPUT_PORT];
	rc = msm_comm_get_dpb_bufreqs(inst, &dpb);
	if (rc) {
		s_vpr_e(inst->sid, "Couldn't retrieve dpb count & size\n");
		return -EINVAL;
	}
	num_buffers = dpb.buffer_count_actual;
	buffer_size = dpb.buffer_size;
	s_vpr_h(inst->sid, "dpb: cnt = %d, size = %d\n",
		num_buffers, buffer_size);


	/* For DPB buffers, Always use min count */
	num_buffers = fmt->count_min;
	hfi_fmt = msm_comm_convert_color_fmt(inst->clk_data.dpb_fourcc,
					inst->sid);
	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	buffer_size = VENUS_BUFFER_SIZE(hfi_fmt, f->fmt.pix_mp.width,
			f->fmt.pix_mp.height);
	s_vpr_h(inst->sid, "output: num = %d, size = %d\n",
		num_buffers,
		buffer_size);


	b.buffer_type = get_hfi_buffer(buffer_type, inst->sid);
	b.buffer_type = get_hfi_buffer(buffer_type, inst->sid);
	if (!b.buffer_type)
	if (!b.buffer_type)
@@ -4697,14 +4875,6 @@ int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
{
{
	int rc = -EINVAL, i = 0;
	int rc = -EINVAL, i = 0;
	union hal_get_property hprop;
	union hal_get_property hprop;
	enum hal_buffer int_buf[] = {
			HAL_BUFFER_INTERNAL_SCRATCH,
			HAL_BUFFER_INTERNAL_SCRATCH_1,
			HAL_BUFFER_INTERNAL_SCRATCH_2,
			HAL_BUFFER_INTERNAL_PERSIST,
			HAL_BUFFER_INTERNAL_PERSIST_1,
			HAL_BUFFER_INTERNAL_RECON,
	};


	memset(&hprop, 0x0, sizeof(hprop));
	memset(&hprop, 0x0, sizeof(hprop));
	/*
	/*
@@ -4733,8 +4903,13 @@ int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
		}
		}


		/* reset internal buffers */
		/* reset internal buffers */
		for (i = 0; i < ARRAY_SIZE(int_buf); i++)
		for (i = 0; i < HAL_BUFFER_MAX; i++) {
			msm_comm_reset_bufreqs(inst, int_buf[i]);
			struct hal_buffer_requirements *req;

			req = &inst->buff_req.buffer[i];
			if (is_internal_buffer(req->buffer_type))
				msm_comm_reset_bufreqs(inst, req->buffer_type);
		}


		for (i = 0; i < HAL_BUFFER_MAX; i++) {
		for (i = 0; i < HAL_BUFFER_MAX; i++) {
			struct hal_buffer_requirements req;
			struct hal_buffer_requirements req;
@@ -4750,16 +4925,7 @@ int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
			if (!curr_req)
			if (!curr_req)
				return -EINVAL;
				return -EINVAL;


			if (req.buffer_type == HAL_BUFFER_INTERNAL_SCRATCH ||
			if (is_internal_buffer(req.buffer_type)) {
				req.buffer_type ==
					HAL_BUFFER_INTERNAL_SCRATCH_1 ||
				req.buffer_type ==
					HAL_BUFFER_INTERNAL_SCRATCH_2 ||
				req.buffer_type ==
					HAL_BUFFER_INTERNAL_PERSIST ||
				req.buffer_type ==
					HAL_BUFFER_INTERNAL_PERSIST_1 ||
				req.buffer_type == HAL_BUFFER_INTERNAL_RECON) {
				memcpy(curr_req, &req,
				memcpy(curr_req, &req,
					sizeof(struct hal_buffer_requirements));
					sizeof(struct hal_buffer_requirements));
			}
			}
@@ -5569,6 +5735,95 @@ static int msm_vidc_check_mbpf_supported(struct msm_vidc_inst *inst)
	return 0;
	return 0;
}
}


static u32 msm_comm_get_memory_limit(struct msm_vidc_core *core)
{
	struct memory_limit_table *memory_limits_tbl;
	u32 memory_limits_tbl_size = 0;
	u32 i, memory_limit = 0, memory_size = 0;
	u32 memory_limit_mbytes = 0;

	memory_limits_tbl = core->resources.mem_limit_tbl;
	memory_limits_tbl_size = core->resources.memory_limit_table_size;
	memory_limit_mbytes = ((u64)totalram_pages * PAGE_SIZE) >> 20;
	for (i = memory_limits_tbl_size - 1; i >= 0; i--) {
		memory_size = memory_limits_tbl[i].ddr_size;
		memory_limit = memory_limits_tbl[i].mem_limit;
		if (memory_size >= memory_limit_mbytes)
			break;
	}

	return memory_limit;
}

int msm_comm_check_memory_supported(struct msm_vidc_inst *vidc_inst)
{
	struct msm_vidc_core *core;
	struct msm_vidc_inst *inst;
	struct msm_vidc_format *fmt;
	struct v4l2_format *f;
	struct hal_buffer_requirements *req;
	u32 i, dpb_cnt = 0, dpb_size = 0, rc = 0;
	u64 mem_size = 0;
	u32 memory_limit_mbytes;

	core = vidc_inst->core;

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		/* input port buffers memory size */
		fmt = &inst->fmts[INPUT_PORT];
		f = &fmt->v4l2_fmt;
		for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
			mem_size += f->fmt.pix_mp.plane_fmt[i].sizeimage *
							fmt->count_actual;

		/* output port buffers memory size */
		fmt = &inst->fmts[OUTPUT_PORT];
		f = &fmt->v4l2_fmt;
		for (i = 0; i < f->fmt.pix_mp.num_planes; i++)
			mem_size += f->fmt.pix_mp.plane_fmt[i].sizeimage *
							fmt->count_actual;

		/* dpb buffers memory size */
		if (msm_comm_get_stream_output_mode(inst) ==
			HAL_VIDEO_DECODER_SECONDARY) {
			struct hal_buffer_requirements dpb = {0};

			rc = msm_comm_get_dpb_bufreqs(inst, &dpb);
			if (rc) {
				s_vpr_e(inst->sid,
					"Couldn't retrieve dpb count & size\n");
				mutex_unlock(&core->lock);
				return rc;
			}
			dpb_cnt = dpb.buffer_count_actual;
			dpb_size = dpb.buffer_size;
			mem_size += dpb_cnt * dpb_size;
		}

		/* internal buffers memory size */
		for (i = 0; i < HAL_BUFFER_MAX; i++) {
			req = &inst->buff_req.buffer[i];
			if (is_internal_buffer(req->buffer_type))
				mem_size += req->buffer_size *
						req->buffer_count_actual;
		}
	}
	mutex_unlock(&core->lock);

	memory_limit_mbytes = msm_comm_get_memory_limit(core);

	if ((mem_size >> 20) > memory_limit_mbytes) {
		s_vpr_e(vidc_inst->sid,
			"%s: video mem overshoot - reached %llu MB, max_limit %llu MB\n",
			__func__, mem_size >> 20, memory_limit_mbytes);
		msm_comm_print_mem_usage(core);
		return -EBUSY;
	}

	return 0;
}

static int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst)
static int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst)
{
{
	int num_mbs_per_sec = 0, max_load_adj = 0;
	int num_mbs_per_sec = 0, max_load_adj = 0;
+14 −0
Original line number Original line Diff line number Diff line
@@ -167,6 +167,18 @@ static inline bool is_output_buffer(struct msm_vidc_buffer *mbuf)
	return mbuf->vvb.vb2_buf.type == OUTPUT_MPLANE;
	return mbuf->vvb.vb2_buf.type == OUTPUT_MPLANE;
}
}


static inline bool is_internal_buffer(enum hal_buffer type)
{
	u32 buf_type =
		HAL_BUFFER_INTERNAL_SCRATCH |
		HAL_BUFFER_INTERNAL_SCRATCH_1 |
		HAL_BUFFER_INTERNAL_SCRATCH_2 |
		HAL_BUFFER_INTERNAL_PERSIST |
		HAL_BUFFER_INTERNAL_PERSIST_1 |
		HAL_BUFFER_INTERNAL_RECON;
	return !!(buf_type & type);
}

static inline int msm_comm_g_ctrl(struct msm_vidc_inst *inst,
static inline int msm_comm_g_ctrl(struct msm_vidc_inst *inst,
		struct v4l2_control *ctrl)
		struct v4l2_control *ctrl)
{
{
@@ -359,4 +371,6 @@ void msm_comm_clear_window_data(struct msm_vidc_inst *inst);
void msm_comm_release_window_data(struct msm_vidc_inst *inst);
void msm_comm_release_window_data(struct msm_vidc_inst *inst);
int msm_comm_set_cvp_skip_ratio(struct msm_vidc_inst *inst,
int msm_comm_set_cvp_skip_ratio(struct msm_vidc_inst *inst,
	uint32_t capture_rate, uint32_t cvp_rate);
	uint32_t capture_rate, uint32_t cvp_rate);
int msm_comm_check_memory_supported(struct msm_vidc_inst *vidc_inst);
int msm_comm_update_dpb_bufreqs(struct msm_vidc_inst *inst);
#endif
#endif
+12 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,15 @@ enum clock_properties {
	CLOCK_PROP_HAS_MEM_RETENTION    = 1 << 1,
	CLOCK_PROP_HAS_MEM_RETENTION    = 1 << 1,
};
};


static struct memory_limit_table memory_limit_tbl_mbytes[] = {
	/* target_memory_size - max_video_cap */
	{12288, 4096},  /* 12 GB - 4 Gb*/
	{8192, 3584},   /*  8 GB - 3.5 Gb*/
	{6144, 2560},   /*  6 GB - 2.5 Gb*/
	{4096, 1536},   /*  4 GB - 1.5 Gb*/
	{2048, 768},    /*  2 GB - 0.75 Gb*/
};

static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
{
{
	return NULL;
	return NULL;
@@ -757,6 +766,9 @@ int read_platform_resources_from_drv_data(
	res->codec_data = platform_data->codec_data;
	res->codec_data = platform_data->codec_data;


	res->sku_version = platform_data->sku_version;
	res->sku_version = platform_data->sku_version;
	res->mem_limit_tbl = memory_limit_tbl_mbytes;
	res->memory_limit_table_size =
		ARRAY_SIZE(memory_limit_tbl_mbytes);


	res->fw_name = "venus";
	res->fw_name = "venus";


+7 −0
Original line number Original line Diff line number Diff line
@@ -107,6 +107,11 @@ struct allowed_clock_rates_table {
	u32 clock_rate;
	u32 clock_rate;
};
};


struct memory_limit_table {
	u32 ddr_size; /* mega bytes */
	u32 mem_limit; /* mega bytes */
};

struct clock_profile_entry {
struct clock_profile_entry {
	u32 codec_mask;
	u32 codec_mask;
	u32 vpp_cycles;
	u32 vpp_cycles;
@@ -144,6 +149,8 @@ struct msm_vidc_platform_resources {
	struct allowed_clock_rates_table *allowed_clks_tbl;
	struct allowed_clock_rates_table *allowed_clks_tbl;
	u32 allowed_clks_tbl_size;
	u32 allowed_clks_tbl_size;
	struct clock_freq_table clock_freq_tbl;
	struct clock_freq_table clock_freq_tbl;
	struct memory_limit_table *mem_limit_tbl;
	u32 memory_limit_table_size;
	bool sys_cache_present;
	bool sys_cache_present;
	bool sys_cache_res_set;
	bool sys_cache_res_set;
	struct subcache_set subcache_set;
	struct subcache_set subcache_set;