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

Commit bb1be52e authored by Gauri Joshi's avatar Gauri Joshi
Browse files

msm: mhi: Prevent flush queue if channel is closed



Change is to prevent flush events being queued post channel close and
wait for pending flush event callbacks prior to channel close.

Change-Id: Ic168be0a187b3edcfeccedc565fb02673eaee883
Signed-off-by: default avatarSubramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent 446bace1
Loading
Loading
Loading
Loading
+33 −14
Original line number Diff line number Diff line
@@ -615,18 +615,21 @@ static int mhi_dev_flush_transfer_completion_events(struct mhi_dev *mhi,
	unsigned long flags;
	struct event_req *flush_ereq;

	do {

		/*
		 * Channel got stopped or closed with transfers pending
		 * Do not send completion events to host
		 */
		if (ch->state == MHI_DEV_CH_CLOSED ||
			ch->state == MHI_DEV_CH_STOPPED) {
		mhi_log(MHI_MSG_DBG, "Ch %d closed with %d writes pending\n",
			mhi_log(MHI_MSG_DBG,
				"Ch %d closed with %d writes pending\n",
				ch->ch_id, ch->pend_wr_count + 1);
		return -ENODEV;
			rc = -ENODEV;
			break;
		}

	do {
		spin_lock_irqsave(&mhi->lock, flags);
		if (list_empty(&ch->flush_event_req_buffers)) {
			spin_unlock_irqrestore(&mhi->lock, flags);
@@ -652,7 +655,8 @@ static int mhi_dev_flush_transfer_completion_events(struct mhi_dev *mhi,
				"Invalid cmpl evt buf - start %pK, end %pK\n",
				flush_ereq->tr_events,
				flush_ereq->tr_events + flush_ereq->num_events);
			return -EINVAL;
			rc = -EINVAL;
			break;
		}
		rc = mhi_dev_send_multiple_tr_events(mhi,
				mhi->ch_ctx_cache[ch->ch_id].err_indx,
@@ -2429,6 +2433,7 @@ static void mhi_dev_transfer_completion_cb(void *mreq)
	/* Trigger client call back */
	req->client_cb(req);

	mutex_lock(&ch->ch_lock);
	/* Flush read completions to host */
	if (snd_cmpl && mhi_ctx->ch_ctx_cache[ch->ch_id].ch_type ==
				MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL) {
@@ -2439,7 +2444,7 @@ static void mhi_dev_transfer_completion_cb(void *mreq)
				"Failed to flush read completions to host\n");
		}
	}

	mutex_unlock(&ch->ch_lock);
	if (ch->state == MHI_DEV_CH_PENDING_STOP) {
		ch->state = MHI_DEV_CH_STOPPED;
		rc = mhi_dev_process_stop_cmd(ch->ring, ch->ch_id, mhi_ctx);
@@ -3134,7 +3139,8 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle)
	ch = handle->channel;

	do {
		if (ch->pend_wr_count) {
		if (ch->pend_wr_count &&
			!list_empty(&ch->event_req_buffers)) {
			usleep_range(MHI_DEV_CH_CLOSE_TIMEOUT_MIN,
					MHI_DEV_CH_CLOSE_TIMEOUT_MAX);
		} else
@@ -3146,6 +3152,9 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle)
	if (ch->pend_wr_count)
		mhi_log(MHI_MSG_ERROR, "%d writes pending for channel %d\n",
			ch->pend_wr_count, ch->ch_id);
	if (!list_empty(&ch->event_req_buffers))
		mhi_log(MHI_MSG_ERROR, "%d pending flush for channel %d\n",
			ch->pend_wr_count, ch->ch_id);

	if (ch->state != MHI_DEV_CH_PENDING_START)
		if ((ch->ch_type == MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL &&
@@ -3157,14 +3166,24 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle)
	ch->state = MHI_DEV_CH_CLOSED;
	ch->active_client = NULL;
	kfree(ch->ereqs);
	mhi_log(MHI_MSG_INFO,
		"MEM_DEALLOC:ch:%d size:%d EREQ\n",
		ch->ch_id, ch->evt_req_size);
	kfree(ch->tr_events);
	mhi_log(MHI_MSG_INFO,
		"MEM_DEALLOC:ch:%d size:%d TR_EVENTS\n",
		ch->ch_id, ch->evt_buf_size);
	ch->evt_buf_size = 0;
	ch->evt_req_size = 0;
	ch->ereqs = NULL;
	ch->tr_events = NULL;
	kfree(handle);
	mhi_log(MHI_MSG_INFO,
		"MEM_ALLOC:ch:%d size:%d CLNT_HANDLE\n",
		ch->ch_id, sizeof(struct mhi_dev_client));

	mutex_unlock(&ch->ch_lock);
	return;
}
EXPORT_SYMBOL(mhi_dev_close_channel);