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

Commit f1b85962 authored by David Herrmann's avatar David Herrmann
Browse files

drm: make minor->index available early



Instead of allocating the minor-index during registration, we now do this
during allocation. This way, debug-messages between minor-allocation and
minor-registration will now use the correct minor instead of 0. Same is
done for unregistration vs. free, so debug-messages between
device-shutdown and device-destruction show proper indices.

Even though minor-indices are allocated early, we don't enable minor
lookup early. Instead, we keep the entry set to NULL and replace it during
registration / unregistration. This way, the index is allocated but lookup
only works if registered.

Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
parent ec8f112d
Loading
Loading
Loading
Loading
+46 −38
Original line number Original line Diff line number Diff line
@@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
{
{
	struct drm_minor *minor;
	struct drm_minor *minor;
	unsigned long flags;
	int r;


	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
	if (!minor)
	if (!minor)
@@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
	minor->type = type;
	minor->type = type;
	minor->dev = dev;
	minor->dev = dev;


	idr_preload(GFP_KERNEL);
	spin_lock_irqsave(&drm_minor_lock, flags);
	r = idr_alloc(&drm_minors_idr,
		      NULL,
		      64 * type,
		      64 * (type + 1),
		      GFP_NOWAIT);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	idr_preload_end();

	if (r < 0)
		goto err_free;

	minor->index = r;

	*drm_minor_get_slot(dev, type) = minor;
	*drm_minor_get_slot(dev, type) = minor;
	return 0;
	return 0;

err_free:
	kfree(minor);
	return r;
}
}


static void drm_minor_free(struct drm_device *dev, unsigned int type)
static void drm_minor_free(struct drm_device *dev, unsigned int type)
{
{
	struct drm_minor **slot;
	struct drm_minor **slot, *minor;
	unsigned long flags;


	slot = drm_minor_get_slot(dev, type);
	slot = drm_minor_get_slot(dev, type);
	if (*slot) {
	minor = *slot;
		drm_mode_group_destroy(&(*slot)->mode_group);
	if (!minor)
		kfree(*slot);
		return;

	drm_mode_group_destroy(&minor->mode_group);

	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_remove(&drm_minors_idr, minor->index);
	spin_unlock_irqrestore(&drm_minor_lock, flags);

	kfree(minor);
	*slot = NULL;
	*slot = NULL;
}
}
}


static int drm_minor_register(struct drm_device *dev, unsigned int type)
static int drm_minor_register(struct drm_device *dev, unsigned int type)
{
{
	struct drm_minor *new_minor;
	struct drm_minor *minor;
	unsigned long flags;
	unsigned long flags;
	int ret;
	int ret;
	int minor_id;


	DRM_DEBUG("\n");
	DRM_DEBUG("\n");


	new_minor = *drm_minor_get_slot(dev, type);
	minor = *drm_minor_get_slot(dev, type);
	if (!new_minor)
	if (!minor)
		return 0;
		return 0;


	idr_preload(GFP_KERNEL);
	ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
	spin_lock_irqsave(&drm_minor_lock, flags);
	minor_id = idr_alloc(&drm_minors_idr,
			     NULL,
			     64 * type,
			     64 * (type + 1),
			     GFP_NOWAIT);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	idr_preload_end();

	if (minor_id < 0)
		return minor_id;

	new_minor->index = minor_id;

	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
	if (ret) {
	if (ret) {
		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
		goto err_id;
		return ret;
	}
	}


	ret = drm_sysfs_device_add(new_minor);
	ret = drm_sysfs_device_add(minor);
	if (ret) {
	if (ret) {
		DRM_ERROR("DRM: Error sysfs_device_add.\n");
		DRM_ERROR("DRM: Error sysfs_device_add.\n");
		goto err_debugfs;
		goto err_debugfs;
@@ -322,19 +335,14 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)


	/* replace NULL with @minor so lookups will succeed from now on */
	/* replace NULL with @minor so lookups will succeed from now on */
	spin_lock_irqsave(&drm_minor_lock, flags);
	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_replace(&drm_minors_idr, new_minor, new_minor->index);
	idr_replace(&drm_minors_idr, minor, minor->index);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	spin_unlock_irqrestore(&drm_minor_lock, flags);


	DRM_DEBUG("new minor assigned %d\n", minor_id);
	DRM_DEBUG("new minor registered %d\n", minor->index);
	return 0;
	return 0;


err_debugfs:
err_debugfs:
	drm_debugfs_cleanup(new_minor);
	drm_debugfs_cleanup(minor);
err_id:
	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_remove(&drm_minors_idr, minor_id);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	new_minor->index = 0;
	return ret;
	return ret;
}
}


@@ -347,10 +355,10 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
	if (!minor || !minor->kdev)
	if (!minor || !minor->kdev)
		return;
		return;


	/* replace @minor with NULL so lookups will fail from now on */
	spin_lock_irqsave(&drm_minor_lock, flags);
	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_remove(&drm_minors_idr, minor->index);
	idr_replace(&drm_minors_idr, NULL, minor->index);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	minor->index = 0;


	drm_debugfs_cleanup(minor);
	drm_debugfs_cleanup(minor);
	drm_sysfs_device_remove(minor);
	drm_sysfs_device_remove(minor);