Commit e40d6410 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-minor' of git://people.freedesktop.org/~dvdhrm/linux into drm-next

This series contains several cleanups for the DRM-minor handling. All but the
last one reviewed by Daniel and tested by Thierry. Initially, the series
included patches to convert minor-handling to a common base-ID, but have
been NACKed by Daniel so I dropped them and only included the main part in the
last patch. With this in place, drm_global_mutex is no longer needed for
minor-handling (but still for device unregistration..).
There are some pending patches that try to remove the global mutex entirely, but
they need some more reviews and thus are not included.
* 'drm-minor' of git://people.freedesktop.org/~dvdhrm/linux:
  drm: make minors independent of global lock
  drm: inline drm_minor_get_id()
  drm: coding-style fixes in minor handling
  drm: remove redundant minor->device field
  drm: remove unneeded #ifdef CONFIG_DEBUGFS
  drm: rename drm_unplug/get_minor() to drm_minor_register/unregister()
  drm: move drm_put_minor() to drm_minor_free()
  drm: allocate minors early
  drm: add minor-lookup/release helpers
  drm: provide device-refcount
  drm: turn DRM_MINOR_* into enum
  drm: remove unused DRM_MINOR_UNASSIGNED
  drm: skip redundant minor-lookup in open path
  drm: group dev-lifetime related members
parents 28b90a9e 0d639883
...@@ -344,7 +344,7 @@ long drm_ioctl(struct file *filp, ...@@ -344,7 +344,7 @@ long drm_ioctl(struct file *filp,
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
task_pid_nr(current), task_pid_nr(current),
(long)old_encode_dev(file_priv->minor->device), (long)old_encode_dev(file_priv->minor->kdev->devt),
file_priv->authenticated, ioctl->name); file_priv->authenticated, ioctl->name);
/* Do not trust userspace, use our own definition */ /* Do not trust userspace, use our own definition */
...@@ -402,7 +402,7 @@ long drm_ioctl(struct file *filp, ...@@ -402,7 +402,7 @@ long drm_ioctl(struct file *filp,
if (!ioctl) if (!ioctl)
DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
task_pid_nr(current), task_pid_nr(current),
(long)old_encode_dev(file_priv->minor->device), (long)old_encode_dev(file_priv->minor->kdev->devt),
file_priv->authenticated, cmd, nr); file_priv->authenticated, cmd, nr);
if (kdata != stack_kdata) if (kdata != stack_kdata)
......
...@@ -39,12 +39,12 @@ ...@@ -39,12 +39,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
/* from BKL pushdown: note that nothing else serializes idr_find() */ /* from BKL pushdown */
DEFINE_MUTEX(drm_global_mutex); DEFINE_MUTEX(drm_global_mutex);
EXPORT_SYMBOL(drm_global_mutex); EXPORT_SYMBOL(drm_global_mutex);
static int drm_open_helper(struct inode *inode, struct file *filp, static int drm_open_helper(struct inode *inode, struct file *filp,
struct drm_device * dev); struct drm_minor *minor);
static int drm_setup(struct drm_device * dev) static int drm_setup(struct drm_device * dev)
{ {
...@@ -79,24 +79,18 @@ static int drm_setup(struct drm_device * dev) ...@@ -79,24 +79,18 @@ static int drm_setup(struct drm_device * dev)
*/ */
int drm_open(struct inode *inode, struct file *filp) int drm_open(struct inode *inode, struct file *filp)
{ {
struct drm_device *dev = NULL; struct drm_device *dev;
int minor_id = iminor(inode);
struct drm_minor *minor; struct drm_minor *minor;
int retcode = 0; int retcode;
int need_setup = 0; int need_setup = 0;
struct address_space *old_mapping; struct address_space *old_mapping;
struct address_space *old_imapping; struct address_space *old_imapping;
minor = idr_find(&drm_minors_idr, minor_id); minor = drm_minor_acquire(iminor(inode));
if (!minor) if (IS_ERR(minor))
return -ENODEV; return PTR_ERR(minor);
if (!(dev = minor->dev))
return -ENODEV;
if (drm_device_is_unplugged(dev))
return -ENODEV;
dev = minor->dev;
if (!dev->open_count++) if (!dev->open_count++)
need_setup = 1; need_setup = 1;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -110,7 +104,7 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -110,7 +104,7 @@ int drm_open(struct inode *inode, struct file *filp)
filp->f_mapping = dev->dev_mapping; filp->f_mapping = dev->dev_mapping;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
retcode = drm_open_helper(inode, filp, dev); retcode = drm_open_helper(inode, filp, minor);
if (retcode) if (retcode)
goto err_undo; goto err_undo;
if (need_setup) { if (need_setup) {
...@@ -128,6 +122,7 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -128,6 +122,7 @@ int drm_open(struct inode *inode, struct file *filp)
dev->dev_mapping = old_mapping; dev->dev_mapping = old_mapping;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
dev->open_count--; dev->open_count--;
drm_minor_release(minor);
return retcode; return retcode;
} }
EXPORT_SYMBOL(drm_open); EXPORT_SYMBOL(drm_open);
...@@ -143,33 +138,30 @@ EXPORT_SYMBOL(drm_open); ...@@ -143,33 +138,30 @@ EXPORT_SYMBOL(drm_open);
*/ */
int drm_stub_open(struct inode *inode, struct file *filp) int drm_stub_open(struct inode *inode, struct file *filp)
{ {
struct drm_device *dev = NULL; struct drm_device *dev;
struct drm_minor *minor; struct drm_minor *minor;
int minor_id = iminor(inode);
int err = -ENODEV; int err = -ENODEV;
const struct file_operations *new_fops; const struct file_operations *new_fops;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
mutex_lock(&drm_global_mutex); mutex_lock(&drm_global_mutex);
minor = idr_find(&drm_minors_idr, minor_id); minor = drm_minor_acquire(iminor(inode));
if (!minor) if (IS_ERR(minor))
goto out; goto out_unlock;
if (!(dev = minor->dev))
goto out;
if (drm_device_is_unplugged(dev))
goto out;
dev = minor->dev;
new_fops = fops_get(dev->driver->fops); new_fops = fops_get(dev->driver->fops);
if (!new_fops) if (!new_fops)
goto out; goto out_release;
replace_fops(filp, new_fops); replace_fops(filp, new_fops);
if (filp->f_op->open) if (filp->f_op->open)
err = filp->f_op->open(inode, filp); err = filp->f_op->open(inode, filp);
out:
out_release:
drm_minor_release(minor);
out_unlock:
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
return err; return err;
} }
...@@ -196,16 +188,16 @@ static int drm_cpu_valid(void) ...@@ -196,16 +188,16 @@ static int drm_cpu_valid(void)
* *
* \param inode device inode. * \param inode device inode.
* \param filp file pointer. * \param filp file pointer.
* \param dev device. * \param minor acquired minor-object.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Creates and initializes a drm_file structure for the file private data in \p * Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev. * filp and add it into the double linked list in \p dev.
*/ */
static int drm_open_helper(struct inode *inode, struct file *filp, static int drm_open_helper(struct inode *inode, struct file *filp,
struct drm_device * dev) struct drm_minor *minor)
{ {
int minor_id = iminor(inode); struct drm_device *dev = minor->dev;
struct drm_file *priv; struct drm_file *priv;
int ret; int ret;
...@@ -216,7 +208,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -216,7 +208,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
return -EINVAL; return -EINVAL;
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
priv = kzalloc(sizeof(*priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
...@@ -226,11 +218,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -226,11 +218,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
priv->filp = filp; priv->filp = filp;
priv->uid = current_euid(); priv->uid = current_euid();
priv->pid = get_pid(task_pid(current)); priv->pid = get_pid(task_pid(current));
priv->minor = idr_find(&drm_minors_idr, minor_id); priv->minor = minor;
if (!priv->minor) {
ret = -ENODEV;
goto out_put_pid;
}
/* for compatibility root is always authenticated */ /* for compatibility root is always authenticated */
priv->always_authenticated = capable(CAP_SYS_ADMIN); priv->always_authenticated = capable(CAP_SYS_ADMIN);
...@@ -336,7 +324,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -336,7 +324,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
drm_prime_destroy_file_private(&priv->prime); drm_prime_destroy_file_private(&priv->prime);
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, priv); drm_gem_release(dev, priv);
out_put_pid:
put_pid(priv->pid); put_pid(priv->pid);
kfree(priv); kfree(priv);
filp->private_data = NULL; filp->private_data = NULL;
...@@ -458,7 +445,8 @@ int drm_lastclose(struct drm_device * dev) ...@@ -458,7 +445,8 @@ int drm_lastclose(struct drm_device * dev)
int drm_release(struct inode *inode, struct file *filp) int drm_release(struct inode *inode, struct file *filp)
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev; struct drm_minor *minor = file_priv->minor;
struct drm_device *dev = minor->dev;
int retcode = 0; int retcode = 0;
mutex_lock(&drm_global_mutex); mutex_lock(&drm_global_mutex);
...@@ -474,7 +462,7 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -474,7 +462,7 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
task_pid_nr(current), task_pid_nr(current),
(long)old_encode_dev(file_priv->minor->device), (long)old_encode_dev(file_priv->minor->kdev->devt),
dev->open_count); dev->open_count);
/* Release any auth tokens that might point to this file_priv, /* Release any auth tokens that might point to this file_priv,
...@@ -580,6 +568,8 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -580,6 +568,8 @@ int drm_release(struct inode *inode, struct file *filp)
} }
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
drm_minor_release(minor);
return retcode; return retcode;
} }
EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release);
......
...@@ -351,7 +351,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -351,7 +351,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
drm_pci_agp_destroy(dev); drm_pci_agp_destroy(dev);
pci_disable_device(pdev); pci_disable_device(pdev);
err_free: err_free:
drm_dev_free(dev); drm_dev_unref(dev);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_get_pci_dev); EXPORT_SYMBOL(drm_get_pci_dev);
......
...@@ -64,7 +64,7 @@ static int drm_get_platform_dev(struct platform_device *platdev, ...@@ -64,7 +64,7 @@ static int drm_get_platform_dev(struct platform_device *platdev,
return 0; return 0;
err_free: err_free:
drm_dev_free(dev); drm_dev_unref(dev);
return ret; return ret;
} }
......
This diff is collapsed.
...@@ -30,7 +30,7 @@ int drm_get_usb_dev(struct usb_interface *interface, ...@@ -30,7 +30,7 @@ int drm_get_usb_dev(struct usb_interface *interface,
return 0; return 0;
err_free: err_free:
drm_dev_free(dev); drm_dev_unref(dev);
return ret; return ret;
} }
......
...@@ -63,7 +63,7 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device) ...@@ -63,7 +63,7 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
return 0; return 0;
err_free: err_free:
drm_dev_free(drm); drm_dev_unref(drm);
return ret; return ret;
} }
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <asm/current.h> #include <asm/current.h>
#endif /* __alpha__ */ #endif /* __alpha__ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -1008,10 +1009,12 @@ struct drm_driver { ...@@ -1008,10 +1009,12 @@ struct drm_driver {
struct list_head legacy_dev_list; struct list_head legacy_dev_list;
}; };
#define DRM_MINOR_UNASSIGNED 0 enum drm_minor_type {
#define DRM_MINOR_LEGACY 1 DRM_MINOR_LEGACY,
#define DRM_MINOR_CONTROL 2 DRM_MINOR_CONTROL,
#define DRM_MINOR_RENDER 3 DRM_MINOR_RENDER,
DRM_MINOR_CNT,
};
/** /**
* Info file list entry. This structure represents a debugfs or proc file to * Info file list entry. This structure represents a debugfs or proc file to
...@@ -1040,7 +1043,6 @@ struct drm_info_node { ...@@ -1040,7 +1043,6 @@ struct drm_info_node {
struct drm_minor { struct drm_minor {
int index; /**< Minor device number */ int index; /**< Minor device number */
int type; /**< Control or render */ int type; /**< Control or render */
dev_t device; /**< Device number for mknod */
struct device *kdev; /**< Linux device */ struct device *kdev; /**< Linux device */
struct drm_device *dev; struct drm_device *dev;
...@@ -1098,6 +1100,19 @@ struct drm_device { ...@@ -1098,6 +1100,19 @@ struct drm_device {
char *devname; /**< For /proc/interrupts */ char *devname; /**< For /proc/interrupts */
int if_version; /**< Highest interface version set */ int if_version; /**< Highest interface version set */
/** \name Lifetime Management */
/*@{ */
struct kref ref; /**< Object ref-count */
struct device *dev; /**< Device structure of bus-device */
struct drm_driver *driver; /**< DRM driver managing the device */
void *dev_private; /**< DRM driver private data */
struct address_space *dev_mapping; /**< Private addr-space just for the device */
struct drm_minor *control; /**< Control node */
struct drm_minor *primary; /**< Primary node */
struct drm_minor *render; /**< Render node */
atomic_t unplugged; /**< Flag whether dev is dead */
/*@} */
/** \name Locks */ /** \name Locks */
/*@{ */ /*@{ */
spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
...@@ -1171,7 +1186,6 @@ struct drm_device { ...@@ -1171,7 +1186,6 @@ struct drm_device {
struct drm_agp_head *agp; /**< AGP data */ struct drm_agp_head *agp; /**< AGP data */
struct device *dev; /**< Device structure */
struct pci_dev *pdev; /**< PCI device structure */ struct pci_dev *pdev; /**< PCI device structure */
#ifdef __alpha__ #ifdef __alpha__
struct pci_controller *hose; struct pci_controller *hose;
...@@ -1182,17 +1196,11 @@ struct drm_device { ...@@ -1182,17 +1196,11 @@ struct drm_device {
struct drm_sg_mem *sg; /**< Scatter gather memory */ struct drm_sg_mem *sg; /**< Scatter gather memory */
unsigned int num_crtcs; /**< Number of CRTCs on this device */ unsigned int num_crtcs; /**< Number of CRTCs on this device */
void *dev_private; /**< device private data */
struct address_space *dev_mapping;
struct drm_sigdata sigdata; /**< For block_all_signals */ struct drm_sigdata sigdata; /**< For block_all_signals */
sigset_t sigmask; sigset_t sigmask;
struct drm_driver *driver;
struct drm_local_map *agp_buffer_map; struct drm_local_map *agp_buffer_map;
unsigned int agp_buffer_token; unsigned int agp_buffer_token;
struct drm_minor *control; /**< Control node for card */
struct drm_minor *primary; /**< render type primary screen head */
struct drm_minor *render; /**< render node for card */
struct drm_mode_config mode_config; /**< Current mode config */ struct drm_mode_config mode_config; /**< Current mode config */
...@@ -1203,8 +1211,6 @@ struct drm_device { ...@@ -1203,8 +1211,6 @@ struct drm_device {
struct drm_vma_offset_manager *vma_offset_manager; struct drm_vma_offset_manager *vma_offset_manager;
/*@} */ /*@} */
int switch_power_state; int switch_power_state;
atomic_t unplugged; /* device has been unplugged or gone away */
}; };
#define DRM_SWITCH_POWER_ON 0 #define DRM_SWITCH_POWER_ON 0
...@@ -1661,9 +1667,14 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map) ...@@ -1661,9 +1667,14 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map)
struct drm_device *drm_dev_alloc(struct drm_driver *driver, struct drm_device *drm_dev_alloc(struct drm_driver *driver,
struct device *parent); struct device *parent);
void drm_dev_free(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev);
void drm_dev_unref(struct drm_device *dev);
int drm_dev_register(struct drm_device *dev, unsigned long flags); int drm_dev_register(struct drm_device *dev, unsigned long flags);
void drm_dev_unregister(struct drm_device *dev); void drm_dev_unregister(struct drm_device *dev);
struct drm_minor *drm_minor_acquire(unsigned int minor_id);
void drm_minor_release(struct drm_minor *minor);
/*@}*/ /*@}*/
/* PCI section */ /* PCI section */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment