drm: fixup master code to use krefs
parent
af6efc3d77
commit
717dd804d0
|
@ -671,6 +671,8 @@ struct drm_gem_object {
|
|||
/* per-master structure */
|
||||
struct drm_master {
|
||||
|
||||
struct kref refcount; /* refcount for this master */
|
||||
|
||||
struct list_head head; /**< each minor contains a list of masters */
|
||||
struct drm_minor *minor; /**< link back to minor we are a master for */
|
||||
|
||||
|
@ -1345,12 +1347,13 @@ extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv);
|
||||
extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern struct drm_master *drm_get_master(struct drm_minor *minor);
|
||||
extern void drm_put_master(struct drm_master *master);
|
||||
struct drm_master *drm_master_create(struct drm_minor *minor);
|
||||
extern struct drm_master *drm_master_get(struct drm_master *master);
|
||||
extern void drm_master_put(struct drm_master **master);
|
||||
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
struct drm_driver *driver);
|
||||
extern int drm_put_dev(struct drm_device *dev);
|
||||
extern int drm_put_minor(struct drm_device *dev, struct drm_minor **p);
|
||||
extern int drm_put_minor(struct drm_minor **minor_p);
|
||||
extern unsigned int drm_debug; /* 1 to enable debug output */
|
||||
|
||||
extern struct class *drm_class;
|
||||
|
|
|
@ -191,11 +191,6 @@ int drm_lastclose(struct drm_device * dev)
|
|||
drm_drawable_free_all(dev);
|
||||
del_timer(&dev->timer);
|
||||
|
||||
if (dev->primary->master) {
|
||||
drm_put_master(dev->primary->master);
|
||||
dev->primary->master = NULL;
|
||||
}
|
||||
|
||||
/* Clear AGP information */
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
struct drm_agp_mem *entry, *tempe;
|
||||
|
@ -400,9 +395,10 @@ static void drm_cleanup(struct drm_device * dev)
|
|||
drm_ht_remove(&dev->map_hash);
|
||||
drm_memrange_takedown(&dev->offset_manager);
|
||||
|
||||
drm_put_minor(dev, &dev->primary);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(dev, &dev->control);
|
||||
drm_put_minor(&dev->control);
|
||||
|
||||
drm_put_minor(&dev->primary);
|
||||
|
||||
if (drm_put_dev(dev))
|
||||
DRM_ERROR("Cannot unload module\n");
|
||||
|
|
|
@ -260,28 +260,34 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
|||
/* if there is no current master make this fd it */
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!priv->minor->master) {
|
||||
priv->minor->master = drm_get_master(priv->minor);
|
||||
/* create a new master */
|
||||
priv->minor->master = drm_master_create(priv->minor);
|
||||
if (!priv->minor->master) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
priv->is_master = 1;
|
||||
priv->master = priv->minor->master;
|
||||
/* take another reference for the copy in the local file priv */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
|
||||
priv->authenticated = 1;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (dev->driver->master_create) {
|
||||
ret = dev->driver->master_create(dev, priv->master);
|
||||
if (ret) {
|
||||
drm_put_master(priv->minor->master);
|
||||
priv->minor->master = priv->master = NULL;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
/* drop both references if this fails */
|
||||
drm_master_put(&priv->minor->master);
|
||||
drm_master_put(&priv->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
priv->master = priv->minor->master;
|
||||
/* get a reference to the master */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
|
@ -453,6 +459,8 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_fb_release(filp);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (file_priv->is_master) {
|
||||
struct drm_file *temp;
|
||||
list_for_each_entry(temp, &dev->filelist, lhead) {
|
||||
|
@ -461,18 +469,17 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
temp->authenticated = 0;
|
||||
}
|
||||
|
||||
if (file_priv->minor->master == file_priv->master)
|
||||
file_priv->minor->master = NULL;
|
||||
drm_put_master(file_priv->master);
|
||||
if (file_priv->minor->master == file_priv->master) {
|
||||
/* drop the reference held my the minor */
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
}
|
||||
}
|
||||
|
||||
file_priv->master = NULL;
|
||||
/* drop the reference held my the file priv */
|
||||
drm_master_put(&file_priv->master);
|
||||
file_priv->is_master = 0;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
list_del(&file_priv->lhead);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (dev->driver->postclose)
|
||||
|
|
|
@ -88,30 +88,7 @@ again:
|
|||
return new_id;
|
||||
}
|
||||
|
||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->minor->master && file_priv->minor->master != file_priv->master)
|
||||
file_priv->minor->master = file_priv->master;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
file_priv->minor->master = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_master *drm_get_master(struct drm_minor *minor)
|
||||
struct drm_master *drm_master_create(struct drm_minor *minor)
|
||||
{
|
||||
struct drm_master *master;
|
||||
|
||||
|
@ -119,7 +96,7 @@ struct drm_master *drm_get_master(struct drm_minor *minor)
|
|||
if (!master)
|
||||
return NULL;
|
||||
|
||||
// INIT_LIST_HEAD(&master->filelist);
|
||||
kref_init(&master->refcount);
|
||||
spin_lock_init(&master->lock.spinlock);
|
||||
init_waitqueue_head(&master->lock.lock_queue);
|
||||
drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
|
||||
|
@ -131,8 +108,15 @@ struct drm_master *drm_get_master(struct drm_minor *minor)
|
|||
return master;
|
||||
}
|
||||
|
||||
void drm_put_master(struct drm_master *master)
|
||||
struct drm_master *drm_master_get(struct drm_master *master)
|
||||
{
|
||||
kref_get(&master->refcount);
|
||||
return master;
|
||||
}
|
||||
|
||||
static void drm_master_destroy(struct kref *kref)
|
||||
{
|
||||
struct drm_master *master = container_of(kref, struct drm_master, refcount);
|
||||
struct drm_magic_entry *pt, *next;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
|
@ -166,21 +150,56 @@ void drm_put_master(struct drm_master *master)
|
|||
drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
||||
void drm_master_put(struct drm_master **master)
|
||||
{
|
||||
kref_put(&(*master)->refcount, drm_master_destroy);
|
||||
*master = NULL;
|
||||
}
|
||||
|
||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->minor->master && file_priv->minor->master != file_priv->master) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
file_priv->minor->master = drm_master_get(file_priv->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
INIT_LIST_HEAD(&dev->filelist);
|
||||
INIT_LIST_HEAD(&dev->ctxlist);
|
||||
INIT_LIST_HEAD(&dev->vmalist);
|
||||
INIT_LIST_HEAD(&dev->maplist);
|
||||
INIT_LIST_HEAD(&dev->filelist);
|
||||
|
||||
spin_lock_init(&dev->count_lock);
|
||||
spin_lock_init(&dev->drw_lock);
|
||||
spin_lock_init(&dev->tasklet_lock);
|
||||
// spin_lock_init(&dev->lock.spinlock);
|
||||
|
||||
init_timer(&dev->timer);
|
||||
mutex_init(&dev->struct_mutex);
|
||||
mutex_init(&dev->ctxlist_mutex);
|
||||
|
@ -402,10 +421,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
|||
|
||||
return 0;
|
||||
err_g5:
|
||||
drm_put_minor(dev, &dev->primary);
|
||||
drm_put_minor(&dev->primary);
|
||||
err_g4:
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(dev, &dev->control);
|
||||
drm_put_minor(&dev->control);
|
||||
err_g3:
|
||||
if (!drm_fb_loaded)
|
||||
pci_disable_device(pdev);
|
||||
|
@ -456,14 +475,14 @@ int drm_put_dev(struct drm_device * dev)
|
|||
* last minor released.
|
||||
*
|
||||
*/
|
||||
int drm_put_minor(struct drm_device *dev, struct drm_minor **minor_p)
|
||||
int drm_put_minor(struct drm_minor **minor_p)
|
||||
{
|
||||
struct drm_minor *minor = *minor_p;
|
||||
DRM_DEBUG("release secondary minor %d\n", minor->index);
|
||||
|
||||
if (minor->type == DRM_MINOR_LEGACY) {
|
||||
if (dev->driver->proc_cleanup)
|
||||
dev->driver->proc_cleanup(minor);
|
||||
if (minor->dev->driver->proc_cleanup)
|
||||
minor->dev->driver->proc_cleanup(minor);
|
||||
drm_proc_cleanup(minor, drm_proc_root);
|
||||
}
|
||||
drm_sysfs_device_remove(minor);
|
||||
|
|
Loading…
Reference in New Issue