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

Commit c7da03b7 authored by Karthik Anantha Ram's avatar Karthik Anantha Ram Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: sync: Validate if fence is already signaled



This change provides a debugfs to switch between enqueuing
the cb for a signaled fence onto the workq or directly
invoking the cb in the same thread context. By default
the task will be enqueued onto the workq.

To have the sync driver invoke cb in same ctx:
adb shell "echo Y >
	/sys/kernel/debug/camera_sync/trigger_cb_without_switch"

Change-Id: Ic2fd7e0f3b08224020fcd2bd6f317e0da1939d10
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent a5997132
Loading
Loading
Loading
Loading
+53 −11
Original line number Diff line number Diff line
@@ -21,6 +21,13 @@

struct sync_device *sync_dev;

/*
 * Flag to determine whether to enqueue cb of a
 * signaled fence onto the workq or invoke it
 * directly in the same context
 */
static bool trigger_cb_without_switch;

int cam_sync_create(int32_t *sync_obj, const char *name)
{
	int rc;
@@ -59,6 +66,7 @@ int cam_sync_register_callback(sync_callback cb_func,
	struct sync_callback_info *sync_cb;
	struct sync_callback_info *cb_info;
	struct sync_table_row *row = NULL;
	int status = 0;

	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0 || !cb_func)
		return -EINVAL;
@@ -95,18 +103,27 @@ int cam_sync_register_callback(sync_callback cb_func,
	if ((row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS ||
		row->state == CAM_SYNC_STATE_SIGNALED_ERROR) &&
		(!row->remaining)) {
		if (trigger_cb_without_switch) {
			CAM_DBG(CAM_SYNC, "Invoke callback for sync object:%d",
				sync_obj);
			status = row->state;
			kfree(sync_cb);
			spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
			cb_func(sync_obj, status, userdata);
		} else {
			sync_cb->callback_func = cb_func;
			sync_cb->cb_data = userdata;
			sync_cb->sync_obj = sync_obj;
			INIT_WORK(&sync_cb->cb_dispatch_work,
				cam_sync_util_cb_dispatch);
			sync_cb->status = row->state;
		CAM_DBG(CAM_SYNC, "Callback trigger for sync object:%d",
			CAM_DBG(CAM_SYNC, "Enqueue callback for sync object:%d",
				sync_cb->sync_obj);
			queue_work(sync_dev->work_queue,
				&sync_cb->cb_dispatch_work);

			spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
		}

		return 0;
	}

@@ -874,6 +891,26 @@ static void cam_sync_init_entity(struct sync_device *sync_dev)
}
#endif

static int cam_sync_create_debugfs(void)
{
	sync_dev->dentry = debugfs_create_dir("camera_sync", NULL);

	if (!sync_dev->dentry) {
		CAM_ERR(CAM_SYNC, "Failed to create sync dir");
		return -ENOMEM;
	}

	if (!debugfs_create_bool("trigger_cb_without_switch",
		0644, sync_dev->dentry,
		&trigger_cb_without_switch)) {
		CAM_ERR(CAM_SYNC,
			"failed to create trigger_cb_without_switch entry");
		return -ENOMEM;
	}

	return 0;
}

static int cam_sync_probe(struct platform_device *pdev)
{
	int rc;
@@ -939,6 +976,9 @@ static int cam_sync_probe(struct platform_device *pdev)
		goto v4l2_fail;
	}

	trigger_cb_without_switch = false;
	cam_sync_create_debugfs();

	return rc;

v4l2_fail:
@@ -958,6 +998,8 @@ static int cam_sync_remove(struct platform_device *pdev)
	v4l2_device_unregister(sync_dev->vdev->v4l2_dev);
	cam_sync_media_controller_cleanup(sync_dev);
	video_device_release(sync_dev->vdev);
	debugfs_remove_recursive(sync_dev->dentry);
	sync_dev->dentry = NULL;
	kfree(sync_dev);
	sync_dev = NULL;

+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-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
@@ -17,6 +17,7 @@
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/debugfs.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
@@ -177,6 +178,7 @@ struct cam_signalable_info {
 * @row_spinlocks   : Spinlock array, one for each row in the table
 * @table_lock      : Mutex used to lock the table
 * @open_cnt        : Count of file open calls made on the sync driver
 * @dentry          : Debugfs entry
 * @work_queue      : Work queue used for dispatching kernel callbacks
 * @cam_sync_eventq : Event queue used to dispatch user payloads to user space
 * @bitmap          : Bitmap representation of all sync objects
@@ -188,6 +190,7 @@ struct sync_device {
	spinlock_t row_spinlocks[CAM_SYNC_MAX_OBJS];
	struct mutex table_lock;
	int open_cnt;
	struct dentry *dentry;
	struct workqueue_struct *work_queue;
	struct v4l2_fh *cam_sync_eventq;
	spinlock_t cam_sync_eventq_lock;