diff options
author | Dave Airlie <airlied@redhat.com> | 2008-04-21 16:47:32 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-04-26 17:55:07 +1000 |
commit | 2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3 (patch) | |
tree | dbf55c07d1b245a45330e0d879833df29954fe12 /drivers/char/drm | |
parent | 7b832b56bd971348329c3f4c753ca0abfdf3a3d1 (diff) | |
download | linux-2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3.tar.gz linux-2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3.tar.bz2 linux-2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3.zip |
drm: reorganise minor number handling using backported modesetting code.
rips out the head crap and replaces it with an idr and drm_minor structure
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/drm')
-rw-r--r-- | drivers/char/drm/drmP.h | 42 | ||||
-rw-r--r-- | drivers/char/drm/drm_agpsupport.c | 2 | ||||
-rw-r--r-- | drivers/char/drm/drm_drv.c | 60 | ||||
-rw-r--r-- | drivers/char/drm/drm_fops.c | 37 | ||||
-rw-r--r-- | drivers/char/drm/drm_proc.c | 61 | ||||
-rw-r--r-- | drivers/char/drm/drm_stub.c | 138 | ||||
-rw-r--r-- | drivers/char/drm/drm_sysfs.c | 46 | ||||
-rw-r--r-- | drivers/char/drm/drm_vm.c | 20 | ||||
-rw-r--r-- | drivers/char/drm/i810_dma.c | 4 | ||||
-rw-r--r-- | drivers/char/drm/i830_dma.c | 4 |
10 files changed, 230 insertions, 184 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6540948d5176..5446235094d8 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -379,13 +379,12 @@ struct drm_buf_entry { struct drm_file { int authenticated; int master; - int minor; pid_t pid; uid_t uid; drm_magic_t magic; unsigned long ioctl_count; struct list_head lhead; - struct drm_head *head; + struct drm_minor *minor; int remove_auth_on_close; unsigned long lock_count; struct file *filp; @@ -630,16 +629,19 @@ struct drm_driver { struct pci_driver pci_driver; }; +#define DRM_MINOR_UNASSIGNED 0 +#define DRM_MINOR_LEGACY 1 + /** - * DRM head structure. This structure represent a video head on a card - * that may contain multiple heads. Embed one per head of these in the - * private drm_device structure. + * DRM minor structure. This structure represents a drm minor number. */ -struct drm_head { - int minor; /**< Minor device number */ +struct drm_minor { + int index; /**< Minor device number */ + int type; /**< Control or render */ + dev_t device; /**< Device number for mknod */ + struct device kdev; /**< Linux device */ struct drm_device *dev; struct proc_dir_entry *dev_root; /**< proc directory entry */ - dev_t device; /**< Device number for mknod */ }; /** @@ -647,7 +649,6 @@ struct drm_head { * may contain multiple heads. */ struct drm_device { - struct device dev; /**< Linux device */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ char *devname; /**< For /proc/interrupts */ @@ -763,7 +764,7 @@ struct drm_device { struct drm_driver *driver; drm_local_map_t *agp_buffer_map; unsigned int agp_buffer_token; - struct drm_head primary; /**< primary screen head */ + struct drm_minor *primary; /**< render type primary screen head */ /** \name Drawable information */ /*@{ */ @@ -1030,23 +1031,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); -extern int drm_put_head(struct drm_head *head); +extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; -extern unsigned int drm_cards_limit; -extern struct drm_head **drm_heads; + extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; +extern struct idr drm_minors_idr; + extern drm_local_map_t *drm_getsarea(struct drm_device *dev); /* Proc support (drm_proc.h) */ -extern int drm_proc_init(struct drm_device *dev, - int minor, - struct proc_dir_entry *root, - struct proc_dir_entry **dev_root); -extern int drm_proc_cleanup(int minor, - struct proc_dir_entry *root, - struct proc_dir_entry *dev_root); +extern int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root); +extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root); /* Scatter Gather Support (drm_scatter.h) */ extern void drm_sg_cleanup(struct drm_sg_mem * entry); @@ -1071,8 +1069,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); struct drm_sysfs_class; extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); -extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head); -extern void drm_sysfs_device_remove(struct drm_device *dev); +extern int drm_sysfs_device_add(struct drm_minor *minor); +extern void drm_sysfs_device_remove(struct drm_minor *minor); /* * Basic memory manager support (drm_mm.c) diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index 9468c7889ff1..aefa5ac4c0b1 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c @@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire); int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return drm_agp_acquire((struct drm_device *) file_priv->head->dev); + return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); } /** diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 0e7af53c87de..fc54140551a7 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev) drm_ht_remove(&dev->map_hash); drm_ctxbitmap_cleanup(dev); - drm_put_head(&dev->primary); + drm_put_minor(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } -void drm_exit(struct drm_driver *driver) +int drm_minors_cleanup(int id, void *ptr, void *data) { - int i; - struct drm_device *dev = NULL; - struct drm_head *head; + struct drm_minor *minor = ptr; + struct drm_device *dev; + struct drm_driver *driver = data; + + dev = minor->dev; + if (minor->dev->driver != driver) + return 0; + + if (minor->type != DRM_MINOR_LEGACY) + return 0; + if (dev) + pci_dev_put(dev->pdev); + drm_cleanup(dev); + return 1; +} + +void drm_exit(struct drm_driver *driver) +{ DRM_DEBUG("\n"); - for (i = 0; i < drm_cards_limit; i++) { - head = drm_heads[i]; - if (!head) - continue; - if (!head->dev) - continue; - if (head->dev->driver != driver) - continue; - dev = head->dev; - if (dev) { - /* release the pci driver */ - if (dev->pdev) - pci_dev_put(dev->pdev); - drm_cleanup(dev); - } - } + idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); + DRM_INFO("Module unloaded\n"); } @@ -357,13 +358,7 @@ static int __init drm_core_init(void) { int ret = -ENOMEM; - drm_cards_limit = - (drm_cards_limit < - DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1); - drm_heads = - drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB); - if (!drm_heads) - goto err_p1; + idr_init(&drm_minors_idr); if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) goto err_p1; @@ -391,7 +386,8 @@ err_p3: drm_sysfs_destroy(); err_p2: unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + + idr_destroy(&drm_minors_idr); err_p1: return ret; } @@ -403,7 +399,7 @@ static void __exit drm_core_exit(void) unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + idr_destroy(&drm_minors_idr); } module_init(drm_core_init); @@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); @@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", task_pid_nr(current), cmd, nr, - (long)old_encode_dev(file_priv->head->device), + (long)old_encode_dev(file_priv->minor->device), file_priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index f09d4b5002b0..df7bf48be692 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev) int drm_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + int minor_id = iminor(inode); + struct drm_minor *minor; int retcode = 0; - if (!((minor >= 0) && (minor < drm_cards_limit))) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - if (!drm_heads[minor]) - return -ENODEV; - - if (!(dev = drm_heads[minor]->dev)) + if (!(dev = minor->dev)) return -ENODEV; retcode = drm_open_helper(inode, filp, dev); @@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open); int drm_stub_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + struct drm_minor *minor; + int minor_id = iminor(inode); int err = -ENODEV; const struct file_operations *old_fops; DRM_DEBUG("\n"); - if (!((minor >= 0) && (minor < drm_cards_limit))) - return -ENODEV; - - if (!drm_heads[minor]) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - if (!(dev = drm_heads[minor]->dev)) + if (!(dev = minor->dev)) return -ENODEV; old_fops = filp->f_op; @@ -225,7 +223,7 @@ static int drm_cpu_valid(void) static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev) { - int minor = iminor(inode); + int minor_id = iminor(inode); struct drm_file *priv; int ret; @@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (!drm_cpu_valid()) return -EINVAL; - DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor); + DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); if (!priv) @@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->filp = filp; priv->uid = current->euid; priv->pid = task_pid_nr(current); - priv->minor = minor; - priv->head = drm_heads[minor]; + priv->minor = idr_find(&drm_minors_idr, minor_id); priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); @@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp, int drm_fasync(int fd, struct file *filp, int on) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int retcode; DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, - (long)old_encode_dev(priv->head->device)); + (long)old_encode_dev(priv->minor->device)); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; @@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync); int drm_release(struct inode *inode, struct file *filp) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int retcode = 0; unsigned long irqflags; @@ -341,7 +338,7 @@ int drm_release(struct inode *inode, struct file *filp) DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", task_pid_nr(current), - (long)old_encode_dev(file_priv->head->device), + (long)old_encode_dev(file_priv->minor->device), dev->open_count); if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index d9b560fe9bbe..93b1e0475c93 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c @@ -87,34 +87,35 @@ static struct drm_proc_list { * "/proc/dri/%minor%/", and each entry in proc_list as * "/proc/dri/%minor%/%name%". */ -int drm_proc_init(struct drm_device * dev, int minor, - struct proc_dir_entry *root, struct proc_dir_entry **dev_root) +int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root) { struct proc_dir_entry *ent; int i, j; char name[64]; - sprintf(name, "%d", minor); - *dev_root = proc_mkdir(name, root); - if (!*dev_root) { + sprintf(name, "%d", minor_id); + minor->dev_root = proc_mkdir(name, root); + if (!minor->dev_root) { DRM_ERROR("Cannot create /proc/dri/%s\n", name); return -1; } for (i = 0; i < DRM_PROC_ENTRIES; i++) { ent = create_proc_entry(drm_proc_list[i].name, - S_IFREG | S_IRUGO, *dev_root); + S_IFREG | S_IRUGO, minor->dev_root); if (!ent) { DRM_ERROR("Cannot create /proc/dri/%s/%s\n", name, drm_proc_list[i].name); for (j = 0; j < i; j++) remove_proc_entry(drm_proc_list[i].name, - *dev_root); + minor->dev_root); remove_proc_entry(name, root); + minor->dev_root = NULL; return -1; } ent->read_proc = drm_proc_list[i].f; - ent->data = dev; + ent->data = minor; } return 0; @@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor, * * Remove all proc entries created by proc_init(). */ -int drm_proc_cleanup(int minor, struct proc_dir_entry *root, - struct proc_dir_entry *dev_root) +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) { int i; char name[64]; - if (!root || !dev_root) + if (!root || !minor->dev_root) return 0; for (i = 0; i < DRM_PROC_ENTRIES; i++) - remove_proc_entry(drm_proc_list[i].name, dev_root); - sprintf(name, "%d", minor); + remove_proc_entry(drm_proc_list[i].name, minor->dev_root); + sprintf(name, "%d", minor->index); remove_proc_entry(name, root); return 0; @@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root, static int drm_name_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; if (offset > DRM_PROC_LIMIT) { @@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request, static int drm__vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_map *map; struct drm_map_list *r_list; @@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, static int drm_vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request, static int drm__queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; int i; struct drm_queue *q; @@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset, static int drm_queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, static int drm__bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_device_dma *dma = dev->dma; int i; @@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request, static int drm_bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, static int drm__clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_file *priv; @@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset, list_for_each_entry(priv, &dev->filelist, lhead) { DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", priv->authenticated ? 'y' : 'n', - priv->minor, + priv->minor->index, priv->pid, priv->uid, priv->magic, priv->ioctl_count); } @@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset, static int drm_clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset, static int drm__vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_vma_entry *pt; struct vm_area_struct *vma; @@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, static int drm_vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index d93a217f856a..c2f584f3b46c 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -36,23 +36,49 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_cards_limit = 16; /* Enough for one machine */ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); -MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); MODULE_PARM_DESC(debug, "Enable debug output"); -module_param_named(cards_limit, drm_cards_limit, int, 0444); module_param_named(debug, drm_debug, int, 0600); -struct drm_head **drm_heads; +struct idr drm_minors_idr; + struct class *drm_class; struct proc_dir_entry *drm_proc_root; +static int drm_minor_get_id(struct drm_device *dev, int type) +{ + int new_id; + int ret; + int base = 0, limit = 63; + +again: + if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Out of memory expanding drawable idr\n"); + return -ENOMEM; + } + mutex_lock(&dev->struct_mutex); + ret = idr_get_new_above(&drm_minors_idr, NULL, + base, &new_id); + mutex_unlock(&dev->struct_mutex); + if (ret == -EAGAIN) { + goto again; + } else if (ret) { + return ret; + } + + if (new_id >= limit) { + idr_remove(&drm_minors_idr, new_id); + return -EINVAL; + } + return new_id; +} + static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_head(struct drm_device * dev, struct drm_head * head) +static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) { - struct drm_head **heads = drm_heads; + struct drm_minor *new_minor; int ret; - int minor; + int minor_id; DRM_DEBUG("\n"); - for (minor = 0; minor < drm_cards_limit; minor++, heads++) { - if (!*heads) { - - *head = (struct drm_head) { - .dev = dev,.device = - MKDEV(DRM_MAJOR, minor),.minor = minor,}; - - if ((ret = - drm_proc_init(dev, minor, drm_proc_root, - &head->dev_root))) { - printk(KERN_ERR - "DRM: Failed to initialize /proc/dri.\n"); - goto err_g1; - } - - ret = drm_sysfs_device_add(dev, head); - if (ret) { - printk(KERN_ERR - "DRM: Error sysfs_device_add.\n"); - goto err_g2; - } - *heads = head; - - DRM_DEBUG("new minor assigned %d\n", minor); - return 0; + minor_id = drm_minor_get_id(dev, type); + if (minor_id < 0) + return minor_id; + + new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); + if (!new_minor) { + ret = -ENOMEM; + goto err_idr; + } + + new_minor->type = type; + new_minor->device = MKDEV(DRM_MAJOR, minor_id); + new_minor->dev = dev; + new_minor->index = minor_id; + + idr_replace(&drm_minors_idr, new_minor, minor_id); + + if (type == DRM_MINOR_LEGACY) { + ret = drm_proc_init(new_minor, minor_id, drm_proc_root); + if (ret) { + DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); + goto err_mem; } + } else + new_minor->dev_root = NULL; + + ret = drm_sysfs_device_add(new_minor); + if (ret) { + printk(KERN_ERR + "DRM: Error sysfs_device_add.\n"); + goto err_g2; } - DRM_ERROR("out of minors\n"); - return -ENOMEM; - err_g2: - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); - err_g1: - *head = (struct drm_head) { - .dev = NULL}; + *minor = new_minor; + + DRM_DEBUG("new minor assigned %d\n", minor_id); + return 0; + + +err_g2: + if (new_minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(new_minor, drm_proc_root); +err_mem: + kfree(new_minor); +err_idr: + idr_remove(&drm_minors_idr, minor_id); + *minor = NULL; return ret; } @@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); goto err_g2; } - if ((ret = drm_get_head(dev, &dev->primary))) + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g2; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, - driver->date, dev->primary.minor); + driver->date, dev->primary->index); return 0; @@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev) * last minor released. * */ -int drm_put_head(struct drm_head * head) +int drm_put_minor(struct drm_minor **minor_p) { - int minor = head->minor; - - DRM_DEBUG("release secondary minor %d\n", minor); - - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); - drm_sysfs_device_remove(head->dev); + struct drm_minor *minor = *minor_p; + DRM_DEBUG("release secondary minor %d\n", minor->index); - *head = (struct drm_head) {.dev = NULL}; + if (minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(minor, drm_proc_root); + drm_sysfs_device_remove(minor); - drm_heads[minor] = NULL; + idr_remove(&drm_minors_idr, minor->index); + kfree(minor); + *minor_p = NULL; return 0; } diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 05ed5043254f..7a1d9a782ddb 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -19,7 +19,7 @@ #include "drm_core.h" #include "drmP.h" -#define to_drm_device(d) container_of(d, struct drm_device, dev) +#define to_drm_minor(d) container_of(d, struct drm_minor, kdev) /** * drm_sysfs_suspend - DRM class suspend hook @@ -31,7 +31,8 @@ */ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; printk(KERN_ERR "%s\n", __FUNCTION__); @@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) */ static int drm_sysfs_resume(struct device *dev) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; if (drm_dev->driver->resume) return drm_dev->driver->resume(drm_dev); @@ -120,10 +122,11 @@ void drm_sysfs_destroy(void) static ssize_t show_dri(struct device *device, struct device_attribute *attr, char *buf) { - struct drm_device *dev = to_drm_device(device); - if (dev->driver->dri_library_name) - return dev->driver->dri_library_name(dev, buf); - return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); + struct drm_minor *drm_minor = to_drm_minor(device); + struct drm_device *drm_dev = drm_minor->dev; + if (drm_dev->driver->dri_library_name) + return drm_dev->driver->dri_library_name(drm_dev, buf); + return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); } static struct device_attribute device_attrs[] = { @@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev) * as the parent for the Linux device, and make sure it has a file containing * the driver we're using (for userspace compatibility). */ -int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) +int drm_sysfs_device_add(struct drm_minor *minor) { int err; int i, j; + char *minor_str; - dev->dev.parent = &dev->pdev->dev; - dev->dev.class = drm_class; - dev->dev.release = drm_sysfs_device_release; - dev->dev.devt = head->device; - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); + minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.class = drm_class; + minor->kdev.release = drm_sysfs_device_release; + minor->kdev.devt = minor->device; + minor_str = "card%d"; - err = device_register(&dev->dev); + snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); + + err = device_register(&minor->kdev); if (err) { DRM_ERROR("device add failed: %d\n", err); goto err_out; } for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - err = device_create_file(&dev->dev, &device_attrs[i]); + err = device_create_file(&minor->kdev, &device_attrs[i]); if (err) goto err_out_files; } @@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) err_out_files: if (i > 0) for (j = 0; j < i; j++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); err_out: return err; @@ -194,11 +200,11 @@ err_out: * This call unregisters and cleans up a class device that was created with a * call to drm_sysfs_device_add() */ -void drm_sysfs_device_remove(struct drm_device *dev) +void drm_sysfs_device_remove(struct drm_minor *minor) { int i; for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); } diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index b20c1e950d3e..c234c6f24a8d 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; struct drm_map_list *r_list; struct drm_hash_item *hash; @@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static void drm_vm_shm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; struct drm_map *map; struct drm_map_list *r_list; @@ -286,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_device_dma *dma = dev->dma; unsigned long offset; unsigned long page_nr; @@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_sg_mem *entry = dev->sg; unsigned long offset; unsigned long map_offset; @@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { static void drm_vm_open_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *vma_entry; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -420,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma) static void drm_vm_open(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; mutex_lock(&dev->struct_mutex); drm_vm_open_locked(vma); @@ -438,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma) static void drm_vm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -473,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) struct drm_device_dma *dma; unsigned long length = vma->vm_end - vma->vm_start; - dev = priv->head->dev; + dev = priv->minor->dev; dma = dev->dma; DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", vma->vm_start, vma->vm_end, vma->vm_pgoff); @@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; unsigned long offset = 0; struct drm_hash_item *hash; @@ -661,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) int drm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 8d7ea81c4b66..e5de8ea41544 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) drm_i810_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->head->dev; + dev = priv->minor->dev; dev_priv = dev->dev_private; buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; @@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = { static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 9df08105f4f3..60c9376be486 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) drm_i830_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->head->dev; + dev = priv->minor->dev; dev_priv = dev->dev_private; buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; @@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = { static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; drm_i830_buf_priv_t *buf_priv = buf->dev_private; drm_i830_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; |