Merge tag 'vfio-v3.14-rc1' of git://github.com/awilliam/linux-vfio
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mei / main.c
index cabeddd66c1f406f73f7e5bed2a56b7e52cd7621..5424f8ff3f7f7d2653f1089517e67b790cec03d5 100644 (file)
@@ -48,7 +48,7 @@
  *
  * @inode: pointer to inode structure
  * @file: pointer to file structure
- e
+ *
  * returns 0 on success, <0 on error
  */
 static int mei_open(struct inode *inode, struct file *file)
@@ -60,48 +60,45 @@ static int mei_open(struct inode *inode, struct file *file)
 
        int err;
 
-       err = -ENODEV;
        if (!misc->parent)
-               goto out;
+               return -ENODEV;
 
        pdev = container_of(misc->parent, struct pci_dev, dev);
 
        dev = pci_get_drvdata(pdev);
        if (!dev)
-               goto out;
+               return -ENODEV;
 
        mutex_lock(&dev->device_lock);
-       err = -ENOMEM;
-       cl = mei_cl_allocate(dev);
-       if (!cl)
-               goto out_unlock;
+
+       cl = NULL;
 
        err = -ENODEV;
        if (dev->dev_state != MEI_DEV_ENABLED) {
                dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
                    mei_dev_state_str(dev->dev_state));
-               goto out_unlock;
-       }
-       err = -EMFILE;
-       if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
-               dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
-                       MEI_MAX_OPEN_HANDLE_COUNT);
-               goto out_unlock;
+               goto err_unlock;
        }
 
+       err = -ENOMEM;
+       cl = mei_cl_allocate(dev);
+       if (!cl)
+               goto err_unlock;
+
+       /* open_handle_count check is handled in the mei_cl_link */
        err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
        if (err)
-               goto out_unlock;
+               goto err_unlock;
 
        file->private_data = cl;
+
        mutex_unlock(&dev->device_lock);
 
        return nonseekable_open(inode, file);
 
-out_unlock:
+err_unlock:
        mutex_unlock(&dev->device_lock);
        kfree(cl);
-out:
        return err;
 }
 
@@ -144,10 +141,6 @@ static int mei_release(struct inode *inode, struct file *file)
            cl->host_client_id,
            cl->me_client_id);
 
-       if (dev->open_handle_count > 0) {
-               clear_bit(cl->host_client_id, dev->host_clients_map);
-               dev->open_handle_count--;
-       }
        mei_cl_unlink(cl);
 
 
@@ -165,10 +158,7 @@ static int mei_release(struct inode *inode, struct file *file)
 
        file->private_data = NULL;
 
-       if (cb) {
-               mei_io_cb_free(cb);
-               cb = NULL;
-       }
+       mei_io_cb_free(cb);
 
        kfree(cl);
 out:
@@ -203,12 +193,18 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 
        dev = cl->dev;
 
+
        mutex_lock(&dev->device_lock);
        if (dev->dev_state != MEI_DEV_ENABLED) {
                rets = -ENODEV;
                goto out;
        }
 
+       if (length == 0) {
+               rets = 0;
+               goto out;
+       }
+
        if (cl == &dev->iamthif_cl) {
                rets = mei_amthif_read(dev, file, ubuf, length, offset);
                goto out;
@@ -347,8 +343,14 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                rets = -ENODEV;
                goto out;
        }
-       if (length > dev->me_clients[id].props.max_msg_length || length <= 0) {
-               rets = -EMSGSIZE;
+
+       if (length == 0) {
+               rets = 0;
+               goto out;
+       }
+
+       if (length > dev->me_clients[id].props.max_msg_length) {
+               rets = -EFBIG;
                goto out;
        }
 
@@ -401,8 +403,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                goto out;
 
        rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
-       if (rets)
+       if (rets) {
+               dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
+               rets = -EFAULT;
                goto out;
+       }
 
        if (cl == &dev->iamthif_cl) {
                rets = mei_amthif_write(dev, write_cb);
@@ -489,11 +494,11 @@ static int mei_ioctl_connect_client(struct file *file,
                        rets = -ENODEV;
                        goto end;
                }
-               clear_bit(cl->host_client_id, dev->host_clients_map);
                mei_cl_unlink(cl);
 
                kfree(cl);
                cl = NULL;
+               dev->iamthif_open_count++;
                file->private_data = &dev->iamthif_cl;
 
                client = &data->out_client_properties;
@@ -564,7 +569,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
        dev_dbg(&dev->pdev->dev, "copy connect data from user\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");
+               dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
                rets = -EFAULT;
                goto out;
        }