aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_drv.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/drm_drv.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
-rw-r--r--drivers/gpu/drm/drm_drv.c540
1 files changed, 540 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
new file mode 100644
index 000000000000..564138714bb5
--- /dev/null
+++ b/drivers/gpu/drm/drm_drv.c
@@ -0,0 +1,540 @@
1/**
2 * \file drm_drv.c
3 * Generic driver template
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 *
8 * To use this template, you must at least define the following (samples
9 * given for the MGA driver):
10 *
11 * \code
12 * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
13 *
14 * #define DRIVER_NAME "mga"
15 * #define DRIVER_DESC "Matrox G200/G400"
16 * #define DRIVER_DATE "20001127"
17 *
18 * #define drm_x mga_##x
19 * \endcode
20 */
21
22/*
23 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
24 *
25 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
26 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
27 * All Rights Reserved.
28 *
29 * Permission is hereby granted, free of charge, to any person obtaining a
30 * copy of this software and associated documentation files (the "Software"),
31 * to deal in the Software without restriction, including without limitation
32 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
33 * and/or sell copies of the Software, and to permit persons to whom the
34 * Software is furnished to do so, subject to the following conditions:
35 *
36 * The above copyright notice and this permission notice (including the next
37 * paragraph) shall be included in all copies or substantial portions of the
38 * Software.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 * OTHER DEALINGS IN THE SOFTWARE.
47 */
48
49#include "drmP.h"
50#include "drm_core.h"
51
52static int drm_version(struct drm_device *dev, void *data,
53 struct drm_file *file_priv);
54
55/** Ioctl table */
56static struct drm_ioctl_desc drm_ioctls[] = {
57 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
58 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
59 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
60 DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
61 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
62 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
63 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
64 DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
65
66 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
67 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
68 DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
69 DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
70
71 DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
72 DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
73
74 DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
75 DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
76
77 DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
78 DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
79 DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
80 DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
81 DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
82 DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
83 DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
84
85 DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
86 DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
87
88 DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
89 DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
90
91 DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
92
93 DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
94 DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
95 DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
96 DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
97 DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
98 /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
99 DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
100
101 DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
102
103#if __OS_HAS_AGP
104 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
105 DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
106 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
107 DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
108 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
109 DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
110 DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
111 DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
112#endif
113
114 DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
115 DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
116
117 DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
118
119 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
120};
121
122#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
123
124/**
125 * Take down the DRM device.
126 *
127 * \param dev DRM device structure.
128 *
129 * Frees every resource in \p dev.
130 *
131 * \sa drm_device
132 */
133int drm_lastclose(struct drm_device * dev)
134{
135 struct drm_magic_entry *pt, *next;
136 struct drm_map_list *r_list, *list_t;
137 struct drm_vma_entry *vma, *vma_temp;
138 int i;
139
140 DRM_DEBUG("\n");
141
142 if (dev->driver->lastclose)
143 dev->driver->lastclose(dev);
144 DRM_DEBUG("driver lastclose completed\n");
145
146 if (dev->unique) {
147 drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
148 dev->unique = NULL;
149 dev->unique_len = 0;
150 }
151
152 if (dev->irq_enabled)
153 drm_irq_uninstall(dev);
154
155 mutex_lock(&dev->struct_mutex);
156
157 /* Free drawable information memory */
158 drm_drawable_free_all(dev);
159 del_timer(&dev->timer);
160
161 /* Clear pid list */
162 if (dev->magicfree.next) {
163 list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
164 list_del(&pt->head);
165 drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
166 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
167 }
168 drm_ht_remove(&dev->magiclist);
169 }
170
171 /* Clear AGP information */
172 if (drm_core_has_AGP(dev) && dev->agp) {
173 struct drm_agp_mem *entry, *tempe;
174
175 /* Remove AGP resources, but leave dev->agp
176 intact until drv_cleanup is called. */
177 list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
178 if (entry->bound)
179 drm_unbind_agp(entry->memory);
180 drm_free_agp(entry->memory, entry->pages);
181 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
182 }
183 INIT_LIST_HEAD(&dev->agp->memory);
184
185 if (dev->agp->acquired)
186 drm_agp_release(dev);
187
188 dev->agp->acquired = 0;
189 dev->agp->enabled = 0;
190 }
191 if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
192 drm_sg_cleanup(dev->sg);
193 dev->sg = NULL;
194 }
195
196 /* Clear vma list (only built for debugging) */
197 list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
198 list_del(&vma->head);
199 drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
200 }
201
202 list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
203 if (!(r_list->map->flags & _DRM_DRIVER)) {
204 drm_rmmap_locked(dev, r_list->map);
205 r_list = NULL;
206 }
207 }
208
209 if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
210 for (i = 0; i < dev->queue_count; i++) {
211 if (dev->queuelist[i]) {
212 drm_free(dev->queuelist[i],
213 sizeof(*dev->queuelist[0]),
214 DRM_MEM_QUEUES);
215 dev->queuelist[i] = NULL;
216 }
217 }
218 drm_free(dev->queuelist,
219 dev->queue_slots * sizeof(*dev->queuelist),
220 DRM_MEM_QUEUES);
221 dev->queuelist = NULL;
222 }
223 dev->queue_count = 0;
224
225 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
226 drm_dma_takedown(dev);
227
228 if (dev->lock.hw_lock) {
229 dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
230 dev->lock.file_priv = NULL;
231 wake_up_interruptible(&dev->lock.lock_queue);
232 }
233 mutex_unlock(&dev->struct_mutex);
234
235 DRM_DEBUG("lastclose completed\n");
236 return 0;
237}
238
239/**
240 * Module initialization. Called via init_module at module load time, or via
241 * linux/init/main.c (this is not currently supported).
242 *
243 * \return zero on success or a negative number on failure.
244 *
245 * Initializes an array of drm_device structures, and attempts to
246 * initialize all available devices, using consecutive minors, registering the
247 * stubs and initializing the AGP device.
248 *
249 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
250 * after the initialization for driver customization.
251 */
252int drm_init(struct drm_driver *driver)
253{
254 struct pci_dev *pdev = NULL;
255 struct pci_device_id *pid;
256 int i;
257
258 DRM_DEBUG("\n");
259
260 for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
261 pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
262
263 pdev = NULL;
264 /* pass back in pdev to account for multiple identical cards */
265 while ((pdev =
266 pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
267 pid->subdevice, pdev)) != NULL) {
268 /* stealth mode requires a manual probe */
269 pci_dev_get(pdev);
270 drm_get_dev(pdev, pid, driver);
271 }
272 }
273 return 0;
274}
275
276EXPORT_SYMBOL(drm_init);
277
278/**
279 * Called via cleanup_module() at module unload time.
280 *
281 * Cleans up all DRM device, calling drm_lastclose().
282 *
283 * \sa drm_init
284 */
285static void drm_cleanup(struct drm_device * dev)
286{
287 DRM_DEBUG("\n");
288
289 if (!dev) {
290 DRM_ERROR("cleanup called no dev\n");
291 return;
292 }
293
294 drm_lastclose(dev);
295
296 if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
297 dev->agp && dev->agp->agp_mtrr >= 0) {
298 int retval;
299 retval = mtrr_del(dev->agp->agp_mtrr,
300 dev->agp->agp_info.aper_base,
301 dev->agp->agp_info.aper_size * 1024 * 1024);
302 DRM_DEBUG("mtrr_del=%d\n", retval);
303 }
304
305 if (drm_core_has_AGP(dev) && dev->agp) {
306 drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
307 dev->agp = NULL;
308 }
309
310 if (dev->driver->unload)
311 dev->driver->unload(dev);
312
313 drm_ht_remove(&dev->map_hash);
314 drm_ctxbitmap_cleanup(dev);
315
316 drm_put_minor(&dev->primary);
317 if (drm_put_dev(dev))
318 DRM_ERROR("Cannot unload module\n");
319}
320
321int drm_minors_cleanup(int id, void *ptr, void *data)
322{
323 struct drm_minor *minor = ptr;
324 struct drm_device *dev;
325 struct drm_driver *driver = data;
326
327 dev = minor->dev;
328 if (minor->dev->driver != driver)
329 return 0;
330
331 if (minor->type != DRM_MINOR_LEGACY)
332 return 0;
333
334 if (dev)
335 pci_dev_put(dev->pdev);
336 drm_cleanup(dev);
337 return 1;
338}
339
340void drm_exit(struct drm_driver *driver)
341{
342 DRM_DEBUG("\n");
343
344 idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
345
346 DRM_INFO("Module unloaded\n");
347}
348
349EXPORT_SYMBOL(drm_exit);
350
351/** File operations structure */
352static const struct file_operations drm_stub_fops = {
353 .owner = THIS_MODULE,
354 .open = drm_stub_open
355};
356
357static int __init drm_core_init(void)
358{
359 int ret = -ENOMEM;
360
361 idr_init(&drm_minors_idr);
362
363 if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
364 goto err_p1;
365
366 drm_class = drm_sysfs_create(THIS_MODULE, "drm");
367 if (IS_ERR(drm_class)) {
368 printk(KERN_ERR "DRM: Error creating drm class.\n");
369 ret = PTR_ERR(drm_class);
370 goto err_p2;
371 }
372
373 drm_proc_root = proc_mkdir("dri", NULL);
374 if (!drm_proc_root) {
375 DRM_ERROR("Cannot create /proc/dri\n");
376 ret = -1;
377 goto err_p3;
378 }
379
380 drm_mem_init();
381
382 DRM_INFO("Initialized %s %d.%d.%d %s\n",
383 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
384 return 0;
385err_p3:
386 drm_sysfs_destroy();
387err_p2:
388 unregister_chrdev(DRM_MAJOR, "drm");
389
390 idr_destroy(&drm_minors_idr);
391err_p1:
392 return ret;
393}
394
395static void __exit drm_core_exit(void)
396{
397 remove_proc_entry("dri", NULL);
398 drm_sysfs_destroy();
399
400 unregister_chrdev(DRM_MAJOR, "drm");
401
402 idr_destroy(&drm_minors_idr);
403}
404
405module_init(drm_core_init);
406module_exit(drm_core_exit);
407
408/**
409 * Get version information
410 *
411 * \param inode device inode.
412 * \param filp file pointer.
413 * \param cmd command.
414 * \param arg user argument, pointing to a drm_version structure.
415 * \return zero on success or negative number on failure.
416 *
417 * Fills in the version information in \p arg.
418 */
419static int drm_version(struct drm_device *dev, void *data,
420 struct drm_file *file_priv)
421{
422 struct drm_version *version = data;
423 int len;
424
425 version->version_major = dev->driver->major;
426 version->version_minor = dev->driver->minor;
427 version->version_patchlevel = dev->driver->patchlevel;
428 DRM_COPY(version->name, dev->driver->name);
429 DRM_COPY(version->date, dev->driver->date);
430 DRM_COPY(version->desc, dev->driver->desc);
431
432 return 0;
433}
434
435/**
436 * Called whenever a process performs an ioctl on /dev/drm.
437 *
438 * \param inode device inode.
439 * \param file_priv DRM file private.
440 * \param cmd command.
441 * \param arg user argument.
442 * \return zero on success or negative number on failure.
443 *
444 * Looks up the ioctl function in the ::ioctls table, checking for root
445 * previleges if so required, and dispatches to the respective function.
446 */
447int drm_ioctl(struct inode *inode, struct file *filp,
448 unsigned int cmd, unsigned long arg)
449{
450 struct drm_file *file_priv = filp->private_data;
451 struct drm_device *dev = file_priv->minor->dev;
452 struct drm_ioctl_desc *ioctl;
453 drm_ioctl_t *func;
454 unsigned int nr = DRM_IOCTL_NR(cmd);
455 int retcode = -EINVAL;
456 char *kdata = NULL;
457
458 atomic_inc(&dev->ioctl_count);
459 atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
460 ++file_priv->ioctl_count;
461
462 DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
463 task_pid_nr(current), cmd, nr,
464 (long)old_encode_dev(file_priv->minor->device),
465 file_priv->authenticated);
466
467 if ((nr >= DRM_CORE_IOCTL_COUNT) &&
468 ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
469 goto err_i1;
470 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
471 (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
472 ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
473 else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
474 ioctl = &drm_ioctls[nr];
475 cmd = ioctl->cmd;
476 } else
477 goto err_i1;
478
479 /* Do not trust userspace, use our own definition */
480 func = ioctl->func;
481 /* is there a local override? */
482 if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
483 func = dev->driver->dma_ioctl;
484
485 if (!func) {
486 DRM_DEBUG("no function\n");
487 retcode = -EINVAL;
488 } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
489 ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
490 ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
491 retcode = -EACCES;
492 } else {
493 if (cmd & (IOC_IN | IOC_OUT)) {
494 kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
495 if (!kdata) {
496 retcode = -ENOMEM;
497 goto err_i1;
498 }
499 }
500
501 if (cmd & IOC_IN) {
502 if (copy_from_user(kdata, (void __user *)arg,
503 _IOC_SIZE(cmd)) != 0) {
504 retcode = -EFAULT;
505 goto err_i1;
506 }
507 }
508 retcode = func(dev, kdata, file_priv);
509
510 if ((retcode == 0) && (cmd & IOC_OUT)) {
511 if (copy_to_user((void __user *)arg, kdata,
512 _IOC_SIZE(cmd)) != 0)
513 retcode = -EFAULT;
514 }
515 }
516
517 err_i1:
518 if (kdata)
519 kfree(kdata);
520 atomic_dec(&dev->ioctl_count);
521 if (retcode)
522 DRM_DEBUG("ret = %x\n", retcode);
523 return retcode;
524}
525
526EXPORT_SYMBOL(drm_ioctl);
527
528drm_local_map_t *drm_getsarea(struct drm_device *dev)
529{
530 struct drm_map_list *entry;
531
532 list_for_each_entry(entry, &dev->maplist, head) {
533 if (entry->map && entry->map->type == _DRM_SHM &&
534 (entry->map->flags & _DRM_CONTAINS_LOCK)) {
535 return entry->map;
536 }
537 }
538 return NULL;
539}
540EXPORT_SYMBOL(drm_getsarea);