msm: camera: req_mgr: Support for 3 links in CRM

Add third link to support 3 concurrent camera in
sync. This change contain support same max pipeline
delay and different max pipeline delay as well.

CRs-Fixed: 2723787
Change-Id: I25e50e8e9a19c4c306a01dd3b700f8a990f3eb66
Signed-off-by: Ayush Kumar <ayushkr@codeaurora.org>
This commit is contained in:
Ayush Kumar
2020-06-21 03:04:47 +05:30
parent c83f67df47
commit bef2e958a1
2 changed files with 145 additions and 127 deletions

View File

@@ -22,6 +22,7 @@ static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];
void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
{
uint32_t pd = 0;
int i = 0;
link->link_hdl = 0;
link->num_devs = 0;
@@ -37,7 +38,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
link->parent = NULL;
link->subscribe_event = 0;
link->trigger_mask = 0;
link->sync_link = 0;
link->sync_link_sof_skip = false;
link->open_req_cnt = 0;
link->last_flush_id = 0;
@@ -52,12 +52,16 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
link->sof_timestamp = 0;
link->prev_sof_timestamp = 0;
link->skip_init_frame = false;
link->num_sync_links = 0;
atomic_set(&link->eof_event_cnt, 0);
for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) {
link->req.apply_data[pd].req_id = -1;
link->req.prev_apply_data[pd].req_id = -1;
}
for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++)
link->sync_link[i] = NULL;
}
void cam_req_mgr_handle_core_shutdown(void)
@@ -1100,20 +1104,19 @@ static int32_t __cam_req_mgr_find_slot_for_req(
*/
static int __cam_req_mgr_check_sync_for_mslave(
struct cam_req_mgr_core_link *link,
struct cam_req_mgr_core_link *sync_link,
struct cam_req_mgr_slot *slot)
{
struct cam_req_mgr_core_link *sync_link = NULL;
struct cam_req_mgr_slot *sync_slot = NULL;
int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0;
int64_t req_id = 0, sync_req_id = 0;
int32_t sync_num_slots = 0;
if (!link->sync_link) {
if (!sync_link) {
CAM_ERR(CAM_CRM, "Sync link null");
return -EINVAL;
}
sync_link = link->sync_link;
req_id = slot->req_id;
sync_num_slots = sync_link->req.in_q->num_slots;
sync_rd_idx = sync_link->req.in_q->rd_idx;
@@ -1288,15 +1291,6 @@ static int __cam_req_mgr_check_sync_for_mslave(
"Req: %lld ready to apply on link: %x [validation successful]",
req_id, link->link_hdl);
/*
* At this point all validation is successfully done
* and we can proceed to apply the given request.
* Ideally the next call should return success.
*/
rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
if (rc)
CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
return 0;
}
@@ -1313,9 +1307,9 @@ static int __cam_req_mgr_check_sync_for_mslave(
*/
static int __cam_req_mgr_check_sync_req_is_ready(
struct cam_req_mgr_core_link *link,
struct cam_req_mgr_core_link *sync_link,
struct cam_req_mgr_slot *slot)
{
struct cam_req_mgr_core_link *sync_link = NULL;
struct cam_req_mgr_slot *sync_rd_slot = NULL;
int64_t req_id = 0, sync_req_id = 0;
int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
@@ -1325,12 +1319,11 @@ static int __cam_req_mgr_check_sync_req_is_ready(
uint64_t master_slave_diff = 0;
bool ready = true, sync_ready = true;
if (!link->sync_link) {
if (!sync_link) {
CAM_ERR(CAM_CRM, "Sync link null");
return -EINVAL;
}
sync_link = link->sync_link;
req_id = slot->req_id;
sync_num_slots = sync_link->req.in_q->num_slots;
sync_rd_idx = sync_link->req.in_q->rd_idx;
@@ -1520,6 +1513,50 @@ static int __cam_req_mgr_check_sync_req_is_ready(
"Req: %lld ready to apply on link: %x [validation successful]",
req_id, link->link_hdl);
return 0;
}
static int __cam_req_mgr_check_multi_sync_link_ready(
struct cam_req_mgr_core_link *link,
struct cam_req_mgr_slot *slot)
{
int i, rc = 0;
for (i = 0; i < link->num_sync_links; i++) {
if (link->sync_link[i]) {
if (link->max_delay == link->sync_link[i]->max_delay) {
rc = __cam_req_mgr_check_sync_req_is_ready(
link, link->sync_link[i], slot);
if (rc < 0) {
CAM_DBG(CAM_CRM, "link %x not ready",
link->link_hdl);
return rc;
}
} else if (link->max_delay >
link->sync_link[i]->max_delay) {
link->is_master = true;
link->sync_link[i]->is_master = false;
rc = __cam_req_mgr_check_sync_for_mslave(
link, link->sync_link[i], slot);
if (rc < 0) {
CAM_DBG(CAM_CRM, "link%x not ready",
link->link_hdl);
return rc;
}
} else {
link->is_master = false;
link->sync_link[i]->is_master = true;
rc = __cam_req_mgr_check_sync_for_mslave(
link, link->sync_link[i], slot);
if (rc < 0) {
CAM_DBG(CAM_CRM, "link %x not ready",
link->link_hdl);
return rc;
}
}
}
}
/*
* At this point all validation is successfully done
* and we can proceed to apply the given request.
@@ -1545,13 +1582,14 @@ static int __cam_req_mgr_check_sync_req_is_ready(
static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
struct cam_req_mgr_trigger_notify *trigger_data)
{
int rc = 0, idx;
int rc = 0, idx, i;
int reset_step = 0;
uint32_t trigger = trigger_data->trigger;
struct cam_req_mgr_slot *slot = NULL;
struct cam_req_mgr_req_queue *in_q;
struct cam_req_mgr_core_session *session;
struct cam_req_mgr_connected_device *dev;
struct cam_req_mgr_core_link *tmp_link = NULL;
in_q = link->req.in_q;
session = (struct cam_req_mgr_core_session *)link->parent;
@@ -1602,22 +1640,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
goto error;
}
if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
(link->sync_link)) {
if (link->is_master || link->sync_link->is_master) {
if (!link->in_msync_mode) {
CAM_DBG(CAM_CRM,
"Settings master-slave sync mode for link 0x%x",
link->link_hdl);
link->in_msync_mode = true;
}
rc = __cam_req_mgr_check_sync_for_mslave(
link, slot);
} else {
rc = __cam_req_mgr_check_sync_req_is_ready(
link, slot);
}
if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
rc = __cam_req_mgr_check_multi_sync_link_ready(
link, slot);
} else {
if (link->in_msync_mode) {
CAM_DBG(CAM_CRM,
@@ -1625,9 +1650,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
link->link_hdl);
link->in_msync_mode = false;
link->initial_sync_req = -1;
if (link->sync_link) {
link->sync_link->initial_sync_req = -1;
link->sync_link->in_msync_mode = false;
for (i = 0; i < link->num_sync_links; i++) {
if (link->sync_link[i]) {
tmp_link = link->sync_link[i];
tmp_link->initial_sync_req = -1;
tmp_link->in_msync_mode = false;
}
}
}
@@ -1715,11 +1743,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
link->link_hdl);
idx = in_q->rd_idx;
reset_step = link->max_delay;
if (link->sync_link) {
if ((link->in_msync_mode) &&
(link->sync_link->is_master))
reset_step =
link->sync_link->max_delay;
for (i = 0; i < link->num_sync_links; i++) {
if (link->sync_link[i]) {
if ((link->in_msync_mode) &&
(link->sync_link[i]->max_delay >
reset_step))
reset_step =
link->sync_link[i]->max_delay;
}
}
if (slot->req_id > 0)
@@ -2160,7 +2192,10 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
in_q->num_slots = 0;
link->state = CAM_CRM_LINK_STATE_IDLE;
link->parent = (void *)session;
link->sync_link = NULL;
for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++)
link->sync_link[i] = NULL;
mutex_unlock(&link->lock);
mutex_lock(&session->lock);
@@ -2223,7 +2258,7 @@ static void __cam_req_mgr_unreserve_link(
struct cam_req_mgr_core_session *session,
struct cam_req_mgr_core_link *link)
{
int i;
int i, j;
if (!session || !link) {
CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK",
@@ -2242,14 +2277,16 @@ static void __cam_req_mgr_unreserve_link(
for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (session->links[i] == link)
session->links[i] = NULL;
if (link->sync_link) {
if (link->sync_link == session->links[i])
session->links[i]->sync_link = NULL;
for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) {
if (link->sync_link[j]) {
if (link->sync_link[j] == session->links[i])
session->links[i]->sync_link[j] = NULL;
}
}
}
link->sync_link = NULL;
for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++)
link->sync_link[j] = NULL;
session->num_links--;
CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
mutex_unlock(&session->lock);
@@ -2361,7 +2398,7 @@ end:
*/
int cam_req_mgr_process_sched_req(void *priv, void *data)
{
int rc = 0;
int rc = 0, i;
struct cam_req_mgr_sched_request *sched_req = NULL;
struct cam_req_mgr_core_link *link = NULL;
struct cam_req_mgr_req_queue *in_q = NULL;
@@ -2421,8 +2458,10 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
link->initial_sync_req = slot->req_id;
} else {
link->initial_sync_req = -1;
if (link->sync_link)
link->sync_link->initial_sync_req = -1;
for (i = 0; i < link->num_sync_links; i++) {
if (link->sync_link[i])
link->sync_link[i]->initial_sync_req = -1;
}
}
mutex_unlock(&link->req.lock);
@@ -2655,7 +2694,7 @@ int cam_req_mgr_process_error(void *priv, void *data)
__cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
in_q->rd_idx = idx;
in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
if (link->sync_link) {
if (link->sync_link[0]) {
in_q->slot[idx].sync_mode = 0;
__cam_req_mgr_inc_idx(&idx, 1,
link->req.l_tbl->num_slots);
@@ -3905,40 +3944,13 @@ end:
return rc;
}
/**
* __cam_req_mgr_set_master_link()
*
* @brief : Each links sets its max pd delay based on the devices on the
* link. The link with higher pd is assigned master.
* @link1 : One of the sync links
* @link2 : The other sync link
*/
static void __cam_req_mgr_set_master_link(
struct cam_req_mgr_core_link *link1,
struct cam_req_mgr_core_link *link2)
{
if (link1->max_delay > link2->max_delay) {
link1->is_master = true;
link2->initial_skip = true;
} else if (link2->max_delay > link1->max_delay) {
link2->is_master = true;
link1->initial_skip = true;
}
CAM_DBG(CAM_CRM,
"link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]",
link1->link_hdl, link1->is_master,
link2->link_hdl, link2->is_master);
}
int cam_req_mgr_sync_config(
struct cam_req_mgr_sync_mode *sync_info)
{
int rc = 0;
int i, j, rc = 0;
int sync_idx = 0;
struct cam_req_mgr_core_session *cam_session;
struct cam_req_mgr_core_link *link1 = NULL;
struct cam_req_mgr_core_link *link2 = NULL;
struct cam_req_mgr_core_link *link[MAX_LINKS_PER_SESSION];
if (!sync_info) {
CAM_ERR(CAM_CRM, "NULL pointer");
@@ -3976,58 +3988,61 @@ 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]);
for (i = 0; i < sync_info->num_links; i++) {
/* only two links existing per session in dual cam use case*/
link1 = cam_get_device_priv(sync_info->link_hdls[0]);
if (!link1) {
CAM_ERR(CAM_CRM, "link1 NULL pointer");
rc = -EINVAL;
goto done;
if (!sync_info->link_hdls[i]) {
CAM_ERR(CAM_CRM, "link handle %d is null", i);
rc = -EINVAL;
goto done;
}
link[i] = cam_get_device_priv(sync_info->link_hdls[i]);
if (!link[i]) {
CAM_ERR(CAM_CRM, "link%d NULL pointer", i);
rc = -EINVAL;
goto done;
}
link[i]->sync_link_sof_skip = false;
link[i]->is_master = false;
link[i]->in_msync_mode = false;
link[i]->initial_sync_req = -1;
for (j = 0; j < sync_info->num_links-1; j++)
link[i]->sync_link[j] = NULL;
}
link2 = cam_get_device_priv(sync_info->link_hdls[1]);
if (!link2) {
CAM_ERR(CAM_CRM, "link2 NULL pointer");
rc = -EINVAL;
goto done;
}
link1->sync_link_sof_skip = false;
link1->sync_link = NULL;
link2->sync_link_sof_skip = false;
link2->sync_link = NULL;
link1->is_master = false;
link2->is_master = false;
link1->in_msync_mode = false;
link2->in_msync_mode = false;
link1->initial_sync_req = -1;
link2->initial_sync_req = -1;
if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
link1->sync_link = link2;
link2->sync_link = link1;
__cam_req_mgr_set_master_link(link1, link2);
for (i = 0; i < sync_info->num_links; i++) {
j = 0;
sync_idx = 0;
CAM_DBG(CAM_REQ, "link %x adds sync link:",
link[i]->link_hdl);
while (j < sync_info->num_links) {
if (i != j) {
link[i]->sync_link[sync_idx++] =
link[j];
link[i]->num_sync_links++;
CAM_DBG(CAM_REQ, "sync_link[%d] : %x",
sync_idx-1, link[j]->link_hdl);
}
j++;
}
link[i]->initial_skip = true;
link[i]->sof_timestamp = 0;
}
} else {
/*
* Reset below info after the mode is configured
* to NO-SYNC mode since they may be overridden
* if the sync config is invoked after SOF comes.
*/
link1->initial_skip = true;
link2->initial_skip = true;
link1->sof_timestamp = 0;
link2->sof_timestamp = 0;
for (j = 0; j < sync_info->num_links; j++) {
link[j]->initial_skip = true;
link[j]->sof_timestamp = 0;
link[j]->num_sync_links = 0;
}
}
cam_session->sync_mode = sync_info->sync_mode;
CAM_DBG(CAM_REQ,
"Sync config on link1 0x%x & link2 0x%x with sync_mode %d",
link1->link_hdl, link2->link_hdl, cam_session->sync_mode);
"Sync config completed on %d links with sync_mode %d",
sync_info->num_links, sync_info->sync_mode);
done:
mutex_unlock(&cam_session->lock);

View File

@@ -343,7 +343,8 @@ struct cam_req_mgr_connected_device {
* @subscribe_event : irqs that link subscribes, IFE should send
* notification to CRM at those hw events.
* @trigger_mask : mask on which irq the req is already applied
* @sync_link : pointer to the sync link for synchronization
* @sync_link : array of pointer to the sync link for synchronization
* @num_sync_links : num of links sync associated with this link
* @sync_link_sof_skip : flag determines if a pkt is not available for a given
* frame in a particular link skip corresponding
* frame in sync link as well.
@@ -387,7 +388,9 @@ struct cam_req_mgr_core_link {
spinlock_t link_state_spin_lock;
uint32_t subscribe_event;
uint32_t trigger_mask;
struct cam_req_mgr_core_link *sync_link;
struct cam_req_mgr_core_link
*sync_link[MAXIMUM_LINKS_PER_SESSION - 1];
int32_t num_sync_links;
bool sync_link_sof_skip;
int32_t open_req_cnt;
uint32_t last_flush_id;