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

Commit 3659544d authored by Ayush Kumar's avatar Ayush Kumar Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: core: Fix context release timing issue



When sync object is invalid and num_in_map > 1,
it will lead to context ref leak. Check sync
object first, then register sync call back.

CRs-Fixed: 2594185
Change-Id: I2d39ce3ea43bbe7bc05420b86b37fdfba4aa795a
Signed-off-by: default avatarAyush Kumar <ayushkr@codeaurora.org>
parent ee0bc60d
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/debugfs.h>
@@ -451,6 +451,17 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
				"[%s][%d] : Moving req[%llu] from free_list to pending_list",
				ctx->dev_name, ctx->ctx_id, req->request_id);

		for (j = 0; j < req->num_in_map_entries; j++) {
			rc = cam_sync_check_valid(
				req->in_map_entries[j].sync_id);
			if (rc) {
				CAM_ERR(CAM_CTXT,
					"invalid in map sync object %d",
					req->in_map_entries[j].sync_id);
				goto put_ref;
			}
		}

		for (j = 0; j < req->num_in_map_entries; j++) {
			cam_context_getref(ctx);
			rc = cam_sync_register_callback(
@@ -472,7 +483,8 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
						ctx->dev_name, ctx->ctx_id,
						req->request_id);

				goto put_ctx_ref;
				cam_context_putref(ctx);
				goto put_ref;
			}
			CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d",
				req->in_map_entries[j].sync_id, rc);
@@ -480,9 +492,6 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
	}

	return rc;
put_ctx_ref:
	for (; j >= 0; j--)
		cam_context_putref(ctx);
put_ref:
	for (--i; i >= 0; i--) {
		if (cam_sync_put_obj_ref(req->out_map_entries[i].sync_id))
+34 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/init.h>
@@ -286,6 +286,7 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
	int rc;
	long idx = 0;
	bool bit;
	int i = 0;

	if (!sync_obj || !merged_obj) {
		CAM_ERR(CAM_SYNC, "Invalid pointer(s)");
@@ -303,6 +304,14 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
		return -EINVAL;
	}

	for (i = 0; i < num_objs; i++) {
		rc = cam_sync_check_valid(sync_obj[i]);
		if (rc) {
			CAM_ERR(CAM_SYNC, "Sync_obj[%d] %d valid check fail",
				i, sync_obj[i]);
			return rc;
		}
	}
	do {
		idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
		if (idx >= CAM_SYNC_MAX_OBJS)
@@ -374,6 +383,30 @@ int cam_sync_destroy(int32_t sync_obj)
	return cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
}

int cam_sync_check_valid(int32_t sync_obj)
{
	struct sync_table_row *row = NULL;

	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
		return -EINVAL;

	row = sync_dev->sync_table + sync_obj;

	if (!test_bit(sync_obj, sync_dev->bitmap)) {
		CAM_ERR(CAM_SYNC, "Error: Released sync obj received %d",
			sync_obj);
		return -EINVAL;
	}

	if (row->state == CAM_SYNC_STATE_INVALID) {
		CAM_ERR(CAM_SYNC,
			"Error: accessing an uninitialized sync obj = %d",
			sync_obj);
		return -EINVAL;
	}
	return 0;
}

int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms)
{
	unsigned long timeleft;
+10 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef __CAM_SYNC_API_H__
@@ -140,5 +140,14 @@ int cam_sync_destroy(int32_t sync_obj);
 */
int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms);

/**
 * @brief: Check if sync object is valid
 *
 * @param sync_obj: int referencing the sync object to be checked
 *
 * @return 0 upon success, -EINVAL if sync object is in bad state or arguments
 * are invalid
 */
int cam_sync_check_valid(int32_t sync_obj);

#endif /* __CAM_SYNC_API_H__ */