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

Commit 6dd037c9 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mdss: rotator: add trace and debug logs"

parents 7622cba3 258191ea
Loading
Loading
Loading
Loading
+145 −56
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#include "mdss_rotator_internal.h"
#include "mdss_mdp.h"
#include "mdss_debug.h"

/* waiting for hw time out, 3 vsync for 30fps*/
#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100
@@ -72,6 +73,7 @@ static int mdss_rotator_bus_scale_set_quota(struct mdss_rot_bus_data_type *bus,
		u64 quota)
{
	int new_uc_idx;
	int ret;

	if (bus->bus_hdl < 1) {
		pr_err("invalid bus handle %d\n", bus->bus_hdl);
@@ -113,8 +115,13 @@ static int mdss_rotator_bus_scale_set_quota(struct mdss_rot_bus_data_type *bus,
	bus->curr_quota_val = quota;

	pr_debug("uc_idx=%d quota=%llu\n", new_uc_idx, quota);
	return msm_bus_scale_client_update_request(bus->bus_hdl,
	MDSS_XLOG(new_uc_idx, ((quota >> 32) & 0xFFFFFFFF),
		(quota & 0xFFFFFFFF));
	ATRACE_BEGIN("msm_bus_scale_req_rot");
	ret = msm_bus_scale_client_update_request(bus->bus_hdl,
		new_uc_idx);
	ATRACE_END("msm_bus_scale_req_rot");
	return ret;
}

static int mdss_rotator_enable_reg_bus(struct mdss_rot_mgr *mgr, u64 quota)
@@ -136,9 +143,12 @@ static int mdss_rotator_enable_reg_bus(struct mdss_rot_mgr *mgr, u64 quota)
	pr_debug("%s, changed=%d register bus %s\n", __func__, changed,
		quota ? "Enable":"Disable");

	if (changed)
	if (changed) {
		ATRACE_BEGIN("msm_bus_scale_req_rot_reg");
		ret = msm_bus_scale_client_update_request(mgr->reg_bus.bus_hdl,
			usecase_ndx);
		ATRACE_END("msm_bus_scale_req_rot_reg");
	}

	return ret;
}
@@ -160,12 +170,13 @@ static unsigned long mdss_rotator_clk_rate_calc(
	mutex_lock(&private->perf_lock);
	list_for_each_entry(perf, &private->perf_list, list) {
		bool rate_accounted_for = false;
		mutex_lock(&perf->work_dis_lock);
		/*
		 * If there is one session that has two work items across
		 * different hw blocks rate is accounted for in both blocks.
		 */
		for (i = 0; i < mgr->queue_count; i++) {
			if (atomic_read(&perf->work_distribution[i])) {
			if (perf->work_distribution[i]) {
				clk_rate[i] += perf->clk_rate;
				rate_accounted_for = true;
			}
@@ -180,6 +191,7 @@ static unsigned long mdss_rotator_clk_rate_calc(
		if ((!rate_accounted_for) && (wb_idx >= 0) &&
				(wb_idx < mgr->queue_count))
			clk_rate[wb_idx] += perf->clk_rate;
		mutex_unlock(&perf->work_dis_lock);
	}
	mutex_unlock(&private->perf_lock);

@@ -214,10 +226,12 @@ static void mdss_rotator_set_clk_rate(struct mdss_rot_mgr *mgr,
			pr_err("unable to round rate err=%ld\n", clk_rate);
		} else if (clk_rate != clk_get_rate(clk)) {
			ret = clk_set_rate(clk, clk_rate);
			if (IS_ERR_VALUE(ret))
			if (IS_ERR_VALUE(ret)) {
				pr_err("clk_set_rate failed, err:%d\n", ret);
			else
			} else {
				pr_debug("rotator clk rate=%lu\n", clk_rate);
				MDSS_XLOG(clk_rate);
			}
		}
		mutex_unlock(&mgr->clk_lock);
	} else {
@@ -321,6 +335,7 @@ int mdss_rotator_resource_ctrl(struct mdss_rot_mgr *mgr, int enable)

	pr_debug("%s: res_cnt=%d changed=%d enable=%d\n",
		__func__, mgr->res_ref_cnt, changed, enable);
	MDSS_XLOG(mgr->res_ref_cnt, changed, enable);

	if (changed) {
		if (enable) {
@@ -335,14 +350,14 @@ int mdss_rotator_resource_ctrl(struct mdss_rot_mgr *mgr, int enable)
	return ret;
}

/* caller is expected to hold perf->work_dis_lock lock */
static bool mdss_rotator_is_work_pending(struct mdss_rot_mgr *mgr,
	struct mdss_rot_perf *perf)
{
	int i;

	for (i = 0; i < mgr->queue_count; i++) {
		atomic_t *wrk_dis = &perf->work_distribution[i];
		if (atomic_read(wrk_dis)) {
		if (perf->work_distribution[i]) {
			pr_debug("Work is still scheduled to complete\n");
			return true;
		}
@@ -394,6 +409,7 @@ static int mdss_rotator_create_fence(struct mdss_rot_entry *entry)

	entry->output_fence_fd = fd;
	entry->output_fence = fence;
	pr_debug("output sync point created at val=%u\n", val);

	return 0;

@@ -502,9 +518,12 @@ static int mdss_rotator_map_and_check_data(struct mdss_rot_entry *entry)

	rotation = (entry->item.flags &  MDP_ROTATION_90) ? true : false;

	ATRACE_BEGIN(__func__);
	ret = mdss_iommu_ctrl(1);
	if (IS_ERR_VALUE(ret))
	if (IS_ERR_VALUE(ret)) {
		ATRACE_END(__func__);
		return ret;
	}

	/* if error during map, the caller will release the data */
	ret = mdss_mdp_data_map(&entry->src_buf, true, DMA_TO_DEVICE);
@@ -561,32 +580,40 @@ static int mdss_rotator_map_and_check_data(struct mdss_rot_entry *entry)

end:
	mdss_iommu_ctrl(0);
	ATRACE_END(__func__);

	return ret;
}

static struct mdss_rot_perf *mdss_rotator_find_session(
static struct mdss_rot_perf *__mdss_rotator_find_session(
	struct mdss_rot_file_private *private,
	u32 session_id)
{
	struct mdss_rot_perf *perf, *perf_next;
	bool found = false;

	mutex_lock(&private->perf_lock);

	list_for_each_entry_safe(perf, perf_next, &private->perf_list, list) {
		if (perf->config.session_id == session_id) {
			found = true;
			break;
		}
	}

	mutex_unlock(&private->perf_lock);
	if (!found)
		perf = NULL;
	return perf;
}

static struct mdss_rot_perf *mdss_rotator_find_session(
	struct mdss_rot_file_private *private,
	u32 session_id)
{
	struct mdss_rot_perf *perf;

	mutex_lock(&private->perf_lock);
	perf = __mdss_rotator_find_session(private, session_id);
	mutex_unlock(&private->perf_lock);
	return perf;
}

static void mdss_rotator_release_data(struct mdss_rot_entry *entry)
{
	mdss_mdp_data_free(&entry->src_buf, true, DMA_TO_DEVICE);
@@ -946,7 +973,6 @@ static void mdss_rotator_queue_request(struct mdss_rot_mgr *mgr,
	struct mdss_rot_entry *entry;
	struct mdss_rot_queue *queue;
	unsigned long clk_rate;
	atomic_t *wrk_dis;
	u32 wb_idx;
	int i;

@@ -954,8 +980,9 @@ static void mdss_rotator_queue_request(struct mdss_rot_mgr *mgr,
		entry = req->entries + i;
		queue = entry->queue;
		wb_idx = queue->hw->wb_id;
		wrk_dis = &entry->perf->work_distribution[wb_idx];
		atomic_inc(wrk_dis);
		mutex_lock(&entry->perf->work_dis_lock);
		entry->perf->work_distribution[wb_idx]++;
		mutex_unlock(&entry->perf->work_dis_lock);
		entry->work_assigned = true;
	}

@@ -1022,6 +1049,8 @@ static int mdss_rotator_update_perf(struct mdss_rot_mgr *mgr)
	int not_in_suspend_mode;
	u64 total_bw = 0;

	ATRACE_BEGIN(__func__);

	not_in_suspend_mode = !atomic_read(&mgr->device_suspended);

	if (not_in_suspend_mode) {
@@ -1037,9 +1066,12 @@ static int mdss_rotator_update_perf(struct mdss_rot_mgr *mgr)
	}

	mutex_lock(&mgr->bus_lock);
	total_bw += mgr->pending_close_bw_vote;
	mdss_rotator_enable_reg_bus(mgr, total_bw);
	mdss_rotator_bus_scale_set_quota(&mgr->data_bus, total_bw);
	mutex_unlock(&mgr->bus_lock);

	ATRACE_END(__func__);
	return 0;
}

@@ -1048,17 +1080,30 @@ static void mdss_rotator_release_from_work_distribution(
		struct mdss_rot_entry *entry)
{
	if (entry->work_assigned) {
		atomic_t *wrk_dis;
		bool free_perf = false;
		u32 wb_idx = entry->queue->hw->wb_id;

		wrk_dis = &entry->perf->work_distribution[wb_idx];
		atomic_add_unless(wrk_dis, -1, 0);
		mutex_lock(&entry->perf->work_dis_lock);
		if (entry->perf->work_distribution[wb_idx])
			entry->perf->work_distribution[wb_idx]--;

		if (!entry->perf->work_distribution[wb_idx]
				&& list_empty(&entry->perf->list)) {
			/* close session has offloaded perf free to us */
			free_perf = true;
		}
		mutex_unlock(&entry->perf->work_dis_lock);
		entry->work_assigned = false;
		if (entry->perf->waiting_for_completion &&
				!mdss_rotator_is_work_pending(mgr,
				entry->perf)) {
			complete(&entry->perf->stop_comp);
			entry->perf->waiting_for_completion = false;
		if (free_perf) {
			mutex_lock(&mgr->bus_lock);
			mgr->pending_close_bw_vote -= entry->perf->bw;
			mutex_unlock(&mgr->bus_lock);
			mdss_rotator_resource_ctrl(mgr, false);
			devm_kfree(&mgr->pdev->dev,
				entry->perf->work_distribution);
			devm_kfree(&mgr->pdev->dev, entry->perf);
			mdss_rotator_update_perf(mgr);
			entry->perf = NULL;
		}
	}
}
@@ -1332,7 +1377,6 @@ static int mdss_rotator_validate_entry(struct mdss_rot_mgr *mgr,
		pr_err("fail to configure downscale factor\n");
		return ret;
	}

	return ret;
}

@@ -1393,6 +1437,14 @@ static int mdss_rotator_add_request(struct mdss_rot_mgr *mgr,
			return ret;
		}
		item->output.fence = entry->output_fence_fd;

		pr_debug("Entry added. wbidx=%u, src{%u,%u,%u,%u}f=%u\n"
			"dst{%u,%u,%u,%u}f=%u session_id=%u\n", item->wb_idx,
			item->src_rect.x, item->src_rect.y,
			item->src_rect.w, item->src_rect.h, item->input.format,
			item->dst_rect.x, item->dst_rect.y,
			item->dst_rect.w, item->dst_rect.h, item->output.format,
			item->session_id);
	}

	mutex_lock(&private->req_lock);
@@ -1446,6 +1498,7 @@ static void mdss_rotator_cancel_all_requests(struct mdss_rot_mgr *mgr,
	struct mdss_rot_file_private *private)
{
	struct mdss_rot_entry_container *req, *req_next;
	pr_debug("Canceling all rotator requests\n");

	mutex_lock(&private->req_lock);
	list_for_each_entry_safe(req, req_next, &private->req_list, list)
@@ -1474,6 +1527,7 @@ static void mdss_rotator_release_rotator_perf_session(
{
	struct mdss_rot_perf *perf, *perf_next;

	pr_debug("Releasing all rotator request\n");
	mdss_rotator_cancel_all_requests(mgr, private);

	mutex_lock(&private->perf_lock);
@@ -1568,6 +1622,7 @@ static int mdss_rotator_config_hw(struct mdss_rot_hw_resource *hw,
	struct mdp_rotation_item *item;
	int ret;

	ATRACE_BEGIN(__func__);
	pipe = hw->pipe;
	item = &entry->item;

@@ -1584,11 +1639,22 @@ static int mdss_rotator_config_hw(struct mdss_rot_hw_resource *hw,

	ret = mdss_mdp_smp_reserve(pipe);
	if (ret) {
		pr_debug("unable to mdss_mdp_smp_reserve rot data\n");
		return ret;
		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
		goto done;
	}

	ret = mdss_mdp_pipe_queue_data(pipe, &entry->src_buf);
	pr_debug("Config pipe. src{%u,%u,%u,%u}f=%u\n"
		"dst{%u,%u,%u,%u}f=%u session_id=%u\n",
		item->src_rect.x, item->src_rect.y,
		item->src_rect.w, item->src_rect.h, item->input.format,
		item->dst_rect.x, item->dst_rect.y,
		item->dst_rect.w, item->dst_rect.h, item->output.format,
		item->session_id);
	MDSS_XLOG(item->input.format, pipe->img_width, pipe->img_height,
		pipe->flags);
done:
	ATRACE_END(__func__);
	return ret;
}

@@ -1742,7 +1808,7 @@ static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr,
{
	struct mdp_rotation_config config;
	struct mdss_rot_perf *perf;
	int ret, i;
	int ret;

	ret = copy_from_user(&config, (void __user *)arg, sizeof(config));
	if (ret) {
@@ -1762,8 +1828,9 @@ static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr,
		return -ENOMEM;
	}

	ATRACE_BEGIN(__func__); /* Open session votes for bw */
	perf->work_distribution = devm_kzalloc(&mgr->pdev->dev,
		sizeof(atomic_t) * mgr->queue_count, GFP_KERNEL);
		sizeof(u32) * mgr->queue_count, GFP_KERNEL);
	if (!perf->work_distribution) {
		pr_err("fail to allocate work_distribution\n");
		ret = -ENOMEM;
@@ -1773,9 +1840,7 @@ static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr,
	config.session_id = mdss_rotator_generator_session_id(mgr);
	perf->config = config;
	perf->last_wb_idx = -1;
	init_completion(&perf->stop_comp);
	for (i = 0; i < mgr->queue_count; i++)
		atomic_set(&perf->work_distribution[i], 0);
	mutex_init(&perf->work_dis_lock);

	INIT_LIST_HEAD(&perf->list);

@@ -1806,8 +1871,12 @@ static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr,
		pr_err("fail to open session, not enough clk/bw\n");
		goto perf_err;
	}
	pr_debug("open session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n",
		config.session_id, config.input.width, config.input.height,
		config.input.format, config.output.width, config.output.height,
		config.output.format);

	return ret;
	goto done;
perf_err:
	mdss_rotator_resource_ctrl(mgr, false);
resource_err:
@@ -1818,6 +1887,8 @@ copy_user_err:
	devm_kfree(&mgr->pdev->dev, perf->work_distribution);
alloc_err:
	devm_kfree(&mgr->pdev->dev, perf);
done:
	ATRACE_END(__func__);
	return ret;
}

@@ -1825,47 +1896,51 @@ static int mdss_rotator_close_session(struct mdss_rot_mgr *mgr,
	struct mdss_rot_file_private *private, unsigned long arg)
{
	struct mdss_rot_perf *perf;
	bool offload_release_work = false;
	u32 id;

	id = (u32)arg;
	perf = mdss_rotator_find_session(private, id);
	mutex_lock(&mgr->lock);
	mutex_lock(&private->perf_lock);
	perf = __mdss_rotator_find_session(private, id);
	if (!perf) {
		mutex_unlock(&private->perf_lock);
		mutex_unlock(&mgr->lock);
		pr_err("Trying to close session that does not exist\n");
		return -EINVAL;
	}

	/*
	 * Client should not be calling close session when there
	 * are pending rotation work. Driver will attempt to
	 * wait for request to complete.
	 */

	if (mdss_rotator_is_work_pending(mgr, perf)) {
		pr_debug("Work is still pending, attempting to wait\n");
		reinit_completion(&perf->stop_comp);
		perf->waiting_for_completion = true;
		wait_for_completion_timeout(&perf->stop_comp, 3 * KOFF_TIMEOUT);

	ATRACE_BEGIN(__func__);
	mutex_lock(&perf->work_dis_lock);
	if (mdss_rotator_is_work_pending(mgr, perf)) {
			pr_err("Calling session close, rot work is pending\n");
			return -EBUSY;
		}
		pr_debug("Work is still pending, offload free to wq\n");
		mutex_lock(&mgr->bus_lock);
		mgr->pending_close_bw_vote += perf->bw;
		mutex_unlock(&mgr->bus_lock);
		offload_release_work = true;
	}

	mdss_rotator_resource_ctrl(mgr, false);
	mutex_lock(&private->perf_lock);
	list_del_init(&perf->list);
	mutex_unlock(&perf->work_dis_lock);
	mutex_unlock(&private->perf_lock);
	mutex_unlock(&mgr->lock);

	if (offload_release_work)
		goto done;

	mdss_rotator_resource_ctrl(mgr, false);
	devm_kfree(&mgr->pdev->dev, perf->work_distribution);
	devm_kfree(&mgr->pdev->dev, perf);
	mdss_rotator_update_perf(mgr);
done:
	pr_debug("Closed session id:%u", id);
	ATRACE_END(__func__);
	return 0;
}

static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr,
	struct mdss_rot_file_private *private, unsigned long arg)
{
	int ret;
	int ret = 0;
	struct mdss_rot_perf *perf;
	struct mdp_rotation_config config;

@@ -1883,9 +1958,13 @@ static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr,
	}

	perf = mdss_rotator_find_session(private, config.session_id);
	if (!perf)
	if (!perf) {
		pr_err("No session with id=%u could be found\n",
			config.session_id);
		return -EINVAL;
	}

	ATRACE_BEGIN(__func__);
	mutex_lock(&private->perf_lock);
	perf->config = config;
	ret = mdss_rotator_calc_perf(perf);
@@ -1893,11 +1972,17 @@ static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr,

	if (ret) {
		pr_err("error in configuring the session %d\n", ret);
		return ret;
		goto done;
	}

	ret = mdss_rotator_update_perf(mgr);

	pr_debug("reconfig session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n",
		config.session_id, config.input.width, config.input.height,
		config.input.format, config.output.width, config.output.height,
		config.output.format);
done:
	ATRACE_END(__func__);
	return ret;
}

@@ -2199,7 +2284,9 @@ static long mdss_rotator_compat_ioctl(struct file *file, unsigned int cmd,

	switch (cmd) {
	case MDSS_ROTATION_REQUEST:
		ATRACE_BEGIN("rotator_request32");
		ret = mdss_rotator_handle_request32(rot_mgr, private, arg);
		ATRACE_END("rotator_request32");
		break;
	case MDSS_ROTATION_OPEN:
		ret = mdss_rotator_open_session(rot_mgr, private, arg);
@@ -2245,7 +2332,9 @@ static long mdss_rotator_ioctl(struct file *file, unsigned int cmd,

	switch (cmd) {
	case MDSS_ROTATION_REQUEST:
		ATRACE_BEGIN("rotator_request");
		ret = mdss_rotator_handle_request(rot_mgr, private, arg);
		ATRACE_END("rotator_request");
		break;
	case MDSS_ROTATION_OPEN:
		ret = mdss_rotator_open_session(rot_mgr, private, arg);
+3 −3
Original line number Diff line number Diff line
@@ -110,9 +110,8 @@ struct mdss_rot_perf {
	struct mdp_rotation_config config;
	unsigned long clk_rate;
	u64 bw;
	bool waiting_for_completion;
	struct completion stop_comp;
	atomic_t *work_distribution;
	struct mutex work_dis_lock;
	u32 *work_distribution;
	int last_wb_idx; /* last known wb index, used when above count is 0 */
};

@@ -164,6 +163,7 @@ struct mdss_rot_mgr {
	struct list_head file_list;

	struct mutex bus_lock;
	u64 pending_close_bw_vote;
	struct mdss_rot_bus_data_type data_bus;
	struct mdss_rot_bus_data_type reg_bus;