Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6796cb16 authored by David Herrmann's avatar David Herrmann
Browse files

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: default avatarDavid Herrmann <dh.herrmann@gmail.com>
parent 31bbe16f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align,
	}

	astbo->bo.bdev = &ast->ttm.bdev;
	astbo->bo.bdev->dev_mapping = dev->dev_mapping;
	astbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping;

	ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);

+1 −1
Original line number Diff line number Diff line
@@ -359,7 +359,7 @@ static int bochs_bo_create(struct drm_device *dev, int size, int align,
	}

	bochsbo->bo.bdev = &bochs->ttm.bdev;
	bochsbo->bo.bdev->dev_mapping = dev->dev_mapping;
	bochsbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping;

	bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);

+1 −1
Original line number Diff line number Diff line
@@ -329,7 +329,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align,
	}

	cirrusbo->bo.bdev = &cirrus->ttm.bdev;
	cirrusbo->bo.bdev->dev_mapping = dev->dev_mapping;
	cirrusbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping;

	cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);

+3 −22
Original line number Diff line number Diff line
@@ -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);
+11 −1
Original line number Diff line number Diff line
@@ -526,8 +526,15 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
	mutex_init(&dev->struct_mutex);
	mutex_init(&dev->ctxlist_mutex);

	if (drm_ht_create(&dev->map_hash, 12))
	dev->anon_inode = drm_fs_inode_new();
	if (IS_ERR(dev->anon_inode)) {
		ret = PTR_ERR(dev->anon_inode);
		DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
		goto err_free;
	}

	if (drm_ht_create(&dev->map_hash, 12))
		goto err_inode;

	ret = drm_ctxbitmap_init(dev);
	if (ret) {
@@ -549,6 +556,8 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
	drm_ctxbitmap_cleanup(dev);
err_ht:
	drm_ht_remove(&dev->map_hash);
err_inode:
	drm_fs_inode_free(dev->anon_inode);
err_free:
	kfree(dev);
	return NULL;
@@ -576,6 +585,7 @@ void drm_dev_free(struct drm_device *dev)

	drm_ctxbitmap_cleanup(dev);
	drm_ht_remove(&dev->map_hash);
	drm_fs_inode_free(dev->anon_inode);

	kfree(dev->devname);
	kfree(dev);
Loading