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

Commit a84df413 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: synx: fix synx handle/s mapping to synx object"

parents c59c16d3 b28b8b8b
Loading
Loading
Loading
Loading
+64 −49
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ struct synx_device *synx_dev;

void synx_external_callback(s32 sync_obj, int status, void *data)
{
	s32 synx_obj;
	struct synx_table_row *row = NULL;
	struct synx_external_data *bind_data = data;

	if (bind_data) {
		synx_obj = bind_data->synx_obj;
		row = synx_from_key(bind_data->synx_obj, bind_data->secure_key);
		kfree(bind_data);
	}
@@ -32,7 +34,7 @@ void synx_external_callback(s32 sync_obj, int status, void *data)
		spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);

		pr_debug("signaling synx 0x%x from external callback %d\n",
			row->synx_obj, sync_obj);
			synx_obj, sync_obj);
		synx_signal_core(row, status);
	} else {
		pr_err("invalid callback from sync external obj %d\n",
@@ -115,10 +117,10 @@ int synx_create(s32 *synx_obj, const char *name)
		return -EINVAL;
	}

	*synx_obj = row->synx_obj;
	*synx_obj = id;

	pr_debug("row: synx id: 0x%x, index: %d\n",
		row->synx_obj, row->index);
		id, row->index);
	pr_debug("Exit %s\n", __func__);

	return rc;
@@ -144,7 +146,7 @@ int synx_register_callback(s32 synx_obj,
		if (temp_cb_info->callback_func == cb_func &&
			temp_cb_info->cb_data == userdata) {
			pr_err("duplicate registration for synx 0x%x\n",
				row->synx_obj);
				synx_obj);
			spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);
			return -EALREADY;
		}
@@ -198,7 +200,7 @@ int synx_deregister_callback(s32 synx_obj,

	state = synx_status_locked(row);
	pr_debug("de-registering callback for synx 0x%x\n",
		row->synx_obj);
		synx_obj);
	list_for_each_entry_safe(synx_cb, temp, &row->callback_list, list) {
		if (synx_cb->callback_func == cb_func &&
			synx_cb->cb_data == userdata) {
@@ -243,8 +245,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
	}

	if (is_merged_synx(row)) {
		pr_err("signaling a composite synx object 0x%x\n",
			row->synx_obj);
		pr_err("signaling a composite synx object at %d\n",
			row->index);
		return -EINVAL;
	}

@@ -252,8 +254,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status)

	if (synx_status_locked(row) != SYNX_STATE_ACTIVE) {
		spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);
		pr_err("object already signaled synx = 0x%x\n",
			row->synx_obj);
		pr_err("object already signaled synx at %d\n",
			row->index);
		return -EALREADY;
	}

@@ -263,8 +265,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status)

	rc = dma_fence_signal_locked(row->fence);
	if (rc < 0) {
		pr_err("unable to signal synx 0x%x, err: %d\n",
			row->synx_obj, rc);
		pr_err("unable to signal synx at %d, err: %d\n",
			row->index, rc);
		if (status != SYNX_STATE_SIGNALED_ERROR) {
			dma_fence_set_error(row->fence, -EINVAL);
			status = SYNX_STATE_SIGNALED_ERROR;
@@ -414,10 +416,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged)
		goto clear;
	}

	*synx_merged = row->synx_obj;
	*synx_merged = id;

	pr_debug("row (merged): synx 0x%x, index: %d\n",
		row->synx_obj, row->index);
		id, row->index);
	pr_debug("Exit %s\n", __func__);

	return 0;
@@ -431,19 +433,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged)
	return rc;
}

int synx_release(s32 synx_obj)
static int synx_release_core(struct synx_table_row *row)
{
	s32 idx;
	struct dma_fence *fence = NULL;
	struct synx_table_row *row  = NULL;

	pr_debug("Enter %s\n", __func__);

	row = synx_from_handle(synx_obj);
	if (!row) {
		pr_err("invalid synx: 0x%x\n", synx_obj);
		return -EINVAL;
	}

	/*
	 * metadata might be cleared after invoking dma_fence_put
@@ -453,13 +446,6 @@ int synx_release(s32 synx_obj)
	fence = row->fence;
	idx = row->index;
	spin_lock_bh(&synx_dev->row_spinlocks[idx]);
	if (synx_status_locked(row) == SYNX_STATE_ACTIVE) {
		pr_err("need to signal before release synx = 0x%x\n",
			synx_obj);
		spin_unlock_bh(&synx_dev->row_spinlocks[idx]);
		return -EINVAL;
	}

	/*
	 * we need to clear the metadata for merged synx obj upon synx_release
	 * itself as it does not invoke the synx_fence_release function.
@@ -476,6 +462,21 @@ int synx_release(s32 synx_obj)
	return 0;
}

int synx_release(s32 synx_obj)
{
	struct synx_table_row *row  = NULL;

	pr_debug("Enter %s\n", __func__);

	row = synx_from_handle(synx_obj);
	if (!row) {
		pr_err("invalid synx: 0x%x\n", synx_obj);
		return -EINVAL;
	}

	return synx_release_core(row);
}

int synx_wait(s32 synx_obj, u64 timeout_ms)
{
	unsigned long timeleft;
@@ -568,7 +569,7 @@ int synx_bind(s32 synx_obj, struct synx_external_desc external_sync)
	}

	/* data passed to external callback */
	data->synx_obj = row->synx_obj;
	data->synx_obj = synx_obj;
	data->secure_key = synx_generate_secure_key(row);

	rc = bind_ops->register_callback(synx_external_callback,
@@ -637,6 +638,7 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj)
{
	s32 id;
	struct dma_fence *fence;
	struct synx_obj_node *obj_node;
	struct synx_table_row *row = NULL;

	pr_debug("Enter %s\n", __func__);
@@ -648,6 +650,10 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj)
	if (!row)
		return -EINVAL;

	obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL);
	if (!obj_node)
		return -ENOMEM;

	/* new global synx id */
	id = synx_create_handle(row);
	if (id < 0) {
@@ -658,10 +664,15 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj)
		}
		/* release the reference obtained during export */
		dma_fence_put(fence);
		kfree(obj_node);
		return -EINVAL;
	}

	row->synx_obj = id;
	spin_lock_bh(&synx_dev->row_spinlocks[row->index]);
	obj_node->synx_obj = id;
	list_add(&obj_node->list, &row->synx_obj_list);
	spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);

	*new_synx_obj = id;
	pr_debug("Exit %s\n", __func__);

@@ -679,7 +690,7 @@ int synx_export(s32 synx_obj, u32 *import_key)
	if (!row)
		return -EINVAL;

	rc = synx_generate_import_key(row, import_key);
	rc = synx_generate_import_key(row, synx_obj, import_key);
	if (rc < 0)
		return rc;

@@ -881,6 +892,7 @@ static int synx_handle_wait(struct synx_private_ioctl_arg *k_ioctl)
static int synx_handle_register_user_payload(
	struct synx_private_ioctl_arg *k_ioctl)
{
	s32 synx_obj;
	u32 state = SYNX_STATE_INVALID;
	struct synx_userpayload_info userpayload_info;
	struct synx_cb_data *user_payload_kernel;
@@ -898,9 +910,10 @@ static int synx_handle_register_user_payload(
		k_ioctl->size))
		return -EFAULT;

	row = synx_from_handle(userpayload_info.synx_obj);
	synx_obj = userpayload_info.synx_obj;
	row = synx_from_handle(synx_obj);
	if (!row) {
		pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj);
		pr_err("invalid synx: 0x%x\n", synx_obj);
		return -EINVAL;
	}

@@ -918,7 +931,7 @@ static int synx_handle_register_user_payload(
		return -ENOMEM;

	user_payload_kernel->client = client;
	user_payload_kernel->data.synx_obj = row->synx_obj;
	user_payload_kernel->data.synx_obj = synx_obj;
	memcpy(user_payload_kernel->data.payload_data,
		userpayload_info.payload,
		SYNX_PAYLOAD_WORDS * sizeof(__u64));
@@ -944,7 +957,7 @@ static int synx_handle_register_user_payload(
			user_payload_iter->data.payload_data[1] ==
				user_payload_kernel->data.payload_data[1]) {
			pr_err("callback already registered on 0x%x\n",
				row->synx_obj);
				synx_obj);
			spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);
			kfree(user_payload_kernel);
			return -EALREADY;
@@ -961,6 +974,7 @@ static int synx_handle_register_user_payload(
static int synx_handle_deregister_user_payload(
	struct synx_private_ioctl_arg *k_ioctl)
{
	s32 synx_obj;
	u32 state = SYNX_STATE_INVALID;
	struct synx_client *client = NULL;
	struct synx_userpayload_info userpayload_info;
@@ -978,9 +992,10 @@ static int synx_handle_deregister_user_payload(
		k_ioctl->size))
		return -EFAULT;

	row = synx_from_handle(userpayload_info.synx_obj);
	synx_obj = userpayload_info.synx_obj;
	row = synx_from_handle(synx_obj);
	if (!row) {
		pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj);
		pr_err("invalid synx: 0x%x\n", synx_obj);
		return -EINVAL;
	}

@@ -1028,7 +1043,7 @@ static int synx_handle_deregister_user_payload(
			SYNX_PAYLOAD_WORDS * sizeof(__u64));

		user_payload_kernel->client = client;
		data->synx_obj = row->synx_obj;
		data->synx_obj = synx_obj;
		data->status = SYNX_CALLBACK_RESULT_CANCELED;

		spin_lock_bh(&client->eventq_lock);
@@ -1299,15 +1314,15 @@ static int synx_close(struct inode *inode, struct file *filep)
			 * signal all ACTIVE objects as ERR, but we don't care
			 * about the return status here apart from logging it.
			 */
			if (row->synx_obj && !is_merged_synx(row) &&
			if (row->index && !is_merged_synx(row) &&
				(synx_status(row) == SYNX_STATE_ACTIVE)) {
				pr_debug("synx 0x%x still active at shutdown\n",
					row->synx_obj);
				pr_debug("synx still active at shutdown at %d\n",
					row->index);
				rc = synx_signal_core(row,
						SYNX_STATE_SIGNALED_ERROR);
				if (rc < 0)
					pr_err("cleanup signal fail idx:0x%x\n",
						row->synx_obj);
					pr_err("cleanup signal fail at %d\n",
						row->index);
			}
		}

@@ -1325,11 +1340,11 @@ static int synx_close(struct inode *inode, struct file *filep)
			struct synx_table_row *row =
				synx_dev->synx_table + i;

			if (row->synx_obj) {
				rc = synx_release(row->synx_obj);
			if (row->index) {
				rc = synx_release_core(row);
				if (rc < 0) {
					pr_err("cleanup destroy fail idx:0x%x\n",
						row->synx_obj);
					pr_err("cleanup destroy fail at %d\n",
						row->index);
				}
			}
		}
+11 −6
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ static ssize_t synx_table_read(struct file *file,
	struct error_node *err_node, *err_node_tmp;
	struct synx_table_row *row;
	char *dbuf, *cur, *end;
	struct synx_obj_node *obj_node;

	int i = 0;
	int state = SYNX_STATE_INVALID;
@@ -60,26 +61,23 @@ static ssize_t synx_table_read(struct file *file,
	end = cur + MAX_DBG_BUF_SIZE;
	if (columns & NAME_COLUMN)
		cur += scnprintf(cur, end - cur, "|   Name   |");
	if (columns & ID_COLUMN)
		cur += scnprintf(cur, end - cur, "|    ID    |");
	if (columns & BOUND_COLUMN)
		cur += scnprintf(cur, end - cur, "|   Bound   |");
	if (columns & STATE_COLUMN)
		cur += scnprintf(cur, end - cur, "|  Status  |");
	if (columns & ID_COLUMN)
		cur += scnprintf(cur, end - cur, "|    ID    |");
	cur += scnprintf(cur, end - cur, "\n");
	for (i = 0; i < SYNX_MAX_OBJS; i++) {
		row = &dev->synx_table[i];

		if (!row || !row->synx_obj)
		if (!row->index)
			continue;

		spin_lock_bh(&dev->row_spinlocks[row->index]);
		if (columns & NAME_COLUMN)
			cur += scnprintf(cur, end - cur,
				"|%10s|", row->name);
		if (columns & ID_COLUMN)
			cur += scnprintf(cur, end - cur,
				"|%10d|", row->synx_obj);
		if (columns & BOUND_COLUMN)
			cur += scnprintf(cur, end - cur,
				"|%11d|", row->num_bound_synxs);
@@ -96,6 +94,13 @@ static ssize_t synx_table_read(struct file *file,
				cur,
				end);
		}
		if (columns & ID_COLUMN) {
			list_for_each_entry(obj_node,
				&row->synx_obj_list, list) {
				cur += scnprintf(cur, end - cur,
					"|0x%8x|", obj_node->synx_obj);
				}
		}
		spin_unlock_bh(&dev->row_spinlocks[row->index]);
		cur += scnprintf(cur, end - cur, "\n");
	}
+14 −2
Original line number Diff line number Diff line
@@ -111,13 +111,25 @@ struct synx_cb_data {
	struct list_head list;
};

/**
 * struct synx_obj_node - Single node of info for the synx handle
 * mapped to synx object metadata
 *
 * @synx_obj : Synx integer handle
 * @list     : List member used to append to synx handle list
 */
struct synx_obj_node {
	s32 synx_obj;
	struct list_head list;
};

/**
 * struct synx_table_row - Single row of information about a synx object, used
 * for internal book keeping in the synx driver
 *
 * @name              : Optional string representation of the synx object
 * @fence             : dma fence backing the synx object
 * @synx_obj          : Integer id representing this synx object
 * @synx_obj_list     : List of synx integer handles mapped
 * @index             : Index of the spin lock table associated with synx obj
 * @num_bound_synxs   : Number of external bound synx objects
 * @signaling_id      : ID of the external sync object invoking the callback
@@ -129,7 +141,7 @@ struct synx_cb_data {
struct synx_table_row {
	char name[SYNX_OBJ_NAME_LEN];
	struct dma_fence *fence;
	s32 synx_obj;
	struct list_head synx_obj_list;
	s32 index;
	u32 num_bound_synxs;
	s32 signaling_id;
+81 −31
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ int synx_init_object(struct synx_table_row *table,
{
	struct dma_fence *fence = NULL;
	struct synx_table_row *row = table + idx;
	struct synx_obj_node *obj_node;

	if (!table || idx <= 0 || idx >= SYNX_MAX_OBJS)
		return -EINVAL;
@@ -39,20 +40,28 @@ int synx_init_object(struct synx_table_row *table,
	if (!fence)
		return -ENOMEM;

	obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL);
	if (!obj_node) {
		kfree(fence);
		return -ENOMEM;
	}

	dma_fence_init(fence, ops, &synx_dev->row_spinlocks[idx],
		synx_dev->dma_context, 1);

	row->fence = fence;
	row->synx_obj = id;
	obj_node->synx_obj = id;
	row->index = idx;
	INIT_LIST_HEAD(&row->synx_obj_list);
	INIT_LIST_HEAD(&row->callback_list);
	INIT_LIST_HEAD(&row->user_payload_list);

	list_add(&obj_node->list, &row->synx_obj_list);
	if (name)
		strlcpy(row->name, name, sizeof(row->name));

	pr_debug("synx obj init: id:0x%x state:%u fence: 0x%pK\n",
		row->synx_obj, synx_status_locked(row), fence);
		synx_status_locked(row), fence);

	return 0;
}
@@ -65,20 +74,27 @@ int synx_init_group_object(struct synx_table_row *table,
{
	struct synx_table_row *row = table + idx;
	struct dma_fence_array *array;
	struct synx_obj_node *obj_node;

	array = dma_fence_array_create(num_objs,
				fences, synx_dev->dma_context, 1, false);
	if (!array)
		return -EINVAL;

	obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL);
	if (!obj_node)
		return -ENOMEM;

	row->fence = &array->base;
	row->synx_obj = id;
	obj_node->synx_obj = id;
	row->index = idx;
	INIT_LIST_HEAD(&row->synx_obj_list);
	INIT_LIST_HEAD(&row->callback_list);
	INIT_LIST_HEAD(&row->user_payload_list);

	pr_debug("synx group obj init: id:0x%x state:%u fence: 0x%pK\n",
		row->synx_obj, synx_status_locked(row), row->fence);
	list_add(&obj_node->list, &row->synx_obj_list);
	pr_debug("synx group obj init: id:%d state:%u fence: 0x%pK\n",
		id, synx_status_locked(row), row->fence);

	return 0;
}
@@ -139,23 +155,31 @@ int synx_activate(struct synx_table_row *row)

int synx_deinit_object(struct synx_table_row *row)
{
	s32 synx_obj;
	s32 index;
	struct synx_client *client;
	struct synx_callback_info *synx_cb, *temp_cb;
	struct synx_cb_data  *upayload_info, *temp_upayload;
	struct synx_obj_node *obj_node, *temp_obj_node;

	if (!row || !synx_dev)
		return -EINVAL;

	synx_obj = row->synx_obj;

	index = row->index;
	spin_lock_bh(&synx_dev->idr_lock);
	list_for_each_entry_safe(obj_node,
		temp_obj_node, &row->synx_obj_list, list) {
		if ((struct synx_table_row *)idr_remove(&synx_dev->synx_ids,
			row->synx_obj) != row) {
				obj_node->synx_obj) != row) {
			pr_err("removing data in idr table failed 0x%x\n",
			row->synx_obj);
				obj_node->synx_obj);
			spin_unlock_bh(&synx_dev->idr_lock);
			return -EINVAL;
		}
		pr_debug("removed synx obj at 0x%x successful\n",
			obj_node->synx_obj);
		list_del_init(&obj_node->list);
		kfree(obj_node);
	}
	spin_unlock_bh(&synx_dev->idr_lock);

	/*
@@ -163,27 +187,51 @@ int synx_deinit_object(struct synx_table_row *row)
	 * dma fence array will release all the allocated mem
	 * in its registered release function.
	 */
	if (!is_merged_synx(row))
	if (!is_merged_synx(row)) {
		kfree(row->fence);

		/*
		 * invoke remaining userspace and kernel callbacks on
		 * synx obj destroyed, not signaled, with cancellation
		 * event.
		 */
		list_for_each_entry_safe(upayload_info, temp_upayload,
				&row->user_payload_list, list) {
		pr_err("pending user callback payload\n");
		list_del_init(&upayload_info->list);
		kfree(upayload_info);
			upayload_info->data.status =
				SYNX_CALLBACK_RESULT_CANCELED;
			memcpy(&upayload_info->data.payload_data[2],
				&upayload_info->data.payload_data[0],
				sizeof(u64));
			client = upayload_info->client;
			if (!client) {
				pr_err("invalid client member in cb list\n");
				continue;
			}
			spin_lock_bh(&client->eventq_lock);
			list_move_tail(&upayload_info->list, &client->eventq);
			spin_unlock_bh(&client->eventq_lock);
			/*
			 * since cb can be registered by multiple clients,
			 * wake the process right away
			 */
			wake_up_all(&client->wq);
			pr_debug("dispatched user cb\n");
		}

		list_for_each_entry_safe(synx_cb, temp_cb,
				&row->callback_list, list) {
		pr_err("pending kernel callback payload\n");
			synx_cb->status = SYNX_CALLBACK_RESULT_CANCELED;
			list_del_init(&synx_cb->list);
		kfree(synx_cb);
			queue_work(synx_dev->work_queue,
				&synx_cb->cb_dispatch_work);
			pr_debug("dispatched kernel cb\n");
		}
	}

	clear_bit(row->index, synx_dev->bitmap);
	memset(row, 0, sizeof(*row));

	pr_debug("destroying synx obj: 0x%x successful\n", synx_obj);
	pr_debug("destroying synx obj at %d successful\n", index);
	return 0;
}

@@ -570,8 +618,8 @@ struct synx_table_row *synx_from_fence(struct dma_fence *fence)
	for (idx = 0; idx < SYNX_MAX_OBJS; idx++) {
		if (table[idx].fence == fence) {
			row = table + idx;
			pr_debug("synx global data found for 0x%x\n",
				row->synx_obj);
			pr_debug("synx global data found at %d\n",
				row->index);
			break;
		}
	}
@@ -602,6 +650,7 @@ struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key)
}

int synx_generate_import_key(struct synx_table_row *row,
	s32 synx_obj,
	u32 *key)
{
	bool bit;
@@ -623,7 +672,7 @@ int synx_generate_import_key(struct synx_table_row *row,
	} while (!*key);

	data->key = *key;
	data->synx_obj = row->synx_obj;
	data->synx_obj = synx_obj;
	/*
	 * Reason for separate metadata (for merged synx)
	 * being dma fence array has separate release func
@@ -657,6 +706,7 @@ int synx_generate_import_key(struct synx_table_row *row,
		/* both metadata points to same dma fence */
		new_row->fence = row->fence;
		new_row->index = idx;
		INIT_LIST_HEAD(&new_row->synx_obj_list);
		INIT_LIST_HEAD(&new_row->callback_list);
		INIT_LIST_HEAD(&new_row->user_payload_list);
		data->row = new_row;
@@ -665,7 +715,7 @@ int synx_generate_import_key(struct synx_table_row *row,
	}
	list_add(&data->list, &synx_dev->import_list);
	pr_debug("allocated import key for 0x%x\n",
		row->synx_obj);
		synx_obj);
	mutex_unlock(&synx_dev->table_lock);

	return 0;
+4 −2
Original line number Diff line number Diff line
@@ -234,11 +234,13 @@ int synx_generate_secure_key(struct synx_table_row *row);
 *         verified during import.
 *
 * @param row      : Pointer to the synx object row
 * @param synx_obj : Synx handle
 * @param key      : Pointer to key (filled by the function)
 *
 * @return Status of operation. Negative in case of error. Zero otherwise.
 */
int synx_generate_import_key(struct synx_table_row *row,
	s32 synx_obj,
	u32 *key);

/**