1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include <drm/drmP.h>
38#include <linux/poll.h>
39#include <linux/slab.h>
40#include <linux/module.h>
41#include "drm_legacy.h"
42#include "drm_internal.h"
43#include "drm_crtc_internal.h"
44
45
46DEFINE_MUTEX(drm_global_mutex);
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88static int drm_open_helper(struct file *filp, struct drm_minor *minor);
89
90static int drm_setup(struct drm_device * dev)
91{
92 int ret;
93
94 if (dev->driver->firstopen &&
95 drm_core_check_feature(dev, DRIVER_LEGACY)) {
96 ret = dev->driver->firstopen(dev);
97 if (ret != 0)
98 return ret;
99 }
100
101 ret = drm_legacy_dma_setup(dev);
102 if (ret < 0)
103 return ret;
104
105
106 DRM_DEBUG("\n");
107 return 0;
108}
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123int drm_open(struct inode *inode, struct file *filp)
124{
125 struct drm_device *dev;
126 struct drm_minor *minor;
127 int retcode;
128 int need_setup = 0;
129
130 minor = drm_minor_acquire(iminor(inode));
131 if (IS_ERR(minor))
132 return PTR_ERR(minor);
133
134 dev = minor->dev;
135 if (!dev->open_count++)
136 need_setup = 1;
137
138
139 filp->f_mapping = dev->anon_inode->i_mapping;
140
141 retcode = drm_open_helper(filp, minor);
142 if (retcode)
143 goto err_undo;
144 if (need_setup) {
145 retcode = drm_setup(dev);
146 if (retcode)
147 goto err_undo;
148 }
149 return 0;
150
151err_undo:
152 dev->open_count--;
153 drm_minor_release(minor);
154 return retcode;
155}
156EXPORT_SYMBOL(drm_open);
157
158
159
160
161
162
163static int drm_cpu_valid(void)
164{
165#if defined(__sparc__) && !defined(__sparc_v9__)
166 return 0;
167#endif
168 return 1;
169}
170
171
172
173
174
175
176
177
178
179
180
181static int drm_open_helper(struct file *filp, struct drm_minor *minor)
182{
183 struct drm_device *dev = minor->dev;
184 struct drm_file *priv;
185 int ret;
186
187 if (filp->f_flags & O_EXCL)
188 return -EBUSY;
189 if (!drm_cpu_valid())
190 return -EINVAL;
191 if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
192 return -EINVAL;
193
194 DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
195
196 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
197 if (!priv)
198 return -ENOMEM;
199
200 filp->private_data = priv;
201 priv->filp = filp;
202 priv->pid = get_pid(task_pid(current));
203 priv->minor = minor;
204
205
206 priv->authenticated = capable(CAP_SYS_ADMIN);
207 priv->lock_count = 0;
208
209 INIT_LIST_HEAD(&priv->lhead);
210 INIT_LIST_HEAD(&priv->fbs);
211 mutex_init(&priv->fbs_lock);
212 INIT_LIST_HEAD(&priv->blobs);
213 INIT_LIST_HEAD(&priv->pending_event_list);
214 INIT_LIST_HEAD(&priv->event_list);
215 init_waitqueue_head(&priv->event_wait);
216 priv->event_space = 4096;
217
218 mutex_init(&priv->event_read_lock);
219
220 if (drm_core_check_feature(dev, DRIVER_GEM))
221 drm_gem_open(dev, priv);
222
223 if (drm_core_check_feature(dev, DRIVER_PRIME))
224 drm_prime_init_file_private(&priv->prime);
225
226 if (dev->driver->open) {
227 ret = dev->driver->open(dev, priv);
228 if (ret < 0)
229 goto out_prime_destroy;
230 }
231
232 if (drm_is_primary_client(priv)) {
233 ret = drm_master_open(priv);
234 if (ret)
235 goto out_close;
236 }
237
238 mutex_lock(&dev->filelist_mutex);
239 list_add(&priv->lhead, &dev->filelist);
240 mutex_unlock(&dev->filelist_mutex);
241
242#ifdef __alpha__
243
244
245
246 if (!dev->hose) {
247 struct pci_dev *pci_dev;
248 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
249 if (pci_dev) {
250 dev->hose = pci_dev->sysdata;
251 pci_dev_put(pci_dev);
252 }
253 if (!dev->hose) {
254 struct pci_bus *b = list_entry(pci_root_buses.next,
255 struct pci_bus, node);
256 if (b)
257 dev->hose = b->sysdata;
258 }
259 }
260#endif
261
262 return 0;
263
264out_close:
265 if (dev->driver->postclose)
266 dev->driver->postclose(dev, priv);
267out_prime_destroy:
268 if (drm_core_check_feature(dev, DRIVER_PRIME))
269 drm_prime_destroy_file_private(&priv->prime);
270 if (drm_core_check_feature(dev, DRIVER_GEM))
271 drm_gem_release(dev, priv);
272 put_pid(priv->pid);
273 kfree(priv);
274 filp->private_data = NULL;
275 return ret;
276}
277
278static void drm_events_release(struct drm_file *file_priv)
279{
280 struct drm_device *dev = file_priv->minor->dev;
281 struct drm_pending_event *e, *et;
282 unsigned long flags;
283
284 spin_lock_irqsave(&dev->event_lock, flags);
285
286
287 list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
288 pending_link) {
289 list_del(&e->pending_link);
290 e->file_priv = NULL;
291 }
292
293
294 list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
295 list_del(&e->link);
296 kfree(e);
297 }
298
299 spin_unlock_irqrestore(&dev->event_lock, flags);
300}
301
302
303
304
305
306
307static void drm_legacy_dev_reinit(struct drm_device *dev)
308{
309 if (dev->irq_enabled)
310 drm_irq_uninstall(dev);
311
312 mutex_lock(&dev->struct_mutex);
313
314 drm_legacy_agp_clear(dev);
315
316 drm_legacy_sg_cleanup(dev);
317 drm_legacy_vma_flush(dev);
318 drm_legacy_dma_takedown(dev);
319
320 mutex_unlock(&dev->struct_mutex);
321
322 dev->sigdata.lock = NULL;
323
324 dev->context_flag = 0;
325 dev->last_context = 0;
326 dev->if_version = 0;
327
328 DRM_DEBUG("lastclose completed\n");
329}
330
331
332
333
334
335
336
337
338
339
340void drm_lastclose(struct drm_device * dev)
341{
342 DRM_DEBUG("\n");
343
344 if (dev->driver->lastclose)
345 dev->driver->lastclose(dev);
346 DRM_DEBUG("driver lastclose completed\n");
347
348 if (drm_core_check_feature(dev, DRIVER_LEGACY))
349 drm_legacy_dev_reinit(dev);
350}
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365int drm_release(struct inode *inode, struct file *filp)
366{
367 struct drm_file *file_priv = filp->private_data;
368 struct drm_minor *minor = file_priv->minor;
369 struct drm_device *dev = minor->dev;
370
371 mutex_lock(&drm_global_mutex);
372
373 DRM_DEBUG("open_count = %d\n", dev->open_count);
374
375 mutex_lock(&dev->filelist_mutex);
376 list_del(&file_priv->lhead);
377 mutex_unlock(&dev->filelist_mutex);
378
379 if (dev->driver->preclose)
380 dev->driver->preclose(dev, file_priv);
381
382
383
384
385
386 DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
387 task_pid_nr(current),
388 (long)old_encode_dev(file_priv->minor->kdev->devt),
389 dev->open_count);
390
391 if (drm_core_check_feature(dev, DRIVER_LEGACY))
392 drm_legacy_lock_release(dev, filp);
393
394 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
395 drm_legacy_reclaim_buffers(dev, file_priv);
396
397 drm_events_release(file_priv);
398
399 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
400 drm_fb_release(file_priv);
401 drm_property_destroy_user_blobs(dev, file_priv);
402 }
403
404 if (drm_core_check_feature(dev, DRIVER_GEM))
405 drm_gem_release(dev, file_priv);
406
407 drm_legacy_ctxbitmap_flush(dev, file_priv);
408
409 if (drm_is_primary_client(file_priv))
410 drm_master_release(file_priv);
411
412 if (dev->driver->postclose)
413 dev->driver->postclose(dev, file_priv);
414
415 if (drm_core_check_feature(dev, DRIVER_PRIME))
416 drm_prime_destroy_file_private(&file_priv->prime);
417
418 WARN_ON(!list_empty(&file_priv->event_list));
419
420 put_pid(file_priv->pid);
421 kfree(file_priv);
422
423
424
425
426
427 if (!--dev->open_count) {
428 drm_lastclose(dev);
429 if (drm_device_is_unplugged(dev))
430 drm_put_dev(dev);
431 }
432 mutex_unlock(&drm_global_mutex);
433
434 drm_minor_release(minor);
435
436 return 0;
437}
438EXPORT_SYMBOL(drm_release);
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466ssize_t drm_read(struct file *filp, char __user *buffer,
467 size_t count, loff_t *offset)
468{
469 struct drm_file *file_priv = filp->private_data;
470 struct drm_device *dev = file_priv->minor->dev;
471 ssize_t ret;
472
473 if (!access_ok(VERIFY_WRITE, buffer, count))
474 return -EFAULT;
475
476 ret = mutex_lock_interruptible(&file_priv->event_read_lock);
477 if (ret)
478 return ret;
479
480 for (;;) {
481 struct drm_pending_event *e = NULL;
482
483 spin_lock_irq(&dev->event_lock);
484 if (!list_empty(&file_priv->event_list)) {
485 e = list_first_entry(&file_priv->event_list,
486 struct drm_pending_event, link);
487 file_priv->event_space += e->event->length;
488 list_del(&e->link);
489 }
490 spin_unlock_irq(&dev->event_lock);
491
492 if (e == NULL) {
493 if (ret)
494 break;
495
496 if (filp->f_flags & O_NONBLOCK) {
497 ret = -EAGAIN;
498 break;
499 }
500
501 mutex_unlock(&file_priv->event_read_lock);
502 ret = wait_event_interruptible(file_priv->event_wait,
503 !list_empty(&file_priv->event_list));
504 if (ret >= 0)
505 ret = mutex_lock_interruptible(&file_priv->event_read_lock);
506 if (ret)
507 return ret;
508 } else {
509 unsigned length = e->event->length;
510
511 if (length > count - ret) {
512put_back_event:
513 spin_lock_irq(&dev->event_lock);
514 file_priv->event_space -= length;
515 list_add(&e->link, &file_priv->event_list);
516 spin_unlock_irq(&dev->event_lock);
517 break;
518 }
519
520 if (copy_to_user(buffer + ret, e->event, length)) {
521 if (ret == 0)
522 ret = -EFAULT;
523 goto put_back_event;
524 }
525
526 ret += length;
527 kfree(e);
528 }
529 }
530 mutex_unlock(&file_priv->event_read_lock);
531
532 return ret;
533}
534EXPORT_SYMBOL(drm_read);
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
553{
554 struct drm_file *file_priv = filp->private_data;
555 unsigned int mask = 0;
556
557 poll_wait(filp, &file_priv->event_wait, wait);
558
559 if (!list_empty(&file_priv->event_list))
560 mask |= POLLIN | POLLRDNORM;
561
562 return mask;
563}
564EXPORT_SYMBOL(drm_poll);
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590int drm_event_reserve_init_locked(struct drm_device *dev,
591 struct drm_file *file_priv,
592 struct drm_pending_event *p,
593 struct drm_event *e)
594{
595 if (file_priv->event_space < e->length)
596 return -ENOMEM;
597
598 file_priv->event_space -= e->length;
599
600 p->event = e;
601 list_add(&p->pending_link, &file_priv->pending_event_list);
602 p->file_priv = file_priv;
603
604 return 0;
605}
606EXPORT_SYMBOL(drm_event_reserve_init_locked);
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632int drm_event_reserve_init(struct drm_device *dev,
633 struct drm_file *file_priv,
634 struct drm_pending_event *p,
635 struct drm_event *e)
636{
637 unsigned long flags;
638 int ret;
639
640 spin_lock_irqsave(&dev->event_lock, flags);
641 ret = drm_event_reserve_init_locked(dev, file_priv, p, e);
642 spin_unlock_irqrestore(&dev->event_lock, flags);
643
644 return ret;
645}
646EXPORT_SYMBOL(drm_event_reserve_init);
647
648
649
650
651
652
653
654
655
656void drm_event_cancel_free(struct drm_device *dev,
657 struct drm_pending_event *p)
658{
659 unsigned long flags;
660 spin_lock_irqsave(&dev->event_lock, flags);
661 if (p->file_priv) {
662 p->file_priv->event_space += p->event->length;
663 list_del(&p->pending_link);
664 }
665 spin_unlock_irqrestore(&dev->event_lock, flags);
666 kfree(p);
667}
668EXPORT_SYMBOL(drm_event_cancel_free);
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
685{
686 assert_spin_locked(&dev->event_lock);
687
688 if (e->completion) {
689
690 complete_all(e->completion);
691 e->completion = NULL;
692 }
693
694 if (e->fence) {
695 fence_signal(e->fence);
696 fence_put(e->fence);
697 }
698
699 if (!e->file_priv) {
700 kfree(e);
701 return;
702 }
703
704 list_del(&e->pending_link);
705 list_add_tail(&e->link,
706 &e->file_priv->event_list);
707 wake_up_interruptible(&e->file_priv->event_wait);
708}
709EXPORT_SYMBOL(drm_send_event_locked);
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
726{
727 unsigned long irqflags;
728
729 spin_lock_irqsave(&dev->event_lock, irqflags);
730 drm_send_event_locked(dev, e);
731 spin_unlock_irqrestore(&dev->event_lock, irqflags);
732}
733EXPORT_SYMBOL(drm_send_event);
734