X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fdrm%2Fdrm_stub.c;h=120d10256feb6d5371da2d3c9652f8e26ce73aa4;hb=refs%2Fheads%2Fvserver;hp=1ff42134ebaae2c7446486de4190e24d0ccf9109;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 1ff42134e..120d10256 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -37,134 +37,161 @@ #include "drm_core.h" unsigned int drm_cards_limit = 16; /* Enough for one machine */ -unsigned int drm_debug = 0; /* 1 to enable debug output */ +unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(CORE_AUTHOR); +MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); -MODULE_PARM_DESC(drm_cards_limit, "Maximum number of graphics cards"); -MODULE_PARM_DESC(drm_debug, "Enable debug output"); +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, 0666); +module_param_named(debug, drm_debug, int, 0600); -drm_minor_t *drm_minors; -struct drm_sysfs_class *drm_class; +drm_head_t **drm_heads; +struct class *drm_class; struct proc_dir_entry *drm_proc_root; -static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) +static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, + const struct pci_device_id *ent, + struct drm_driver *driver) { int retcode; spin_lock_init(&dev->count_lock); - init_timer( &dev->timer ); - sema_init( &dev->struct_sem, 1 ); - sema_init( &dev->ctxlist_sem, 1 ); + spin_lock_init(&dev->drw_lock); + spin_lock_init(&dev->tasklet_lock); + init_timer(&dev->timer); + mutex_init(&dev->struct_mutex); + mutex_init(&dev->ctxlist_mutex); - dev->pdev = pdev; + dev->pdev = pdev; + dev->pci_device = pdev->device; + dev->pci_vendor = pdev->vendor; #ifdef __alpha__ - dev->hose = pdev->sysdata; - dev->pci_domain = dev->hose->bus->number; -#else - dev->pci_domain = 0; + dev->hose = pdev->sysdata; #endif - dev->pci_bus = pdev->bus->number; - dev->pci_slot = PCI_SLOT(pdev->devfn); - dev->pci_func = PCI_FUNC(pdev->devfn); dev->irq = pdev->irq; + dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); + if (dev->maplist == NULL) + return -ENOMEM; + INIT_LIST_HEAD(&dev->maplist->head); + if (drm_ht_create(&dev->map_hash, 12)) { + drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); + return -ENOMEM; + } + /* the DRM has 6 basic counters */ dev->counters = 6; - dev->types[0] = _DRM_STAT_LOCK; - dev->types[1] = _DRM_STAT_OPENS; - dev->types[2] = _DRM_STAT_CLOSES; - dev->types[3] = _DRM_STAT_IOCTLS; - dev->types[4] = _DRM_STAT_LOCKS; - dev->types[5] = _DRM_STAT_UNLOCKS; + dev->types[0] = _DRM_STAT_LOCK; + dev->types[1] = _DRM_STAT_OPENS; + dev->types[2] = _DRM_STAT_CLOSES; + dev->types[3] = _DRM_STAT_IOCTLS; + dev->types[4] = _DRM_STAT_LOCKS; + dev->types[5] = _DRM_STAT_UNLOCKS; dev->driver = driver; - - if (dev->driver->preinit) - if ((retcode = dev->driver->preinit(dev, ent->driver_data))) + + if (dev->driver->load) + if ((retcode = dev->driver->load(dev, ent->driver_data))) goto error_out_unreg; if (drm_core_has_AGP(dev)) { - dev->agp = drm_agp_init(); - if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { - DRM_ERROR( "Cannot initialize the agpgart module.\n" ); + if (drm_device_is_agp(dev)) + dev->agp = drm_agp_init(dev); + if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) + && (dev->agp == NULL)) { + DRM_ERROR("Cannot initialize the agpgart module.\n"); retcode = -EINVAL; goto error_out_unreg; } if (drm_core_has_MTRR(dev)) { if (dev->agp) - dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, - dev->agp->agp_info.aper_size*1024*1024, - MTRR_TYPE_WRCOMB, - 1 ); + dev->agp->agp_mtrr = + mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size * + 1024 * 1024, MTRR_TYPE_WRCOMB, 1); } } - retcode = drm_ctxbitmap_init( dev ); - if( retcode ) { - DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); + retcode = drm_ctxbitmap_init(dev); + if (retcode) { + DRM_ERROR("Cannot allocate memory for context bitmap.\n"); goto error_out_unreg; } - dev->device = MKDEV(DRM_MAJOR, dev->minor ); - - /* postinit is a required function to display the signon banner */ - if ((retcode = dev->driver->postinit(dev, ent->driver_data))) - goto error_out_unreg; - return 0; - -error_out_unreg: - drm_takedown(dev); + + error_out_unreg: + drm_lastclose(dev); return retcode; } + /** - * File \c open operation. + * Get a secondary minor number. * - * \param inode device inode. - * \param filp file pointer. + * \param dev device data structure + * \param sec-minor structure to hold the assigned minor + * \return negative number on failure. * - * Puts the dev->fops corresponding to the device minor number into - * \p filp, call the \c open method, and restore the file operations. + * Search an empty entry and initialize it to the given parameters, and + * create the proc init entry via proc_init(). This routines assigns + * minor numbers to secondary heads of multi-headed cards */ -int drm_stub_open(struct inode *inode, struct file *filp) +static int drm_get_head(drm_device_t * dev, drm_head_t * head) { - drm_device_t *dev = NULL; - int minor = iminor(inode); - int err = -ENODEV; - struct file_operations *old_fops; - + drm_head_t **heads = drm_heads; + int ret; + int minor; + DRM_DEBUG("\n"); - if (!((minor >= 0) && (minor < drm_cards_limit))) - return -ENODEV; + for (minor = 0; minor < drm_cards_limit; minor++, heads++) { + if (!*heads) { - dev = drm_minors[minor].dev; - if (!dev) - return -ENODEV; + *head = (drm_head_t) { + .dev = dev,.device = + MKDEV(DRM_MAJOR, minor),.minor = minor,}; - old_fops = filp->f_op; - filp->f_op = fops_get(&dev->driver->fops); - if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { - fops_put(filp->f_op); - filp->f_op = fops_get(old_fops); - } - fops_put(old_fops); + 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; + } + + head->dev_class = drm_sysfs_device_add(drm_class, head); + if (IS_ERR(head->dev_class)) { + printk(KERN_ERR + "DRM: Error sysfs_device_add.\n"); + ret = PTR_ERR(head->dev_class); + goto err_g2; + } + *heads = head; - return err; + DRM_DEBUG("new minor assigned %d\n", minor); + return 0; + } + } + DRM_ERROR("out of minors\n"); + return -ENOMEM; + err_g2: + drm_proc_cleanup(minor, drm_proc_root, head->dev_root); + err_g1: + *head = (drm_head_t) { + .dev = NULL}; + return ret; } /** - * Get a device minor number. + * Register. * - * \param pdev PCI device structure + * \param pdev - PCI device structure * \param ent entry from the PCI ID table with device type flags * \return zero on success or a negative number on failure. * @@ -172,88 +199,92 @@ int drm_stub_open(struct inode *inode, struct file *filp) * then register the character device and inter module information. * Try and register, if we fail to register, backout previous work. */ -int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) +int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + struct drm_driver *driver) { - struct class_device *dev_class; drm_device_t *dev; int ret; - int minor; - drm_minor_t *minors = &drm_minors[0]; DRM_DEBUG("\n"); - for (minor = 0; minor < drm_cards_limit; minor++, minors++) { - if (minors->type == DRM_MINOR_FREE) { - - DRM_DEBUG("assigning minor %d\n", minor); - dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB); - if (!dev) - return -ENOMEM; + dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB); + if (!dev) + return -ENOMEM; - *minors = (drm_minor_t){.dev = dev, .type=DRM_MINOR_PRIMARY}; - dev->minor = minor; + ret = pci_enable_device(pdev); + if (ret) + goto err_g1; - pci_enable_device(pdev); + if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { + printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); + goto err_g2; + } + if ((ret = drm_get_head(dev, &dev->primary))) + 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); - if ((ret=drm_fill_in_dev(dev, pdev, ent, driver))) { - printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); - goto err_g1; - } - if ((ret = drm_proc_init(dev, minor, drm_proc_root, &minors->dev_root))) { - printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n"); - goto err_g1; - } + return 0; - - dev_class = drm_sysfs_device_add(drm_class, - MKDEV(DRM_MAJOR, - minor), - &pdev->dev, - "card%d", minor); - if (IS_ERR(dev_class)) { - printk(KERN_ERR "DRM: Error sysfs_device_add.\n"); - ret = PTR_ERR(dev_class); - goto err_g2; - } - - DRM_DEBUG("new minor assigned %d\n", minor); - return 0; - } - } - DRM_ERROR("out of minors\n"); - return -ENOMEM; err_g2: - drm_proc_cleanup(minor, drm_proc_root, minors->dev_root); + pci_disable_device(pdev); err_g1: - *minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE}; drm_free(dev, sizeof(*dev), DRM_MEM_STUB); return ret; } -EXPORT_SYMBOL(drm_probe); - /** * Put a device minor number. * - * \param minor minor number. - * \return always zero. + * \param dev device data structure + * \return always zero * - * Cleans up the proc resources. If a minor is zero then release the foreign - * "drm" data, otherwise unregisters the "drm" data, frees the stub list and - * unregisters the character device. + * Cleans up the proc resources. If it is the last minor then release the foreign + * "drm" data, otherwise unregisters the "drm" data, frees the dev list and + * unregisters the character device. */ -int drm_put_minor(drm_device_t *dev) +int drm_put_dev(drm_device_t * dev) { - drm_minor_t *minors = &drm_minors[dev->minor]; - - DRM_DEBUG("release minor %d\n", dev->minor); - - drm_proc_cleanup(dev->minor, drm_proc_root, minors->dev_root); - drm_sysfs_device_remove(MKDEV(DRM_MAJOR, dev->minor)); - - *minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE}; + DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname) + 1, + DRM_MEM_DRIVER); + dev->devname = NULL; + } drm_free(dev, sizeof(*dev), DRM_MEM_STUB); - return 0; } +/** + * Put a secondary minor number. + * + * \param sec_minor - structure to be released + * \return always zero + * + * Cleans up the proc resources. Not legal for this to be the + * last minor released. + * + */ +int drm_put_head(drm_head_t * head) +{ + 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_class); + + *head = (drm_head_t) {.dev = NULL}; + + drm_heads[minor] = NULL; + + return 0; +}