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

Commit fa230469 authored by Nitesh Gupta's avatar Nitesh Gupta Committed by Gauri Joshi
Browse files

msm: mhi_dev: Handle potential deadlock situation



With the current logic, MHI driver will hold channel
lock while processing the ring element and triggers
callback for the clients. Some clients are issuing
read requests for the channel in the callback context.
MHI driver will try to acquire the same channel lock
in read api leading to a deadlock situation.

Modify the logic to avoid holding channel lock
while processing the ring elements.

Change-Id: I62ac28d5eb06e3c9b12437f02288cfe1cdb2bea2
Signed-off-by: default avatarNitesh Gupta <nitegupt@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent cdc28c2b
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -2171,15 +2171,14 @@ static void mhi_dev_process_ring_pending(struct work_struct *work)
		}

		ch = &mhi->ch[ring->id - mhi->ch_ring_start];
		mutex_lock(&ch->ch_lock);

		rc = mhi_dev_process_ring(ring);
		if (rc) {
			mhi_log(MHI_MSG_ERROR,
				"error processing ring %d\n", ring->id);
			mutex_unlock(&ch->ch_lock);
			goto exit;
		}
		mutex_lock(&ch->ch_lock);
		ch->db_pending = false;

		if (ch->reset_pending) {
@@ -3262,9 +3261,9 @@ int mhi_dev_read_channel(struct mhi_req *mreq)
	mutex_lock(&ch->ch_lock);

	do {
		if (ch->state == MHI_DEV_CH_STOPPED) {
		if (ch->state == MHI_DEV_CH_STOPPED || ch->reset_pending) {
			mhi_log(MHI_MSG_VERBOSE,
				"channel (%d) already stopped\n",
				"channel (%d) already stopped or RST pending\n",
				mreq->chan);
			bytes_read = -1;
			goto exit;
@@ -3445,9 +3444,10 @@ int mhi_dev_write_channel(struct mhi_req *wreq)
	}

	ch->pend_wr_count++;
	if (ch->state == MHI_DEV_CH_STOPPED) {
	if (ch->state == MHI_DEV_CH_STOPPED || ch->reset_pending) {
		mhi_log(MHI_MSG_ERROR,
			"channel %d already stopped\n", wreq->chan);
			"channel %d already stopped or RST pending\n",
			wreq->chan);
		bytes_written = -1;
		goto exit;
	}