drm_stub.c revision b78315f051de8d207bead90470aa216c0617572b
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>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h"
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm_core.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlieunsigned int drm_debug = 0;	/* 1 to enable debug output */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(drm_debug);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42b5e89ed53ed8d24f83ba1941c07382af00ed238eDave AirlieMODULE_AUTHOR(CORE_AUTHOR);
43b5e89ed53ed8d24f83ba1941c07382af00ed238eDave AirlieMODULE_DESCRIPTION(CORE_DESC);
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL and additional rights");
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Enable debug output");
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47c0758146adbe39514e75ac860ce7e49f865c2297Dave Jonesmodule_param_named(debug, drm_debug, int, 0600);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
492c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airliestruct idr drm_minors_idr;
502c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
510650fd5824e07570f0c43980b81bb23ae917f1d7Greg Kroah-Hartmanstruct class *drm_class;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct proc_dir_entry *drm_proc_root;
53955b12def42e83287c1bdb1411d99451753c1391Ben Gamaristruct dentry *drm_debugfs_root;
544fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhaovoid drm_ut_debug_printk(unsigned int request_level,
554fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *prefix,
564fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *function_name,
574fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			 const char *format, ...)
584fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao{
594fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	va_list args;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
614fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	if (drm_debug & request_level) {
624fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		if (function_name)
634fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao			printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
644fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		va_start(args, format);
654fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		vprintk(format, args);
664fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao		va_end(args);
674fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao	}
684fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhao}
694fefcb27050b98c97b1c32bc710fc2f874449deeyakui_zhaoEXPORT_SYMBOL(drm_ut_debug_printk);
702c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airliestatic int drm_minor_get_id(struct drm_device *dev, int type)
712c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie{
722c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int new_id;
732c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int ret;
742c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int base = 0, limit = 63;
752c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
76f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	if (type == DRM_MINOR_CONTROL) {
77f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                base += 64;
78f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                limit = base + 127;
79f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie        } else if (type == DRM_MINOR_RENDER) {
80f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                base += 128;
81f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie                limit = base + 255;
82f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie        }
83f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie
842c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieagain:
852c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
862c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		DRM_ERROR("Out of memory expanding drawable idr\n");
872c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return -ENOMEM;
882c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
892c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	mutex_lock(&dev->struct_mutex);
902c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	ret = idr_get_new_above(&drm_minors_idr, NULL,
912c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie				base, &new_id);
922c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	mutex_unlock(&dev->struct_mutex);
932c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (ret == -EAGAIN) {
942c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto again;
952c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	} else if (ret) {
962c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return ret;
972c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
982c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
992c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (new_id >= limit) {
1002c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		idr_remove(&drm_minors_idr, new_id);
1012c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return -EINVAL;
1022c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
1032c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	return new_id;
1042c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie}
1052c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
1067c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestruct drm_master *drm_master_create(struct drm_minor *minor)
1077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1087c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_master *master;
1097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1109a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	master = kzalloc(sizeof(*master), GFP_KERNEL);
1117c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master)
1127c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return NULL;
1137c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1147c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_init(&master->refcount);
1157c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	spin_lock_init(&master->lock.spinlock);
1167c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	init_waitqueue_head(&master->lock.lock_queue);
1177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
1187c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	INIT_LIST_HEAD(&master->magicfree);
1197c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->minor = minor;
1207c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1217c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_add_tail(&master->head, &minor->master_list);
1227c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1237c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return master;
1247c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
1257c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1267c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestruct drm_master *drm_master_get(struct drm_master *master)
1277c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1287c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_get(&master->refcount);
1297c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return master;
1307c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
13185bb0c377f259100d049937e30c85f7a8dea0fa0Thomas HellstromEXPORT_SYMBOL(drm_master_get);
1327c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1337c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airliestatic void drm_master_destroy(struct kref *kref)
1347c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1357c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_master *master = container_of(kref, struct drm_master, refcount);
1367c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_magic_entry *pt, *next;
1377c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_device *dev = master->minor->dev;
138c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	struct drm_map_list *r_list, *list_temp;
1397c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1407c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_del(&master->head);
1417c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1427c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (dev->driver->master_destroy)
1437c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		dev->driver->master_destroy(dev, master);
1447c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
145c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
146c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie		if (r_list->master == master) {
147c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie			drm_rmmap_locked(dev, r_list->map);
148c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie			r_list = NULL;
149c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie		}
150c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie	}
151c1ff85d97708550e634fb6fa099c463db90fc40dDave Airlie
1527c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master->unique) {
1539a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(master->unique);
1547c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master->unique = NULL;
1557c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master->unique_len = 0;
1567c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
1577c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
1597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		list_del(&pt->head);
1607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
1619a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(pt);
1627c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
1637c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1647c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_ht_remove(&master->magiclist);
1657c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1669a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(master);
1677c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
1687c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1697c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid drm_master_put(struct drm_master **master)
1707c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
1717c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	kref_put(&(*master)->refcount, drm_master_destroy);
1727c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	*master = NULL;
1737c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
17485bb0c377f259100d049937e30c85f7a8dea0fa0Thomas HellstromEXPORT_SYMBOL(drm_master_put);
1757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1767c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint drm_setmaster_ioctl(struct drm_device *dev, void *data,
1777c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie			struct drm_file *file_priv)
1787c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
179862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom	int ret = 0;
180862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom
1816b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	if (file_priv->is_master)
1826b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn		return 0;
1836b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn
1847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
1857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
1867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!file_priv->master)
1887c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
1897c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1907c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!file_priv->minor->master &&
1917c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    file_priv->minor->master != file_priv->master) {
1927c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		mutex_lock(&dev->struct_mutex);
1937c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		file_priv->minor->master = drm_master_get(file_priv->master);
1946b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn		file_priv->is_master = 1;
195862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		if (dev->driver->master_set) {
196862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			ret = dev->driver->master_set(dev, file_priv, false);
197862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			if (unlikely(ret != 0)) {
198862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom				file_priv->is_master = 0;
199862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom				drm_master_put(&file_priv->minor->master);
200862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom			}
201862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		}
2025ad8b7d12605e88d1e532061699102797fdefe08Helge Bahmann		mutex_unlock(&dev->struct_mutex);
2037c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	}
2047c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2057c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
2067c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
2077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
2087c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint drm_dropmaster_ioctl(struct drm_device *dev, void *data,
2097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie			 struct drm_file *file_priv)
2107c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
2116b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	if (!file_priv->is_master)
2127c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -EINVAL;
2136b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn
21407f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie	if (!file_priv->minor->master)
21507f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie		return -EINVAL;
21607f1c7a7f6736d9ec2eba57d209c5f48888d841eDave Airlie
2177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	mutex_lock(&dev->struct_mutex);
218862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom	if (dev->driver->master_drop)
219862302ffe422378a5213f558fc5cdf62c37050a9Thomas Hellstrom		dev->driver->master_drop(dev, file_priv, false);
2207c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_master_put(&file_priv->minor->master);
2216b0084266c1d4917ad9259759a1e7bd623cb3888Jonas Bonn	file_priv->is_master = 0;
2227c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	mutex_unlock(&dev->struct_mutex);
2237c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
2247c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
2257c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
22684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
227b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   const struct pci_device_id *ent,
228b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   struct drm_driver *driver)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
232bd1b331fae2813d9f03ceee649296f02edc0b893Dave Airlie	INIT_LIST_HEAD(&dev->filelist);
2337c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->ctxlist);
2347c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->vmalist);
2357c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie	INIT_LIST_HEAD(&dev->maplist);
236c9a9c5e02aedc1a2815877b0268f886d2640b771Kristian Høgsberg	INIT_LIST_HEAD(&dev->vblank_event_list);
2377c158acef8f0e51c3a5f71133aaf402628370a64Dave Airlie
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&dev->count_lock);
239bea5679f9cb97b7e41786c8500df56665cd21e56Michel Dänzer	spin_lock_init(&dev->drw_lock);
240c9a9c5e02aedc1a2815877b0268f886d2640b771Kristian Høgsberg	spin_lock_init(&dev->event_lock);
241b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	init_timer(&dev->timer);
24230e2fb188194908e48d3f27a53ccea6740eb1e98Dave Airlie	mutex_init(&dev->struct_mutex);
24330e2fb188194908e48d3f27a53ccea6740eb1e98Dave Airlie	mutex_init(&dev->ctxlist_mutex);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24545ea5dcde62db8eccc8503defae3c3353256975dDave Airlie	idr_init(&dev->drw_idr);
24645ea5dcde62db8eccc8503defae3c3353256975dDave Airlie
247b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->pdev = pdev;
2482f02cc3fb8960754a2a5df6a33f53528e0d830beEric Anholt	dev->pci_device = pdev->device;
2492f02cc3fb8960754a2a5df6a33f53528e0d830beEric Anholt	dev->pci_vendor = pdev->vendor;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __alpha__
252b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->hose = pdev->sysdata;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2558d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom	if (drm_ht_create(&dev->map_hash, 12)) {
2568d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom		return -ENOMEM;
2578d153f7107ff2c5d6e32053ae377c961187ab6b9Thomas Hellstrom	}
258836cf0465c422ee6d654060edd7c620d9cf0c09cDave Airlie
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the DRM has 6 basic counters */
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->counters = 6;
261b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[0] = _DRM_STAT_LOCK;
262b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[1] = _DRM_STAT_OPENS;
263b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[2] = _DRM_STAT_CLOSES;
264b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[3] = _DRM_STAT_IOCTLS;
265b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[4] = _DRM_STAT_LOCKS;
266b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	dev->types[5] = _DRM_STAT_UNLOCKS;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->driver = driver;
269b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drm_core_has_AGP(dev)) {
271cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie		if (drm_device_is_agp(dev))
272cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie			dev->agp = drm_agp_init(dev);
273b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
274b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    && (dev->agp == NULL)) {
275b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			DRM_ERROR("Cannot initialize the agpgart module.\n");
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retcode = -EINVAL;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto error_out_unreg;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (drm_core_has_MTRR(dev)) {
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->agp)
281b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				dev->agp->agp_mtrr =
282b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    mtrr_add(dev->agp->agp_info.aper_base,
283b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					     dev->agp->agp_info.aper_size *
284b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					     1024 * 1024, MTRR_TYPE_WRCOMB, 1);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2882716a02f607c964ccaa6fa7266abd3acd73d9033Dave Airlie
289b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	retcode = drm_ctxbitmap_init(dev);
290b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (retcode) {
291b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_out_unreg;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
295673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (driver->driver_features & DRIVER_GEM) {
296673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		retcode = drm_gem_init(dev);
297673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (retcode) {
298673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Cannot initialize graphics execution "
299673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "manager (GEM)\n");
300673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			goto error_out_unreg;
301673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
302673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	}
303673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
305b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
306b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie      error_out_unreg:
30722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	drm_lastclose(dev);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a secondary minor number.
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param dev device data structure
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec-minor structure to hold the assigned minor
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return negative number on failure.
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Search an empty entry and initialize it to the given parameters, and
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * create the proc init entry via proc_init(). This routines assigns
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * minor numbers to secondary heads of multi-headed cards
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3232c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airliestatic int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3252c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	struct drm_minor *new_minor;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
3272c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	int minor_id;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("\n");
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3312c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	minor_id = drm_minor_get_id(dev, type);
3322c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (minor_id < 0)
3332c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		return minor_id;
3342c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3352c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
3362c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (!new_minor) {
3372c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		ret = -ENOMEM;
3382c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto err_idr;
3392c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	}
3402c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3412c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->type = type;
3422c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->device = MKDEV(DRM_MAJOR, minor_id);
3432c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->dev = dev;
3442c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	new_minor->index = minor_id;
3457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	INIT_LIST_HEAD(&new_minor->master_list);
3462c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3472c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_replace(&drm_minors_idr, new_minor, minor_id);
3482c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3492c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (type == DRM_MINOR_LEGACY) {
3502c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
3512c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		if (ret) {
3522c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie			DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
3532c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie			goto err_mem;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3552c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	} else
356955b12def42e83287c1bdb1411d99451753c1391Ben Gamari		new_minor->proc_root = NULL;
357955b12def42e83287c1bdb1411d99451753c1391Ben Gamari
358955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#if defined(CONFIG_DEBUG_FS)
359955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
360955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	if (ret) {
361156f5a7801195fa2ce44aeeb62d6cf8468f3332aGeunSik Lim		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
362955b12def42e83287c1bdb1411d99451753c1391Ben Gamari		goto err_g2;
363955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	}
364955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#endif
3652c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3662c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	ret = drm_sysfs_device_add(new_minor);
3672c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (ret) {
3682c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		printk(KERN_ERR
3692c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		       "DRM: Error sysfs_device_add.\n");
3702c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		goto err_g2;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3722c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor = new_minor;
3732c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3742c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	DRM_DEBUG("new minor assigned %d\n", minor_id);
3752c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	return 0;
3762c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3772c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie
3782c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_g2:
3792c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (new_minor->type == DRM_MINOR_LEGACY)
3802c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		drm_proc_cleanup(new_minor, drm_proc_root);
3812c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_mem:
3822c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	kfree(new_minor);
3832c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieerr_idr:
3842c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_remove(&drm_minors_idr, minor_id);
3852c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor = NULL;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
388b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
389c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie/**
390c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Register.
391c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie *
392c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \param pdev - PCI device structure
393c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \param ent entry from the PCI ID table with device type flags
394c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \return zero on success or a negative number on failure.
395c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie *
396c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Attempt to gets inter module "drm" information. If we are first
397c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * then register the character device and inter module information.
398c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Try and register, if we fail to register, backout previous work.
399c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie */
400c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
401b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		struct drm_driver *driver)
402c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie{
40384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlie	struct drm_device *dev;
404c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	int ret;
405c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
406c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	DRM_DEBUG("\n");
407c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
4089a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
409c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	if (!dev)
410c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie		return -ENOMEM;
411c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
4122c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzik	ret = pci_enable_device(pdev);
4132c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzik	if (ret)
4142c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzik		goto err_g1;
415c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
41619a8f59ab8ceee751ea720085098355d53f727d6Dave Airlie	pci_set_master(pdev);
417c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
418c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
4192c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzik		goto err_g2;
420c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	}
421f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie
422f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
423112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		pci_set_drvdata(pdev, dev);
424f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
425f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		if (ret)
426f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie			goto err_g2;
427f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	}
428f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie
4292c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
430f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		goto err_g3;
431bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie
432f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	if (dev->driver->load) {
433f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		ret = dev->driver->load(dev, ent->driver_data);
434f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		if (ret)
4353788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggs			goto err_g4;
436f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	}
437f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie
438f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie        /* setup the grouping for the legacy output */
439f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
440f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
441f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie		if (ret)
4423788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggs			goto err_g4;
443f453ba0460742ad027ae0c4c7d61e62817b3e7efDave Airlie	}
444a9d51a5ad1154b5b20add1e8d30a5564f8aabbe9Dave Airlie
445e7f7ab45ebcb54fd5f814ea15ea079e079662f67Dave Airlie	list_add_tail(&dev->driver_item, &driver->device_list);
446e7f7ab45ebcb54fd5f814ea15ea079e079662f67Dave Airlie
447cd00f95aff6b4cfeccb261fd4100cceb4f5270eaBenjamin Herrenschmidt	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
44822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie		 driver->name, driver->major, driver->minor, driver->patchlevel,
449cd00f95aff6b4cfeccb261fd4100cceb4f5270eaBenjamin Herrenschmidt		 driver->date, pci_name(pdev), dev->primary->index);
450c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
451c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	return 0;
452c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
4533788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggserr_g4:
454a9d51a5ad1154b5b20add1e8d30a5564f8aabbe9Dave Airlie	drm_put_minor(&dev->primary);
4553788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggserr_g3:
4563788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggs	if (drm_core_check_feature(dev, DRIVER_MODESET))
4573788f48a0fad246dbab826e8b2f07b403b0e3279Ben Skeggs		drm_put_minor(&dev->control);
4582c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzikerr_g2:
4592c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzik	pci_disable_device(pdev);
4602c3f0eddfbd7f5c7a5450de287bad805722888c3Jeff Garzikerr_g1:
4619a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev);
462c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie	return ret;
463c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie}
464112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian HøgsbergEXPORT_SYMBOL(drm_get_dev);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put a secondary minor number.
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec_minor - structure to be released
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return always zero
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cleans up the proc resources. Not legal for this to be the
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last minor released.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4762c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlieint drm_put_minor(struct drm_minor **minor_p)
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4782c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	struct drm_minor *minor = *minor_p;
479673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
4802c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	DRM_DEBUG("release secondary minor %d\n", minor->index);
481b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
4822c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	if (minor->type == DRM_MINOR_LEGACY)
4832c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie		drm_proc_cleanup(minor, drm_proc_root);
484955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#if defined(CONFIG_DEBUG_FS)
485955b12def42e83287c1bdb1411d99451753c1391Ben Gamari	drm_debugfs_cleanup(minor);
486955b12def42e83287c1bdb1411d99451753c1391Ben Gamari#endif
487955b12def42e83287c1bdb1411d99451753c1391Ben Gamari
4882c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	drm_sysfs_device_remove(minor);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4902c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	idr_remove(&drm_minors_idr, minor->index);
491b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
4922c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	kfree(minor);
4932c14f28be2a3f2a2e9861b156d64fbe2bc7000c3Dave Airlie	*minor_p = NULL;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
496112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
497112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg/**
498112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * Called via drm_exit() at module unload time or when pci device is
499112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * unplugged.
500112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg *
501112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * Cleans up all DRM device, calling drm_lastclose().
502112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg *
503112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg * \sa drm_init
504112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg */
505112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsbergvoid drm_put_dev(struct drm_device *dev)
506112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg{
507ecca0683230b83e8f830ff157911fad20bc43015Julia Lawall	struct drm_driver *driver;
508112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	struct drm_map_list *r_list, *list_temp;
509112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
510112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	DRM_DEBUG("\n");
511112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
512112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (!dev) {
513112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		DRM_ERROR("cleanup called no dev\n");
514112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		return;
515112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
516ecca0683230b83e8f830ff157911fad20bc43015Julia Lawall	driver = dev->driver;
517112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
518112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	drm_lastclose(dev);
519112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
520112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
521112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	    dev->agp && dev->agp->agp_mtrr >= 0) {
522112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		int retval;
523112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		retval = mtrr_del(dev->agp->agp_mtrr,
524112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg				  dev->agp->agp_info.aper_base,
525112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg				  dev->agp->agp_info.aper_size * 1024 * 1024);
526112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		DRM_DEBUG("mtrr_del=%d\n", retval);
527112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
528112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
529112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (dev->driver->unload)
530112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->driver->unload(dev);
531112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
532112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_has_AGP(dev) && dev->agp) {
5339a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(dev->agp);
534112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->agp = NULL;
535112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
536112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
537b78315f051de8d207bead90470aa216c0617572bJesse Barnes	drm_vblank_cleanup(dev);
538b78315f051de8d207bead90470aa216c0617572bJesse Barnes
539112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
540112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_rmmap(dev, r_list->map);
54130ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs	drm_ht_remove(&dev->map_hash);
54230ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs
54330ddbd94401a132f4d932775d1902b3c9a8c41b5Ben Skeggs	drm_ctxbitmap_cleanup(dev);
544112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
545112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (drm_core_check_feature(dev, DRIVER_MODESET))
546112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_put_minor(&dev->control);
547112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
548112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (driver->driver_features & DRIVER_GEM)
549112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		drm_gem_destroy(dev);
550112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
551112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	drm_put_minor(&dev->primary);
552112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg
553112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	if (dev->devname) {
5549a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		kfree(dev->devname);
555112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg		dev->devname = NULL;
556112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg	}
5579a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev);
558112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian Høgsberg}
559112b715e8e2f9ef7b96930888bb099ce10b4c3ccKristian HøgsbergEXPORT_SYMBOL(drm_put_dev);
560