drm: Move master functions into drm_auth.c
For modern drivers pretty much the only thing drm_master does is handling authentication for the primary/legacy drm_minor node. Instead of having it all over drm files, move it all together into drm_auth.c. This patch just does code-motion, follow up patches will also extract the master logic from file open&release paths. Reviewed-by: Chris Wilson Mchris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1465930269-7883-5-git-send-email-daniel.vetter@ffwll.ch
This commit is contained in:
parent
34a839c689
commit
6548f4e7a3
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include "drm_internal.h"
|
#include "drm_internal.h"
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_getmagic - Get unique magic of a client
|
* drm_getmagic - Get unique magic of a client
|
||||||
|
@ -91,3 +92,165 @@ int drm_authmagic(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
return file ? 0 : -EINVAL;
|
return file ? 0 : -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct drm_master *drm_master_create(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_master *master;
|
||||||
|
|
||||||
|
master = kzalloc(sizeof(*master), GFP_KERNEL);
|
||||||
|
if (!master)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
kref_init(&master->refcount);
|
||||||
|
spin_lock_init(&master->lock.spinlock);
|
||||||
|
init_waitqueue_head(&master->lock.lock_queue);
|
||||||
|
idr_init(&master->magic_map);
|
||||||
|
master->dev = dev;
|
||||||
|
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drm_new_set_master - Allocate a new master object and become master for the
|
||||||
|
* associated master realm.
|
||||||
|
*
|
||||||
|
* @dev: The associated device.
|
||||||
|
* @fpriv: File private identifying the client.
|
||||||
|
*
|
||||||
|
* This function must be called with dev::struct_mutex held.
|
||||||
|
* Returns negative error code on failure. Zero on success.
|
||||||
|
*/
|
||||||
|
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
||||||
|
{
|
||||||
|
struct drm_master *old_master;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lockdep_assert_held_once(&dev->master_mutex);
|
||||||
|
|
||||||
|
/* create a new master */
|
||||||
|
fpriv->minor->master = drm_master_create(fpriv->minor->dev);
|
||||||
|
if (!fpriv->minor->master)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* take another reference for the copy in the local file priv */
|
||||||
|
old_master = fpriv->master;
|
||||||
|
fpriv->master = drm_master_get(fpriv->minor->master);
|
||||||
|
|
||||||
|
if (dev->driver->master_create) {
|
||||||
|
ret = dev->driver->master_create(dev, fpriv->master);
|
||||||
|
if (ret)
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
if (dev->driver->master_set) {
|
||||||
|
ret = dev->driver->master_set(dev, fpriv, true);
|
||||||
|
if (ret)
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpriv->is_master = 1;
|
||||||
|
fpriv->allowed_master = 1;
|
||||||
|
fpriv->authenticated = 1;
|
||||||
|
if (old_master)
|
||||||
|
drm_master_put(&old_master);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
/* drop both references and restore old master on failure */
|
||||||
|
drm_master_put(&fpriv->minor->master);
|
||||||
|
drm_master_put(&fpriv->master);
|
||||||
|
fpriv->master = old_master;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&dev->master_mutex);
|
||||||
|
if (file_priv->is_master)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
if (file_priv->minor->master) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_priv->master) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_priv->allowed_master) {
|
||||||
|
ret = drm_new_set_master(dev, file_priv);
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_priv->minor->master = drm_master_get(file_priv->master);
|
||||||
|
file_priv->is_master = 1;
|
||||||
|
if (dev->driver->master_set) {
|
||||||
|
ret = dev->driver->master_set(dev, file_priv, false);
|
||||||
|
if (unlikely(ret != 0)) {
|
||||||
|
file_priv->is_master = 0;
|
||||||
|
drm_master_put(&file_priv->minor->master);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&dev->master_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv)
|
||||||
|
{
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&dev->master_mutex);
|
||||||
|
if (!file_priv->is_master)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
if (!file_priv->minor->master)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (dev->driver->master_drop)
|
||||||
|
dev->driver->master_drop(dev, file_priv, false);
|
||||||
|
drm_master_put(&file_priv->minor->master);
|
||||||
|
file_priv->is_master = 0;
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&dev->master_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drm_master *drm_master_get(struct drm_master *master)
|
||||||
|
{
|
||||||
|
kref_get(&master->refcount);
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_master_get);
|
||||||
|
|
||||||
|
static void drm_master_destroy(struct kref *kref)
|
||||||
|
{
|
||||||
|
struct drm_master *master = container_of(kref, struct drm_master, refcount);
|
||||||
|
struct drm_device *dev = master->dev;
|
||||||
|
|
||||||
|
if (dev->driver->master_destroy)
|
||||||
|
dev->driver->master_destroy(dev, master);
|
||||||
|
|
||||||
|
drm_legacy_master_rmmaps(dev, master);
|
||||||
|
|
||||||
|
idr_destroy(&master->magic_map);
|
||||||
|
kfree(master->unique);
|
||||||
|
kfree(master);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drm_master_put(struct drm_master **master)
|
||||||
|
{
|
||||||
|
kref_put(&(*master)->refcount, drm_master_destroy);
|
||||||
|
*master = NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_master_put);
|
||||||
|
|
|
@ -93,114 +93,6 @@ void drm_ut_debug_printk(const char *function_name, const char *format, ...)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_ut_debug_printk);
|
EXPORT_SYMBOL(drm_ut_debug_printk);
|
||||||
|
|
||||||
struct drm_master *drm_master_create(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
struct drm_master *master;
|
|
||||||
|
|
||||||
master = kzalloc(sizeof(*master), GFP_KERNEL);
|
|
||||||
if (!master)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
kref_init(&master->refcount);
|
|
||||||
spin_lock_init(&master->lock.spinlock);
|
|
||||||
init_waitqueue_head(&master->lock.lock_queue);
|
|
||||||
idr_init(&master->magic_map);
|
|
||||||
master->dev = dev;
|
|
||||||
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct drm_master *drm_master_get(struct drm_master *master)
|
|
||||||
{
|
|
||||||
kref_get(&master->refcount);
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_master_get);
|
|
||||||
|
|
||||||
static void drm_master_destroy(struct kref *kref)
|
|
||||||
{
|
|
||||||
struct drm_master *master = container_of(kref, struct drm_master, refcount);
|
|
||||||
struct drm_device *dev = master->dev;
|
|
||||||
|
|
||||||
if (dev->driver->master_destroy)
|
|
||||||
dev->driver->master_destroy(dev, master);
|
|
||||||
|
|
||||||
drm_legacy_master_rmmaps(dev, master);
|
|
||||||
|
|
||||||
idr_destroy(&master->magic_map);
|
|
||||||
kfree(master->unique);
|
|
||||||
kfree(master);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drm_master_put(struct drm_master **master)
|
|
||||||
{
|
|
||||||
kref_put(&(*master)->refcount, drm_master_destroy);
|
|
||||||
*master = NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_master_put);
|
|
||||||
|
|
||||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
mutex_lock(&dev->master_mutex);
|
|
||||||
if (file_priv->is_master)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
if (file_priv->minor->master) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_priv->master) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_priv->allowed_master) {
|
|
||||||
ret = drm_new_set_master(dev, file_priv);
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_priv->minor->master = drm_master_get(file_priv->master);
|
|
||||||
file_priv->is_master = 1;
|
|
||||||
if (dev->driver->master_set) {
|
|
||||||
ret = dev->driver->master_set(dev, file_priv, false);
|
|
||||||
if (unlikely(ret != 0)) {
|
|
||||||
file_priv->is_master = 0;
|
|
||||||
drm_master_put(&file_priv->minor->master);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&dev->master_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv)
|
|
||||||
{
|
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
mutex_lock(&dev->master_mutex);
|
|
||||||
if (!file_priv->is_master)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
if (!file_priv->minor->master)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
if (dev->driver->master_drop)
|
|
||||||
dev->driver->master_drop(dev, file_priv, false);
|
|
||||||
drm_master_put(&file_priv->minor->master);
|
|
||||||
file_priv->is_master = 0;
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&dev->master_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DRM Minors
|
* DRM Minors
|
||||||
* A DRM device can provide several char-dev interfaces on the DRM-Major. Each
|
* A DRM device can provide several char-dev interfaces on the DRM-Major. Each
|
||||||
|
|
|
@ -167,60 +167,6 @@ static int drm_cpu_valid(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* drm_new_set_master - Allocate a new master object and become master for the
|
|
||||||
* associated master realm.
|
|
||||||
*
|
|
||||||
* @dev: The associated device.
|
|
||||||
* @fpriv: File private identifying the client.
|
|
||||||
*
|
|
||||||
* This function must be called with dev::struct_mutex held.
|
|
||||||
* Returns negative error code on failure. Zero on success.
|
|
||||||
*/
|
|
||||||
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
|
||||||
{
|
|
||||||
struct drm_master *old_master;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
lockdep_assert_held_once(&dev->master_mutex);
|
|
||||||
|
|
||||||
/* create a new master */
|
|
||||||
fpriv->minor->master = drm_master_create(fpriv->minor->dev);
|
|
||||||
if (!fpriv->minor->master)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* take another reference for the copy in the local file priv */
|
|
||||||
old_master = fpriv->master;
|
|
||||||
fpriv->master = drm_master_get(fpriv->minor->master);
|
|
||||||
|
|
||||||
if (dev->driver->master_create) {
|
|
||||||
ret = dev->driver->master_create(dev, fpriv->master);
|
|
||||||
if (ret)
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
if (dev->driver->master_set) {
|
|
||||||
ret = dev->driver->master_set(dev, fpriv, true);
|
|
||||||
if (ret)
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpriv->is_master = 1;
|
|
||||||
fpriv->allowed_master = 1;
|
|
||||||
fpriv->authenticated = 1;
|
|
||||||
if (old_master)
|
|
||||||
drm_master_put(&old_master);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_err:
|
|
||||||
/* drop both references and restore old master on failure */
|
|
||||||
drm_master_put(&fpriv->minor->master);
|
|
||||||
drm_master_put(&fpriv->master);
|
|
||||||
fpriv->master = old_master;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called whenever a process opens /dev/drm.
|
* Called whenever a process opens /dev/drm.
|
||||||
*
|
*
|
||||||
|
|
|
@ -62,6 +62,11 @@ int drm_getmagic(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
int drm_authmagic(struct drm_device *dev, void *data,
|
int drm_authmagic(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv);
|
||||||
|
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv);
|
||||||
|
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv);
|
||||||
|
|
||||||
/* drm_sysfs.c */
|
/* drm_sysfs.c */
|
||||||
extern struct class *drm_class;
|
extern struct class *drm_class;
|
||||||
|
@ -87,13 +92,6 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
||||||
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
|
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
|
||||||
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
|
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
|
||||||
|
|
||||||
/* drm_drv.c */
|
|
||||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
struct drm_master *drm_master_create(struct drm_device *dev);
|
|
||||||
|
|
||||||
/* drm_debugfs.c */
|
/* drm_debugfs.c */
|
||||||
#if defined(CONFIG_DEBUG_FS)
|
#if defined(CONFIG_DEBUG_FS)
|
||||||
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
||||||
|
|
|
@ -928,7 +928,6 @@ int drm_open(struct inode *inode, struct file *filp);
|
||||||
ssize_t drm_read(struct file *filp, char __user *buffer,
|
ssize_t drm_read(struct file *filp, char __user *buffer,
|
||||||
size_t count, loff_t *offset);
|
size_t count, loff_t *offset);
|
||||||
int drm_release(struct inode *inode, struct file *filp);
|
int drm_release(struct inode *inode, struct file *filp);
|
||||||
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv);
|
|
||||||
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
||||||
int drm_event_reserve_init_locked(struct drm_device *dev,
|
int drm_event_reserve_init_locked(struct drm_device *dev,
|
||||||
struct drm_file *file_priv,
|
struct drm_file *file_priv,
|
||||||
|
|
Loading…
Reference in New Issue