| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /** | 
 | 2 |  * \file drm_stub.h | 
 | 3 |  * Stub support | 
 | 4 |  * | 
 | 5 |  * \author Rickard E. (Rik) Faith <faith@valinux.com> | 
 | 6 |  */ | 
 | 7 |  | 
 | 8 | /* | 
 | 9 |  * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org | 
 | 10 |  * | 
 | 11 |  * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. | 
 | 12 |  * All Rights Reserved. | 
 | 13 |  * | 
 | 14 |  * Permission is hereby granted, free of charge, to any person obtaining a | 
 | 15 |  * copy of this software and associated documentation files (the "Software"), | 
 | 16 |  * to deal in the Software without restriction, including without limitation | 
 | 17 |  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 | 18 |  * and/or sell copies of the Software, and to permit persons to whom the | 
 | 19 |  * Software is furnished to do so, subject to the following conditions: | 
 | 20 |  * | 
 | 21 |  * The above copyright notice and this permission notice (including the next | 
 | 22 |  * paragraph) shall be included in all copies or substantial portions of the | 
 | 23 |  * Software. | 
 | 24 |  * | 
 | 25 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | 26 |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | 27 |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 | 28 |  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | 
 | 29 |  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | 
 | 30 |  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
 | 31 |  * DEALINGS IN THE SOFTWARE. | 
 | 32 |  */ | 
 | 33 |  | 
 | 34 | #include <linux/module.h> | 
 | 35 | #include <linux/moduleparam.h> | 
 | 36 | #include "drmP.h" | 
 | 37 | #include "drm_core.h" | 
 | 38 |  | 
 | 39 | unsigned int drm_cards_limit = 16;	/* Enough for one machine */ | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 40 | unsigned int drm_debug = 0;	/* 1 to enable debug output */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | EXPORT_SYMBOL(drm_debug); | 
 | 42 |  | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 43 | MODULE_AUTHOR(CORE_AUTHOR); | 
 | 44 | MODULE_DESCRIPTION(CORE_DESC); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 45 | MODULE_LICENSE("GPL and additional rights"); | 
 | 46 | MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); | 
 | 47 | MODULE_PARM_DESC(debug, "Enable debug output"); | 
 | 48 |  | 
 | 49 | module_param_named(cards_limit, drm_cards_limit, int, 0444); | 
| Dave Jones | c075814 | 2005-10-03 15:02:20 -0400 | [diff] [blame] | 50 | module_param_named(debug, drm_debug, int, 0600); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 |  | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 52 | struct drm_head **drm_heads; | 
| Greg Kroah-Hartman | 0650fd5 | 2006-01-20 14:08:59 -0800 | [diff] [blame] | 53 | struct class *drm_class; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 | struct proc_dir_entry *drm_proc_root; | 
 | 55 |  | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 56 | static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 57 | 			   const struct pci_device_id *ent, | 
 | 58 | 			   struct drm_driver *driver) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 | { | 
 | 60 | 	int retcode; | 
 | 61 |  | 
| Dave Airlie | bd1b331 | 2007-05-26 05:01:51 +1000 | [diff] [blame] | 62 | 	INIT_LIST_HEAD(&dev->filelist); | 
| Dave Airlie | 7c158ac | 2007-07-11 12:05:36 +1000 | [diff] [blame] | 63 | 	INIT_LIST_HEAD(&dev->ctxlist); | 
 | 64 | 	INIT_LIST_HEAD(&dev->vmalist); | 
 | 65 | 	INIT_LIST_HEAD(&dev->maplist); | 
 | 66 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 | 	spin_lock_init(&dev->count_lock); | 
| =?utf-8?q?Michel_D=C3=A4nzer?= | bea5679 | 2006-10-24 23:04:19 +1000 | [diff] [blame] | 68 | 	spin_lock_init(&dev->drw_lock); | 
| =?utf-8?q?Michel_D=C3=A4nzer?= | 8163e41 | 2006-10-24 23:30:01 +1000 | [diff] [blame] | 69 | 	spin_lock_init(&dev->tasklet_lock); | 
| Thomas Hellstrom | 040ac32 | 2007-03-23 13:28:33 +1100 | [diff] [blame] | 70 | 	spin_lock_init(&dev->lock.spinlock); | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 71 | 	init_timer(&dev->timer); | 
| Dave Airlie | 30e2fb1 | 2006-02-02 19:37:46 +1100 | [diff] [blame] | 72 | 	mutex_init(&dev->struct_mutex); | 
 | 73 | 	mutex_init(&dev->ctxlist_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 74 |  | 
| Dave Airlie | 45ea5dcd | 2007-07-17 14:20:07 +1000 | [diff] [blame] | 75 | 	idr_init(&dev->drw_idr); | 
 | 76 |  | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 77 | 	dev->pdev = pdev; | 
| Eric Anholt | 2f02cc3 | 2006-09-22 04:19:34 +1000 | [diff] [blame] | 78 | 	dev->pci_device = pdev->device; | 
 | 79 | 	dev->pci_vendor = pdev->vendor; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 |  | 
 | 81 | #ifdef __alpha__ | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 82 | 	dev->hose = pdev->sysdata; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | 	dev->irq = pdev->irq; | 
 | 85 |  | 
| Thomas Hellstrom | 8d153f7 | 2006-08-07 22:36:47 +1000 | [diff] [blame] | 86 | 	if (drm_ht_create(&dev->map_hash, 12)) { | 
| Thomas Hellstrom | 8d153f7 | 2006-08-07 22:36:47 +1000 | [diff] [blame] | 87 | 		return -ENOMEM; | 
 | 88 | 	} | 
| Dave Airlie | 836cf04 | 2005-07-10 19:27:04 +1000 | [diff] [blame] | 89 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | 	/* the DRM has 6 basic counters */ | 
 | 91 | 	dev->counters = 6; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 92 | 	dev->types[0] = _DRM_STAT_LOCK; | 
 | 93 | 	dev->types[1] = _DRM_STAT_OPENS; | 
 | 94 | 	dev->types[2] = _DRM_STAT_CLOSES; | 
 | 95 | 	dev->types[3] = _DRM_STAT_IOCTLS; | 
 | 96 | 	dev->types[4] = _DRM_STAT_LOCKS; | 
 | 97 | 	dev->types[5] = _DRM_STAT_UNLOCKS; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 |  | 
 | 99 | 	dev->driver = driver; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 100 |  | 
| Dave Airlie | 22eae94 | 2005-11-10 22:16:34 +1100 | [diff] [blame] | 101 | 	if (dev->driver->load) | 
 | 102 | 		if ((retcode = dev->driver->load(dev, ent->driver_data))) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 | 			goto error_out_unreg; | 
 | 104 |  | 
 | 105 | 	if (drm_core_has_AGP(dev)) { | 
| Dave Airlie | cda1738 | 2005-07-10 17:31:26 +1000 | [diff] [blame] | 106 | 		if (drm_device_is_agp(dev)) | 
 | 107 | 			dev->agp = drm_agp_init(dev); | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 108 | 		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) | 
 | 109 | 		    && (dev->agp == NULL)) { | 
 | 110 | 			DRM_ERROR("Cannot initialize the agpgart module.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | 			retcode = -EINVAL; | 
 | 112 | 			goto error_out_unreg; | 
 | 113 | 		} | 
 | 114 | 		if (drm_core_has_MTRR(dev)) { | 
 | 115 | 			if (dev->agp) | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 116 | 				dev->agp->agp_mtrr = | 
 | 117 | 				    mtrr_add(dev->agp->agp_info.aper_base, | 
 | 118 | 					     dev->agp->agp_info.aper_size * | 
 | 119 | 					     1024 * 1024, MTRR_TYPE_WRCOMB, 1); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 120 | 		} | 
 | 121 | 	} | 
 | 122 |  | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 123 | 	retcode = drm_ctxbitmap_init(dev); | 
 | 124 | 	if (retcode) { | 
 | 125 | 		DRM_ERROR("Cannot allocate memory for context bitmap.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 126 | 		goto error_out_unreg; | 
 | 127 | 	} | 
 | 128 |  | 
 | 129 | 	return 0; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 130 |  | 
 | 131 |       error_out_unreg: | 
| Dave Airlie | 22eae94 | 2005-11-10 22:16:34 +1100 | [diff] [blame] | 132 | 	drm_lastclose(dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 133 | 	return retcode; | 
 | 134 | } | 
 | 135 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 136 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 137 | /** | 
 | 138 |  * Get a secondary minor number. | 
 | 139 |  * | 
 | 140 |  * \param dev device data structure | 
 | 141 |  * \param sec-minor structure to hold the assigned minor | 
 | 142 |  * \return negative number on failure. | 
 | 143 |  * | 
 | 144 |  * Search an empty entry and initialize it to the given parameters, and | 
 | 145 |  * create the proc init entry via proc_init(). This routines assigns | 
 | 146 |  * minor numbers to secondary heads of multi-headed cards | 
 | 147 |  */ | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 148 | static int drm_get_head(struct drm_device * dev, struct drm_head * head) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 149 | { | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 150 | 	struct drm_head **heads = drm_heads; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 151 | 	int ret; | 
 | 152 | 	int minor; | 
 | 153 |  | 
 | 154 | 	DRM_DEBUG("\n"); | 
 | 155 |  | 
 | 156 | 	for (minor = 0; minor < drm_cards_limit; minor++, heads++) { | 
 | 157 | 		if (!*heads) { | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 158 |  | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 159 | 			*head = (struct drm_head) { | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 160 | 			.dev = dev,.device = | 
 | 161 | 				    MKDEV(DRM_MAJOR, minor),.minor = minor,}; | 
 | 162 |  | 
 | 163 | 			if ((ret = | 
 | 164 | 			     drm_proc_init(dev, minor, drm_proc_root, | 
 | 165 | 					   &head->dev_root))) { | 
 | 166 | 				printk(KERN_ERR | 
 | 167 | 				       "DRM: Failed to initialize /proc/dri.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 168 | 				goto err_g1; | 
 | 169 | 			} | 
 | 170 |  | 
| Dave Airlie | 732052e | 2005-11-11 22:07:35 +1100 | [diff] [blame] | 171 | 			head->dev_class = drm_sysfs_device_add(drm_class, head); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 172 | 			if (IS_ERR(head->dev_class)) { | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 173 | 				printk(KERN_ERR | 
 | 174 | 				       "DRM: Error sysfs_device_add.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 175 | 				ret = PTR_ERR(head->dev_class); | 
 | 176 | 				goto err_g2; | 
 | 177 | 			} | 
 | 178 | 			*heads = head; | 
 | 179 |  | 
 | 180 | 			DRM_DEBUG("new minor assigned %d\n", minor); | 
 | 181 | 			return 0; | 
 | 182 | 		} | 
 | 183 | 	} | 
 | 184 | 	DRM_ERROR("out of minors\n"); | 
 | 185 | 	return -ENOMEM; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 186 |       err_g2: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 187 | 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root); | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 188 |       err_g1: | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 189 | 	*head = (struct drm_head) { | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 190 | 	.dev = NULL}; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 191 | 	return ret; | 
 | 192 | } | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 193 |  | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 194 | /** | 
 | 195 |  * Register. | 
 | 196 |  * | 
 | 197 |  * \param pdev - PCI device structure | 
 | 198 |  * \param ent entry from the PCI ID table with device type flags | 
 | 199 |  * \return zero on success or a negative number on failure. | 
 | 200 |  * | 
 | 201 |  * Attempt to gets inter module "drm" information. If we are first | 
 | 202 |  * then register the character device and inter module information. | 
 | 203 |  * Try and register, if we fail to register, backout previous work. | 
 | 204 |  */ | 
 | 205 | int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 206 | 		struct drm_driver *driver) | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 207 | { | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 208 | 	struct drm_device *dev; | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 209 | 	int ret; | 
 | 210 |  | 
 | 211 | 	DRM_DEBUG("\n"); | 
 | 212 |  | 
 | 213 | 	dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB); | 
 | 214 | 	if (!dev) | 
 | 215 | 		return -ENOMEM; | 
 | 216 |  | 
| Jeff Garzik | 2c3f0ed | 2006-12-09 10:50:22 +1100 | [diff] [blame] | 217 | 	ret = pci_enable_device(pdev); | 
 | 218 | 	if (ret) | 
 | 219 | 		goto err_g1; | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 220 |  | 
 | 221 | 	if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { | 
 | 222 | 		printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | 
| Jeff Garzik | 2c3f0ed | 2006-12-09 10:50:22 +1100 | [diff] [blame] | 223 | 		goto err_g2; | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 224 | 	} | 
 | 225 | 	if ((ret = drm_get_head(dev, &dev->primary))) | 
| Jeff Garzik | 2c3f0ed | 2006-12-09 10:50:22 +1100 | [diff] [blame] | 226 | 		goto err_g2; | 
| Dave Airlie | 22eae94 | 2005-11-10 22:16:34 +1100 | [diff] [blame] | 227 | 	 | 
 | 228 | 	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | 
 | 229 | 		 driver->name, driver->major, driver->minor, driver->patchlevel, | 
 | 230 | 		 driver->date, dev->primary.minor); | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 231 |  | 
 | 232 | 	return 0; | 
 | 233 |  | 
| Jeff Garzik | 2c3f0ed | 2006-12-09 10:50:22 +1100 | [diff] [blame] | 234 | err_g2: | 
 | 235 | 	pci_disable_device(pdev); | 
 | 236 | err_g1: | 
| Dave Airlie | c94f702 | 2005-07-07 21:03:38 +1000 | [diff] [blame] | 237 | 	drm_free(dev, sizeof(*dev), DRM_MEM_STUB); | 
 | 238 | 	return ret; | 
 | 239 | } | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 240 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 241 | /** | 
 | 242 |  * Put a device minor number. | 
 | 243 |  * | 
 | 244 |  * \param dev device data structure | 
 | 245 |  * \return always zero | 
 | 246 |  * | 
 | 247 |  * Cleans up the proc resources. If it is the last minor then release the foreign | 
 | 248 |  * "drm" data, otherwise unregisters the "drm" data, frees the dev list and | 
 | 249 |  * unregisters the character device. | 
 | 250 |  */ | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 251 | int drm_put_dev(struct drm_device * dev) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 252 | { | 
 | 253 | 	DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); | 
 | 254 |  | 
 | 255 | 	if (dev->unique) { | 
 | 256 | 		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); | 
 | 257 | 		dev->unique = NULL; | 
 | 258 | 		dev->unique_len = 0; | 
 | 259 | 	} | 
 | 260 | 	if (dev->devname) { | 
 | 261 | 		drm_free(dev->devname, strlen(dev->devname) + 1, | 
 | 262 | 			 DRM_MEM_DRIVER); | 
 | 263 | 		dev->devname = NULL; | 
 | 264 | 	} | 
 | 265 | 	drm_free(dev, sizeof(*dev), DRM_MEM_STUB); | 
 | 266 | 	return 0; | 
 | 267 | } | 
 | 268 |  | 
 | 269 | /** | 
 | 270 |  * Put a secondary minor number. | 
 | 271 |  * | 
 | 272 |  * \param sec_minor - structure to be released | 
 | 273 |  * \return always zero | 
 | 274 |  * | 
 | 275 |  * Cleans up the proc resources. Not legal for this to be the | 
 | 276 |  * last minor released. | 
 | 277 |  * | 
 | 278 |  */ | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 279 | int drm_put_head(struct drm_head * head) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 280 | { | 
 | 281 | 	int minor = head->minor; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 282 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 283 | 	DRM_DEBUG("release secondary minor %d\n", minor); | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 284 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 285 | 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root); | 
| Dave Airlie | 732052e | 2005-11-11 22:07:35 +1100 | [diff] [blame] | 286 | 	drm_sysfs_device_remove(head->dev_class); | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 287 |  | 
| Dave Airlie | 84b1fd1 | 2007-07-11 15:53:27 +1000 | [diff] [blame] | 288 | 	*head = (struct drm_head) {.dev = NULL}; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 289 |  | 
 | 290 | 	drm_heads[minor] = NULL; | 
| Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 291 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 292 | 	return 0; | 
 | 293 | } |