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

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

Merge "msm: mhi_dev: Add UCI support if client req > TRE length"

parents 4dcf58f7 52f01d50
Loading
Loading
Loading
Loading
+16 −13
Original line number Diff line number Diff line
@@ -2278,6 +2278,12 @@ static int mhi_dev_process_tre_ring(struct mhi_dev *mhi,
	ch = &mhi->ch[ring->id - mhi->ch_ring_start];
	reason.ch_id = ch->ch_id;
	reason.reason = MHI_DEV_TRE_AVAILABLE;
	/*
	 * Save lowest value of tre_len to split packets in UCI layer
	 * for write request of size more than tre_len.
	 */
	if (!ch->tre_size || ch->tre_size > el->tre.len)
		ch->tre_size = el->tre.len;

	/* Invoke a callback to let the client know its data is ready.
	 * Copy this event to the clients context so that it can be
@@ -3466,7 +3472,7 @@ int mhi_dev_read_channel(struct mhi_req *mreq)
	uint64_t read_from_loc;
	ssize_t bytes_read = 0;
	size_t write_to_loc = 0;
	uint32_t usr_buf_remaining;
	uint32_t usr_buf_remaining, tre_size;
	int td_done = 0, rc = 0;
	struct mhi_dev_client *handle_client;

@@ -3509,10 +3515,9 @@ int mhi_dev_read_channel(struct mhi_req *mreq)
		}

		el = &ring->ring_cache[ring->rd_offset];
		mhi_log(MHI_MSG_VERBOSE, "evtptr : 0x%llx\n",
						el->tre.data_buf_ptr);
		mhi_log(MHI_MSG_VERBOSE, "evntlen : 0x%x, offset:%lu\n",
						el->tre.len, ring->rd_offset);
		mhi_log(MHI_MSG_VERBOSE,
				"TRE.PTR: 0x%llx, TRE.LEN: 0x%x, rd offset: %lu\n",
				el->tre.data_buf_ptr, el->tre.len, ring->rd_offset);

		if (ch->tre_loc) {
			bytes_to_read = min(usr_buf_remaining,
@@ -3531,17 +3536,15 @@ int mhi_dev_read_channel(struct mhi_req *mreq)


			ch->tre_loc = el->tre.data_buf_ptr;
			ch->tre_size = el->tre.len;
			ch->tre_bytes_left = ch->tre_size;

			mhi_log(MHI_MSG_VERBOSE,
			"user_buf_remaining %d, ch->tre_size %d\n",
			usr_buf_remaining, ch->tre_size);
			bytes_to_read = min(usr_buf_remaining, ch->tre_size);
			tre_size = el->tre.len;
			ch->tre_bytes_left = el->tre.len;
			mhi_log(MHI_MSG_VERBOSE, "user_buf_remaining %d, tre_size %d\n",
					usr_buf_remaining, el->tre.len);
			bytes_to_read = min(usr_buf_remaining, tre_size);
		}

		bytes_read += bytes_to_read;
		addr_offset = ch->tre_size - ch->tre_bytes_left;
		addr_offset = el->tre.len - ch->tre_bytes_left;
		read_from_loc = ch->tre_loc + addr_offset;
		write_to_loc = (size_t) mreq->buf +
			(mreq->len - usr_buf_remaining);
+82 −18
Original line number Diff line number Diff line
@@ -391,6 +391,7 @@ struct uci_client {
	int (*read)(struct uci_client *h, int *bytes);
	unsigned int tiocm;
	unsigned int at_ctrl_mask;
	int tre_len;
};

struct mhi_uci_ctxt_t {
@@ -1466,8 +1467,9 @@ static ssize_t mhi_uci_client_write(struct file *file,
{
	struct uci_client *uci_handle = NULL;
	void *data_loc;
	const char __user *cur_buf;
	unsigned long memcpy_result;
	int rc;
	int rc = 0, tre_len, cur_rc = 0, count_left, cur_txfr_len;

	if (!file || !buf || !count || !file->private_data) {
		uci_log(UCI_DBG_DBG, "Invalid access to write\n");
@@ -1475,6 +1477,8 @@ static ssize_t mhi_uci_client_write(struct file *file,
	}

	uci_handle = file->private_data;
	tre_len = uci_handle->tre_len;

	if (!uci_handle->send || !uci_handle->out_handle) {
		uci_log(UCI_DBG_DBG, "Invalid handle or send\n");
		return -EINVAL;
@@ -1497,17 +1501,47 @@ static ssize_t mhi_uci_client_write(struct file *file,
			count, uci_handle->out_chan_attr->max_packet_size);
	}

	data_loc = kmalloc(count, GFP_KERNEL);
	if (!data_loc)
	cur_txfr_len = count;

	if (!tre_len)
		uci_log(UCI_DBG_ERROR, "tre_len is 0, not updated yet\n");
	else if (count > tre_len) {
		uci_log(UCI_DBG_DBG, "Write req size (%d) > tre_len (%d)\n", count, tre_len);
		cur_txfr_len = tre_len;
	}

	count_left = count;
	cur_buf = buf;

	do {
		data_loc = kmalloc(cur_txfr_len, GFP_KERNEL);
		if (!data_loc) {
			uci_log(UCI_DBG_ERROR, "Memory allocation failed\n");
			return -ENOMEM;
		}

	memcpy_result = copy_from_user(data_loc, buf, count);
		memcpy_result = copy_from_user(data_loc, cur_buf, cur_txfr_len);
		if (memcpy_result) {
			uci_log(UCI_DBG_ERROR, "Mem copy failed\n");
			rc = -EFAULT;
			goto error_memcpy;
		}

	rc = mhi_uci_send_packet(uci_handle, data_loc, count);
		cur_rc = mhi_uci_send_packet(uci_handle, data_loc, cur_txfr_len);
		if (cur_rc != cur_txfr_len) {
			uci_log(UCI_DBG_ERROR,
					"Send failed with error %d, after sending %d data\n",
					cur_rc, rc);
			rc = cur_rc;
			goto error_memcpy;
		}
		rc += cur_rc;
		cur_buf += cur_txfr_len;
		count_left -= cur_txfr_len;

		if (count_left < tre_len)
			cur_txfr_len = count_left;
	} while (count_left);
	if (rc == count)
		return rc;

@@ -1523,7 +1557,7 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb,
	struct uci_client *uci_handle = NULL;
	void *data_loc;
	unsigned long memcpy_result;
	int rc;
	int rc = 0, tre_len, cur_rc = 0, count_left, cur_txfr_len;
	struct file *file = iocb->ki_filp;
	ssize_t count = iov_iter_count(buf);

@@ -1533,6 +1567,8 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb,
	}

	uci_handle = file->private_data;
	tre_len = uci_handle->tre_len;

	if (!uci_handle->send || !uci_handle->out_handle) {
		uci_log(UCI_DBG_DBG, "Invalid handle or send\n");
		return -EINVAL;
@@ -1555,17 +1591,44 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb,
			count, uci_handle->out_chan_attr->max_packet_size);
	}

	data_loc = kmalloc(count, GFP_KERNEL);
	if (!data_loc)
	cur_txfr_len = count;

	if (!tre_len)
		uci_log(UCI_DBG_ERROR, "tre_len is 0, not updated yet\n");
	else if (count > tre_len) {
		uci_log(UCI_DBG_DBG, "Write req size (%d) > tre_len (%d)\n", count, tre_len);
		cur_txfr_len = tre_len;
	}

	count_left = count;

	do {
		data_loc = kmalloc(cur_txfr_len, GFP_KERNEL);
		if (!data_loc) {
			uci_log(UCI_DBG_ERROR, "Memory allocation failed\n");
			return -ENOMEM;
		}

	memcpy_result = copy_from_iter_full(data_loc, count, buf);
		memcpy_result = copy_from_iter_full(data_loc, cur_txfr_len, buf);
		if (!memcpy_result) {
			uci_log(UCI_DBG_ERROR, "Mem copy failed\n");
			rc = -EFAULT;
			goto error_memcpy;
		}
		cur_rc = mhi_uci_send_packet(uci_handle, data_loc, cur_txfr_len);
		if (cur_rc != cur_txfr_len) {
			uci_log(UCI_DBG_ERROR,
					"Send failed with error %d, after sending %d data\n",
					cur_rc, rc);
			rc = cur_rc;
			goto error_memcpy;
		}
		rc += cur_rc;
		count_left -= cur_txfr_len;
		if (count_left < tre_len)
			cur_txfr_len = count_left;
	} while (count_left);

	rc = mhi_uci_send_packet(uci_handle, data_loc, count);
	if (rc == count)
		return rc;

@@ -1683,6 +1746,7 @@ static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason)
			uci_handle->in_chan);
		if (reason->ch_id % 2) {
			atomic_set(&uci_handle->write_data_ready, 1);
			uci_handle->tre_len = uci_handle->out_handle->channel->tre_size;
			wake_up(&uci_handle->write_wq);
		} else {
			atomic_set(&uci_handle->read_data_ready, 1);