11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \file drm_stub.h
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stub support
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \author Rickard E. (Rik) Faith <faith@valinux.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All Rights Reserved.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Permission is hereby granted, free of charge, to any person obtaining a
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy of this software and associated documentation files (the "Software"),
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to deal in the Software without restriction, including without limitation
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the rights to use, copy, modify, merge, publish, distribute, sublicense,
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and/or sell copies of the Software, and to permit persons to whom the
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software is furnished to do so, subject to the following conditions:
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The above copyright notice and this permission notice (including the next
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * paragraph) shall be included in all copies or substantial portions of the
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DEALINGS IN THE SOFTWARE.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
365a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm_core.h"
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlieunsigned int drm_debug = 0;	/* 1 to enable debug output */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(drm_debug);
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4327641c3f003e7f3b6585c01d8a788883603eb262Mario Kleinerunsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
4427641c3f003e7f3b6585c01d8a788883603eb262Mario KleinerEXPORT_SYMBOL(drm_vblank_offdelay);
4527641c3f003e7f3b6585c01d8a788883603eb262Mario Kleiner
4627641c3f003e7f3b6585c01d8a788883603eb262Mario Kleinerunsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
4727641c3f003e7f3b6585c01d8a788883603eb262Mario KleinerEXPORT_SYMBOL(drm_timestamp_precision);
4827641c3f003e7f3b6585c01d8a788883603eb262Mario Kleiner
49b5e89ed53ed8d24f83ba1941c07382af00ed238eDave AirlieMODULE_AUTHOR(CORE_AUTHOR);
50b5e89ed53ed8d24f83ba1941c07382af00ed238eDave AirlieMODULE_DESCRIPTION(CORE_DESC);
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL and additional rights");
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Enable debug output");
5327641c3f003e7f3b6585c01d8a788883603eb262Mario KleinerMODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
5427641c3f003e7f3b6585c01d8a788883603eb262Mario KleinerMODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56c0758146adbe39514e75ac860ce7e49f865c2297Dave Jonesmodule_param_named(debug, drm_debug, int, 0600);
5727641c3f003e7f3b6585c01d8a788883603eb262Mario Kleinermodule_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
5827641c3f003e7f3b6585c01d8a788883603eb262Mario Kleinermodule_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
602c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airliestruct idr drm_minors_idr;
612c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
620650fd5824e07570f0c43980b81bb23ae917f1d7Greg Kroah-Hartmanstruct class *drm_class;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct proc_dir_entry *drm_proc_root;
64955b12def42e83287c1bdb1411d99451753c1391Ben Gamaristruct dentry *drm_debugfs_root;
655ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
665ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perchesint drm_err(const char *func, const char *format, ...)
675ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches{
685ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	struct va_format vaf;
695ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	va_list args;
705ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	int r;
715ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
725ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	va_start(args, format);
735ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
745ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	vaf.fmt = format;
755ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	vaf.va = &args;
765ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
775ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
785ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
795ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	va_end(args);
805ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
815ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches	return r;
825ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches}
835ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe PerchesEXPORT_SYMBOL(drm_err);
845ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
854fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhaovoid drm_ut_debug_printk(unsigned int request_level,
864fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *prefix,
874fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *function_name,
884fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *format, ...)
894fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao{
904fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	va_list args;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
924fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	if (drm_debug & request_level) {
934fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		if (function_name)
944fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
954fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		va_start(args, format);
964fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		vprintk(format, args);
974fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		va_end(args);
984fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	}
994fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao}
1004fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhaoEXPORT_SYMBOL(drm_ut_debug_printk);
1015ad3d8831f0c97257460c11ddcc1cc0466c762d4Joe Perches
1022c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airliestatic int drm_minor_get_id(struct drm_device *dev, int type)
1032c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie{
1042c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int new_id;
1052c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int ret;
1062c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int base = 0, limit = 63;
1072c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
108f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	if (type == DRM_MINOR_CONTROL) {
109f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                base += 64;
110f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                limit = base + 127;
111f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie        } else if (type == DRM_MINOR_RENDER) {
112f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                base += 128;
113f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                limit = base + 255;
114f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie        }
115f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie
1162c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieagain:
1172c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
1182c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		DRM_ERROR("Out of memory expanding drawable idr\n");
1192c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return -ENOMEM;
1202c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
1212c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	mutex_lock(&dev->struct_mutex);
1222c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	ret = idr_get_new_above(&drm_minors_idr, NULL,
1232c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie				base, &new_id);
1242c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	mutex_unlock(&dev->struct_mutex);
1252c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (ret == -EAGAIN) {
1262c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto again;
1272c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	} else if (ret) {
1282c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return ret;
1292c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
1302c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
1312c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (new_id >= limit) {
1322c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		idr_remove(&drm_minors_idr, new_id);
1332c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return -EINVAL;
1342c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
1352c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	return new_id;
1362c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie}
1372c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
1387c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestruct drm_master *drm_master_create(struct drm_minor *minor)
1397c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1407c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_master *master;
1417c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1429a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	master = kzalloc(sizeof(*master), GFP_KERNEL);
1437c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master)
1447c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return NULL;
1457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1467c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_init(&master->refcount);
1477c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	spin_lock_init(&master->lock.spinlock);
1487c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	init_waitqueue_head(&master->lock.lock_queue);
1497c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
1507c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	INIT_LIST_HEAD(&master->magicfree);
1517c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->minor = minor;
1527c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1537c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_add_tail(&master->head, &minor->master_list);
1547c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1557c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return master;
1567c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
1577c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestruct drm_master *drm_master_get(struct drm_master *master)
1597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_get(&master->refcount);
1617c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return master;
1627c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
16385bb0c377f259100d049937e30c85f7a8dea0fa0Thomas HellstromEXPORT_SYMBOL(drm_master_get);
1647c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1657c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestatic void drm_master_destroy(struct kref *kref)
1667c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1677c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_master *master = container_of(kref, struct drm_master, refcount);
1687c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_magic_entry *pt, *next;
1697c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_device *dev = master->minor->dev;
170c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	struct drm_map_list *r_list, *list_temp;
1717c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1727c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_del(&master->head);
1737c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1747c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (dev->driver->master_destroy)
1757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		dev->driver->master_destroy(dev, master);
1767c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
177c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
178c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie		if (r_list->master == master) {
179c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie			drm_rmmap_locked(dev, r_list->map);
180c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie			r_list = NULL;
181c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie		}
182c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	}
183c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie
1847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master->unique) {
1859a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(master->unique);
1867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master->unique = NULL;
1877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master->unique_len = 0;
1887c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
1897c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1906e35023ffad0ee74689710f0e81ee80c1019f93bChris Wilson	kfree(dev->devname);
1916e35023ffad0ee74689710f0e81ee80c1019f93bChris Wilson	dev->devname = NULL;
1926e35023ffad0ee74689710f0e81ee80c1019f93bChris Wilson
1937c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
1947c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		list_del(&pt->head);
1957c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
1969a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(pt);
1977c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
1987c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1997c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_ht_remove(&master->magiclist);
2007c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2019a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(master);
2027c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
2037c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2047c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid drm_master_put(struct drm_master **master)
2057c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
2067c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_put(&(*master)->refcount, drm_master_destroy);
2077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	*master = NULL;
2087c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
20985bb0c377f259100d049937e30c85f7a8dea0fa0Thomas HellstromEXPORT_SYMBOL(drm_master_put);
2107c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2117c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint drm_setmaster_ioctl(struct drm_device *dev, void *data,
2127c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie			struct drm_file *file_priv)
2137c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
214862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom	int ret = 0;
215862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom
2166b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	if (file_priv->is_master)
2176b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn		return 0;
2186b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn
2197c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
2207c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
2217c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2227c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!file_priv->master)
2237c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
2247c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2257c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!file_priv->minor->master &&
2267c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    file_priv->minor->master != file_priv->master) {
2277c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		mutex_lock(&dev->struct_mutex);
2287c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		file_priv->minor->master = drm_master_get(file_priv->master);
2296b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn		file_priv->is_master = 1;
230862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		if (dev->driver->master_set) {
231862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			ret = dev->driver->master_set(dev, file_priv, false);
232862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			if (unlikely(ret != 0)) {
233862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom				file_priv->is_master = 0;
234862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom				drm_master_put(&file_priv->minor->master);
235862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			}
236862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		}
2375ad8b7d12605e88d1e532061699102797fdefe08Helge Bahmann		mutex_unlock(&dev->struct_mutex);
2387c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
2397c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2407c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
2417c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
2427c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2437c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint drm_dropmaster_ioctl(struct drm_device *dev, void *data,
2447c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie			 struct drm_file *file_priv)
2457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
2466b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	if (!file_priv->is_master)
2477c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
2486b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn
24907f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie	if (!file_priv->minor->master)
25007f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie		return -EINVAL;
25107f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie
2527c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	mutex_lock(&dev->struct_mutex);
253862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom	if (dev->driver->master_drop)
254862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		dev->driver->master_drop(dev, file_priv, false);
2557c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_master_put(&file_priv->minor->master);
2566b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	file_priv->is_master = 0;
2577c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	mutex_unlock(&dev->struct_mutex);
2587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
2597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
2607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
261dcdb167402cbdca1d021bdfa5f63995ee0a79317Jordan Crouseint drm_fill_in_dev(struct drm_device *dev,
262b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   const struct pci_device_id *ent,
263b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   struct drm_driver *driver)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
267bd1b331fae2813d9f03ceee649296f02edc0b893Dave Airlie	INIT_LIST_HEAD(&dev->filelist);
2687c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->ctxlist);
2697c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->vmalist);
2707c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->maplist);
271c9a9c5e02aedc1a2815877b0268f886d2640b771Kristian Høgsberg	INIT_LIST_HEAD(&dev->vblank_event_list);
2727c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&dev->count_lock);
274c9a9c5e02aedc1a2815877b0268f886d2640b771Kristian Høgsberg	spin_lock_init(&dev->event_lock);
27530e2fb188194908e48d3f27a53ccea6740eb1e98Dave Airlie	mutex_init(&dev->struct_mutex);
27630e2fb188194908e48d3f27a53ccea6740eb1e98Dave Airlie	mutex_init(&dev->ctxlist_mutex);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2788d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom	if (drm_ht_create(&dev->map_hash, 12)) {
2798d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom		return -ENOMEM;
2808d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom	}
281836cf0465c422ee6d654060edd7c620d9cf0c09cDave Airlie
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the DRM has 6 basic counters */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->counters = 6;
284b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[0] = _DRM_STAT_LOCK;
285b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[1] = _DRM_STAT_OPENS;
286b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[2] = _DRM_STAT_CLOSES;
287b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[3] = _DRM_STAT_IOCTLS;
288b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[4] = _DRM_STAT_LOCKS;
289b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[5] = _DRM_STAT_UNLOCKS;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->driver = driver;
292b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
2938410ea3b95d105a5be5db501656f44bbb91197c1Dave Airlie	if (dev->driver->bus->agp_init) {
2948410ea3b95d105a5be5db501656f44bbb91197c1Dave Airlie		retcode = dev->driver->bus->agp_init(dev);
2958410ea3b95d105a5be5db501656f44bbb91197c1Dave Airlie		if (retcode)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto error_out_unreg;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2992716a02f607c964ccaa6fa7266abd3acd73d9033Dave Airlie
3008410ea3b95d105a5be5db501656f44bbb91197c1Dave Airlie
301b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	retcode = drm_ctxbitmap_init(dev);
302b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (retcode) {
303b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_out_unreg;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
307673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (driver->driver_features & DRIVER_GEM) {
308673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		retcode = drm_gem_init(dev);
309673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (retcode) {
310673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Cannot initialize graphics execution "
311673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "manager (GEM)\n");
312673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			goto error_out_unreg;
313673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
314673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	}
315673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
317b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
318b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie      error_out_unreg:
31922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	drm_lastclose(dev);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3229c1dfc5574a7f7115c0fe5bd8f838a8b7a52ee6dDave AirlieEXPORT_SYMBOL(drm_fill_in_dev);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a secondary minor number.
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param dev device data structure
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec-minor structure to hold the assigned minor
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return negative number on failure.
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Search an empty entry and initialize it to the given parameters, and
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * create the proc init entry via proc_init(). This routines assigns
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * minor numbers to secondary heads of multi-headed cards
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
336dcdb167402cbdca1d021bdfa5f63995ee0a79317Jordan Crouseint drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3382c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	struct drm_minor *new_minor;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
3402c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int minor_id;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("\n");
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3442c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	minor_id = drm_minor_get_id(dev, type);
3452c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (minor_id < 0)
3462c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return minor_id;
3472c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3482c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
3492c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (!new_minor) {
3502c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		ret = -ENOMEM;
3512c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto err_idr;
3522c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
3532c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3542c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->type = type;
3552c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->device = MKDEV(DRM_MAJOR, minor_id);
3562c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->dev = dev;
3572c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->index = minor_id;
3587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	INIT_LIST_HEAD(&new_minor->master_list);
3592c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3602c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_replace(&drm_minors_idr, new_minor, minor_id);
3612c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3622c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (type == DRM_MINOR_LEGACY) {
3632c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
3642c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		if (ret) {
3652c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie			DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
3662c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie			goto err_mem;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3682c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	} else
369955b12def42e83287c1bdb1411d99451753c1391Ben Gamari		new_minor->proc_root = NULL;
370955b12def42e83287c1bdb1411d99451753c1391Ben Gamari
371955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#if defined(CONFIG_DEBUG_FS)
372955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
373955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	if (ret) {
374156f5a7801195fa2ce44aeeb62d6cf8468f3332aGeunSik Lim		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
375955b12def42e83287c1bdb1411d99451753c1391Ben Gamari		goto err_g2;
376955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	}
377955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#endif
3782c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3792c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	ret = drm_sysfs_device_add(new_minor);
3802c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (ret) {
3812c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		printk(KERN_ERR
3822c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		       "DRM: Error sysfs_device_add.\n");
3832c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto err_g2;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3852c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor = new_minor;
3862c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3872c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	DRM_DEBUG("new minor assigned %d\n", minor_id);
3882c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	return 0;
3892c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3902c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3912c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_g2:
3922c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (new_minor->type == DRM_MINOR_LEGACY)
3932c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		drm_proc_cleanup(new_minor, drm_proc_root);
3942c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_mem:
3952c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	kfree(new_minor);
3962c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_idr:
3972c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_remove(&drm_minors_idr, minor_id);
3982c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor = NULL;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4019c1dfc5574a7f7115c0fe5bd8f838a8b7a52ee6dDave AirlieEXPORT_SYMBOL(drm_get_minor);
402b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
403c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie/**
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put a secondary minor number.
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec_minor - structure to be released
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return always zero
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cleans up the proc resources. Not legal for this to be the
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last minor released.
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4132c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieint drm_put_minor(struct drm_minor **minor_p)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4152c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	struct drm_minor *minor = *minor_p;
416673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
4172c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	DRM_DEBUG("release secondary minor %d\n", minor->index);
418b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
4192c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (minor->type == DRM_MINOR_LEGACY)
4202c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		drm_proc_cleanup(minor, drm_proc_root);
421955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#if defined(CONFIG_DEBUG_FS)
422955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	drm_debugfs_cleanup(minor);
423955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#endif
424955b12def42e83287c1bdb1411d99451753c1391Ben Gamari
4252c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	drm_sysfs_device_remove(minor);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4272c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_remove(&drm_minors_idr, minor->index);
428b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
4292c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	kfree(minor);
4302c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor_p = NULL;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4339c1dfc5574a7f7115c0fe5bd8f838a8b7a52ee6dDave AirlieEXPORT_SYMBOL(drm_put_minor);
434112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
4352c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airliestatic void drm_unplug_minor(struct drm_minor *minor)
4362c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie{
4372c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	drm_sysfs_device_remove(minor);
4382c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie}
4392c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie
440112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg/**
441112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * Called via drm_exit() at module unload time or when pci device is
442112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * unplugged.
443112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg *
444112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * Cleans up all DRM device, calling drm_lastclose().
445112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg *
446112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg */
447112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsbergvoid drm_put_dev(struct drm_device *dev)
448112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg{
449ecca0683230b83e8f830ff157911fad20bc43015Julia Lawall	struct drm_driver *driver;
450112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	struct drm_map_list *r_list, *list_temp;
451112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
452112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	DRM_DEBUG("\n");
453112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
454112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (!dev) {
455112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		DRM_ERROR("cleanup called no dev\n");
456112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		return;
457112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
458ecca0683230b83e8f830ff157911fad20bc43015Julia Lawall	driver = dev->driver;
459112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
460112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	drm_lastclose(dev);
461112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
462112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
463112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	    dev->agp && dev->agp->agp_mtrr >= 0) {
464112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		int retval;
465112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		retval = mtrr_del(dev->agp->agp_mtrr,
466112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg				  dev->agp->agp_info.aper_base,
467112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg				  dev->agp->agp_info.aper_size * 1024 * 1024);
468112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		DRM_DEBUG("mtrr_del=%d\n", retval);
469112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
470112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
471112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (dev->driver->unload)
472112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->driver->unload(dev);
473112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
474112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_has_AGP(dev) && dev->agp) {
4759a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(dev->agp);
476112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->agp = NULL;
477112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
478112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
479b78315f051de8d207bead90470aa216c0617572bJesse Barnes	drm_vblank_cleanup(dev);
480b78315f051de8d207bead90470aa216c0617572bJesse Barnes
481112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
482112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_rmmap(dev, r_list->map);
48330ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs	drm_ht_remove(&dev->map_hash);
48430ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs
48530ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs	drm_ctxbitmap_cleanup(dev);
486112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
487112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_check_feature(dev, DRIVER_MODESET))
488112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_put_minor(&dev->control);
489112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
490112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (driver->driver_features & DRIVER_GEM)
491112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_gem_destroy(dev);
492112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
493112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	drm_put_minor(&dev->primary);
494112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
495a250b9fdc53a286d32e22f21170382a46b3a3ef5Dave Airlie	list_del(&dev->driver_item);
496112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (dev->devname) {
4979a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(dev->devname);
498112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->devname = NULL;
499112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
5009a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev);
501112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg}
502112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian HøgsbergEXPORT_SYMBOL(drm_put_dev);
5032c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie
5042c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlievoid drm_unplug_dev(struct drm_device *dev)
5052c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie{
5062c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	/* for a USB device */
5072c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	if (drm_core_check_feature(dev, DRIVER_MODESET))
5082c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie		drm_unplug_minor(dev->control);
5092c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	drm_unplug_minor(dev->primary);
5102c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie
5112c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	mutex_lock(&drm_global_mutex);
5122c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie
5132c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	drm_device_set_unplugged(dev);
5142c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie
5152c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	if (dev->open_count == 0) {
5162c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie		drm_put_dev(dev);
5172c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	}
5182c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie	mutex_unlock(&drm_global_mutex);
5192c07a21d6fb0be47fda696a618b726ea258ed1ddDave Airlie}
5202c07a21d6fb0be47fda696a618b726ea258ed1ddDave AirlieEXPORT_SYMBOL(drm_unplug_dev);
521