1 /* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
2 *
3 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors: Kevin E. Martin <martin@valinux.com>
27 * Rickard E. (Rik) Faith <faith@valinux.com>
28 *
29 */
30
31 #include <linux/config.h>
32 #include "drmP.h"
33 #include "radeon_drv.h"
34
35 #define RADEON_NAME "radeon"
36 #define RADEON_DESC "ATI Radeon"
37 #define RADEON_DATE "20010105"
38 #define RADEON_MAJOR 1
39 #define RADEON_MINOR 0
40 #define RADEON_PATCHLEVEL 0
41
42 static drm_device_t radeon_device;
43 drm_ctx_t radeon_res_ctx;
44
45 static struct file_operations radeon_fops = {
46 #if LINUX_VERSION_CODE >= 0x020400
47 /* This started being used during 2.4.0-test */
48 owner: THIS_MODULE,
49 #endif
50 open: radeon_open,
51 flush: drm_flush,
52 release: radeon_release,
53 ioctl: radeon_ioctl,
54 mmap: drm_mmap,
55 read: drm_read,
56 fasync: drm_fasync,
57 poll: drm_poll,
58 };
59
60 static struct miscdevice radeon_misc = {
61 minor: MISC_DYNAMIC_MINOR,
62 name: RADEON_NAME,
63 fops: &radeon_fops,
64 };
65
66 static drm_ioctl_desc_t radeon_ioctls[] = {
67 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { radeon_version, 0, 0 },
68 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
69 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
70 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
71
72 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
73 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
74 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
75 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
76 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
77 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { radeon_addbufs, 1, 1 },
78 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
79 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
80 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { radeon_mapbufs, 1, 0 },
81 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
82
83 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { radeon_addctx, 1, 1 },
84 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { radeon_rmctx, 1, 1 },
85 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { radeon_modctx, 1, 1 },
86 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { radeon_getctx, 1, 0 },
87 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { radeon_switchctx, 1, 1 },
88 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { radeon_newctx, 1, 1 },
89 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { radeon_resctx, 1, 0 },
90 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
91 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
92 [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 },
93 [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { radeon_lock, 1, 0 },
94 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { radeon_unlock, 1, 0 },
95 [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
96
97 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
98 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
99 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
100 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
101 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
102 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
103 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
104 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
105 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
106 #endif
107
108 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
109 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
110 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
111 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
112 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
113 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
114 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
115
116 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
117 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
118 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
119 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
120 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 },
121 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
122 [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]= { radeon_cp_indirect,1, 1 },
123 };
124 #define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls)
125
126 #ifdef MODULE
127 static char *radeon = NULL;
128 #endif
129
130 MODULE_AUTHOR("VA Linux Systems, Inc.");
131 MODULE_DESCRIPTION("radeon");
132 MODULE_LICENSE("GPL and additional rights");
133 MODULE_PARM(radeon, "s");
134
135 #ifndef MODULE
136 /* radeon_options is called by the kernel to parse command-line options
137 * passed via the boot-loader (e.g., LILO). It calls the insmod option
138 * routine, drm_parse_drm.
139 */
140
radeon_options(char * str)141 static int __init radeon_options(char *str)
142 {
143 drm_parse_options(str);
144 return 1;
145 }
146
147 __setup("radeon=", radeon_options);
148 #endif
149
radeon_setup(drm_device_t * dev)150 static int radeon_setup(drm_device_t *dev)
151 {
152 int i;
153
154 atomic_set(&dev->ioctl_count, 0);
155 atomic_set(&dev->vma_count, 0);
156 dev->buf_use = 0;
157 atomic_set(&dev->buf_alloc, 0);
158
159 drm_dma_setup(dev);
160
161 atomic_set(&dev->total_open, 0);
162 atomic_set(&dev->total_close, 0);
163 atomic_set(&dev->total_ioctl, 0);
164 atomic_set(&dev->total_irq, 0);
165 atomic_set(&dev->total_ctx, 0);
166 atomic_set(&dev->total_locks, 0);
167 atomic_set(&dev->total_unlocks, 0);
168 atomic_set(&dev->total_contends, 0);
169 atomic_set(&dev->total_sleeps, 0);
170
171 for (i = 0; i < DRM_HASH_SIZE; i++) {
172 dev->magiclist[i].head = NULL;
173 dev->magiclist[i].tail = NULL;
174 }
175 dev->maplist = NULL;
176 dev->map_count = 0;
177 dev->vmalist = NULL;
178 dev->lock.hw_lock = NULL;
179 init_waitqueue_head(&dev->lock.lock_queue);
180 dev->queue_count = 0;
181 dev->queue_reserved = 0;
182 dev->queue_slots = 0;
183 dev->queuelist = NULL;
184 dev->irq = 0;
185 dev->context_flag = 0;
186 dev->interrupt_flag = 0;
187 dev->dma_flag = 0;
188 dev->last_context = 0;
189 dev->last_switch = 0;
190 dev->last_checked = 0;
191 init_timer(&dev->timer);
192 init_waitqueue_head(&dev->context_wait);
193
194 dev->ctx_start = 0;
195 dev->lck_start = 0;
196
197 dev->buf_rp = dev->buf;
198 dev->buf_wp = dev->buf;
199 dev->buf_end = dev->buf + DRM_BSZ;
200 dev->buf_async = NULL;
201 init_waitqueue_head(&dev->buf_readers);
202 init_waitqueue_head(&dev->buf_writers);
203
204 radeon_res_ctx.handle = -1;
205
206 DRM_DEBUG("\n");
207
208 /* The kernel's context could be created here, but is now created
209 in drm_dma_enqueue. This is more resource-efficient for
210 hardware that does not do DMA, but may mean that
211 drm_select_queue fails between the time the interrupt is
212 initialized and the time the queues are initialized. */
213
214 return 0;
215 }
216
217
radeon_takedown(drm_device_t * dev)218 static int radeon_takedown(drm_device_t *dev)
219 {
220 int i;
221 drm_magic_entry_t *pt, *next;
222 drm_map_t *map;
223 drm_vma_entry_t *vma, *vma_next;
224
225 DRM_DEBUG("\n");
226
227 down(&dev->struct_sem);
228 del_timer(&dev->timer);
229
230 if (dev->devname) {
231 drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
232 dev->devname = NULL;
233 }
234
235 if (dev->unique) {
236 drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
237 dev->unique = NULL;
238 dev->unique_len = 0;
239 }
240 /* Clear pid list */
241 for (i = 0; i < DRM_HASH_SIZE; i++) {
242 for (pt = dev->magiclist[i].head; pt; pt = next) {
243 next = pt->next;
244 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
245 }
246 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
247 }
248
249 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
250 /* Clear AGP information */
251 if (dev->agp) {
252 drm_agp_mem_t *entry;
253 drm_agp_mem_t *nexte;
254
255 /* Remove AGP resources, but leave dev->agp
256 intact until radeon_cleanup is called. */
257 for (entry = dev->agp->memory; entry; entry = nexte) {
258 nexte = entry->next;
259 if (entry->bound) drm_unbind_agp(entry->memory);
260 drm_free_agp(entry->memory, entry->pages);
261 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
262 }
263 dev->agp->memory = NULL;
264
265 if (dev->agp->acquired) _drm_agp_release();
266
267 dev->agp->acquired = 0;
268 dev->agp->enabled = 0;
269 }
270 #endif
271
272 /* Clear vma list (only built for debugging) */
273 if (dev->vmalist) {
274 for (vma = dev->vmalist; vma; vma = vma_next) {
275 vma_next = vma->next;
276 drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
277 }
278 dev->vmalist = NULL;
279 }
280
281 /* Clear map area and mtrr information */
282 if (dev->maplist) {
283 for (i = 0; i < dev->map_count; i++) {
284 map = dev->maplist[i];
285 switch (map->type) {
286 case _DRM_REGISTERS:
287 case _DRM_FRAME_BUFFER:
288 #ifdef CONFIG_MTRR
289 if (map->mtrr >= 0) {
290 int retcode;
291 retcode = mtrr_del(map->mtrr,
292 map->offset,
293 map->size);
294 DRM_DEBUG("mtrr_del = %d\n", retcode);
295 }
296 #endif
297 drm_ioremapfree(map->handle, map->size, dev);
298 break;
299 case _DRM_SHM:
300 drm_free_pages((unsigned long)map->handle,
301 drm_order(map->size)
302 - PAGE_SHIFT,
303 DRM_MEM_SAREA);
304 break;
305 case _DRM_AGP:
306 /* Do nothing here, because this is all
307 handled in the AGP/GART driver. */
308 break;
309 }
310 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
311 }
312 drm_free(dev->maplist,
313 dev->map_count * sizeof(*dev->maplist),
314 DRM_MEM_MAPS);
315 dev->maplist = NULL;
316 dev->map_count = 0;
317 }
318
319 drm_dma_takedown(dev);
320
321 dev->queue_count = 0;
322 if (dev->lock.hw_lock) {
323 dev->lock.hw_lock = NULL; /* SHM removed */
324 dev->lock.pid = 0;
325 wake_up_interruptible(&dev->lock.lock_queue);
326 }
327 up(&dev->struct_sem);
328
329 return 0;
330 }
331
332 /* radeon_init is called via init_module at module load time, or via
333 * linux/init/main.c (this is not currently supported). */
334
radeon_init(void)335 static int __init radeon_init(void)
336 {
337 int retcode;
338 drm_device_t *dev = &radeon_device;
339
340 DRM_DEBUG("\n");
341
342 memset((void *)dev, 0, sizeof(*dev));
343 dev->count_lock = SPIN_LOCK_UNLOCKED;
344 sema_init(&dev->struct_sem, 1);
345
346 #ifdef MODULE
347 drm_parse_options(radeon);
348 #endif
349
350 if ((retcode = misc_register(&radeon_misc))) {
351 DRM_ERROR("Cannot register \"%s\"\n", RADEON_NAME);
352 return retcode;
353 }
354 dev->device = MKDEV(MISC_MAJOR, radeon_misc.minor);
355 dev->name = RADEON_NAME;
356
357 drm_mem_init();
358 drm_proc_init(dev);
359
360 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
361 dev->agp = drm_agp_init();
362 if (dev->agp == NULL) {
363 DRM_ERROR("Cannot initialize agpgart module.\n");
364 drm_proc_cleanup();
365 misc_deregister(&radeon_misc);
366 radeon_takedown(dev);
367 return -ENOMEM;
368 }
369
370 #ifdef CONFIG_MTRR
371 dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
372 dev->agp->agp_info.aper_size*1024*1024,
373 MTRR_TYPE_WRCOMB,
374 1);
375 #endif
376 #endif
377
378 if((retcode = drm_ctxbitmap_init(dev))) {
379 DRM_ERROR("Cannot allocate memory for context bitmap.\n");
380 drm_proc_cleanup();
381 misc_deregister(&radeon_misc);
382 radeon_takedown(dev);
383 return retcode;
384 }
385
386 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
387 RADEON_NAME,
388 RADEON_MAJOR,
389 RADEON_MINOR,
390 RADEON_PATCHLEVEL,
391 RADEON_DATE,
392 radeon_misc.minor);
393
394 return 0;
395 }
396
397 /* radeon_cleanup is called via cleanup_module at module unload time. */
398
radeon_cleanup(void)399 static void __exit radeon_cleanup(void)
400 {
401 drm_device_t *dev = &radeon_device;
402
403 DRM_DEBUG("\n");
404
405 drm_proc_cleanup();
406 if (misc_deregister(&radeon_misc)) {
407 DRM_ERROR("Cannot unload module\n");
408 } else {
409 DRM_INFO("Module unloaded\n");
410 }
411 drm_ctxbitmap_cleanup(dev);
412 radeon_takedown(dev);
413 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
414 if (dev->agp) {
415 drm_agp_uninit();
416 drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
417 dev->agp = NULL;
418 }
419 #endif
420 }
421
422 module_init(radeon_init);
423 module_exit(radeon_cleanup);
424
425
radeon_version(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)426 int radeon_version(struct inode *inode, struct file *filp, unsigned int cmd,
427 unsigned long arg)
428 {
429 drm_version_t version;
430 int len;
431
432 if (copy_from_user(&version,
433 (drm_version_t *)arg,
434 sizeof(version)))
435 return -EFAULT;
436
437 #define DRM_COPY(name,value) \
438 len = strlen(value); \
439 if (len > name##_len) len = name##_len; \
440 name##_len = strlen(value); \
441 if (len && name) { \
442 if (copy_to_user(name, value, len)) \
443 return -EFAULT; \
444 }
445
446 version.version_major = RADEON_MAJOR;
447 version.version_minor = RADEON_MINOR;
448 version.version_patchlevel = RADEON_PATCHLEVEL;
449
450 DRM_COPY(version.name, RADEON_NAME);
451 DRM_COPY(version.date, RADEON_DATE);
452 DRM_COPY(version.desc, RADEON_DESC);
453
454 if (copy_to_user((drm_version_t *)arg,
455 &version,
456 sizeof(version)))
457 return -EFAULT;
458 return 0;
459 }
460
radeon_open(struct inode * inode,struct file * filp)461 int radeon_open(struct inode *inode, struct file *filp)
462 {
463 drm_device_t *dev = &radeon_device;
464 int retcode = 0;
465
466 DRM_DEBUG("open_count = %d\n", dev->open_count);
467 if (!(retcode = drm_open_helper(inode, filp, dev))) {
468 #if LINUX_VERSION_CODE < 0x020333
469 MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
470 #endif
471 atomic_inc(&dev->total_open);
472 spin_lock(&dev->count_lock);
473 if (!dev->open_count++) {
474 spin_unlock(&dev->count_lock);
475 return radeon_setup(dev);
476 }
477 spin_unlock(&dev->count_lock);
478 }
479
480 return retcode;
481 }
482
radeon_release(struct inode * inode,struct file * filp)483 int radeon_release(struct inode *inode, struct file *filp)
484 {
485 drm_file_t *priv = filp->private_data;
486 drm_device_t *dev;
487 int retcode = 0;
488
489 lock_kernel();
490 dev = priv->dev;
491
492 DRM_DEBUG("open_count = %d\n", dev->open_count);
493
494 /* Force the cleanup of page flipping when required */
495 if ( dev->dev_private ) {
496 drm_radeon_private_t *dev_priv = dev->dev_private;
497 if ( dev_priv->page_flipping ) {
498 radeon_do_cleanup_pageflip( dev );
499 }
500 }
501
502 if (!(retcode = drm_release(inode, filp))) {
503 #if LINUX_VERSION_CODE < 0x020333
504 MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
505 #endif
506 atomic_inc(&dev->total_close);
507 spin_lock(&dev->count_lock);
508 if (!--dev->open_count) {
509 if (atomic_read(&dev->ioctl_count) || dev->blocked) {
510 DRM_ERROR("Device busy: %d %d\n",
511 atomic_read(&dev->ioctl_count),
512 dev->blocked);
513 spin_unlock(&dev->count_lock);
514 unlock_kernel();
515 return -EBUSY;
516 }
517 spin_unlock(&dev->count_lock);
518 unlock_kernel();
519 return radeon_takedown(dev);
520 }
521 spin_unlock(&dev->count_lock);
522 }
523
524 unlock_kernel();
525 return retcode;
526 }
527
528 /* radeon_ioctl is called whenever a process performs an ioctl on /dev/drm. */
529
radeon_ioctl(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)530 int radeon_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
531 unsigned long arg)
532 {
533 int nr = DRM_IOCTL_NR(cmd);
534 drm_file_t *priv = filp->private_data;
535 drm_device_t *dev = priv->dev;
536 int retcode = 0;
537 drm_ioctl_desc_t *ioctl;
538 drm_ioctl_t *func;
539
540 atomic_inc(&dev->ioctl_count);
541 atomic_inc(&dev->total_ioctl);
542 ++priv->ioctl_count;
543
544 DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
545 current->pid, cmd, nr, dev->device, priv->authenticated);
546
547 if (nr >= RADEON_IOCTL_COUNT) {
548 retcode = -EINVAL;
549 } else {
550 ioctl = &radeon_ioctls[nr];
551 func = ioctl->func;
552
553 if (!func) {
554 DRM_DEBUG("no function\n");
555 retcode = -EINVAL;
556 } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
557 || (ioctl->auth_needed && !priv->authenticated)) {
558 retcode = -EACCES;
559 } else {
560 retcode = (func)(inode, filp, cmd, arg);
561 }
562 }
563
564 atomic_dec(&dev->ioctl_count);
565 return retcode;
566 }
567
radeon_lock(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)568 int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd,
569 unsigned long arg)
570 {
571 drm_file_t *priv = filp->private_data;
572 drm_device_t *dev = priv->dev;
573 DECLARE_WAITQUEUE(entry, current);
574 int ret = 0;
575 drm_lock_t lock;
576 #if DRM_DMA_HISTOGRAM
577 cycles_t start;
578
579 dev->lck_start = start = get_cycles();
580 #endif
581
582 if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
583 return -EFAULT;
584
585 if (lock.context == DRM_KERNEL_CONTEXT) {
586 DRM_ERROR("Process %d using kernel context %d\n",
587 current->pid, lock.context);
588 return -EINVAL;
589 }
590
591 DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
592 lock.context, current->pid, dev->lock.hw_lock->lock,
593 lock.flags);
594
595 if (lock.context < 0 /* || lock.context >= dev->queue_count */)
596 return -EINVAL;
597
598 if (!ret) {
599 add_wait_queue(&dev->lock.lock_queue, &entry);
600 for (;;) {
601 current->state = TASK_INTERRUPTIBLE;
602 if (!dev->lock.hw_lock) {
603 /* Device has been unregistered */
604 ret = -EINTR;
605 break;
606 }
607 if (drm_lock_take(&dev->lock.hw_lock->lock,
608 lock.context)) {
609 dev->lock.pid = current->pid;
610 dev->lock.lock_time = jiffies;
611 atomic_inc(&dev->total_locks);
612 break; /* Got lock */
613 }
614
615 /* Contention */
616 atomic_inc(&dev->total_sleeps);
617 schedule();
618 if (signal_pending(current)) {
619 ret = -ERESTARTSYS;
620 break;
621 }
622 }
623 current->state = TASK_RUNNING;
624 remove_wait_queue(&dev->lock.lock_queue, &entry);
625 }
626
627 if (!ret) {
628 sigemptyset(&dev->sigmask);
629 sigaddset(&dev->sigmask, SIGSTOP);
630 sigaddset(&dev->sigmask, SIGTSTP);
631 sigaddset(&dev->sigmask, SIGTTIN);
632 sigaddset(&dev->sigmask, SIGTTOU);
633 dev->sigdata.context = lock.context;
634 dev->sigdata.lock = dev->lock.hw_lock;
635 block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
636 if (lock.flags & _DRM_LOCK_READY) {
637 /* Wait for space in DMA/FIFO */
638 }
639 if (lock.flags & _DRM_LOCK_QUIESCENT) {
640 /* Make hardware quiescent */
641 DRM_DEBUG("not quiescent!\n");
642 #if 0
643 radeon_quiescent(dev);
644 #endif
645 }
646 }
647
648 #if LINUX_VERSION_CODE < 0x020400
649 if (lock.context != radeon_res_ctx.handle) {
650 current->counter = 5;
651 current->priority = DEF_PRIORITY/4;
652 }
653 #endif
654 DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
655
656 #if DRM_DMA_HISTOGRAM
657 atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
658 #endif
659
660 return ret;
661 }
662
663
radeon_unlock(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)664 int radeon_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
665 unsigned long arg)
666 {
667 drm_file_t *priv = filp->private_data;
668 drm_device_t *dev = priv->dev;
669 drm_lock_t lock;
670
671 if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
672 return -EFAULT;
673
674 if (lock.context == DRM_KERNEL_CONTEXT) {
675 DRM_ERROR("Process %d using kernel context %d\n",
676 current->pid, lock.context);
677 return -EINVAL;
678 }
679
680 DRM_DEBUG("%d frees lock (%d holds)\n",
681 lock.context,
682 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
683 atomic_inc(&dev->total_unlocks);
684 if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
685 atomic_inc(&dev->total_contends);
686 drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
687 /* FIXME: Try to send data to card here */
688 if (!dev->context_flag) {
689 if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
690 DRM_KERNEL_CONTEXT)) {
691 DRM_ERROR("\n");
692 }
693 }
694
695 #if LINUX_VERSION_CODE < 0x020400
696 if (lock.context != radeon_res_ctx.handle) {
697 current->counter = 5;
698 current->priority = DEF_PRIORITY;
699 }
700 #endif
701 unblock_all_signals();
702 return 0;
703 }
704