Commit 6b0084266c1d4917ad9259759a1e7bd623cb3888

Authored by Jonas Bonn
Committed by Dave Airlie
1 parent 77d26dc9b9

drm: set/clear is_master when master changed

The variable is_master is being used to track the drm_file that is currently
master, so its value needs to be updated accordingly when the master is
changed.

Signed-off-by: Jonas Bonn <jonas@southpole.se>
Signed-off-by: Dave Airlie <airlied@redhat.com>

Showing 1 changed file with 7 additions and 1 deletions Inline Diff

drivers/gpu/drm/drm_stub.c
1 /** 1 /**
2 * \file drm_stub.h 2 * \file drm_stub.h
3 * Stub support 3 * Stub support
4 * 4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com> 5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 */ 6 */
7 7
8 /* 8 /*
9 * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org 9 * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
10 * 10 *
11 * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. 11 * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved. 12 * All Rights Reserved.
13 * 13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a 14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"), 15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation 16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 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 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: 19 * Software is furnished to do so, subject to the following conditions:
20 * 20 *
21 * The above copyright notice and this permission notice (including the next 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 22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software. 23 * Software.
24 * 24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 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, 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 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 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, 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 30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE. 31 * DEALINGS IN THE SOFTWARE.
32 */ 32 */
33 33
34 #include <linux/module.h> 34 #include <linux/module.h>
35 #include <linux/moduleparam.h> 35 #include <linux/moduleparam.h>
36 #include "drmP.h" 36 #include "drmP.h"
37 #include "drm_core.h" 37 #include "drm_core.h"
38 38
39 unsigned int drm_debug = 0; /* 1 to enable debug output */ 39 unsigned int drm_debug = 0; /* 1 to enable debug output */
40 EXPORT_SYMBOL(drm_debug); 40 EXPORT_SYMBOL(drm_debug);
41 41
42 MODULE_AUTHOR(CORE_AUTHOR); 42 MODULE_AUTHOR(CORE_AUTHOR);
43 MODULE_DESCRIPTION(CORE_DESC); 43 MODULE_DESCRIPTION(CORE_DESC);
44 MODULE_LICENSE("GPL and additional rights"); 44 MODULE_LICENSE("GPL and additional rights");
45 MODULE_PARM_DESC(debug, "Enable debug output"); 45 MODULE_PARM_DESC(debug, "Enable debug output");
46 46
47 module_param_named(debug, drm_debug, int, 0600); 47 module_param_named(debug, drm_debug, int, 0600);
48 48
49 struct idr drm_minors_idr; 49 struct idr drm_minors_idr;
50 50
51 struct class *drm_class; 51 struct class *drm_class;
52 struct proc_dir_entry *drm_proc_root; 52 struct proc_dir_entry *drm_proc_root;
53 struct dentry *drm_debugfs_root; 53 struct dentry *drm_debugfs_root;
54 54
55 static int drm_minor_get_id(struct drm_device *dev, int type) 55 static int drm_minor_get_id(struct drm_device *dev, int type)
56 { 56 {
57 int new_id; 57 int new_id;
58 int ret; 58 int ret;
59 int base = 0, limit = 63; 59 int base = 0, limit = 63;
60 60
61 if (type == DRM_MINOR_CONTROL) { 61 if (type == DRM_MINOR_CONTROL) {
62 base += 64; 62 base += 64;
63 limit = base + 127; 63 limit = base + 127;
64 } else if (type == DRM_MINOR_RENDER) { 64 } else if (type == DRM_MINOR_RENDER) {
65 base += 128; 65 base += 128;
66 limit = base + 255; 66 limit = base + 255;
67 } 67 }
68 68
69 again: 69 again:
70 if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { 70 if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
71 DRM_ERROR("Out of memory expanding drawable idr\n"); 71 DRM_ERROR("Out of memory expanding drawable idr\n");
72 return -ENOMEM; 72 return -ENOMEM;
73 } 73 }
74 mutex_lock(&dev->struct_mutex); 74 mutex_lock(&dev->struct_mutex);
75 ret = idr_get_new_above(&drm_minors_idr, NULL, 75 ret = idr_get_new_above(&drm_minors_idr, NULL,
76 base, &new_id); 76 base, &new_id);
77 mutex_unlock(&dev->struct_mutex); 77 mutex_unlock(&dev->struct_mutex);
78 if (ret == -EAGAIN) { 78 if (ret == -EAGAIN) {
79 goto again; 79 goto again;
80 } else if (ret) { 80 } else if (ret) {
81 return ret; 81 return ret;
82 } 82 }
83 83
84 if (new_id >= limit) { 84 if (new_id >= limit) {
85 idr_remove(&drm_minors_idr, new_id); 85 idr_remove(&drm_minors_idr, new_id);
86 return -EINVAL; 86 return -EINVAL;
87 } 87 }
88 return new_id; 88 return new_id;
89 } 89 }
90 90
91 struct drm_master *drm_master_create(struct drm_minor *minor) 91 struct drm_master *drm_master_create(struct drm_minor *minor)
92 { 92 {
93 struct drm_master *master; 93 struct drm_master *master;
94 94
95 master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER); 95 master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
96 if (!master) 96 if (!master)
97 return NULL; 97 return NULL;
98 98
99 kref_init(&master->refcount); 99 kref_init(&master->refcount);
100 spin_lock_init(&master->lock.spinlock); 100 spin_lock_init(&master->lock.spinlock);
101 init_waitqueue_head(&master->lock.lock_queue); 101 init_waitqueue_head(&master->lock.lock_queue);
102 drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); 102 drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
103 INIT_LIST_HEAD(&master->magicfree); 103 INIT_LIST_HEAD(&master->magicfree);
104 master->minor = minor; 104 master->minor = minor;
105 105
106 list_add_tail(&master->head, &minor->master_list); 106 list_add_tail(&master->head, &minor->master_list);
107 107
108 return master; 108 return master;
109 } 109 }
110 110
111 struct drm_master *drm_master_get(struct drm_master *master) 111 struct drm_master *drm_master_get(struct drm_master *master)
112 { 112 {
113 kref_get(&master->refcount); 113 kref_get(&master->refcount);
114 return master; 114 return master;
115 } 115 }
116 116
117 static void drm_master_destroy(struct kref *kref) 117 static void drm_master_destroy(struct kref *kref)
118 { 118 {
119 struct drm_master *master = container_of(kref, struct drm_master, refcount); 119 struct drm_master *master = container_of(kref, struct drm_master, refcount);
120 struct drm_magic_entry *pt, *next; 120 struct drm_magic_entry *pt, *next;
121 struct drm_device *dev = master->minor->dev; 121 struct drm_device *dev = master->minor->dev;
122 struct drm_map_list *r_list, *list_temp; 122 struct drm_map_list *r_list, *list_temp;
123 123
124 list_del(&master->head); 124 list_del(&master->head);
125 125
126 if (dev->driver->master_destroy) 126 if (dev->driver->master_destroy)
127 dev->driver->master_destroy(dev, master); 127 dev->driver->master_destroy(dev, master);
128 128
129 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) { 129 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
130 if (r_list->master == master) { 130 if (r_list->master == master) {
131 drm_rmmap_locked(dev, r_list->map); 131 drm_rmmap_locked(dev, r_list->map);
132 r_list = NULL; 132 r_list = NULL;
133 } 133 }
134 } 134 }
135 135
136 if (master->unique) { 136 if (master->unique) {
137 drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER); 137 drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER);
138 master->unique = NULL; 138 master->unique = NULL;
139 master->unique_len = 0; 139 master->unique_len = 0;
140 } 140 }
141 141
142 list_for_each_entry_safe(pt, next, &master->magicfree, head) { 142 list_for_each_entry_safe(pt, next, &master->magicfree, head) {
143 list_del(&pt->head); 143 list_del(&pt->head);
144 drm_ht_remove_item(&master->magiclist, &pt->hash_item); 144 drm_ht_remove_item(&master->magiclist, &pt->hash_item);
145 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); 145 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
146 } 146 }
147 147
148 drm_ht_remove(&master->magiclist); 148 drm_ht_remove(&master->magiclist);
149 149
150 drm_free(master, sizeof(*master), DRM_MEM_DRIVER); 150 drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
151 } 151 }
152 152
153 void drm_master_put(struct drm_master **master) 153 void drm_master_put(struct drm_master **master)
154 { 154 {
155 kref_put(&(*master)->refcount, drm_master_destroy); 155 kref_put(&(*master)->refcount, drm_master_destroy);
156 *master = NULL; 156 *master = NULL;
157 } 157 }
158 158
159 int drm_setmaster_ioctl(struct drm_device *dev, void *data, 159 int drm_setmaster_ioctl(struct drm_device *dev, void *data,
160 struct drm_file *file_priv) 160 struct drm_file *file_priv)
161 { 161 {
162 if (file_priv->is_master)
163 return 0;
164
162 if (file_priv->minor->master && file_priv->minor->master != file_priv->master) 165 if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
163 return -EINVAL; 166 return -EINVAL;
164 167
165 if (!file_priv->master) 168 if (!file_priv->master)
166 return -EINVAL; 169 return -EINVAL;
167 170
168 if (!file_priv->minor->master && 171 if (!file_priv->minor->master &&
169 file_priv->minor->master != file_priv->master) { 172 file_priv->minor->master != file_priv->master) {
170 mutex_lock(&dev->struct_mutex); 173 mutex_lock(&dev->struct_mutex);
171 file_priv->minor->master = drm_master_get(file_priv->master); 174 file_priv->minor->master = drm_master_get(file_priv->master);
175 file_priv->is_master = 1;
172 mutex_unlock(&dev->struct_mutex); 176 mutex_unlock(&dev->struct_mutex);
173 } 177 }
174 178
175 return 0; 179 return 0;
176 } 180 }
177 181
178 int drm_dropmaster_ioctl(struct drm_device *dev, void *data, 182 int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
179 struct drm_file *file_priv) 183 struct drm_file *file_priv)
180 { 184 {
181 if (!file_priv->master) 185 if (!file_priv->is_master)
182 return -EINVAL; 186 return -EINVAL;
187
183 mutex_lock(&dev->struct_mutex); 188 mutex_lock(&dev->struct_mutex);
184 drm_master_put(&file_priv->minor->master); 189 drm_master_put(&file_priv->minor->master);
190 file_priv->is_master = 0;
185 mutex_unlock(&dev->struct_mutex); 191 mutex_unlock(&dev->struct_mutex);
186 return 0; 192 return 0;
187 } 193 }
188 194
189 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, 195 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
190 const struct pci_device_id *ent, 196 const struct pci_device_id *ent,
191 struct drm_driver *driver) 197 struct drm_driver *driver)
192 { 198 {
193 int retcode; 199 int retcode;
194 200
195 INIT_LIST_HEAD(&dev->filelist); 201 INIT_LIST_HEAD(&dev->filelist);
196 INIT_LIST_HEAD(&dev->ctxlist); 202 INIT_LIST_HEAD(&dev->ctxlist);
197 INIT_LIST_HEAD(&dev->vmalist); 203 INIT_LIST_HEAD(&dev->vmalist);
198 INIT_LIST_HEAD(&dev->maplist); 204 INIT_LIST_HEAD(&dev->maplist);
199 205
200 spin_lock_init(&dev->count_lock); 206 spin_lock_init(&dev->count_lock);
201 spin_lock_init(&dev->drw_lock); 207 spin_lock_init(&dev->drw_lock);
202 init_timer(&dev->timer); 208 init_timer(&dev->timer);
203 mutex_init(&dev->struct_mutex); 209 mutex_init(&dev->struct_mutex);
204 mutex_init(&dev->ctxlist_mutex); 210 mutex_init(&dev->ctxlist_mutex);
205 211
206 idr_init(&dev->drw_idr); 212 idr_init(&dev->drw_idr);
207 213
208 dev->pdev = pdev; 214 dev->pdev = pdev;
209 dev->pci_device = pdev->device; 215 dev->pci_device = pdev->device;
210 dev->pci_vendor = pdev->vendor; 216 dev->pci_vendor = pdev->vendor;
211 217
212 #ifdef __alpha__ 218 #ifdef __alpha__
213 dev->hose = pdev->sysdata; 219 dev->hose = pdev->sysdata;
214 #endif 220 #endif
215 221
216 if (drm_ht_create(&dev->map_hash, 12)) { 222 if (drm_ht_create(&dev->map_hash, 12)) {
217 return -ENOMEM; 223 return -ENOMEM;
218 } 224 }
219 225
220 /* the DRM has 6 basic counters */ 226 /* the DRM has 6 basic counters */
221 dev->counters = 6; 227 dev->counters = 6;
222 dev->types[0] = _DRM_STAT_LOCK; 228 dev->types[0] = _DRM_STAT_LOCK;
223 dev->types[1] = _DRM_STAT_OPENS; 229 dev->types[1] = _DRM_STAT_OPENS;
224 dev->types[2] = _DRM_STAT_CLOSES; 230 dev->types[2] = _DRM_STAT_CLOSES;
225 dev->types[3] = _DRM_STAT_IOCTLS; 231 dev->types[3] = _DRM_STAT_IOCTLS;
226 dev->types[4] = _DRM_STAT_LOCKS; 232 dev->types[4] = _DRM_STAT_LOCKS;
227 dev->types[5] = _DRM_STAT_UNLOCKS; 233 dev->types[5] = _DRM_STAT_UNLOCKS;
228 234
229 dev->driver = driver; 235 dev->driver = driver;
230 236
231 if (drm_core_has_AGP(dev)) { 237 if (drm_core_has_AGP(dev)) {
232 if (drm_device_is_agp(dev)) 238 if (drm_device_is_agp(dev))
233 dev->agp = drm_agp_init(dev); 239 dev->agp = drm_agp_init(dev);
234 if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) 240 if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
235 && (dev->agp == NULL)) { 241 && (dev->agp == NULL)) {
236 DRM_ERROR("Cannot initialize the agpgart module.\n"); 242 DRM_ERROR("Cannot initialize the agpgart module.\n");
237 retcode = -EINVAL; 243 retcode = -EINVAL;
238 goto error_out_unreg; 244 goto error_out_unreg;
239 } 245 }
240 if (drm_core_has_MTRR(dev)) { 246 if (drm_core_has_MTRR(dev)) {
241 if (dev->agp) 247 if (dev->agp)
242 dev->agp->agp_mtrr = 248 dev->agp->agp_mtrr =
243 mtrr_add(dev->agp->agp_info.aper_base, 249 mtrr_add(dev->agp->agp_info.aper_base,
244 dev->agp->agp_info.aper_size * 250 dev->agp->agp_info.aper_size *
245 1024 * 1024, MTRR_TYPE_WRCOMB, 1); 251 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
246 } 252 }
247 } 253 }
248 254
249 255
250 retcode = drm_ctxbitmap_init(dev); 256 retcode = drm_ctxbitmap_init(dev);
251 if (retcode) { 257 if (retcode) {
252 DRM_ERROR("Cannot allocate memory for context bitmap.\n"); 258 DRM_ERROR("Cannot allocate memory for context bitmap.\n");
253 goto error_out_unreg; 259 goto error_out_unreg;
254 } 260 }
255 261
256 if (driver->driver_features & DRIVER_GEM) { 262 if (driver->driver_features & DRIVER_GEM) {
257 retcode = drm_gem_init(dev); 263 retcode = drm_gem_init(dev);
258 if (retcode) { 264 if (retcode) {
259 DRM_ERROR("Cannot initialize graphics execution " 265 DRM_ERROR("Cannot initialize graphics execution "
260 "manager (GEM)\n"); 266 "manager (GEM)\n");
261 goto error_out_unreg; 267 goto error_out_unreg;
262 } 268 }
263 } 269 }
264 270
265 return 0; 271 return 0;
266 272
267 error_out_unreg: 273 error_out_unreg:
268 drm_lastclose(dev); 274 drm_lastclose(dev);
269 return retcode; 275 return retcode;
270 } 276 }
271 277
272 278
273 /** 279 /**
274 * Get a secondary minor number. 280 * Get a secondary minor number.
275 * 281 *
276 * \param dev device data structure 282 * \param dev device data structure
277 * \param sec-minor structure to hold the assigned minor 283 * \param sec-minor structure to hold the assigned minor
278 * \return negative number on failure. 284 * \return negative number on failure.
279 * 285 *
280 * Search an empty entry and initialize it to the given parameters, and 286 * Search an empty entry and initialize it to the given parameters, and
281 * create the proc init entry via proc_init(). This routines assigns 287 * create the proc init entry via proc_init(). This routines assigns
282 * minor numbers to secondary heads of multi-headed cards 288 * minor numbers to secondary heads of multi-headed cards
283 */ 289 */
284 static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) 290 static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
285 { 291 {
286 struct drm_minor *new_minor; 292 struct drm_minor *new_minor;
287 int ret; 293 int ret;
288 int minor_id; 294 int minor_id;
289 295
290 DRM_DEBUG("\n"); 296 DRM_DEBUG("\n");
291 297
292 minor_id = drm_minor_get_id(dev, type); 298 minor_id = drm_minor_get_id(dev, type);
293 if (minor_id < 0) 299 if (minor_id < 0)
294 return minor_id; 300 return minor_id;
295 301
296 new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); 302 new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
297 if (!new_minor) { 303 if (!new_minor) {
298 ret = -ENOMEM; 304 ret = -ENOMEM;
299 goto err_idr; 305 goto err_idr;
300 } 306 }
301 307
302 new_minor->type = type; 308 new_minor->type = type;
303 new_minor->device = MKDEV(DRM_MAJOR, minor_id); 309 new_minor->device = MKDEV(DRM_MAJOR, minor_id);
304 new_minor->dev = dev; 310 new_minor->dev = dev;
305 new_minor->index = minor_id; 311 new_minor->index = minor_id;
306 INIT_LIST_HEAD(&new_minor->master_list); 312 INIT_LIST_HEAD(&new_minor->master_list);
307 313
308 idr_replace(&drm_minors_idr, new_minor, minor_id); 314 idr_replace(&drm_minors_idr, new_minor, minor_id);
309 315
310 if (type == DRM_MINOR_LEGACY) { 316 if (type == DRM_MINOR_LEGACY) {
311 ret = drm_proc_init(new_minor, minor_id, drm_proc_root); 317 ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
312 if (ret) { 318 if (ret) {
313 DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); 319 DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
314 goto err_mem; 320 goto err_mem;
315 } 321 }
316 } else 322 } else
317 new_minor->proc_root = NULL; 323 new_minor->proc_root = NULL;
318 324
319 #if defined(CONFIG_DEBUG_FS) 325 #if defined(CONFIG_DEBUG_FS)
320 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root); 326 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
321 if (ret) { 327 if (ret) {
322 DRM_ERROR("DRM: Failed to initialize /debugfs/dri.\n"); 328 DRM_ERROR("DRM: Failed to initialize /debugfs/dri.\n");
323 goto err_g2; 329 goto err_g2;
324 } 330 }
325 #endif 331 #endif
326 332
327 ret = drm_sysfs_device_add(new_minor); 333 ret = drm_sysfs_device_add(new_minor);
328 if (ret) { 334 if (ret) {
329 printk(KERN_ERR 335 printk(KERN_ERR
330 "DRM: Error sysfs_device_add.\n"); 336 "DRM: Error sysfs_device_add.\n");
331 goto err_g2; 337 goto err_g2;
332 } 338 }
333 *minor = new_minor; 339 *minor = new_minor;
334 340
335 DRM_DEBUG("new minor assigned %d\n", minor_id); 341 DRM_DEBUG("new minor assigned %d\n", minor_id);
336 return 0; 342 return 0;
337 343
338 344
339 err_g2: 345 err_g2:
340 if (new_minor->type == DRM_MINOR_LEGACY) 346 if (new_minor->type == DRM_MINOR_LEGACY)
341 drm_proc_cleanup(new_minor, drm_proc_root); 347 drm_proc_cleanup(new_minor, drm_proc_root);
342 err_mem: 348 err_mem:
343 kfree(new_minor); 349 kfree(new_minor);
344 err_idr: 350 err_idr:
345 idr_remove(&drm_minors_idr, minor_id); 351 idr_remove(&drm_minors_idr, minor_id);
346 *minor = NULL; 352 *minor = NULL;
347 return ret; 353 return ret;
348 } 354 }
349 355
350 /** 356 /**
351 * Register. 357 * Register.
352 * 358 *
353 * \param pdev - PCI device structure 359 * \param pdev - PCI device structure
354 * \param ent entry from the PCI ID table with device type flags 360 * \param ent entry from the PCI ID table with device type flags
355 * \return zero on success or a negative number on failure. 361 * \return zero on success or a negative number on failure.
356 * 362 *
357 * Attempt to gets inter module "drm" information. If we are first 363 * Attempt to gets inter module "drm" information. If we are first
358 * then register the character device and inter module information. 364 * then register the character device and inter module information.
359 * Try and register, if we fail to register, backout previous work. 365 * Try and register, if we fail to register, backout previous work.
360 */ 366 */
361 int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, 367 int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
362 struct drm_driver *driver) 368 struct drm_driver *driver)
363 { 369 {
364 struct drm_device *dev; 370 struct drm_device *dev;
365 int ret; 371 int ret;
366 372
367 DRM_DEBUG("\n"); 373 DRM_DEBUG("\n");
368 374
369 dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB); 375 dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
370 if (!dev) 376 if (!dev)
371 return -ENOMEM; 377 return -ENOMEM;
372 378
373 ret = pci_enable_device(pdev); 379 ret = pci_enable_device(pdev);
374 if (ret) 380 if (ret)
375 goto err_g1; 381 goto err_g1;
376 382
377 pci_set_master(pdev); 383 pci_set_master(pdev);
378 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { 384 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
379 printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); 385 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
380 goto err_g2; 386 goto err_g2;
381 } 387 }
382 388
383 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 389 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
384 pci_set_drvdata(pdev, dev); 390 pci_set_drvdata(pdev, dev);
385 ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); 391 ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
386 if (ret) 392 if (ret)
387 goto err_g2; 393 goto err_g2;
388 } 394 }
389 395
390 if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) 396 if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
391 goto err_g3; 397 goto err_g3;
392 398
393 if (dev->driver->load) { 399 if (dev->driver->load) {
394 ret = dev->driver->load(dev, ent->driver_data); 400 ret = dev->driver->load(dev, ent->driver_data);
395 if (ret) 401 if (ret)
396 goto err_g3; 402 goto err_g3;
397 } 403 }
398 404
399 /* setup the grouping for the legacy output */ 405 /* setup the grouping for the legacy output */
400 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 406 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
401 ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); 407 ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
402 if (ret) 408 if (ret)
403 goto err_g3; 409 goto err_g3;
404 } 410 }
405 411
406 list_add_tail(&dev->driver_item, &driver->device_list); 412 list_add_tail(&dev->driver_item, &driver->device_list);
407 413
408 DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", 414 DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
409 driver->name, driver->major, driver->minor, driver->patchlevel, 415 driver->name, driver->major, driver->minor, driver->patchlevel,
410 driver->date, pci_name(pdev), dev->primary->index); 416 driver->date, pci_name(pdev), dev->primary->index);
411 417
412 return 0; 418 return 0;
413 419
414 err_g3: 420 err_g3:
415 drm_put_minor(&dev->primary); 421 drm_put_minor(&dev->primary);
416 err_g2: 422 err_g2:
417 pci_disable_device(pdev); 423 pci_disable_device(pdev);
418 err_g1: 424 err_g1:
419 drm_free(dev, sizeof(*dev), DRM_MEM_STUB); 425 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
420 return ret; 426 return ret;
421 } 427 }
422 EXPORT_SYMBOL(drm_get_dev); 428 EXPORT_SYMBOL(drm_get_dev);
423 429
424 /** 430 /**
425 * Put a secondary minor number. 431 * Put a secondary minor number.
426 * 432 *
427 * \param sec_minor - structure to be released 433 * \param sec_minor - structure to be released
428 * \return always zero 434 * \return always zero
429 * 435 *
430 * Cleans up the proc resources. Not legal for this to be the 436 * Cleans up the proc resources. Not legal for this to be the
431 * last minor released. 437 * last minor released.
432 * 438 *
433 */ 439 */
434 int drm_put_minor(struct drm_minor **minor_p) 440 int drm_put_minor(struct drm_minor **minor_p)
435 { 441 {
436 struct drm_minor *minor = *minor_p; 442 struct drm_minor *minor = *minor_p;
437 443
438 DRM_DEBUG("release secondary minor %d\n", minor->index); 444 DRM_DEBUG("release secondary minor %d\n", minor->index);
439 445
440 if (minor->type == DRM_MINOR_LEGACY) 446 if (minor->type == DRM_MINOR_LEGACY)
441 drm_proc_cleanup(minor, drm_proc_root); 447 drm_proc_cleanup(minor, drm_proc_root);
442 #if defined(CONFIG_DEBUG_FS) 448 #if defined(CONFIG_DEBUG_FS)
443 drm_debugfs_cleanup(minor); 449 drm_debugfs_cleanup(minor);
444 #endif 450 #endif
445 451
446 drm_sysfs_device_remove(minor); 452 drm_sysfs_device_remove(minor);
447 453
448 idr_remove(&drm_minors_idr, minor->index); 454 idr_remove(&drm_minors_idr, minor->index);
449 455
450 kfree(minor); 456 kfree(minor);
451 *minor_p = NULL; 457 *minor_p = NULL;
452 return 0; 458 return 0;
453 } 459 }
454 460
455 /** 461 /**
456 * Called via drm_exit() at module unload time or when pci device is 462 * Called via drm_exit() at module unload time or when pci device is
457 * unplugged. 463 * unplugged.
458 * 464 *
459 * Cleans up all DRM device, calling drm_lastclose(). 465 * Cleans up all DRM device, calling drm_lastclose().
460 * 466 *
461 * \sa drm_init 467 * \sa drm_init
462 */ 468 */
463 void drm_put_dev(struct drm_device *dev) 469 void drm_put_dev(struct drm_device *dev)
464 { 470 {
465 struct drm_driver *driver = dev->driver; 471 struct drm_driver *driver = dev->driver;
466 struct drm_map_list *r_list, *list_temp; 472 struct drm_map_list *r_list, *list_temp;
467 473
468 DRM_DEBUG("\n"); 474 DRM_DEBUG("\n");
469 475
470 if (!dev) { 476 if (!dev) {
471 DRM_ERROR("cleanup called no dev\n"); 477 DRM_ERROR("cleanup called no dev\n");
472 return; 478 return;
473 } 479 }
474 480
475 drm_vblank_cleanup(dev); 481 drm_vblank_cleanup(dev);
476 482
477 drm_lastclose(dev); 483 drm_lastclose(dev);
478 484
479 if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && 485 if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
480 dev->agp && dev->agp->agp_mtrr >= 0) { 486 dev->agp && dev->agp->agp_mtrr >= 0) {
481 int retval; 487 int retval;
482 retval = mtrr_del(dev->agp->agp_mtrr, 488 retval = mtrr_del(dev->agp->agp_mtrr,
483 dev->agp->agp_info.aper_base, 489 dev->agp->agp_info.aper_base,
484 dev->agp->agp_info.aper_size * 1024 * 1024); 490 dev->agp->agp_info.aper_size * 1024 * 1024);
485 DRM_DEBUG("mtrr_del=%d\n", retval); 491 DRM_DEBUG("mtrr_del=%d\n", retval);
486 } 492 }
487 493
488 if (dev->driver->unload) 494 if (dev->driver->unload)
489 dev->driver->unload(dev); 495 dev->driver->unload(dev);
490 496
491 if (drm_core_has_AGP(dev) && dev->agp) { 497 if (drm_core_has_AGP(dev) && dev->agp) {
492 drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); 498 drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
493 dev->agp = NULL; 499 dev->agp = NULL;
494 } 500 }
495 501
496 drm_ht_remove(&dev->map_hash); 502 drm_ht_remove(&dev->map_hash);
497 drm_ctxbitmap_cleanup(dev); 503 drm_ctxbitmap_cleanup(dev);
498 504
499 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 505 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
500 drm_rmmap(dev, r_list->map); 506 drm_rmmap(dev, r_list->map);
501 507
502 if (drm_core_check_feature(dev, DRIVER_MODESET)) 508 if (drm_core_check_feature(dev, DRIVER_MODESET))
503 drm_put_minor(&dev->control); 509 drm_put_minor(&dev->control);
504 510
505 if (driver->driver_features & DRIVER_GEM) 511 if (driver->driver_features & DRIVER_GEM)
506 drm_gem_destroy(dev); 512 drm_gem_destroy(dev);
507 513
508 drm_put_minor(&dev->primary); 514 drm_put_minor(&dev->primary);
509 515
510 if (dev->devname) { 516 if (dev->devname) {
511 drm_free(dev->devname, strlen(dev->devname) + 1, 517 drm_free(dev->devname, strlen(dev->devname) + 1,
512 DRM_MEM_DRIVER); 518 DRM_MEM_DRIVER);
513 dev->devname = NULL; 519 dev->devname = NULL;
514 } 520 }
515 drm_free(dev, sizeof(*dev), DRM_MEM_STUB); 521 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
516 } 522 }
517 EXPORT_SYMBOL(drm_put_dev); 523 EXPORT_SYMBOL(drm_put_dev);
518 524