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

Commit 093583a7 authored by Seemanta Dutta's avatar Seemanta Dutta
Browse files

msm: camera: Set proper state of parent object while merging



When merging multiple children to create a parent merged object,
set the state of the parent sync object after going through each
child sync object.

Apply the following logic in order, while arriving at the state of
the parent object:
  - If any child is in error, set parent state as error
  - If any child is in active, set parent state as active
  - If all objects are success, set parent state as success

If resulting parent state is not active (i.e. either success or error),
signal the completion variable so that any waiting threads on the sync
object can wake up.

CRs-Fixed: 1108613
Change-Id: I1c1902e87979e421840f501f3c709b337225bb9c
Signed-off-by: default avatarSeemanta Dutta <seemanta@codeaurora.org>
parent ed98af78
Loading
Loading
Loading
Loading
+52 −1
Original line number Diff line number Diff line
@@ -57,6 +57,48 @@ int cam_sync_init_object(struct sync_table_row *table,
	return 0;
}

uint32_t cam_sync_util_get_group_object_state(struct sync_table_row *table,
	uint32_t *sync_objs,
	uint32_t num_objs)
{
	int i;
	struct sync_table_row *child_row = NULL;
	int success_count = 0;
	int active_count = 0;

	if (!table || !sync_objs)
		return CAM_SYNC_STATE_SIGNALED_ERROR;

	/*
	 * We need to arrive at the state of the merged object based on
	 * counts of error, active and success states of all children objects
	 */
	for (i = 0; i < num_objs; i++) {
		child_row = table + sync_objs[i];
		switch (child_row->state) {
		case CAM_SYNC_STATE_SIGNALED_ERROR:
			return CAM_SYNC_STATE_SIGNALED_ERROR;
		case CAM_SYNC_STATE_SIGNALED_SUCCESS:
			success_count++;
			break;
		case CAM_SYNC_STATE_ACTIVE:
			active_count++;
			break;
		default:
			pr_err("Invalid state of child object during merge\n");
			return CAM_SYNC_STATE_SIGNALED_ERROR;
		}
	}

	if (active_count)
		return CAM_SYNC_STATE_ACTIVE;

	if (success_count == num_objs)
		return CAM_SYNC_STATE_SIGNALED_SUCCESS;

	return CAM_SYNC_STATE_SIGNALED_ERROR;
}

int cam_sync_init_group_object(struct sync_table_row *table,
	uint32_t idx,
	uint32_t *sync_objs,
@@ -113,12 +155,16 @@ int cam_sync_init_group_object(struct sync_table_row *table,

	row->type = CAM_SYNC_TYPE_GROUP;
	row->sync_id = idx;
	row->state = CAM_SYNC_STATE_ACTIVE;
	row->state = cam_sync_util_get_group_object_state(table,
		sync_objs, num_objs);
	row->remaining = num_objs;
	init_completion(&row->signaled);
	INIT_LIST_HEAD(&row->callback_list);
	INIT_LIST_HEAD(&row->user_payload_list);

	if (row->state != CAM_SYNC_STATE_ACTIVE)
		complete_all(&row->signaled);

	spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
	return 0;
}
@@ -208,6 +254,11 @@ int cam_sync_util_validate_merge(uint32_t *sync_obj, uint32_t num_objs)
	int i;
	struct sync_table_row *row = NULL;

	if (num_objs <= 1) {
		pr_err("Single object merge is not allowed\n");
		return -EINVAL;
	}

	for (i = 0; i < num_objs; i++) {
		row = sync_dev->sync_table + sync_obj[i];
		spin_lock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);