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

Commit 686c9e5e authored by Venkat Chinta's avatar Venkat Chinta Committed by vhajeri
Browse files

msm: camera: crm: Mutliple fixes in request manager



Adds tag for camera heap id. Adds better logging across CRM. Adds return
value to indicate success/failure for destroy link info. Provides
spinlock protection for crm timer. Skips destroy device handle if destroy
link info fails. Changes memory type for crm timer to cache. Adds validity
check around cache allocation for crm timer.

Change-Id: I8868f3608f44c6296567cc8a038d61cb14413e21
Signed-off-by: default avatarVenkat Chinta <vchinta@codeaurora.org>
parent ddbe5137
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2,9 +2,9 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils

obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o \
obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_core.o\
				cam_req_mgr_dev.o \
				cam_req_mgr_util.o \
				cam_req_mgr_core.o \
				cam_req_mgr_workq.o \
				cam_mem_mgr.o \
				cam_req_mgr_timer.o \
+6 −3
Original line number Diff line number Diff line
@@ -377,7 +377,8 @@ static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
		heap_id = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
		ion_flag |= ION_FLAG_SECURE | ION_FLAG_CP_CAMERA;
	} else {
		heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID);
		heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) |
			ION_HEAP(ION_CAMERA_HEAP_ID);
	}

	if (cmd->flags & CAM_MEM_FLAG_CACHE)
@@ -947,7 +948,8 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
	else
		ion_flag &= ~ION_FLAG_CACHED;

	heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID);
	heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) |
		ION_HEAP(ION_CAMERA_HEAP_ID);

	rc = cam_mem_util_get_dma_buf(inp->size,
		inp->align,
@@ -1111,7 +1113,8 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
		return -EINVAL;
	}

	heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID);
	heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) |
		ION_HEAP(ION_CAMERA_HEAP_ID);
	rc = cam_mem_util_get_dma_buf(inp->size,
		inp->align,
		heap_id,
+89 −42
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@

static struct cam_req_mgr_core_device *g_crm_core_dev;


void cam_req_mgr_handle_core_shutdown(void)
{
	struct cam_req_mgr_core_session *session;
@@ -200,7 +199,8 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
		tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
		traverse_data->in_q->slot[curr_idx].skip_idx);

	if (tbl->inject_delay > 0 && (traverse_data->validate_only == false)) {
	if ((tbl->inject_delay > 0) &&
		(traverse_data->validate_only == false)) {
		CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
		apply_data[tbl->pd].req_id = -1;
		tbl->inject_delay--;
@@ -222,14 +222,21 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
		}
		if (rc >= 0) {
			SET_SUCCESS_BIT(traverse_data->result, tbl->pd);

			if (traverse_data->validate_only == false) {
				apply_data[tbl->pd].pd = tbl->pd;
				apply_data[tbl->pd].req_id =
					CRM_GET_REQ_ID(traverse_data->in_q,
					curr_idx);
					CRM_GET_REQ_ID(
					traverse_data->in_q, curr_idx);
				apply_data[tbl->pd].idx = curr_idx;

				/* If traverse is success dec traverse skip */
				CAM_DBG(CAM_CRM, "req_id: %d with pd of %d",
				apply_data[tbl->pd].req_id,
				apply_data[tbl->pd].pd);
				/*
				 * If traverse is successful decrement
				 * traverse skip
				 */
				if (tbl->skip_traverse > 0) {
					apply_data[tbl->pd].req_id = -1;
					tbl->skip_traverse--;
@@ -466,8 +473,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
/**
 * __cam_req_mgr_check_link_is_ready()
 *
 * @brief         : traverse through all request tables and see if
 *                  all devices are ready to apply request settings
 * @brief    : traverse through all request tables and see if all devices are
 *             ready to apply request settings.
 * @link     : pointer to link whose input queue and req tbl are
 *             traversed through
 * @idx      : index within input request queue
@@ -487,10 +494,10 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
	in_q = link->req.in_q;

	apply_data = link->req.apply_data;

	if (validate_only == false) {
		memset(apply_data, 0,
			sizeof(struct cam_req_mgr_apply) *
			CAM_PIPELINE_DELAY_MAX);
		    sizeof(struct cam_req_mgr_apply) * CAM_PIPELINE_DELAY_MAX);
	}

	traverse_data.apply_data = apply_data;
@@ -510,8 +517,9 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,

	if (!rc && traverse_data.result == link->pd_mask) {
		CAM_DBG(CAM_CRM,
			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
			"APPLY: link_hdl= %x idx= %d, validate_only=%d, req_id= %lld :%lld :%lld",
			link->link_hdl, idx,
			traverse_data.validate_only,
			apply_data[2].req_id, apply_data[1].req_id,
			apply_data[0].req_id);
	} else
@@ -567,6 +575,11 @@ static void __cam_req_mgr_reset_sof_cnt(
	link->sof_counter = -1;
	link->sync_link->sof_counter = -1;
	link->frame_skip_flag = false;

	CAM_DBG(CAM_CRM,
		"link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
		link->link_hdl, link->sof_counter,
		link->sync_link->sof_counter, link->frame_skip_flag);
}

/**
@@ -585,6 +598,11 @@ static void __cam_req_mgr_sof_cnt_initialize(
	link->sof_counter++;
	link->sync_self_ref = link->sof_counter -
		link->sync_link->sof_counter;

	CAM_DBG(CAM_CRM,
		"link_hdl %x self_counter %lld other_counter %lld",
		link->link_hdl, link->sof_counter,
		link->sync_link->sof_counter);
}

/**
@@ -602,6 +620,11 @@ static void __cam_req_mgr_wrap_sof_cnt(
	link->sof_counter = (MAX_SYNC_COUNT -
		(link->sync_link->sof_counter));
	link->sync_link->sof_counter = 0;

	CAM_DBG(CAM_CRM,
		"link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
		link->link_hdl, link->sof_counter,
		link->sync_link->link_hdl, link->sync_link->sof_counter);
}

/**
@@ -625,12 +648,18 @@ static int __cam_req_mgr_validate_sof_cnt(
		__cam_req_mgr_wrap_sof_cnt(link);

	sync_diff = link->sof_counter - sync_link->sof_counter;

	CAM_DBG(CAM_CRM,
		"link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
		link->link_hdl, link->sof_counter,
		sync_link->sof_counter, sync_diff, link->sync_self_ref);

	if (sync_diff != link->sync_self_ref) {
		link->sync_link->frame_skip_flag = true;
		CAM_WARN(CAM_CRM,
			"Detected anomaly, skip link:%d, self=%lld, other=%lld",
			"Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
			link->link_hdl, link->sof_counter,
			sync_link->sof_counter);
			sync_link->sof_counter, link->sync_self_ref);
		rc = -EPERM;
	}

@@ -663,9 +692,15 @@ static int __cam_req_mgr_process_sync_req(

	sync_link = link->sync_link;
	req_id = slot->req_id;

	CAM_DBG(CAM_CRM,
		"link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
		link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
		link->frame_skip_flag, link->sync_link->sync_self_ref);

	if (link->sof_counter == -1) {
		__cam_req_mgr_sof_cnt_initialize(link);
	} else if (link->frame_skip_flag &&
	} else if ((link->frame_skip_flag) &&
		(sync_link->sync_self_ref != -1)) {
		CAM_DBG(CAM_CRM, "Link[%x] Req[%lld] Resetting values ",
			link->link_hdl, req_id);
@@ -685,6 +720,7 @@ static int __cam_req_mgr_process_sync_req(

	sync_slot_idx = __cam_req_mgr_find_slot_for_req(
		sync_link->req.in_q, req_id);

	if (sync_slot_idx != -1) {
		rc = __cam_req_mgr_check_link_is_ready(
			sync_link, sync_slot_idx, true);
@@ -751,9 +787,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
	 * - if in applied_state, somthign wrong.
	 * - if in no_req state, no new req
	 */
	CAM_DBG(CAM_CRM, "SOF Req[%lld] idx %d req_status %d",
	CAM_DBG(CAM_CRM, "SOF Req[%lld] idx %d req_status %d link_hdl %x",
		in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx,
		in_q->slot[in_q->rd_idx].status);
		in_q->slot[in_q->rd_idx].status, link->link_hdl);

	slot = &in_q->slot[in_q->rd_idx];
	if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
@@ -762,8 +798,8 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		goto error;
	}

	if (trigger != CAM_TRIGGER_POINT_SOF &&
			trigger != CAM_TRIGGER_POINT_EOF)
	if ((trigger != CAM_TRIGGER_POINT_SOF) &&
		(trigger != CAM_TRIGGER_POINT_EOF))
		goto error;

	if ((trigger == CAM_TRIGGER_POINT_EOF) &&
@@ -817,10 +853,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		/* Apply req failed retry at next sof */
		slot->status = CRM_SLOT_STATUS_REQ_PENDING;
	} else {
		CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success",
			slot->req_id, link->link_hdl);
		link->trigger_mask |= trigger;

		CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success",
			slot->req_id, link->link_hdl);
		spin_lock_bh(&link->link_state_spin_lock);
		if (link->state == CAM_CRM_LINK_STATE_ERR) {
			CAM_WARN(CAM_CRM, "Err recovery done idx %d",
@@ -832,7 +868,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		if (link->trigger_mask == link->subscribe_event) {
			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
			link->trigger_mask = 0;
			CAM_DBG(CAM_CRM, "req %d is applied on link %d",
			CAM_DBG(CAM_CRM, "req %d is applied on link %x",
				slot->req_id,
				link->link_hdl);
			idx = in_q->rd_idx;
@@ -842,9 +878,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
			__cam_req_mgr_reset_req_slot(link, idx);
		}
	}

	mutex_unlock(&session->lock);
	return rc;

error:
	mutex_unlock(&session->lock);
	return rc;
@@ -1081,8 +1117,9 @@ static void __cam_req_mgr_destroy_subdev(
 * @brief    : Cleans up the mem allocated while linking
 * @link     : pointer to link, mem associated with this link is freed
 *
 * @return   : returns if unlink for any device was success or failure
 */
static void __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
static int __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
{
	int32_t                                 i = 0;
	struct cam_req_mgr_connected_device    *dev;
@@ -1103,8 +1140,8 @@ static void __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
				rc = dev->ops->link_setup(&link_data);
				if (rc)
					CAM_ERR(CAM_CRM,
						"Unlink failed dev_hdl 0x%x rc=%d",
						dev->dev_hdl, rc);
						"Unlink failed dev_hdl %d",
						dev->dev_hdl);
			}
			dev->dev_hdl = 0;
			dev->parent = NULL;
@@ -1119,6 +1156,8 @@ static void __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
	link->pd_mask = 0;
	link->num_devs = 0;
	link->max_delay = 0;

	return rc;
}

/**
@@ -1181,6 +1220,9 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
	/*  Loop through and find a free index */
	for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
		if (!session->links[i]) {
			CAM_DBG(CAM_CRM,
				"Free link index %d found, num_links=%d",
				i, session->num_links);
			session->links[i] = link;
			break;
		}
@@ -1419,13 +1461,12 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
	link = (struct cam_req_mgr_core_link *)priv;
	task_data = (struct crm_task_payload *)data;
	sched_req  = (struct cam_req_mgr_sched_request *)&task_data->u;
	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld sync_mode %d",
		sched_req->link_hdl,
		sched_req->req_id,
		sched_req->sync_mode);

	in_q = link->req.in_q;

	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld at slot %d sync_mode %d",
		sched_req->link_hdl, sched_req->req_id,
		in_q->wr_idx, sched_req->sync_mode);

	mutex_lock(&link->req.lock);
	slot = &in_q->slot[in_q->wr_idx];

@@ -1433,9 +1474,6 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
		slot->status != CRM_SLOT_STATUS_REQ_APPLIED)
		CAM_WARN(CAM_CRM, "in_q overwrite %d", slot->status);

	CAM_DBG(CAM_CRM, "sched_req %lld at slot %d sync_mode %d",
		sched_req->req_id, in_q->wr_idx, sched_req->sync_mode);

	slot->status = CRM_SLOT_STATUS_REQ_ADDED;
	slot->req_id = sched_req->req_id;
	slot->sync_mode = sched_req->sync_mode;
@@ -1818,9 +1856,9 @@ static int cam_req_mgr_cb_notify_err(
		rc = -EPERM;
		goto end;
	}
	crm_timer_reset(link->watchdog);
	spin_unlock_bh(&link->link_state_spin_lock);

	crm_timer_reset(link->watchdog);
	task = cam_req_mgr_workq_get_task(link->workq);
	if (!task) {
		CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id);
@@ -1881,9 +1919,9 @@ static int cam_req_mgr_cb_notify_trigger(
		rc = -EPERM;
		goto end;
	}
	crm_timer_reset(link->watchdog);
	spin_unlock_bh(&link->link_state_spin_lock);

	crm_timer_reset(link->watchdog);
	task = cam_req_mgr_workq_get_task(link->workq);
	if (!task) {
		CAM_ERR(CAM_CRM, "no empty task frame %lld",
@@ -2112,6 +2150,9 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
	mutex_lock(&link->lock);
	spin_lock_bh(&link->link_state_spin_lock);
	link->state = CAM_CRM_LINK_STATE_IDLE;

	/* Destroy timer of link */
	crm_timer_exit(&link->watchdog);
	spin_unlock_bh(&link->link_state_spin_lock);
	__cam_req_mgr_print_req_tbl(&link->req);

@@ -2119,13 +2160,15 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
	kfree(link->workq->task.pool[0].payload);
	link->workq->task.pool[0].payload = NULL;

	/* Destroy workq and timer of link */
	crm_timer_exit(&link->watchdog);

	/* Destroy workq of link */
	cam_req_mgr_workq_destroy(&link->workq);

	/* Cleanup request tables and unlink devices */
	__cam_req_mgr_destroy_link_info(link);
	rc = __cam_req_mgr_destroy_link_info(link);
	if (rc) {
		CAM_ERR(CAM_CORE, "Unlink failed. Cannot proceed");
		goto done;
	}

	/* Free memory holding data of linked devs */
	__cam_req_mgr_destroy_subdev(link->l_dev);
@@ -2137,6 +2180,7 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
			rc, link->link_hdl);
	}

done:
	mutex_unlock(&link->lock);
	return rc;
}
@@ -2431,6 +2475,7 @@ int cam_req_mgr_sync_config(
	}

	mutex_lock(&cam_session->lock);

	CAM_DBG(CAM_CRM, "link handles %x %x",
		sync_info->link_hdls[0], sync_info->link_hdls[1]);

@@ -2587,7 +2632,9 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
			}
		} else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) {
			/* Destroy SOF watchdog timer */
			spin_lock_bh(&link->link_state_spin_lock);
			crm_timer_exit(&link->watchdog);
			spin_unlock_bh(&link->link_state_spin_lock);
			/* notify nodes */
			for (j = 0; j < link->num_devs; j++) {
				dev = &link->l_dev[j];
+16 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -25,10 +25,12 @@
#include "cam_subdev.h"
#include "cam_mem_mgr.h"
#include "cam_debug_util.h"
#include <linux/slub_def.h>

#define CAM_REQ_MGR_EVENT_MAX 30

static struct cam_req_mgr_device g_dev;
struct kmem_cache *g_cam_req_mgr_timer_cachep;

static int cam_media_device_setup(struct device *dev)
{
@@ -635,6 +637,19 @@ static int cam_req_mgr_probe(struct platform_device *pdev)

	g_dev.state = true;

	if (g_cam_req_mgr_timer_cachep == NULL) {
		g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer",
			sizeof(struct cam_req_mgr_timer), 64,
			SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE |
			SLAB_POISON | SLAB_STORE_USER, NULL);
		if (!g_cam_req_mgr_timer_cachep)
			CAM_ERR(CAM_CRM,
				"Failed to create kmem_cache for crm_timer");
		else
			CAM_DBG(CAM_CRM, "Name : %s",
				g_cam_req_mgr_timer_cachep->name);
	}

	return rc;

req_mgr_core_fail:
+1 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
Loading