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

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

Merge "msm: mhi_dev: Check to prevent in_use_list access"

parents 774e9013 cdc28c2b
Loading
Loading
Loading
Loading
+140 −53
Original line number Diff line number Diff line
@@ -476,6 +476,22 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,

	if (!ereq->is_cmd_cpl) {
		ch = ereq->context;
		/*
		 * Take Channel ring event lock to prevent sending
		 * completion command while the channel is getting
		 * reset/stopped.
		 * Abort sending completion event if channel has moved to
		 * stopped state.
		 */
		mutex_lock(&ch->ring->event_lock);
		if (ch->state == MHI_DEV_CH_STOPPED ||
			ch->state == MHI_DEV_CH_PENDING_STOP) {
			mhi_log(MHI_MSG_ERROR,
				"Ch:%d is in %d state, abort sending completion evnt\n"
					, ch->ch_id, ch->state);
			rc = -ENXIO;
			goto exit;
		}
		mhi_log(MHI_MSG_VERBOSE, "Flushing %d cmpl events of ch %d\n",
				ereq->num_events, ch->ch_id);
	} else {
@@ -487,8 +503,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
	rc = mhi_dev_add_element(ring, ereq->tr_events, ereq, evt_len);
	if (rc) {
		pr_err("%s(): error in adding element rc %d\n", __func__, rc);
		mutex_unlock(&ring->event_lock);
		return rc;
		goto exit;
	}

	ring->ring_ctx_shadow->ev.rp = (ring->rd_offset *
@@ -537,6 +552,9 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
			pr_err("%s: error sending in msi\n", __func__);
	}

exit:
	if (!ereq->is_cmd_cpl)
		mutex_unlock(&ch->ring->event_lock);
	mutex_unlock(&ring->event_lock);
	return rc;
}
@@ -597,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);
@@ -634,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,
@@ -1599,7 +1621,7 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring,
		}
	}

	mutex_lock(&mhi->mhi_event_lock);
	mutex_lock(&ring->event_lock);
	/* add the ring element */
	mhi_dev_add_element(ring, el, NULL, 0);

@@ -1632,7 +1654,6 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring,
	 */
	wmb();

	mutex_unlock(&mhi->mhi_event_lock);
	mhi_log(MHI_MSG_VERBOSE, "event sent:\n");
	mhi_log(MHI_MSG_VERBOSE, "evnt ptr : 0x%llx\n", el->evt_tr_comp.ptr);
	mhi_log(MHI_MSG_VERBOSE, "evnt len : 0x%x\n", el->evt_tr_comp.len);
@@ -1645,6 +1666,7 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring,
	else
		rc = ep_pcie_trigger_msi(mhi_ctx->phandle, ctx->ev.msivec);

	mutex_unlock(&ring->event_lock);
	return rc;
}

@@ -1811,6 +1833,44 @@ static int mhi_dev_process_stop_cmd(struct mhi_dev_ring *ring, uint32_t ch_id,
					MHI_CMD_COMPL_CODE_SUCCESS);
}

static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id)
{
	int rc = 0;
	struct mhi_dev_channel *ch;
	struct mhi_addr host_addr;

	ch = &mhi->ch[ch_id];
	/* hard stop and set the channel to stop */
	mhi->ch_ctx_cache[ch_id].ch_state =
				MHI_DEV_CH_STATE_DISABLED;
	mhi->ch[ch_id].state = MHI_DEV_CH_STOPPED;

	if (mhi->use_ipa)
		host_addr.host_pa =
			mhi->ch_ctx_shadow.host_pa +
			(sizeof(struct mhi_dev_ch_ctx) * ch_id);
	else
		host_addr.device_va =
			mhi->ch_ctx_shadow.device_va +
			(sizeof(struct mhi_dev_ch_ctx) * ch_id);

	host_addr.virt_addr =
			&mhi->ch_ctx_cache[ch_id].ch_state;
	host_addr.size = sizeof(enum mhi_dev_ch_ctx_state);

	/* update the channel state in the host */
	mhi_ctx->write_to_host(mhi, &host_addr, NULL,
			MHI_DEV_DMA_SYNC);

	/* send the completion event to the host */
	rc = mhi_dev_send_cmd_comp_event(mhi,
				MHI_CMD_COMPL_CODE_SUCCESS);
	if (rc)
		pr_err("Error sending command completion event\n");

	ch->reset_pending = false;
}

static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
			union mhi_dev_ring_element_type *el, void *ctx)
{
@@ -1972,6 +2032,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
			ch = &mhi->ch[ch_id];

			mutex_lock(&ch->ch_lock);
			mutex_lock(&ch->ring->event_lock);

			mhi->ch[ch_id].state = MHI_DEV_CH_PENDING_STOP;
			rc = mhi_dev_process_stop_cmd(
@@ -1980,6 +2041,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
			if (rc)
				pr_err("stop event send failed\n");

			mutex_unlock(&ch->ring->event_lock);
			mutex_unlock(&ch->ch_lock);
			mhi_update_state_info_ch(ch_id, MHI_STATE_DISCONNECTED);
			/* Trigger callback to clients */
@@ -2026,37 +2088,20 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
				pr_err("Channel not opened for %d\n", ch_id);
				return;
			}

			ch = &mhi->ch[ch_id];

			mutex_lock(&ch->ch_lock);

			/* hard stop and set the channel to stop */
			mhi->ch_ctx_cache[ch_id].ch_state =
						MHI_DEV_CH_STATE_DISABLED;
			mhi->ch[ch_id].state = MHI_DEV_CH_STOPPED;
			if (MHI_USE_DMA(mhi))
				host_addr.host_pa =
					mhi->ch_ctx_shadow.host_pa +
					(sizeof(struct mhi_dev_ch_ctx) * ch_id);
			else
				host_addr.device_va =
					mhi->ch_ctx_shadow.device_va +
					(sizeof(struct mhi_dev_ch_ctx) * ch_id);

			host_addr.virt_addr =
					&mhi->ch_ctx_cache[ch_id].ch_state;
			host_addr.size = sizeof(enum mhi_dev_ch_ctx_state);

			/* update the channel state in the host */
			mhi_ctx->write_to_host(mhi, &host_addr, NULL,
					MHI_DEV_DMA_SYNC);

			/* send the completion event to the host */
			rc = mhi_dev_send_cmd_comp_event(mhi,
						MHI_CMD_COMPL_CODE_SUCCESS);
			if (rc)
				pr_err("Error sending command completion event\n");
			mutex_lock(&ch->ring->event_lock);
			if (ch->db_pending) {
				mhi_log(MHI_MSG_ERROR,
				"skipping reset cmd ack for channel %d\n",
						ch_id);
				ch->reset_pending = true;
				mutex_unlock(&ch->ring->event_lock);
				mutex_unlock(&ch->ch_lock);
				return;
			}
			mhi_dev_process_reset_cmd(mhi, ch_id);
			mutex_unlock(&ch->ring->event_lock);
			mutex_unlock(&ch->ch_lock);
			mhi_update_state_info_ch(ch_id, MHI_STATE_DISCONNECTED);
			mhi_dev_trigger_cb(ch_id);
@@ -2104,9 +2149,10 @@ static void mhi_dev_process_ring_pending(struct work_struct *work)
	struct list_head *cp, *q;
	struct mhi_dev_ring *ring;
	struct mhi_dev_channel *ch;
	int rc = 0;
	int rc = 0, ch_id;

	mutex_lock(&mhi_ctx->mhi_lock);

	rc = mhi_dev_process_ring(&mhi->ring[mhi->cmd_ring_idx]);
	if (rc) {
		mhi_log(MHI_MSG_ERROR, "error processing command ring\n");
@@ -2117,26 +2163,47 @@ static void mhi_dev_process_ring_pending(struct work_struct *work)
		ring = list_entry(cp, struct mhi_dev_ring, list);
		list_del(cp);
		mhi_log(MHI_MSG_VERBOSE, "processing ring %d\n", ring->id);

		if (ring->id < mhi->ch_ring_start) {
			mhi_log(MHI_MSG_ERROR,
				"ring (%d) is not a channel ring\n", ring->id);
			goto exit;
		}

		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;
		}
		ch->db_pending = false;

		if (ring->id < mhi->ch_ring_start) {
			mhi_log(MHI_MSG_ERROR,
				"ring (%d) is not a channel ring\n", ring->id);
			goto exit;
		if (ch->reset_pending) {
			/*
			 * The channel might be reset asynchronously by the
			 * host, below reset ack is in  case the channel
			 * was stopped/reset with pending DB.
			 */
			ch_id = ch->ch_id;
			mhi_log(MHI_MSG_VERBOSE,
				"processing pending ch:%d reset\n", ch_id);
			mutex_lock(&ch->ring->event_lock);
			mhi_dev_process_reset_cmd(mhi, ch_id);
			mutex_unlock(&ch->ring->event_lock);
		}

		ch = &mhi->ch[ring->id - mhi->ch_ring_start];
		rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch->ch_id);
		if (rc) {
			mhi_log(MHI_MSG_ERROR,
			"error enabling chdb interrupt for %d\n", ch->ch_id);
			mutex_unlock(&ch->ch_lock);
			goto exit;
		}
		mutex_unlock(&ch->ch_lock);
	}

exit:
@@ -2173,6 +2240,7 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi,
					uint32_t chintr_value, uint32_t ch_num)
{
	struct mhi_dev_ring *ring;
	struct mhi_dev_channel *ch;
	int rc = 0;

	for (; chintr_value; ch_num++, chintr_value >>= 1) {
@@ -2184,6 +2252,10 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi,
			}
			mhi_ring_set_state(ring, RING_STATE_PENDING);
			list_add(&ring->list, &mhi->process_ring_list);
			ch = &mhi->ch[ch_num];
			mutex_lock(&ch->ch_lock);
			ch->db_pending = true;
			mutex_unlock(&ch->ch_lock);
			rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_num);
			if (rc) {
				pr_err("Error disabling chdb\n");
@@ -2361,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) {
@@ -2371,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);
@@ -3066,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
@@ -3078,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 &&
@@ -3089,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);

+2 −0
Original line number Diff line number Diff line
@@ -509,6 +509,8 @@ struct mhi_dev_channel {
	uint32_t			msi_cnt;
	uint32_t			flush_req_cnt;
	bool				skip_td;
	bool				db_pending;
	bool				reset_pending;
};

/* Structure device for mhi dev */
+62 −32
Original line number Diff line number Diff line
@@ -375,6 +375,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 */
@@ -557,15 +558,25 @@ static struct mhi_req *mhi_uci_get_req(struct uci_client *uci_handle)
	return req;
}

static void mhi_uci_put_req(struct uci_client *uci_handle, struct mhi_req *req)
static int mhi_uci_put_req(struct uci_client *uci_handle, struct mhi_req *req)
{
	unsigned long flags;

	spin_lock_irqsave(&uci_handle->req_lock, flags);
	if (req->is_stale) {
		uci_log(UCI_DBG_VERBOSE,
			"Got stale completion for ch %d, ignoring\n",
			req->chan);
		spin_unlock_irqrestore(&uci_handle->req_lock, flags);
		return -EINVAL;
	}

	/* Remove from in-use list and add back to free list */
	list_del_init(&req->list);
	list_add_tail(&req->list, &uci_handle->req_list);
	spin_unlock_irqrestore(&uci_handle->req_lock, flags);

	return 0;
}

static void mhi_uci_write_completion_cb(void *req)
@@ -581,17 +592,12 @@ static void mhi_uci_write_completion_cb(void *req)
	 * the stale flag and return. The ureq was added to
	 * the free list when client called release function.
	 */
	if (ureq->is_stale) {
		uci_log(UCI_DBG_VERBOSE,
			"Got stale completion for ch %d\n", ureq->chan);
		ureq->is_stale = false;
	if (mhi_uci_put_req(uci_handle, ureq))
		return;
	}

	if (uci_handle->write_done)
		complete(uci_handle->write_done);

	mhi_uci_put_req(uci_handle, ureq);
	/* Write queue may be waiting for write request structs */
	wake_up(&uci_handle->write_wq);
}
@@ -601,19 +607,19 @@ static void mhi_uci_read_completion_cb(void *req)
	struct mhi_req *ureq = req;
	struct uci_client *uci_handle;

	if (ureq->is_stale) {
		uci_log(UCI_DBG_VERBOSE,
			"Got stale completion for ch %d, ignoring\n",
			ureq->chan);
		return;
	}

	uci_handle = (struct uci_client *)ureq->context;

	uci_handle->pkt_loc = (void *)ureq->buf;
	uci_handle->pkt_size = ureq->transfer_len;

	mhi_uci_put_req(uci_handle, ureq);
	 /*
	  * If this is a delayed read completion, just clear
	  * the stale flag and return. The ureq was added to
	  * the free list when client called release function.
	  */
	if (mhi_uci_put_req(uci_handle, ureq))
		return;

	complete(&uci_handle->read_done);
}

@@ -782,6 +788,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);
	/*
@@ -789,8 +797,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;
@@ -810,6 +820,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;
}

@@ -1069,6 +1081,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));
@@ -1076,6 +1089,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;
@@ -1093,11 +1107,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;

@@ -1110,14 +1126,17 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
	const struct chan_attr *in_chan_attr;
	int count = 0, i;
	struct mhi_req *ureq;
	unsigned long flags;

	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;
	}

@@ -1125,6 +1144,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;
	}

@@ -1162,8 +1182,12 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
		 * to client if the transfer completes later.
		 */
		count = 0;

		spin_lock_irqsave(&uci_handle->req_lock, flags);
		if (!(uci_handle->f_flags & O_SYNC)) {
			while (!(list_empty(&uci_handle->in_use_list))) {
			ureq = container_of(uci_handle->in_use_list.next,
				ureq = container_of(
					uci_handle->in_use_list.next,
					struct mhi_req, list);
				list_del_init(&ureq->list);
				ureq->is_stale = true;
@@ -1173,6 +1197,8 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
				list_add_tail(&ureq->list, &uci_handle->req_list);
				count++;
			}
		}
		spin_unlock_irqrestore(&uci_handle->req_lock, flags);
		if (count)
			uci_log(UCI_DBG_DBG,
				"Client %d closed with %d transfers pending\n",
@@ -1188,6 +1214,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;
}
@@ -1670,6 +1697,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);
@@ -2069,7 +2097,8 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data)
		mhi_dev_close_channel(client->out_handle);
		mhi_dev_close_channel(client->in_handle);

		/* Add back reqs for in-use list, if any, to free list */
		/* Add back reqs from in-use list, if any, to free list */
		if (!(client->f_flags & O_SYNC)) {
			while (!(list_empty(&client->in_use_list))) {
				ureq = container_of(client->in_use_list.next,
							struct mhi_req, list);
@@ -2077,6 +2106,7 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data)
				/* Add to in-use list */
				list_add_tail(&ureq->list, &client->req_list);
			}
		}

		for (i = 0; i < (client->in_chan_attr->nr_trbs); i++) {
			kfree(client->in_buf_list[i].addr);