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

Commit 29edeb73 authored by Sumukh Hallymysore Ravindra's avatar Sumukh Hallymysore Ravindra
Browse files

msm: synx: Perform idr access with lock



Perform IDR function access by holding on to the lock
which otherwise could lead to synchronization issues
and race conditions.
Additionally check for the id returned and return error
if id allocation failed.

Change-Id: I88be2883b20e3bbd6029d9f2caae6096907e4c09
Signed-off-by: default avatarSumukh Hallymysore Ravindra <shallymy@codeaurora.org>
parent 7a04b641
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -96,9 +96,15 @@ int synx_create(s32 *synx_obj, const char *name)

	/* global synx id */
	id = synx_create_handle(synx_dev->synx_table + idx);
	if (id < 0) {
		pr_err("unable to allocate the synx handle\n");
		clear_bit(idx, synx_dev->bitmap);
		return -EINVAL;
	}

	rc = synx_init_object(synx_dev->synx_table,
			idx, id, name, &synx_fence_ops);
	if (rc) {
	if (rc < 0) {
		pr_err("unable to init row at idx = %ld\n", idx);
		clear_bit(idx, synx_dev->bitmap);
		return -EINVAL;
@@ -1442,6 +1448,7 @@ static int __init synx_init(void)
		spin_lock_init(&synx_dev->row_spinlocks[idx]);

	idr_init(&synx_dev->synx_ids);
	spin_lock_init(&synx_dev->idr_lock);

	rc = alloc_chrdev_region(&synx_dev->dev, 0, 1, SYNX_DEVICE_NAME);
	if (rc < 0) {
+2 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ struct bind_operations {
 * @work_queue    : Work queue used for dispatching kernel callbacks
 * @bitmap        : Bitmap representation of all synx objects
 * 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
 * client_list    : All the synx clients
@@ -170,6 +171,7 @@ struct synx_device {
	struct workqueue_struct *work_queue;
	DECLARE_BITMAP(bitmap, SYNX_MAX_OBJS);
	struct idr synx_ids;
	spinlock_t idr_lock;
	u64 dma_context;
	struct bind_operations bind_vtbl[SYNX_MAX_BIND_TYPES];
	struct list_head client_list;
+27 −5
Original line number Diff line number Diff line
@@ -138,17 +138,20 @@ int synx_deinit_object(struct synx_table_row *row)
	struct synx_callback_info *synx_cb, *temp_cb;
	struct synx_cb_data  *upayload_info, *temp_upayload;

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

	synx_obj = row->synx_obj;

	spin_lock_bh(&synx_dev->idr_lock);
	if ((struct synx_table_row *)idr_remove(&synx_dev->synx_ids,
			row->synx_obj) != row) {
		pr_err("removing data in idr table failed 0x%x\n",
			row->synx_obj);
		spin_unlock_bh(&synx_dev->idr_lock);
		return -EINVAL;
	}
	spin_unlock_bh(&synx_dev->idr_lock);

	/*
	 * release the fence memory only for individual obj.
@@ -483,9 +486,15 @@ u32 synx_status_locked(struct synx_table_row *row)
void *synx_from_handle(s32 synx_obj)
{
	s32 base;
	struct synx_table_row *row =
		(struct synx_table_row *) idr_find(&synx_dev->synx_ids,
	struct synx_table_row *row;

	if (!synx_dev)
		return NULL;

	spin_lock_bh(&synx_dev->idr_lock);
	row = (struct synx_table_row *) idr_find(&synx_dev->synx_ids,
		synx_obj);
	spin_unlock_bh(&synx_dev->idr_lock);

	if (!row) {
		pr_err(
@@ -507,8 +516,15 @@ void *synx_from_handle(s32 synx_obj)
s32 synx_create_handle(void *pObj)
{
	s32 base = current->tgid << 16;
	s32 id = idr_alloc(&synx_dev->synx_ids, pObj,
	s32 id;

	if (!synx_dev)
		return -EINVAL;

	spin_lock_bh(&synx_dev->idr_lock);
	id = idr_alloc(&synx_dev->synx_ids, pObj,
			base, base + 0x10000, GFP_ATOMIC);
	spin_unlock_bh(&synx_dev->idr_lock);

	pr_debug("generated Id: 0x%x, base: 0x%x, client: 0x%x\n",
		id, base, current->tgid);
@@ -562,11 +578,17 @@ void *synx_from_key(s32 id, u32 secure_key)
{
	struct synx_table_row *row = NULL;

	if (!synx_dev)
		return NULL;

	spin_lock_bh(&synx_dev->idr_lock);
	row = (struct synx_table_row *) idr_find(&synx_dev->synx_ids, id);
	if (!row) {
		pr_err("invalid synx obj 0x%x\n", id);
		spin_unlock_bh(&synx_dev->idr_lock);
		return NULL;
	}
	spin_unlock_bh(&synx_dev->idr_lock);

	if (row->secure_key != secure_key)
		row = NULL;