drm: use anon-inode instead of relying on cdevs
DRM drivers share a common address_space across all character-devices of a
single DRM device. This allows simple buffer eviction and mapping-control.
However, DRM core currently waits for the first ->open() on any char-dev
to mark the underlying inode as backing inode of the device. This delayed
initialization causes ugly conditions all over the place:
if (dev->dev_mapping)
do_sth();
To avoid delayed initialization and to stop reusing the inode of the
char-dev, we allocate an anonymous inode for each DRM device and reset
filp->f_mapping to it on ->open().
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
@@ -84,8 +84,6 @@ int drm_open(struct inode *inode, struct file *filp)
|
||||
struct drm_minor *minor;
|
||||
int retcode = 0;
|
||||
int need_setup = 0;
|
||||
struct address_space *old_mapping;
|
||||
struct address_space *old_imapping;
|
||||
|
||||
minor = idr_find(&drm_minors_idr, minor_id);
|
||||
if (!minor)
|
||||
@@ -99,16 +97,9 @@ int drm_open(struct inode *inode, struct file *filp)
|
||||
|
||||
if (!dev->open_count++)
|
||||
need_setup = 1;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
old_imapping = inode->i_mapping;
|
||||
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);
|
||||
|
||||
/* share address_space across all char-devs of a single device */
|
||||
filp->f_mapping = dev->anon_inode->i_mapping;
|
||||
|
||||
retcode = drm_open_helper(inode, filp, dev);
|
||||
if (retcode)
|
||||
@@ -121,12 +112,6 @@ int drm_open(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
|
||||
err_undo:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
filp->f_mapping = old_imapping;
|
||||
inode->i_mapping = old_imapping;
|
||||
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;
|
||||
}
|
||||
@@ -434,7 +419,6 @@ int drm_lastclose(struct drm_device * dev)
|
||||
|
||||
drm_legacy_dma_takedown(dev);
|
||||
|
||||
dev->dev_mapping = NULL;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_legacy_dev_reinit(dev);
|
||||
@@ -549,9 +533,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
}
|
||||
}
|
||||
|
||||
BUG_ON(dev->dev_mapping == NULL);
|
||||
iput(container_of(dev->dev_mapping, struct inode, i_data));
|
||||
|
||||
/* drop the reference held my the file priv */
|
||||
if (file_priv->master)
|
||||
drm_master_put(&file_priv->master);
|
||||
|
||||
Reference in New Issue
Block a user