Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dave Airlie and committed by
Dave Airlie
2c14f28b 7b832b56

+230 -184
+20 -22
drivers/char/drm/drmP.h
··· 379 379 struct drm_file { 380 380 int authenticated; 381 381 int master; 382 - int minor; 383 382 pid_t pid; 384 383 uid_t uid; 385 384 drm_magic_t magic; 386 385 unsigned long ioctl_count; 387 386 struct list_head lhead; 388 - struct drm_head *head; 387 + struct drm_minor *minor; 389 388 int remove_auth_on_close; 390 389 unsigned long lock_count; 391 390 struct file *filp; ··· 629 630 struct pci_driver pci_driver; 630 631 }; 631 632 633 + #define DRM_MINOR_UNASSIGNED 0 634 + #define DRM_MINOR_LEGACY 1 635 + 632 636 /** 633 - * DRM head structure. This structure represent a video head on a card 634 - * that may contain multiple heads. Embed one per head of these in the 635 - * private drm_device structure. 637 + * DRM minor structure. This structure represents a drm minor number. 636 638 */ 637 - struct drm_head { 638 - int minor; /**< Minor device number */ 639 + struct drm_minor { 640 + int index; /**< Minor device number */ 641 + int type; /**< Control or render */ 642 + dev_t device; /**< Device number for mknod */ 643 + struct device kdev; /**< Linux device */ 639 644 struct drm_device *dev; 640 645 struct proc_dir_entry *dev_root; /**< proc directory entry */ 641 - dev_t device; /**< Device number for mknod */ 642 646 }; 643 647 644 648 /** ··· 649 647 * may contain multiple heads. 650 648 */ 651 649 struct drm_device { 652 - struct device dev; /**< Linux device */ 653 650 char *unique; /**< Unique identifier: e.g., busid */ 654 651 int unique_len; /**< Length of unique field */ 655 652 char *devname; /**< For /proc/interrupts */ ··· 764 763 struct drm_driver *driver; 765 764 drm_local_map_t *agp_buffer_map; 766 765 unsigned int agp_buffer_token; 767 - struct drm_head primary; /**< primary screen head */ 766 + struct drm_minor *primary; /**< render type primary screen head */ 768 767 769 768 /** \name Drawable information */ 770 769 /*@{ */ ··· 1031 1030 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, 1032 1031 struct drm_driver *driver); 1033 1032 extern int drm_put_dev(struct drm_device *dev); 1034 - extern int drm_put_head(struct drm_head *head); 1033 + extern int drm_put_minor(struct drm_minor **minor); 1035 1034 extern unsigned int drm_debug; 1036 - extern unsigned int drm_cards_limit; 1037 - extern struct drm_head **drm_heads; 1035 + 1038 1036 extern struct class *drm_class; 1039 1037 extern struct proc_dir_entry *drm_proc_root; 1038 + 1039 + extern struct idr drm_minors_idr; 1040 1040 1041 1041 extern drm_local_map_t *drm_getsarea(struct drm_device *dev); 1042 1042 1043 1043 /* Proc support (drm_proc.h) */ 1044 - extern int drm_proc_init(struct drm_device *dev, 1045 - int minor, 1046 - struct proc_dir_entry *root, 1047 - struct proc_dir_entry **dev_root); 1048 - extern int drm_proc_cleanup(int minor, 1049 - struct proc_dir_entry *root, 1050 - struct proc_dir_entry *dev_root); 1044 + extern int drm_proc_init(struct drm_minor *minor, int minor_id, 1045 + struct proc_dir_entry *root); 1046 + extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root); 1051 1047 1052 1048 /* Scatter Gather Support (drm_scatter.h) */ 1053 1049 extern void drm_sg_cleanup(struct drm_sg_mem * entry); ··· 1069 1071 struct drm_sysfs_class; 1070 1072 extern struct class *drm_sysfs_create(struct module *owner, char *name); 1071 1073 extern void drm_sysfs_destroy(void); 1072 - extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head); 1073 - extern void drm_sysfs_device_remove(struct drm_device *dev); 1074 + extern int drm_sysfs_device_add(struct drm_minor *minor); 1075 + extern void drm_sysfs_device_remove(struct drm_minor *minor); 1074 1076 1075 1077 /* 1076 1078 * Basic memory manager support (drm_mm.c)
+1 -1
drivers/char/drm/drm_agpsupport.c
··· 122 122 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, 123 123 struct drm_file *file_priv) 124 124 { 125 - return drm_agp_acquire((struct drm_device *) file_priv->head->dev); 125 + return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); 126 126 } 127 127 128 128 /**
+28 -32
drivers/char/drm/drm_drv.c
··· 313 313 drm_ht_remove(&dev->map_hash); 314 314 drm_ctxbitmap_cleanup(dev); 315 315 316 - drm_put_head(&dev->primary); 316 + drm_put_minor(&dev->primary); 317 317 if (drm_put_dev(dev)) 318 318 DRM_ERROR("Cannot unload module\n"); 319 319 } 320 320 321 + int drm_minors_cleanup(int id, void *ptr, void *data) 322 + { 323 + struct drm_minor *minor = ptr; 324 + struct drm_device *dev; 325 + struct drm_driver *driver = data; 326 + 327 + dev = minor->dev; 328 + if (minor->dev->driver != driver) 329 + return 0; 330 + 331 + if (minor->type != DRM_MINOR_LEGACY) 332 + return 0; 333 + 334 + if (dev) 335 + pci_dev_put(dev->pdev); 336 + drm_cleanup(dev); 337 + return 1; 338 + } 339 + 321 340 void drm_exit(struct drm_driver *driver) 322 341 { 323 - int i; 324 - struct drm_device *dev = NULL; 325 - struct drm_head *head; 326 - 327 342 DRM_DEBUG("\n"); 328 343 329 - for (i = 0; i < drm_cards_limit; i++) { 330 - head = drm_heads[i]; 331 - if (!head) 332 - continue; 333 - if (!head->dev) 334 - continue; 335 - if (head->dev->driver != driver) 336 - continue; 337 - dev = head->dev; 338 - if (dev) { 339 - /* release the pci driver */ 340 - if (dev->pdev) 341 - pci_dev_put(dev->pdev); 342 - drm_cleanup(dev); 343 - } 344 - } 344 + idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); 345 + 345 346 DRM_INFO("Module unloaded\n"); 346 347 } 347 348 ··· 358 357 { 359 358 int ret = -ENOMEM; 360 359 361 - drm_cards_limit = 362 - (drm_cards_limit < 363 - DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1); 364 - drm_heads = 365 - drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB); 366 - if (!drm_heads) 367 - goto err_p1; 360 + idr_init(&drm_minors_idr); 368 361 369 362 if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) 370 363 goto err_p1; ··· 386 391 drm_sysfs_destroy(); 387 392 err_p2: 388 393 unregister_chrdev(DRM_MAJOR, "drm"); 389 - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); 394 + 395 + idr_destroy(&drm_minors_idr); 390 396 err_p1: 391 397 return ret; 392 398 } ··· 399 403 400 404 unregister_chrdev(DRM_MAJOR, "drm"); 401 405 402 - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); 406 + idr_destroy(&drm_minors_idr); 403 407 } 404 408 405 409 module_init(drm_core_init); ··· 448 452 unsigned int cmd, unsigned long arg) 449 453 { 450 454 struct drm_file *file_priv = filp->private_data; 451 - struct drm_device *dev = file_priv->head->dev; 455 + struct drm_device *dev = file_priv->minor->dev; 452 456 struct drm_ioctl_desc *ioctl; 453 457 drm_ioctl_t *func; 454 458 unsigned int nr = DRM_IOCTL_NR(cmd); ··· 461 465 462 466 DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", 463 467 task_pid_nr(current), cmd, nr, 464 - (long)old_encode_dev(file_priv->head->device), 468 + (long)old_encode_dev(file_priv->minor->device), 465 469 file_priv->authenticated); 466 470 467 471 if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+17 -20
drivers/char/drm/drm_fops.c
··· 129 129 int drm_open(struct inode *inode, struct file *filp) 130 130 { 131 131 struct drm_device *dev = NULL; 132 - int minor = iminor(inode); 132 + int minor_id = iminor(inode); 133 + struct drm_minor *minor; 133 134 int retcode = 0; 134 135 135 - if (!((minor >= 0) && (minor < drm_cards_limit))) 136 + minor = idr_find(&drm_minors_idr, minor_id); 137 + if (!minor) 136 138 return -ENODEV; 137 139 138 - if (!drm_heads[minor]) 139 - return -ENODEV; 140 - 141 - if (!(dev = drm_heads[minor]->dev)) 140 + if (!(dev = minor->dev)) 142 141 return -ENODEV; 143 142 144 143 retcode = drm_open_helper(inode, filp, dev); ··· 167 168 int drm_stub_open(struct inode *inode, struct file *filp) 168 169 { 169 170 struct drm_device *dev = NULL; 170 - int minor = iminor(inode); 171 + struct drm_minor *minor; 172 + int minor_id = iminor(inode); 171 173 int err = -ENODEV; 172 174 const struct file_operations *old_fops; 173 175 174 176 DRM_DEBUG("\n"); 175 177 176 - if (!((minor >= 0) && (minor < drm_cards_limit))) 178 + minor = idr_find(&drm_minors_idr, minor_id); 179 + if (!minor) 177 180 return -ENODEV; 178 181 179 - if (!drm_heads[minor]) 180 - return -ENODEV; 181 - 182 - if (!(dev = drm_heads[minor]->dev)) 182 + if (!(dev = minor->dev)) 183 183 return -ENODEV; 184 184 185 185 old_fops = filp->f_op; ··· 223 225 static int drm_open_helper(struct inode *inode, struct file *filp, 224 226 struct drm_device * dev) 225 227 { 226 - int minor = iminor(inode); 228 + int minor_id = iminor(inode); 227 229 struct drm_file *priv; 228 230 int ret; 229 231 ··· 232 234 if (!drm_cpu_valid()) 233 235 return -EINVAL; 234 236 235 - DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor); 237 + DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); 236 238 237 239 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); 238 240 if (!priv) ··· 243 245 priv->filp = filp; 244 246 priv->uid = current->euid; 245 247 priv->pid = task_pid_nr(current); 246 - priv->minor = minor; 247 - priv->head = drm_heads[minor]; 248 + priv->minor = idr_find(&drm_minors_idr, minor_id); 248 249 priv->ioctl_count = 0; 249 250 /* for compatibility root is always authenticated */ 250 251 priv->authenticated = capable(CAP_SYS_ADMIN); ··· 294 297 int drm_fasync(int fd, struct file *filp, int on) 295 298 { 296 299 struct drm_file *priv = filp->private_data; 297 - struct drm_device *dev = priv->head->dev; 300 + struct drm_device *dev = priv->minor->dev; 298 301 int retcode; 299 302 300 303 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, 301 - (long)old_encode_dev(priv->head->device)); 304 + (long)old_encode_dev(priv->minor->device)); 302 305 retcode = fasync_helper(fd, filp, on, &dev->buf_async); 303 306 if (retcode < 0) 304 307 return retcode; ··· 321 324 int drm_release(struct inode *inode, struct file *filp) 322 325 { 323 326 struct drm_file *file_priv = filp->private_data; 324 - struct drm_device *dev = file_priv->head->dev; 327 + struct drm_device *dev = file_priv->minor->dev; 325 328 int retcode = 0; 326 329 unsigned long irqflags; 327 330 ··· 338 341 339 342 DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", 340 343 task_pid_nr(current), 341 - (long)old_encode_dev(file_priv->head->device), 344 + (long)old_encode_dev(file_priv->minor->device), 342 345 dev->open_count); 343 346 344 347 if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+36 -25
drivers/char/drm/drm_proc.c
··· 87 87 * "/proc/dri/%minor%/", and each entry in proc_list as 88 88 * "/proc/dri/%minor%/%name%". 89 89 */ 90 - int drm_proc_init(struct drm_device * dev, int minor, 91 - struct proc_dir_entry *root, struct proc_dir_entry **dev_root) 90 + int drm_proc_init(struct drm_minor *minor, int minor_id, 91 + struct proc_dir_entry *root) 92 92 { 93 93 struct proc_dir_entry *ent; 94 94 int i, j; 95 95 char name[64]; 96 96 97 - sprintf(name, "%d", minor); 98 - *dev_root = proc_mkdir(name, root); 99 - if (!*dev_root) { 97 + sprintf(name, "%d", minor_id); 98 + minor->dev_root = proc_mkdir(name, root); 99 + if (!minor->dev_root) { 100 100 DRM_ERROR("Cannot create /proc/dri/%s\n", name); 101 101 return -1; 102 102 } 103 103 104 104 for (i = 0; i < DRM_PROC_ENTRIES; i++) { 105 105 ent = create_proc_entry(drm_proc_list[i].name, 106 - S_IFREG | S_IRUGO, *dev_root); 106 + S_IFREG | S_IRUGO, minor->dev_root); 107 107 if (!ent) { 108 108 DRM_ERROR("Cannot create /proc/dri/%s/%s\n", 109 109 name, drm_proc_list[i].name); 110 110 for (j = 0; j < i; j++) 111 111 remove_proc_entry(drm_proc_list[i].name, 112 - *dev_root); 112 + minor->dev_root); 113 113 remove_proc_entry(name, root); 114 + minor->dev_root = NULL; 114 115 return -1; 115 116 } 116 117 ent->read_proc = drm_proc_list[i].f; 117 - ent->data = dev; 118 + ent->data = minor; 118 119 } 119 120 120 121 return 0; ··· 131 130 * 132 131 * Remove all proc entries created by proc_init(). 133 132 */ 134 - int drm_proc_cleanup(int minor, struct proc_dir_entry *root, 135 - struct proc_dir_entry *dev_root) 133 + int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) 136 134 { 137 135 int i; 138 136 char name[64]; 139 137 140 - if (!root || !dev_root) 138 + if (!root || !minor->dev_root) 141 139 return 0; 142 140 143 141 for (i = 0; i < DRM_PROC_ENTRIES; i++) 144 - remove_proc_entry(drm_proc_list[i].name, dev_root); 145 - sprintf(name, "%d", minor); 142 + remove_proc_entry(drm_proc_list[i].name, minor->dev_root); 143 + sprintf(name, "%d", minor->index); 146 144 remove_proc_entry(name, root); 147 145 148 146 return 0; ··· 163 163 static int drm_name_info(char *buf, char **start, off_t offset, int request, 164 164 int *eof, void *data) 165 165 { 166 - struct drm_device *dev = (struct drm_device *) data; 166 + struct drm_minor *minor = (struct drm_minor *) data; 167 + struct drm_device *dev = minor->dev; 167 168 int len = 0; 168 169 169 170 if (offset > DRM_PROC_LIMIT) { ··· 206 205 static int drm__vm_info(char *buf, char **start, off_t offset, int request, 207 206 int *eof, void *data) 208 207 { 209 - struct drm_device *dev = (struct drm_device *) data; 208 + struct drm_minor *minor = (struct drm_minor *) data; 209 + struct drm_device *dev = minor->dev; 210 210 int len = 0; 211 211 struct drm_map *map; 212 212 struct drm_map_list *r_list; ··· 263 261 static int drm_vm_info(char *buf, char **start, off_t offset, int request, 264 262 int *eof, void *data) 265 263 { 266 - struct drm_device *dev = (struct drm_device *) data; 264 + struct drm_minor *minor = (struct drm_minor *) data; 265 + struct drm_device *dev = minor->dev; 267 266 int ret; 268 267 269 268 mutex_lock(&dev->struct_mutex); ··· 287 284 static int drm__queues_info(char *buf, char **start, off_t offset, 288 285 int request, int *eof, void *data) 289 286 { 290 - struct drm_device *dev = (struct drm_device *) data; 287 + struct drm_minor *minor = (struct drm_minor *) data; 288 + struct drm_device *dev = minor->dev; 291 289 int len = 0; 292 290 int i; 293 291 struct drm_queue *q; ··· 338 334 static int drm_queues_info(char *buf, char **start, off_t offset, int request, 339 335 int *eof, void *data) 340 336 { 341 - struct drm_device *dev = (struct drm_device *) data; 337 + struct drm_minor *minor = (struct drm_minor *) data; 338 + struct drm_device *dev = minor->dev; 342 339 int ret; 343 340 344 341 mutex_lock(&dev->struct_mutex); ··· 362 357 static int drm__bufs_info(char *buf, char **start, off_t offset, int request, 363 358 int *eof, void *data) 364 359 { 365 - struct drm_device *dev = (struct drm_device *) data; 360 + struct drm_minor *minor = (struct drm_minor *) data; 361 + struct drm_device *dev = minor->dev; 366 362 int len = 0; 367 363 struct drm_device_dma *dma = dev->dma; 368 364 int i; ··· 412 406 static int drm_bufs_info(char *buf, char **start, off_t offset, int request, 413 407 int *eof, void *data) 414 408 { 415 - struct drm_device *dev = (struct drm_device *) data; 409 + struct drm_minor *minor = (struct drm_minor *) data; 410 + struct drm_device *dev = minor->dev; 416 411 int ret; 417 412 418 413 mutex_lock(&dev->struct_mutex); ··· 436 429 static int drm__clients_info(char *buf, char **start, off_t offset, 437 430 int request, int *eof, void *data) 438 431 { 439 - struct drm_device *dev = (struct drm_device *) data; 432 + struct drm_minor *minor = (struct drm_minor *) data; 433 + struct drm_device *dev = minor->dev; 440 434 int len = 0; 441 435 struct drm_file *priv; 442 436 ··· 453 445 list_for_each_entry(priv, &dev->filelist, lhead) { 454 446 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", 455 447 priv->authenticated ? 'y' : 'n', 456 - priv->minor, 448 + priv->minor->index, 457 449 priv->pid, 458 450 priv->uid, priv->magic, priv->ioctl_count); 459 451 } ··· 470 462 static int drm_clients_info(char *buf, char **start, off_t offset, 471 463 int request, int *eof, void *data) 472 464 { 473 - struct drm_device *dev = (struct drm_device *) data; 465 + struct drm_minor *minor = (struct drm_minor *) data; 466 + struct drm_device *dev = minor->dev; 474 467 int ret; 475 468 476 469 mutex_lock(&dev->struct_mutex); ··· 485 476 static int drm__vma_info(char *buf, char **start, off_t offset, int request, 486 477 int *eof, void *data) 487 478 { 488 - struct drm_device *dev = (struct drm_device *) data; 479 + struct drm_minor *minor = (struct drm_minor *) data; 480 + struct drm_device *dev = minor->dev; 489 481 int len = 0; 490 482 struct drm_vma_entry *pt; 491 483 struct vm_area_struct *vma; ··· 545 535 static int drm_vma_info(char *buf, char **start, off_t offset, int request, 546 536 int *eof, void *data) 547 537 { 548 - struct drm_device *dev = (struct drm_device *) data; 538 + struct drm_minor *minor = (struct drm_minor *) data; 539 + struct drm_device *dev = minor->dev; 549 540 int ret; 550 541 551 542 mutex_lock(&dev->struct_mutex);
+88 -50
drivers/char/drm/drm_stub.c
··· 36 36 #include "drmP.h" 37 37 #include "drm_core.h" 38 38 39 - unsigned int drm_cards_limit = 16; /* Enough for one machine */ 40 39 unsigned int drm_debug = 0; /* 1 to enable debug output */ 41 40 EXPORT_SYMBOL(drm_debug); 42 41 43 42 MODULE_AUTHOR(CORE_AUTHOR); 44 43 MODULE_DESCRIPTION(CORE_DESC); 45 44 MODULE_LICENSE("GPL and additional rights"); 46 - MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); 47 45 MODULE_PARM_DESC(debug, "Enable debug output"); 48 46 49 - module_param_named(cards_limit, drm_cards_limit, int, 0444); 50 47 module_param_named(debug, drm_debug, int, 0600); 51 48 52 - struct drm_head **drm_heads; 49 + struct idr drm_minors_idr; 50 + 53 51 struct class *drm_class; 54 52 struct proc_dir_entry *drm_proc_root; 53 + 54 + static int drm_minor_get_id(struct drm_device *dev, int type) 55 + { 56 + int new_id; 57 + int ret; 58 + int base = 0, limit = 63; 59 + 60 + again: 61 + if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { 62 + DRM_ERROR("Out of memory expanding drawable idr\n"); 63 + return -ENOMEM; 64 + } 65 + mutex_lock(&dev->struct_mutex); 66 + ret = idr_get_new_above(&drm_minors_idr, NULL, 67 + base, &new_id); 68 + mutex_unlock(&dev->struct_mutex); 69 + if (ret == -EAGAIN) { 70 + goto again; 71 + } else if (ret) { 72 + return ret; 73 + } 74 + 75 + if (new_id >= limit) { 76 + idr_remove(&drm_minors_idr, new_id); 77 + return -EINVAL; 78 + } 79 + return new_id; 80 + } 55 81 56 82 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, 57 83 const struct pci_device_id *ent, ··· 171 145 * create the proc init entry via proc_init(). This routines assigns 172 146 * minor numbers to secondary heads of multi-headed cards 173 147 */ 174 - static int drm_get_head(struct drm_device * dev, struct drm_head * head) 148 + static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) 175 149 { 176 - struct drm_head **heads = drm_heads; 150 + struct drm_minor *new_minor; 177 151 int ret; 178 - int minor; 152 + int minor_id; 179 153 180 154 DRM_DEBUG("\n"); 181 155 182 - for (minor = 0; minor < drm_cards_limit; minor++, heads++) { 183 - if (!*heads) { 156 + minor_id = drm_minor_get_id(dev, type); 157 + if (minor_id < 0) 158 + return minor_id; 184 159 185 - *head = (struct drm_head) { 186 - .dev = dev,.device = 187 - MKDEV(DRM_MAJOR, minor),.minor = minor,}; 188 - 189 - if ((ret = 190 - drm_proc_init(dev, minor, drm_proc_root, 191 - &head->dev_root))) { 192 - printk(KERN_ERR 193 - "DRM: Failed to initialize /proc/dri.\n"); 194 - goto err_g1; 195 - } 196 - 197 - ret = drm_sysfs_device_add(dev, head); 198 - if (ret) { 199 - printk(KERN_ERR 200 - "DRM: Error sysfs_device_add.\n"); 201 - goto err_g2; 202 - } 203 - *heads = head; 204 - 205 - DRM_DEBUG("new minor assigned %d\n", minor); 206 - return 0; 207 - } 160 + new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); 161 + if (!new_minor) { 162 + ret = -ENOMEM; 163 + goto err_idr; 208 164 } 209 - DRM_ERROR("out of minors\n"); 210 - return -ENOMEM; 211 - err_g2: 212 - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); 213 - err_g1: 214 - *head = (struct drm_head) { 215 - .dev = NULL}; 165 + 166 + new_minor->type = type; 167 + new_minor->device = MKDEV(DRM_MAJOR, minor_id); 168 + new_minor->dev = dev; 169 + new_minor->index = minor_id; 170 + 171 + idr_replace(&drm_minors_idr, new_minor, minor_id); 172 + 173 + if (type == DRM_MINOR_LEGACY) { 174 + ret = drm_proc_init(new_minor, minor_id, drm_proc_root); 175 + if (ret) { 176 + DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); 177 + goto err_mem; 178 + } 179 + } else 180 + new_minor->dev_root = NULL; 181 + 182 + ret = drm_sysfs_device_add(new_minor); 183 + if (ret) { 184 + printk(KERN_ERR 185 + "DRM: Error sysfs_device_add.\n"); 186 + goto err_g2; 187 + } 188 + *minor = new_minor; 189 + 190 + DRM_DEBUG("new minor assigned %d\n", minor_id); 191 + return 0; 192 + 193 + 194 + err_g2: 195 + if (new_minor->type == DRM_MINOR_LEGACY) 196 + drm_proc_cleanup(new_minor, drm_proc_root); 197 + err_mem: 198 + kfree(new_minor); 199 + err_idr: 200 + idr_remove(&drm_minors_idr, minor_id); 201 + *minor = NULL; 216 202 return ret; 217 203 } 218 204 ··· 260 222 printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); 261 223 goto err_g2; 262 224 } 263 - if ((ret = drm_get_head(dev, &dev->primary))) 225 + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) 264 226 goto err_g2; 265 227 266 228 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", 267 229 driver->name, driver->major, driver->minor, driver->patchlevel, 268 - driver->date, dev->primary.minor); 230 + driver->date, dev->primary->index); 269 231 270 232 return 0; 271 233 ··· 314 276 * last minor released. 315 277 * 316 278 */ 317 - int drm_put_head(struct drm_head * head) 279 + int drm_put_minor(struct drm_minor **minor_p) 318 280 { 319 - int minor = head->minor; 281 + struct drm_minor *minor = *minor_p; 282 + DRM_DEBUG("release secondary minor %d\n", minor->index); 320 283 321 - DRM_DEBUG("release secondary minor %d\n", minor); 284 + if (minor->type == DRM_MINOR_LEGACY) 285 + drm_proc_cleanup(minor, drm_proc_root); 286 + drm_sysfs_device_remove(minor); 322 287 323 - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); 324 - drm_sysfs_device_remove(head->dev); 288 + idr_remove(&drm_minors_idr, minor->index); 325 289 326 - *head = (struct drm_head) {.dev = NULL}; 327 - 328 - drm_heads[minor] = NULL; 329 - 290 + kfree(minor); 291 + *minor_p = NULL; 330 292 return 0; 331 293 }
+26 -20
drivers/char/drm/drm_sysfs.c
··· 19 19 #include "drm_core.h" 20 20 #include "drmP.h" 21 21 22 - #define to_drm_device(d) container_of(d, struct drm_device, dev) 22 + #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) 23 23 24 24 /** 25 25 * drm_sysfs_suspend - DRM class suspend hook ··· 31 31 */ 32 32 static int drm_sysfs_suspend(struct device *dev, pm_message_t state) 33 33 { 34 - struct drm_device *drm_dev = to_drm_device(dev); 34 + struct drm_minor *drm_minor = to_drm_minor(dev); 35 + struct drm_device *drm_dev = drm_minor->dev; 35 36 36 37 printk(KERN_ERR "%s\n", __FUNCTION__); 37 38 ··· 51 50 */ 52 51 static int drm_sysfs_resume(struct device *dev) 53 52 { 54 - struct drm_device *drm_dev = to_drm_device(dev); 53 + struct drm_minor *drm_minor = to_drm_minor(dev); 54 + struct drm_device *drm_dev = drm_minor->dev; 55 55 56 56 if (drm_dev->driver->resume) 57 57 return drm_dev->driver->resume(drm_dev); ··· 122 120 static ssize_t show_dri(struct device *device, struct device_attribute *attr, 123 121 char *buf) 124 122 { 125 - struct drm_device *dev = to_drm_device(device); 126 - if (dev->driver->dri_library_name) 127 - return dev->driver->dri_library_name(dev, buf); 128 - return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); 123 + struct drm_minor *drm_minor = to_drm_minor(device); 124 + struct drm_device *drm_dev = drm_minor->dev; 125 + if (drm_dev->driver->dri_library_name) 126 + return drm_dev->driver->dri_library_name(drm_dev, buf); 127 + return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); 129 128 } 130 129 131 130 static struct device_attribute device_attrs[] = { ··· 155 152 * as the parent for the Linux device, and make sure it has a file containing 156 153 * the driver we're using (for userspace compatibility). 157 154 */ 158 - int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) 155 + int drm_sysfs_device_add(struct drm_minor *minor) 159 156 { 160 157 int err; 161 158 int i, j; 159 + char *minor_str; 162 160 163 - dev->dev.parent = &dev->pdev->dev; 164 - dev->dev.class = drm_class; 165 - dev->dev.release = drm_sysfs_device_release; 166 - dev->dev.devt = head->device; 167 - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); 161 + minor->kdev.parent = &minor->dev->pdev->dev; 162 + minor->kdev.class = drm_class; 163 + minor->kdev.release = drm_sysfs_device_release; 164 + minor->kdev.devt = minor->device; 165 + minor_str = "card%d"; 168 166 169 - err = device_register(&dev->dev); 167 + snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); 168 + 169 + err = device_register(&minor->kdev); 170 170 if (err) { 171 171 DRM_ERROR("device add failed: %d\n", err); 172 172 goto err_out; 173 173 } 174 174 175 175 for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { 176 - err = device_create_file(&dev->dev, &device_attrs[i]); 176 + err = device_create_file(&minor->kdev, &device_attrs[i]); 177 177 if (err) 178 178 goto err_out_files; 179 179 } ··· 186 180 err_out_files: 187 181 if (i > 0) 188 182 for (j = 0; j < i; j++) 189 - device_remove_file(&dev->dev, &device_attrs[i]); 190 - device_unregister(&dev->dev); 183 + device_remove_file(&minor->kdev, &device_attrs[i]); 184 + device_unregister(&minor->kdev); 191 185 err_out: 192 186 193 187 return err; ··· 200 194 * This call unregisters and cleans up a class device that was created with a 201 195 * call to drm_sysfs_device_add() 202 196 */ 203 - void drm_sysfs_device_remove(struct drm_device *dev) 197 + void drm_sysfs_device_remove(struct drm_minor *minor) 204 198 { 205 199 int i; 206 200 207 201 for (i = 0; i < ARRAY_SIZE(device_attrs); i++) 208 - device_remove_file(&dev->dev, &device_attrs[i]); 209 - device_unregister(&dev->dev); 202 + device_remove_file(&minor->kdev, &device_attrs[i]); 203 + device_unregister(&minor->kdev); 210 204 }
+10 -10
drivers/char/drm/drm_vm.c
··· 90 90 static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 91 91 { 92 92 struct drm_file *priv = vma->vm_file->private_data; 93 - struct drm_device *dev = priv->head->dev; 93 + struct drm_device *dev = priv->minor->dev; 94 94 struct drm_map *map = NULL; 95 95 struct drm_map_list *r_list; 96 96 struct drm_hash_item *hash; ··· 207 207 static void drm_vm_shm_close(struct vm_area_struct *vma) 208 208 { 209 209 struct drm_file *priv = vma->vm_file->private_data; 210 - struct drm_device *dev = priv->head->dev; 210 + struct drm_device *dev = priv->minor->dev; 211 211 struct drm_vma_entry *pt, *temp; 212 212 struct drm_map *map; 213 213 struct drm_map_list *r_list; ··· 286 286 static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 287 287 { 288 288 struct drm_file *priv = vma->vm_file->private_data; 289 - struct drm_device *dev = priv->head->dev; 289 + struct drm_device *dev = priv->minor->dev; 290 290 struct drm_device_dma *dma = dev->dma; 291 291 unsigned long offset; 292 292 unsigned long page_nr; ··· 321 321 { 322 322 struct drm_map *map = (struct drm_map *) vma->vm_private_data; 323 323 struct drm_file *priv = vma->vm_file->private_data; 324 - struct drm_device *dev = priv->head->dev; 324 + struct drm_device *dev = priv->minor->dev; 325 325 struct drm_sg_mem *entry = dev->sg; 326 326 unsigned long offset; 327 327 unsigned long map_offset; ··· 402 402 static void drm_vm_open_locked(struct vm_area_struct *vma) 403 403 { 404 404 struct drm_file *priv = vma->vm_file->private_data; 405 - struct drm_device *dev = priv->head->dev; 405 + struct drm_device *dev = priv->minor->dev; 406 406 struct drm_vma_entry *vma_entry; 407 407 408 408 DRM_DEBUG("0x%08lx,0x%08lx\n", ··· 420 420 static void drm_vm_open(struct vm_area_struct *vma) 421 421 { 422 422 struct drm_file *priv = vma->vm_file->private_data; 423 - struct drm_device *dev = priv->head->dev; 423 + struct drm_device *dev = priv->minor->dev; 424 424 425 425 mutex_lock(&dev->struct_mutex); 426 426 drm_vm_open_locked(vma); ··· 438 438 static void drm_vm_close(struct vm_area_struct *vma) 439 439 { 440 440 struct drm_file *priv = vma->vm_file->private_data; 441 - struct drm_device *dev = priv->head->dev; 441 + struct drm_device *dev = priv->minor->dev; 442 442 struct drm_vma_entry *pt, *temp; 443 443 444 444 DRM_DEBUG("0x%08lx,0x%08lx\n", ··· 473 473 struct drm_device_dma *dma; 474 474 unsigned long length = vma->vm_end - vma->vm_start; 475 475 476 - dev = priv->head->dev; 476 + dev = priv->minor->dev; 477 477 dma = dev->dma; 478 478 DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", 479 479 vma->vm_start, vma->vm_end, vma->vm_pgoff); ··· 543 543 static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) 544 544 { 545 545 struct drm_file *priv = filp->private_data; 546 - struct drm_device *dev = priv->head->dev; 546 + struct drm_device *dev = priv->minor->dev; 547 547 struct drm_map *map = NULL; 548 548 unsigned long offset = 0; 549 549 struct drm_hash_item *hash; ··· 661 661 int drm_mmap(struct file *filp, struct vm_area_struct *vma) 662 662 { 663 663 struct drm_file *priv = filp->private_data; 664 - struct drm_device *dev = priv->head->dev; 664 + struct drm_device *dev = priv->minor->dev; 665 665 int ret; 666 666 667 667 mutex_lock(&dev->struct_mutex);
+2 -2
drivers/char/drm/i810_dma.c
··· 94 94 drm_i810_buf_priv_t *buf_priv; 95 95 96 96 lock_kernel(); 97 - dev = priv->head->dev; 97 + dev = priv->minor->dev; 98 98 dev_priv = dev->dev_private; 99 99 buf = dev_priv->mmap_buffer; 100 100 buf_priv = buf->dev_private; ··· 122 122 123 123 static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) 124 124 { 125 - struct drm_device *dev = file_priv->head->dev; 125 + struct drm_device *dev = file_priv->minor->dev; 126 126 drm_i810_buf_priv_t *buf_priv = buf->dev_private; 127 127 drm_i810_private_t *dev_priv = dev->dev_private; 128 128 const struct file_operations *old_fops;
+2 -2
drivers/char/drm/i830_dma.c
··· 96 96 drm_i830_buf_priv_t *buf_priv; 97 97 98 98 lock_kernel(); 99 - dev = priv->head->dev; 99 + dev = priv->minor->dev; 100 100 dev_priv = dev->dev_private; 101 101 buf = dev_priv->mmap_buffer; 102 102 buf_priv = buf->dev_private; ··· 124 124 125 125 static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) 126 126 { 127 - struct drm_device *dev = file_priv->head->dev; 127 + struct drm_device *dev = file_priv->minor->dev; 128 128 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 129 129 drm_i830_private_t *dev_priv = dev->dev_private; 130 130 const struct file_operations *old_fops;