summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/mei/main.c111
1 files changed, 87 insertions, 24 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 3d4f6d17d74c..15de4b19caa5 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -516,6 +516,83 @@ out:
}
/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl - mei client
+ * @file: pointer to file structure
+ *
+ * returns mei_cl_cb pointer or NULL;
+ */
+static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+{
+ struct mei_cl_cb *cb;
+ struct mei_device *dev;
+
+ dev = cl->dev;
+
+ cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ if (!cb)
+ return NULL;
+
+ INIT_LIST_HEAD(&cb->cb_list);
+
+ cb->file_object = fp;
+ cb->file_private = cl;
+ cb->buf_idx = 0;
+ return cb;
+}
+
+
+/**
+ * mei_io_cb_alloc_req_buf - allocate request buffer
+ *
+ * @cb - io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ * -EINVAL if cb is NULL
+ * -ENOMEM if allocation failed
+ */
+static int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+{
+ if (!cb)
+ return -EINVAL;
+
+ if (length == 0)
+ return 0;
+
+ cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
+ if (!cb->request_buffer.data)
+ return -ENOMEM;
+ cb->request_buffer.size = length;
+ return 0;
+}
+/**
+ * mei_io_cb_alloc_req_buf - allocate respose buffer
+ *
+ * @cb - io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ * -EINVAL if cb is NULL
+ * -ENOMEM if allocation failed
+ */
+static int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
+{
+ if (!cb)
+ return -EINVAL;
+
+ if (length == 0)
+ return 0;
+
+ cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
+ if (!cb->response_buffer.data)
+ return -ENOMEM;
+ cb->response_buffer.size = length;
+ return 0;
+}
+
+/**
* mei_write - the write function.
*
* @file: pointer to file structure
@@ -581,20 +658,17 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
*offset = 0;
- write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ write_cb = mei_io_cb_init(cl, file);
if (!write_cb) {
- mutex_unlock(&dev->device_lock);
- return -ENOMEM;
+ dev_err(&dev->pdev->dev, "write cb allocation failed\n");
+ rets = -ENOMEM;
+ goto unlock_dev;
}
-
- write_cb->file_object = file;
- write_cb->file_private = cl;
- write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
- rets = -ENOMEM;
- if (!write_cb->request_buffer.data)
+ rets = mei_io_cb_alloc_req_buf(write_cb, length);
+ if (rets)
goto unlock_dev;
- dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
+ dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
rets = -EFAULT;
if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
@@ -610,14 +684,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
write_cb->request_buffer.data, 4) == 0)))
cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
- INIT_LIST_HEAD(&write_cb->cb_list);
if (cl == &dev->iamthif_cl) {
- write_cb->response_buffer.data =
- kmalloc(dev->iamthif_mtu, GFP_KERNEL);
- if (!write_cb->response_buffer.data) {
- rets = -ENOMEM;
- goto unlock_dev;
- }
if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV;
goto unlock_dev;
@@ -632,11 +699,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -EMSGSIZE;
goto unlock_dev;
}
+ rets = mei_io_cb_alloc_resp_buf(write_cb, dev->iamthif_mtu);
+ if (rets)
+ goto unlock_dev;
- write_cb->response_buffer.size = dev->iamthif_mtu;
write_cb->major_file_operations = MEI_IOCTL;
- write_cb->buf_idx = 0;
- write_cb->request_buffer.size = length;
if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
rets = -ENODEV;
goto unlock_dev;
@@ -666,9 +733,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
}
write_cb->major_file_operations = MEI_WRITE;
- /* make sure buffer index is zero before we start */
- write_cb->buf_idx = 0;
- write_cb->request_buffer.size = length;
dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
@@ -688,7 +752,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -EINVAL;
goto unlock_dev;
}
- write_cb->file_private = cl;
rets = mei_flow_ctrl_creds(dev, cl);
if (rets < 0)