diff options
Diffstat (limited to 'drivers/misc/mei/main.c')
| -rw-r--r-- | drivers/misc/mei/main.c | 65 | 
1 files changed, 35 insertions, 30 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index cabeddd66c1f..9661a812f550 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -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;  	}  | 
