diff options
Diffstat (limited to 'drivers/gpu/drm/drm_fops.c')
| -rw-r--r-- | drivers/gpu/drm/drm_fops.c | 44 | 
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7ef1b673e1be..133b4132983e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)  	int minor_id = iminor(inode);  	struct drm_minor *minor;  	int retcode = 0; +	int need_setup = 0; +	struct address_space *old_mapping;  	minor = idr_find(&drm_minors_idr, minor_id);  	if (!minor) @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)  	if (drm_device_is_unplugged(dev))  		return -ENODEV; +	if (!dev->open_count++) +		need_setup = 1; +	mutex_lock(&dev->struct_mutex); +	old_mapping = dev->dev_mapping; +	if (old_mapping == NULL) +		dev->dev_mapping = &inode->i_data; +	/* ihold ensures nobody can remove inode with our i_data */ +	ihold(container_of(dev->dev_mapping, struct inode, i_data)); +	inode->i_mapping = dev->dev_mapping; +	filp->f_mapping = dev->dev_mapping; +	mutex_unlock(&dev->struct_mutex); +  	retcode = drm_open_helper(inode, filp, dev); -	if (!retcode) { -		atomic_inc(&dev->counts[_DRM_STAT_OPENS]); -		if (!dev->open_count++) -			retcode = drm_setup(dev); -	} -	if (!retcode) { -		mutex_lock(&dev->struct_mutex); -		if (dev->dev_mapping == NULL) -			dev->dev_mapping = &inode->i_data; -		/* ihold ensures nobody can remove inode with our i_data */ -		ihold(container_of(dev->dev_mapping, struct inode, i_data)); -		inode->i_mapping = dev->dev_mapping; -		filp->f_mapping = dev->dev_mapping; -		mutex_unlock(&dev->struct_mutex); +	if (retcode) +		goto err_undo; +	atomic_inc(&dev->counts[_DRM_STAT_OPENS]); +	if (need_setup) { +		retcode = drm_setup(dev); +		if (retcode) +			goto err_undo;  	} +	return 0; +err_undo: +	mutex_lock(&dev->struct_mutex); +	filp->f_mapping = old_mapping; +	inode->i_mapping = old_mapping; +	iput(container_of(dev->dev_mapping, struct inode, i_data)); +	dev->dev_mapping = old_mapping; +	mutex_unlock(&dev->struct_mutex); +	dev->open_count--;  	return retcode;  }  EXPORT_SYMBOL(drm_open);  | 
