Merge tag 'ecryptfs-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mei / main.c
index 401a3d526cd0a0a316374974a45ffb21861396f5..beedc91f03a631cc9fd5902d7cd14e840edcef33 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/aio.h>
-#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
@@ -44,7 +44,7 @@
  * @inode: pointer to inode structure
  * @file: pointer to file structure
  *
- * returns 0 on success, <0 on error
+ * Return: 0 on success, <0 on error
  */
 static int mei_open(struct inode *inode, struct file *file)
 {
@@ -63,7 +63,7 @@ static int mei_open(struct inode *inode, struct file *file)
 
        err = -ENODEV;
        if (dev->dev_state != MEI_DEV_ENABLED) {
-               dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
+               dev_dbg(dev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
                    mei_dev_state_str(dev->dev_state));
                goto err_unlock;
        }
@@ -96,7 +96,7 @@ err_unlock:
  * @inode: pointer to inode structure
  * @file: pointer to file structure
  *
- * returns 0 on success, <0 on error
+ * Return: 0 on success, <0 on error
  */
 static int mei_release(struct inode *inode, struct file *file)
 {
@@ -157,7 +157,7 @@ out:
  * @length: buffer length
  * @offset: data offset in buffer
  *
- * returns >=0 data length on success , <0 on error
+ * Return: >=0 data length on success , <0 on error
  */
 static ssize_t mei_read(struct file *file, char __user *ubuf,
                        size_t length, loff_t *offset)
@@ -211,7 +211,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 
        err = mei_cl_read_start(cl, length);
        if (err && err != -EBUSY) {
-               dev_dbg(&dev->pdev->dev,
+               dev_dbg(dev->dev,
                        "mei start read failure with status = %d\n", err);
                rets = err;
                goto out;
@@ -254,7 +254,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
        }
        /* now copy the data to user space */
 copy_buffer:
-       dev_dbg(&dev->pdev->dev, "buf.size = %d buf.idx= %ld\n",
+       dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
            cb->response_buffer.size, cb->buf_idx);
        if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
                rets = -EMSGSIZE;
@@ -266,7 +266,7 @@ copy_buffer:
        length = min_t(size_t, length, cb->buf_idx - *offset);
 
        if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
-               dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
+               dev_dbg(dev->dev, "failed to copy data to userland\n");
                rets = -EFAULT;
                goto free;
        }
@@ -285,7 +285,7 @@ free:
        cl->reading_state = MEI_IDLE;
        cl->read_cb = NULL;
 out:
-       dev_dbg(&dev->pdev->dev, "end mei read rets= %d\n", rets);
+       dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
        mutex_unlock(&dev->device_lock);
        return rets;
 }
@@ -297,17 +297,17 @@ out:
  * @length: buffer length
  * @offset: data offset in buffer
  *
- * returns >=0 data length on success , <0 on error
+ * Return: >=0 data length on success , <0 on error
  */
 static ssize_t mei_write(struct file *file, const char __user *ubuf,
                         size_t length, loff_t *offset)
 {
        struct mei_cl *cl = file->private_data;
+       struct mei_me_client *me_cl;
        struct mei_cl_cb *write_cb = NULL;
        struct mei_device *dev;
        unsigned long timeout = 0;
        int rets;
-       int id;
 
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
@@ -321,8 +321,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                goto out;
        }
 
-       id = mei_me_cl_by_id(dev, cl->me_client_id);
-       if (id < 0) {
+       me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
+       if (!me_cl) {
                rets = -ENOTTY;
                goto out;
        }
@@ -332,13 +332,13 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                goto out;
        }
 
-       if (length > dev->me_clients[id].props.max_msg_length) {
+       if (length > me_cl->props.max_msg_length) {
                rets = -EFBIG;
                goto out;
        }
 
        if (cl->state != MEI_FILE_CONNECTED) {
-               dev_err(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
+               dev_err(dev->dev, "host client = %d,  is not connected to ME client = %d",
                        cl->host_client_id, cl->me_client_id);
                rets = -ENODEV;
                goto out;
@@ -377,7 +377,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
        write_cb = mei_io_cb_init(cl, file);
        if (!write_cb) {
-               dev_err(&dev->pdev->dev, "write cb allocation failed\n");
                rets = -ENOMEM;
                goto out;
        }
@@ -387,7 +386,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
        rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
        if (rets) {
-               dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
+               dev_dbg(dev->dev, "failed to copy data from userland\n");
                rets = -EFAULT;
                goto out;
        }
@@ -396,7 +395,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                rets = mei_amthif_write(dev, write_cb);
 
                if (rets) {
-                       dev_err(&dev->pdev->dev,
+                       dev_err(dev->dev,
                                "amthif write failed with status = %d\n", rets);
                        goto out;
                }
@@ -415,27 +414,23 @@ out:
 /**
  * mei_ioctl_connect_client - the connect to fw client IOCTL function
  *
- * @dev: the device structure
- * @data: IOCTL connect data, input and output parameters
  * @file: private data of the file object
+ * @data: IOCTL connect data, input and output parameters
  *
  * Locking: called under "dev->device_lock" lock
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
 static int mei_ioctl_connect_client(struct file *file,
                        struct mei_connect_client_data *data)
 {
        struct mei_device *dev;
        struct mei_client *client;
+       struct mei_me_client *me_cl;
        struct mei_cl *cl;
-       int i;
        int rets;
 
        cl = file->private_data;
-       if (WARN_ON(!cl || !cl->dev))
-               return -ENODEV;
-
        dev = cl->dev;
 
        if (dev->dev_state != MEI_DEV_ENABLED) {
@@ -450,28 +445,29 @@ static int mei_ioctl_connect_client(struct file *file,
        }
 
        /* find ME client we're trying to connect to */
-       i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
-       if (i < 0 || dev->me_clients[i].props.fixed_address) {
-               dev_dbg(&dev->pdev->dev, "Cannot connect to FW Client UUID = %pUl\n",
+       me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
+       if (!me_cl || me_cl->props.fixed_address) {
+               dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
                                &data->in_client_uuid);
                rets = -ENOTTY;
                goto end;
        }
 
-       cl->me_client_id = dev->me_clients[i].client_id;
+       cl->me_client_id = me_cl->client_id;
+       cl->cl_uuid = me_cl->props.protocol_name;
 
-       dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
+       dev_dbg(dev->dev, "Connect to FW Client ID = %d\n",
                        cl->me_client_id);
-       dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
-                       dev->me_clients[i].props.protocol_version);
-       dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
-                       dev->me_clients[i].props.max_msg_length);
+       dev_dbg(dev->dev, "FW Client - Protocol Version = %d\n",
+                       me_cl->props.protocol_version);
+       dev_dbg(dev->dev, "FW Client - Max Msg Len = %d\n",
+                       me_cl->props.max_msg_length);
 
        /* if we're connecting to amthif client then we will use the
         * existing connection
         */
        if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
-               dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
+               dev_dbg(dev->dev, "FW Client is amthi\n");
                if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
                        rets = -ENODEV;
                        goto end;
@@ -484,10 +480,8 @@ static int mei_ioctl_connect_client(struct file *file,
                file->private_data = &dev->iamthif_cl;
 
                client = &data->out_client_properties;
-               client->max_msg_length =
-                       dev->me_clients[i].props.max_msg_length;
-               client->protocol_version =
-                       dev->me_clients[i].props.protocol_version;
+               client->max_msg_length = me_cl->props.max_msg_length;
+               client->protocol_version = me_cl->props.protocol_version;
                rets = dev->iamthif_cl.status;
 
                goto end;
@@ -496,9 +490,9 @@ static int mei_ioctl_connect_client(struct file *file,
 
        /* prepare the output buffer */
        client = &data->out_client_properties;
-       client->max_msg_length = dev->me_clients[i].props.max_msg_length;
-       client->protocol_version = dev->me_clients[i].props.protocol_version;
-       dev_dbg(&dev->pdev->dev, "Can connect?\n");
+       client->max_msg_length = me_cl->props.max_msg_length;
+       client->protocol_version = me_cl->props.protocol_version;
+       dev_dbg(dev->dev, "Can connect?\n");
 
 
        rets = mei_cl_connect(cl, file);
@@ -507,7 +501,6 @@ end:
        return rets;
 }
 
-
 /**
  * mei_ioctl - the IOCTL function
  *
@@ -515,24 +508,22 @@ end:
  * @cmd: ioctl command
  * @data: pointer to mei message structure
  *
- * returns 0 on success , <0 on error
+ * Return: 0 on success , <0 on error
  */
 static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
 {
        struct mei_device *dev;
        struct mei_cl *cl = file->private_data;
-       struct mei_connect_client_data *connect_data = NULL;
+       struct mei_connect_client_data connect_data;
        int rets;
 
-       if (cmd != IOCTL_MEI_CONNECT_CLIENT)
-               return -EINVAL;
 
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
 
        dev = cl->dev;
 
-       dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
+       dev_dbg(dev->dev, "IOCTL cmd = 0x%x", cmd);
 
        mutex_lock(&dev->device_lock);
        if (dev->dev_state != MEI_DEV_ENABLED) {
@@ -540,38 +531,36 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
                goto out;
        }
 
-       dev_dbg(&dev->pdev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
-
-       connect_data = kzalloc(sizeof(struct mei_connect_client_data),
-                                                       GFP_KERNEL);
-       if (!connect_data) {
-               rets = -ENOMEM;
-               goto out;
-       }
-       dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
-       if (copy_from_user(connect_data, (char __user *)data,
+       switch (cmd) {
+       case IOCTL_MEI_CONNECT_CLIENT:
+               dev_dbg(dev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
+               if (copy_from_user(&connect_data, (char __user *)data,
                                sizeof(struct mei_connect_client_data))) {
-               dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
-               rets = -EFAULT;
-               goto out;
-       }
-
-       rets = mei_ioctl_connect_client(file, connect_data);
+                       dev_dbg(dev->dev, "failed to copy data from userland\n");
+                       rets = -EFAULT;
+                       goto out;
+               }
 
-       /* if all is ok, copying the data back to user. */
-       if (rets)
-               goto out;
+               rets = mei_ioctl_connect_client(file, &connect_data);
+               if (rets)
+                       goto out;
 
-       dev_dbg(&dev->pdev->dev, "copy connect data to user\n");
-       if (copy_to_user((char __user *)data, connect_data,
+               /* if all is ok, copying the data back to user. */
+               if (copy_to_user((char __user *)data, &connect_data,
                                sizeof(struct mei_connect_client_data))) {
-               dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
-               rets = -EFAULT;
-               goto out;
+                       dev_dbg(dev->dev, "failed to copy data to userland\n");
+                       rets = -EFAULT;
+                       goto out;
+               }
+
+               break;
+
+       default:
+               dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
+               rets = -ENOIOCTLCMD;
        }
 
 out:
-       kfree(connect_data);
        mutex_unlock(&dev->device_lock);
        return rets;
 }
@@ -583,7 +572,7 @@ out:
  * @cmd: ioctl command
  * @data: pointer to mei message structure
  *
- * returns 0 on success , <0 on error
+ * Return: 0 on success , <0 on error
  */
 #ifdef CONFIG_COMPAT
 static long mei_compat_ioctl(struct file *file,
@@ -600,7 +589,7 @@ static long mei_compat_ioctl(struct file *file,
  * @file: pointer to file structure
  * @wait: pointer to poll_table structure
  *
- * returns poll mask
+ * Return: poll mask
  */
 static unsigned int mei_poll(struct file *file, poll_table *wait)
 {
@@ -670,7 +659,7 @@ static DEFINE_IDR(mei_idr);
  *
  * @dev:  device pointer
  *
- * returns allocated minor, or -ENOSPC if no free minor left
+ * Return: allocated minor, or -ENOSPC if no free minor left
  */
 static int mei_minor_get(struct mei_device *dev)
 {
@@ -681,7 +670,7 @@ static int mei_minor_get(struct mei_device *dev)
        if (ret >= 0)
                dev->minor = ret;
        else if (ret == -ENOSPC)
-               dev_err(&dev->pdev->dev, "too many mei devices\n");
+               dev_err(dev->dev, "too many mei devices\n");
 
        mutex_unlock(&mei_minor_lock);
        return ret;