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

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

Merge "msm: mhi-dev: Add support for AIO write API"

parents c45fc80a 8838ca56
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/cdev.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/uio.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/sched.h>
@@ -424,6 +425,8 @@ static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *buf,
		size_t count, loff_t *offp);
static ssize_t mhi_uci_client_write(struct file *file,
		const char __user *buf, size_t count, loff_t *offp);
static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb,
					 struct iov_iter *buf);
static int mhi_uci_client_open(struct inode *mhi_inode, struct file*);
static int mhi_uci_ctrl_open(struct inode *mhi_inode, struct file*);
static int mhi_uci_client_release(struct inode *mhi_inode,
@@ -1480,6 +1483,65 @@ static ssize_t mhi_uci_client_write(struct file *file,

}

static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb,
					 struct iov_iter *buf)
{
	struct uci_client *uci_handle = NULL;
	void *data_loc;
	unsigned long memcpy_result;
	int rc;
	struct file *file = iocb->ki_filp;
	ssize_t count = iov_iter_count(buf);

	if (!file || !buf || !count || !file->private_data) {
		uci_log(UCI_DBG_DBG, "Invalid access to write-iter\n");
		return -EINVAL;
	}

	uci_handle = file->private_data;
	if (!uci_handle->send || !uci_handle->out_handle) {
		uci_log(UCI_DBG_DBG, "Invalid handle or send\n");
		return -EINVAL;
	}
	if (atomic_read(&uci_ctxt.mhi_disabled)) {
		uci_log(UCI_DBG_ERROR,
			"Client %d attempted to write while MHI is disabled\n",
			uci_handle->out_chan);
		return -EIO;
	}

	if (!mhi_uci_are_channels_connected(uci_handle)) {
		uci_log(UCI_DBG_ERROR, "%s:Channels are not connected\n",
			__func__);
		return -ENODEV;
	}

	if (count > TRB_MAX_DATA_SIZE) {
		uci_log(UCI_DBG_ERROR,
			"Too big write size: %lu, max supported size is %d\n",
			count, TRB_MAX_DATA_SIZE);
		return -EFBIG;
	}

	data_loc = kmalloc(count, GFP_KERNEL);
	if (!data_loc)
		return -ENOMEM;

	memcpy_result = copy_from_iter_full(data_loc, count, buf);
	if (!memcpy_result) {
		rc = -EFAULT;
		goto error_memcpy;
	}

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

error_memcpy:
	kfree(data_loc);
	return rc;
}

void mhi_uci_chan_state_notify_all(struct mhi_dev *mhi,
		enum mhi_ctrl_info ch_state)
{
@@ -1877,6 +1939,7 @@ static const struct file_operations mhi_uci_ctrl_client_fops = {
static const struct file_operations mhi_uci_client_fops = {
	.read = mhi_uci_client_read,
	.write = mhi_uci_client_write,
	.write_iter = mhi_uci_client_write_iter,
	.open = mhi_uci_client_open,
	.release = mhi_uci_client_release,
	.poll = mhi_uci_client_poll,