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

Commit 6b7d0258 authored by Sumukh Hallymysore Ravindra's avatar Sumukh Hallymysore Ravindra
Browse files

msm: synx: apis for clients to register bind operations



Provide apis for external clients to registers bind operations
with the synx driver. This enables registered external sync
fences to provide bind operation (equivalence) with synx obj.
This also eliminates synx driver dependency with external fence
implementations.

Change-Id: Ia417bc42d485906c4b805820595c6c9e05ee5877
Signed-off-by: default avatarSumukh Hallymysore Ravindra <shallymy@codeaurora.org>
parent 6d464a5c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only

ccflags-$(CONFIG_SPECTRA_CAMERA) += -Idrivers/media/platform/msm/camera/cam_sync
obj-$(CONFIG_MSM_GLOBAL_SYNX) += synx.o synx_util.o synx_debugfs.o
+80 −78
Original line number Diff line number Diff line
@@ -10,10 +10,6 @@
#include <linux/slab.h>
#include <linux/uaccess.h>

#ifdef CONFIG_SPECTRA_CAMERA
#include <cam_sync_api.h>
#endif

#include "synx_api.h"
#include "synx_util.h"
#include "synx_debugfs.h"
@@ -227,7 +223,6 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
	int rc, ret;
	u32 i = 0;
	u32 idx = 0;
	u32 type;
	s32 sync_id;
	struct synx_external_data *data = NULL;
	struct synx_bind_desc bind_descs[SYNX_MAX_NUM_BINDINGS];
@@ -307,14 +302,13 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
	spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);

	for (i = 0; i < idx; i++) {
		type = bind_descs[i].external_desc.type;
		sync_id = bind_descs[i].external_desc.id[0];
		data = bind_descs[i].external_data;
		if (is_valid_type(type)) {
			bind_ops = &synx_dev->bind_vtbl[type];
			if (!bind_ops->deregister_callback ||
				!bind_ops->signal) {
				pr_err("invalid bind ops for %u\n", type);
		bind_ops = synx_get_bind_ops(
					bind_descs[i].external_desc.type);
		if (!bind_ops) {
			pr_err("invalid bind ops for %u\n",
				bind_descs[i].external_desc.type);
			kfree(data);
			continue;
		}
@@ -343,9 +337,6 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
		if (ret < 0)
			pr_err("signaling fail on sync: %d, err: %d\n",
				sync_id, ret);
		} else {
			pr_warn("unimplemented external type: %u\n", type);
		}

		/*
		 * release the memory allocated for external data.
@@ -536,8 +527,10 @@ int synx_bind(s32 synx_obj, struct synx_external_desc external_sync)
		return -EINVAL;
	}

	if (!is_valid_type(external_sync.type)) {
		pr_err("invalid external sync object\n");
	bind_ops = synx_get_bind_ops(external_sync.type);
	if (!bind_ops) {
		pr_err("invalid bind ops for %u\n",
			external_sync.type);
		return -EINVAL;
	}

@@ -574,15 +567,6 @@ int synx_bind(s32 synx_obj, struct synx_external_desc external_sync)
		}
	}

	bind_ops = &synx_dev->bind_vtbl[external_sync.type];
	if (!bind_ops->register_callback) {
		pr_err("invalid bind register for %u\n",
			external_sync.type);
		spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);
		kfree(data);
		return -EINVAL;
	}

	/* data passed to external callback */
	data->synx_obj = row->synx_obj;
	data->secure_key = synx_generate_secure_key(row);
@@ -1397,39 +1381,60 @@ static const struct file_operations synx_fops = {
#endif
};

#ifdef CONFIG_SPECTRA_CAMERA
static void synx_bind_ops_csl_type(struct bind_operations *vtbl)
int synx_register_ops(const struct synx_register_params *params)
{
	if (!vtbl)
		return;

	vtbl->register_callback = cam_sync_register_callback;
	vtbl->deregister_callback = cam_sync_deregister_callback;
	vtbl->enable_signaling = cam_sync_get_obj_ref;
	vtbl->signal = cam_sync_signal;
	s32 rc;
	struct synx_registered_ops *client_ops;

	if (!params || !params->name ||
		!is_valid_type(params->type) ||
		!params->ops.register_callback ||
		!params->ops.deregister_callback ||
		!params->ops.signal) {
		pr_err("invalid register params\n");
		return -EINVAL;
	}

	pr_debug("csl bind functionality set\n");
	mutex_lock(&synx_dev->table_lock);
	client_ops = &synx_dev->bind_vtbl[params->type];
	if (!client_ops->valid) {
		client_ops->valid = true;
		memcpy(&client_ops->ops, &params->ops,
			sizeof(client_ops->ops));
		strlcpy(client_ops->name, params->name,
			sizeof(client_ops->name));
		client_ops->type = params->type;
		pr_info("registered bind ops for %s\n",
			params->name);
		rc = 0;
	} else {
		pr_info("client already registered by %s\n",
			client_ops->name);
		rc = -EINVAL;
	}
#else
static void synx_bind_ops_csl_type(struct bind_operations *vtbl)
{
	pr_debug("csl bind functionality not available\n");
	mutex_unlock(&synx_dev->table_lock);

	return rc;
}
#endif

static void synx_bind_ops_register(struct synx_device *synx_dev)
int synx_deregister_ops(const struct synx_register_params *params)
{
	u32 i;
	struct synx_registered_ops *client_ops;

	for (i = 0; i < SYNX_MAX_BIND_TYPES; i++) {
		switch (i) {
		case SYNX_TYPE_CSL:
			synx_bind_ops_csl_type(&synx_dev->bind_vtbl[i]);
			break;
		default:
			pr_err("invalid external sync type\n");
		}
	if (!params || !params->name ||
		!is_valid_type(params->type)) {
		pr_err("invalid params\n");
		return -EINVAL;
	}

	mutex_lock(&synx_dev->table_lock);
	client_ops = &synx_dev->bind_vtbl[params->type];
	memset(client_ops, 0, sizeof(*client_ops));
	pr_info("deregistered bind ops for %s\n",
		params->name);
	mutex_unlock(&synx_dev->table_lock);

	return 0;
}

static int __init synx_init(void)
@@ -1487,9 +1492,6 @@ static int __init synx_init(void)
	synx_dev->dma_context = dma_fence_context_alloc(1);

	synx_dev->debugfs_root = init_synx_debug_dir(synx_dev);

	synx_bind_ops_register(synx_dev);

	pr_info("synx device init success\n");

	return 0;
+57 −0
Original line number Diff line number Diff line
@@ -11,8 +11,65 @@

typedef void (*synx_callback)(s32 sync_obj, int status, void *data);

/**
 * struct bind_operations - Function pointers that need to be defined
 *    to achieve bind functionality for external fence with synx obj
 *
 * @register_callback   : Function to register with external sync object
 * @deregister_callback : Function to deregister with external sync object
 * @enable_signaling    : Function to enable the signaling on the external
 *                        sync object (optional)
 * @signal              : Function to signal the external sync object
 */
struct bind_operations {
	int (*register_callback)(synx_callback cb_func,
		void *userdata, s32 sync_obj);
	int (*deregister_callback)(synx_callback cb_func,
		void *userdata, s32 sync_obj);
	int (*enable_signaling)(s32 sync_obj);
	int (*signal)(s32 sync_obj, u32 status);
};

/**
 * struct synx_register_params - External registration parameters
 *
 * @ops  : Pointer to bind operations struct
 * @name : Client name
 *         Only first 32 bytes are accepted, rest will be ignored
 * @type : Synx external client type
 */
struct synx_register_params {
	struct bind_operations ops;
	char *name;
	u32 type;
};

/* Kernel APIs */

/* @brief: Register operations for external synchronization
 *
 * Register with synx for enabling external synchronization through bind
 *
 * @param params : Pointer to register params
 *
 * @return Status of operation. Zero in case of success.
 * -EINVAL will be returned if params are invalid.
 * -ENOMEM will be returned if client cannot be registered due to not
 * enough memory.
 * -EALREADY will be returned if client name is already in use
 */
int synx_register_ops(const struct synx_register_params *params);

/**
 * @brief: De-register external synchronization operations
 *
 * @param params : Pointer to register params
 *
 * @return Status of operation. Zero in case of success.
 * -EINVAL will be returned if client not found.
 */
int synx_deregister_ops(const struct synx_register_params *params);

/**
 * @brief: Creates a synx object
 *
+13 −16
Original line number Diff line number Diff line
@@ -140,22 +140,19 @@ struct synx_table_row {
};

/**
 * struct bind_operations - Function pointers that need to be defined
 *    to achieve bind functionality for external fence with synx obj
 * struct synx_registered_ops - External sync clients registered for bind
 * operations with synx driver
 *
 * @register_callback   : Function to register with external sync object
 * @deregister_callback : Function to deregister with external sync object
 * @enable_signaling    : Function to enable the signaling on the external
 *                        sync object (optional)
 * @signal              : Function to signal the external sync object
 * @valid : Validity of the client registered bind ops
 * @name  : Name of the external sync client
 * @ops   : Bind operations struct for the client
 * @type  : External client type
 */
struct bind_operations {
	int (*register_callback)(synx_callback cb_func,
		void *userdata, s32 sync_obj);
	int (*deregister_callback)(synx_callback cb_func,
		void *userdata, s32 sync_obj);
	int (*enable_signaling)(s32 sync_obj);
	int (*signal)(s32 sync_obj, u32 status);
struct synx_registered_ops {
	bool valid;
	char name[32];
	struct bind_operations ops;
	u32 type;
};

/**
@@ -173,7 +170,7 @@ struct bind_operations {
 * synx_ids       : Global unique ids
 * idr_lock       : Spin lock for id allocation
 * dma_context    : dma context id
 * bind_vtbl      : Table with bind ops for supported external sync objects
 * bind_vtbl      : Table with registered bind ops for external sync (bind)
 * client_list    : All the synx clients
 * debugfs_root   : Root directory for debugfs
 * synx_node_head : list head for synx nodes
@@ -192,7 +189,7 @@ struct synx_device {
	struct idr synx_ids;
	spinlock_t idr_lock;
	u64 dma_context;
	struct bind_operations bind_vtbl[SYNX_MAX_BIND_TYPES];
	struct synx_registered_ops bind_vtbl[SYNX_MAX_BIND_TYPES];
	struct list_head client_list;
	struct dentry *debugfs_root;
	struct list_head synx_debug_head;
+19 −0
Original line number Diff line number Diff line
@@ -601,6 +601,25 @@ void *synx_from_key(s32 id, u32 secure_key)
	return row;
}

struct bind_operations *synx_get_bind_ops(u32 type)
{
	struct synx_registered_ops *client_ops;

	if (!is_valid_type(type))
		return NULL;

	mutex_lock(&synx_dev->table_lock);
	client_ops = &synx_dev->bind_vtbl[type];
	if (!client_ops->valid) {
		mutex_unlock(&synx_dev->table_lock);
		return NULL;
	}
	pr_debug("found bind ops for %s\n", client_ops->name);
	mutex_unlock(&synx_dev->table_lock);

	return &client_ops->ops;
}

void generate_timestamp(char *timestamp, size_t size)
{
	struct timeval tv;
Loading