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

Diag client uses asynchronous writes for data transfer.
Adding write_iter API in mhi to support the same.

Change-Id: If14ebdd4aa848046abd15ea93d939691c6962fcd
Signed-off-by: Gauri Joshi <gaurjosh@codeaurora.org>
This commit is contained in:
Gauri Joshi 2021-05-10 23:59:29 -07:00 • committed by Gerrit - the friendly Code Review server
commit 8838ca5600

View file

@ -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 @@ error_memcpy:
}
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,