static void drm_dev_release(struct kref *ref) { struct drm_device *dev = container_of(ref, struct drm_device, ref); if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_destroy(dev); drm_legacy_ctxbitmap_cleanup(dev); drm_ht_remove(&dev->map_hash); drm_fs_inode_free(dev->anon_inode); drm_minor_free(dev, DRM_MINOR_PRIMARY); drm_minor_free(dev, DRM_MINOR_RENDER); drm_minor_free(dev, DRM_MINOR_CONTROL); mutex_destroy(&dev->master_mutex); kfree(dev->unique); kfree(dev); }
/** * drm_dev_init - Initialise new DRM device * @dev: DRM device * @driver: DRM driver * @parent: Parent device object * * Initialize a new DRM device. No device registration is done. * Call drm_dev_register() to advertice the device to user space and register it * with other core subsystems. This should be done last in the device * initialization sequence to make sure userspace can't access an inconsistent * state. * * The initial ref-count of the object is 1. Use drm_dev_ref() and * drm_dev_unref() to take and drop further ref-counts. * * Note that for purely virtual devices @parent can be NULL. * * Drivers that do not want to allocate their own device struct * embedding struct &drm_device can call drm_dev_alloc() instead. * * RETURNS: * 0 on success, or error code on failure. */ int drm_dev_init(struct drm_device *dev, struct drm_driver *driver, struct device *parent) { int ret; kref_init(&dev->ref); dev->dev = parent; dev->driver = driver; INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->buf_lock); spin_lock_init(&dev->event_lock); mutex_init(&dev->struct_mutex); mutex_init(&dev->filelist_mutex); mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->master_mutex); dev->anon_inode = drm_fs_inode_new(); if (IS_ERR(dev->anon_inode)) { ret = PTR_ERR(dev->anon_inode); DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret); goto err_free; } if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL); if (ret) goto err_minors; } if (drm_core_check_feature(dev, DRIVER_RENDER)) { ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); if (ret) goto err_minors; } ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY); if (ret) goto err_minors; ret = drm_ht_create(&dev->map_hash, 12); if (ret) goto err_minors; drm_legacy_ctxbitmap_init(dev); if (drm_core_check_feature(dev, DRIVER_GEM)) { ret = drm_gem_init(dev); if (ret) { DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n"); goto err_ctxbitmap; } } /* Use the parent device name as DRM device unique identifier, but fall * back to the driver name for virtual devices like vgem. */ ret = drm_dev_set_unique(dev, parent ? dev_name(parent) : driver->name); if (ret) goto err_setunique; return 0; err_setunique: if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_destroy(dev); err_ctxbitmap: drm_legacy_ctxbitmap_cleanup(dev); drm_ht_remove(&dev->map_hash); err_minors: drm_minor_free(dev, DRM_MINOR_PRIMARY); drm_minor_free(dev, DRM_MINOR_RENDER); drm_minor_free(dev, DRM_MINOR_CONTROL); drm_fs_inode_free(dev->anon_inode); err_free: mutex_destroy(&dev->master_mutex); return ret; }
static void drm_unload(struct drm_device *dev) { int i; DRM_DEBUG("\n"); drm_sysctl_cleanup(dev); if (dev->devnode != NULL) destroy_dev(dev->devnode); drm_ctxbitmap_cleanup(dev); if (dev->driver->driver_features & DRIVER_GEM) drm_gem_destroy(dev); if (dev->agp && dev->agp->agp_mtrr) { int __unused retcode; retcode = drm_mtrr_del(0, dev->agp->agp_info.ai_aperture_base, dev->agp->agp_info.ai_aperture_size, DRM_MTRR_WC); DRM_DEBUG("mtrr_del = %d", retcode); } drm_vblank_cleanup(dev); DRM_LOCK(dev); drm_lastclose(dev); DRM_UNLOCK(dev); /* Clean up PCI resources allocated by drm_bufs.c. We're not really * worried about resource consumption while the DRM is inactive (between * lastclose and firstopen or unload) because these aren't actually * taking up KVA, just keeping the PCI resource allocated. */ for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { if (dev->pcir[i] == NULL) continue; bus_release_resource(dev->dev, SYS_RES_MEMORY, dev->pcirid[i], dev->pcir[i]); dev->pcir[i] = NULL; } if (dev->agp) { drm_free(dev->agp, M_DRM); dev->agp = NULL; } if (dev->driver->unload != NULL) { DRM_LOCK(dev); dev->driver->unload(dev); DRM_UNLOCK(dev); } drm_mem_uninit(); if (pci_disable_busmaster(dev->dev)) DRM_ERROR("Request to disable bus-master failed.\n"); lockuninit(&dev->vbl_lock); lockuninit(&dev->dev_lock); lockuninit(&dev->event_lock); lockuninit(&dev->struct_mutex); }