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

Commit db6c7f08 authored by Subramanian Ananthanarayanan's avatar Subramanian Ananthanarayanan Committed by Gauri Joshi
Browse files

msm: mhi_dev: Serialize UCI open and close file node operations



Multiple clients might perform open and close file operations
simultaneously on the same file node created by UCI. To avoid
race conditions which might result in invalid accesses or crashes,
the open and close operations are serialized.

Change-Id: Ic6a290a2c6af25bcd60983a7b531bf1287201821
Signed-off-by: default avatarSubramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent bb1be52e
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -372,6 +372,7 @@ struct uci_client {
	struct mhi_uci_ctxt_t *uci_ctxt;
	struct mutex in_chan_lock;
	struct mutex out_chan_lock;
	struct mutex client_lock;
	spinlock_t req_lock;
	unsigned int f_flags;
	/* Pointer to dynamically allocated mhi_req structs */
@@ -779,6 +780,8 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait)
	if (!uci_handle)
		return -ENODEV;

	mutex_lock(&uci_handle->client_lock);

	poll_wait(file, &uci_handle->read_wq, wait);
	poll_wait(file, &uci_handle->write_wq, wait);
	/*
@@ -786,8 +789,10 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait)
	 * to poll are in connected state and return with the
	 * appropriate mask if channels are disconnected.
	 */
	if (!mhi_uci_are_channels_connected(uci_handle)) {
	if (!atomic_read(&uci_handle->mhi_chans_open) ||
		!mhi_uci_are_channels_connected(uci_handle)) {
		mask = POLLHUP;
		mutex_unlock(&uci_handle->client_lock);
		return mask;
	}
	mask = uci_handle->at_ctrl_mask;
@@ -807,6 +812,8 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait)
	uci_log(UCI_DBG_VERBOSE,
		"Client attempted to poll chan %d, returning mask 0x%x\n",
		uci_handle->in_chan, mask);
	mutex_unlock(&uci_handle->client_lock);

	return mask;
}

@@ -1066,6 +1073,7 @@ static int mhi_uci_client_open(struct inode *mhi_inode,
		return -EINVAL;
	}

	mutex_lock(&uci_handle->client_lock);
	uci_log(UCI_DBG_DBG,
		"Client opened struct device node 0x%x, ref count 0x%x\n",
		iminor(mhi_inode), atomic_read(&uci_handle->ref_count));
@@ -1073,6 +1081,7 @@ static int mhi_uci_client_open(struct inode *mhi_inode,
		if (!uci_handle) {
			atomic_dec(&uci_handle->ref_count);
			uci_log(UCI_DBG_DBG, "No memory, returning failure\n");
			mutex_unlock(&uci_handle->client_lock);
			return -ENOMEM;
		}
		uci_handle->uci_ctxt = &uci_ctxt;
@@ -1090,11 +1099,13 @@ static int mhi_uci_client_open(struct inode *mhi_inode,
					uci_log(UCI_DBG_INFO,
						"Closing failed channel\n");
				}
				mutex_unlock(&uci_handle->client_lock);
				return rc;
			}
		}
	}
	file_handle->private_data = uci_handle;
	mutex_unlock(&uci_handle->client_lock);

	return 0;

@@ -1111,10 +1122,12 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
	if (!uci_handle)
		return -EINVAL;

	mutex_lock(&uci_handle->client_lock);
	in_chan_attr = uci_handle->in_chan_attr;
	if (!in_chan_attr) {
		uci_log(UCI_DBG_ERROR, "Null channel attributes for chan %d\n",
				uci_handle->in_chan);
		mutex_unlock(&uci_handle->client_lock);
		return -EINVAL;
	}

@@ -1122,6 +1135,7 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
		uci_log(UCI_DBG_DBG, "Client close chan %d, ref count 0x%x\n",
			iminor(mhi_inode),
			atomic_read(&uci_handle->ref_count));
		mutex_unlock(&uci_handle->client_lock);
		return 0;
	}

@@ -1185,6 +1199,7 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
	atomic_set(&uci_handle->read_data_ready, 0);
	atomic_set(&uci_handle->write_data_ready, 0);
	file_handle->private_data = NULL;
	mutex_unlock(&uci_handle->client_lock);

	return 0;
}
@@ -1667,6 +1682,7 @@ static int mhi_register_client(struct uci_client *mhi_client, int index)

	mutex_init(&mhi_client->in_chan_lock);
	mutex_init(&mhi_client->out_chan_lock);
	mutex_init(&mhi_client->client_lock);
	spin_lock_init(&mhi_client->req_lock);
	/* Init the completion event for AT ctrl read */
	init_completion(&mhi_client->at_ctrl_read_done);