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

Commit 2c07a21d authored by Dave Airlie's avatar Dave Airlie
Browse files

drm: add core support for unplugging a device (v2)



Two parts to this, one is simple unplug from sysfs for the device node.

The second adds an unplugged state, if we have device opens, we
just set the unplugged state and return, if we have no device
opens we drop the drm device.

If after a lastclose we discover we are unplugged we then
drop the drm device.

v2: use an atomic for unplugged and wrap it for users,
add checks on open + mmap + ioctl entry points.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent cbc7e221
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -390,6 +390,10 @@ long drm_ioctl(struct file *filp,
	unsigned int usize, asize;
	unsigned int usize, asize;


	dev = file_priv->minor->dev;
	dev = file_priv->minor->dev;

	if (drm_device_is_unplugged(dev))
		return -ENODEV;

	atomic_inc(&dev->ioctl_count);
	atomic_inc(&dev->ioctl_count);
	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
	++file_priv->ioctl_count;
	++file_priv->ioctl_count;
+8 −0
Original line number Original line Diff line number Diff line
@@ -133,6 +133,9 @@ int drm_open(struct inode *inode, struct file *filp)
	if (!(dev = minor->dev))
	if (!(dev = minor->dev))
		return -ENODEV;
		return -ENODEV;


	if (drm_device_is_unplugged(dev))
		return -ENODEV;

	retcode = drm_open_helper(inode, filp, dev);
	retcode = drm_open_helper(inode, filp, dev);
	if (!retcode) {
	if (!retcode) {
		atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
		atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
@@ -181,6 +184,9 @@ int drm_stub_open(struct inode *inode, struct file *filp)
	if (!(dev = minor->dev))
	if (!(dev = minor->dev))
		goto out;
		goto out;


	if (drm_device_is_unplugged(dev))
		goto out;

	old_fops = filp->f_op;
	old_fops = filp->f_op;
	filp->f_op = fops_get(dev->driver->fops);
	filp->f_op = fops_get(dev->driver->fops);
	if (filp->f_op == NULL) {
	if (filp->f_op == NULL) {
@@ -579,6 +585,8 @@ int drm_release(struct inode *inode, struct file *filp)
			retcode = -EBUSY;
			retcode = -EBUSY;
		} else
		} else
			retcode = drm_lastclose(dev);
			retcode = drm_lastclose(dev);
		if (drm_device_is_unplugged(dev))
			drm_put_dev(dev);
	}
	}
	mutex_unlock(&drm_global_mutex);
	mutex_unlock(&drm_global_mutex);


+3 −0
Original line number Original line Diff line number Diff line
@@ -661,6 +661,9 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
	struct drm_hash_item *hash;
	struct drm_hash_item *hash;
	int ret = 0;
	int ret = 0;


	if (drm_device_is_unplugged(dev))
		return -ENODEV;

	mutex_lock(&dev->struct_mutex);
	mutex_lock(&dev->struct_mutex);


	if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
	if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
+23 −0
Original line number Original line Diff line number Diff line
@@ -429,6 +429,11 @@ int drm_put_minor(struct drm_minor **minor_p)
	return 0;
	return 0;
}
}


static void drm_unplug_minor(struct drm_minor *minor)
{
	drm_sysfs_device_remove(minor);
}

/**
/**
 * Called via drm_exit() at module unload time or when pci device is
 * Called via drm_exit() at module unload time or when pci device is
 * unplugged.
 * unplugged.
@@ -492,3 +497,21 @@ void drm_put_dev(struct drm_device *dev)
	kfree(dev);
	kfree(dev);
}
}
EXPORT_SYMBOL(drm_put_dev);
EXPORT_SYMBOL(drm_put_dev);

void drm_unplug_dev(struct drm_device *dev)
{
	/* for a USB device */
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		drm_unplug_minor(dev->control);
	drm_unplug_minor(dev->primary);

	mutex_lock(&drm_global_mutex);

	drm_device_set_unplugged(dev);

	if (dev->open_count == 0) {
		drm_put_dev(dev);
	}
	mutex_unlock(&drm_global_mutex);
}
EXPORT_SYMBOL(drm_unplug_dev);
+3 −0
Original line number Original line Diff line number Diff line
@@ -680,6 +680,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
	struct drm_device *dev = priv->minor->dev;
	struct drm_device *dev = priv->minor->dev;
	int ret;
	int ret;


	if (drm_device_is_unplugged(dev))
		return -ENODEV;

	mutex_lock(&dev->struct_mutex);
	mutex_lock(&dev->struct_mutex);
	ret = drm_mmap_locked(filp, vma);
	ret = drm_mmap_locked(filp, vma);
	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->struct_mutex);
Loading