drm_fops.c 16.4 KB
Newer Older
L
Linus Torvalds 已提交
1
/**
D
Dave Airlie 已提交
2
 * \file drm_fops.c
L
Linus Torvalds 已提交
3
 * File operations for DRM
D
Dave Airlie 已提交
4
 *
L
Linus Torvalds 已提交
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
 * \author Rickard E. (Rik) Faith <faith@valinux.com>
 * \author Daryll Strauss <daryll@valinux.com>
 * \author Gareth Hughes <gareth@valinux.com>
 */

/*
 * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
 *
 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

37
#include <drm/drmP.h>
L
Linus Torvalds 已提交
38
#include <linux/poll.h>
39
#include <linux/slab.h>
40
#include <linux/module.h>
L
Linus Torvalds 已提交
41

42
/* from BKL pushdown */
A
Arnd Bergmann 已提交
43
DEFINE_MUTEX(drm_global_mutex);
44
EXPORT_SYMBOL(drm_global_mutex);
A
Arnd Bergmann 已提交
45

D
Dave Airlie 已提交
46
static int drm_open_helper(struct inode *inode, struct file *filp,
47
			   struct drm_minor *minor);
D
Dave Airlie 已提交
48

49
static int drm_setup(struct drm_device * dev)
L
Linus Torvalds 已提交
50 51 52
{
	int ret;

53 54
	if (dev->driver->firstopen &&
	    !drm_core_check_feature(dev, DRIVER_MODESET)) {
55
		ret = dev->driver->firstopen(dev);
D
Dave Airlie 已提交
56
		if (ret != 0)
L
Linus Torvalds 已提交
57 58 59
			return ret;
	}

60 61 62
	ret = drm_legacy_dma_setup(dev);
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
63 64


D
Dave Airlie 已提交
65
	DRM_DEBUG("\n");
L
Linus Torvalds 已提交
66 67 68 69 70
	return 0;
}

/**
 * Open file.
D
Dave Airlie 已提交
71
 *
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79
 * \param inode device inode
 * \param filp file pointer.
 * \return zero on success or a negative number on failure.
 *
 * Searches the DRM device with the same minor number, calls open_helper(), and
 * increments the device open count. If the open count was previous at zero,
 * i.e., it's the first that the device is open, then calls setup().
 */
D
Dave Airlie 已提交
80
int drm_open(struct inode *inode, struct file *filp)
L
Linus Torvalds 已提交
81
{
82
	struct drm_device *dev;
83
	struct drm_minor *minor;
84
	int retcode;
85 86
	int need_setup = 0;
	struct address_space *old_mapping;
87
	struct address_space *old_imapping;
L
Linus Torvalds 已提交
88

89 90 91
	minor = drm_minor_acquire(iminor(inode));
	if (IS_ERR(minor))
		return PTR_ERR(minor);
D
Dave Airlie 已提交
92

93
	dev = minor->dev;
94 95 96
	if (!dev->open_count++)
		need_setup = 1;
	mutex_lock(&dev->struct_mutex);
97
	old_imapping = inode->i_mapping;
98 99 100 101 102 103 104 105 106
	old_mapping = dev->dev_mapping;
	if (old_mapping == NULL)
		dev->dev_mapping = &inode->i_data;
	/* ihold ensures nobody can remove inode with our i_data */
	ihold(container_of(dev->dev_mapping, struct inode, i_data));
	inode->i_mapping = dev->dev_mapping;
	filp->f_mapping = dev->dev_mapping;
	mutex_unlock(&dev->struct_mutex);

107
	retcode = drm_open_helper(inode, filp, minor);
108 109 110 111 112 113
	if (retcode)
		goto err_undo;
	if (need_setup) {
		retcode = drm_setup(dev);
		if (retcode)
			goto err_undo;
D
Dave Airlie 已提交
114
	}
115
	return 0;
J
Jesse Barnes 已提交
116

117 118
err_undo:
	mutex_lock(&dev->struct_mutex);
119 120
	filp->f_mapping = old_imapping;
	inode->i_mapping = old_imapping;
121 122 123 124
	iput(container_of(dev->dev_mapping, struct inode, i_data));
	dev->dev_mapping = old_mapping;
	mutex_unlock(&dev->struct_mutex);
	dev->open_count--;
125
	drm_minor_release(minor);
L
Linus Torvalds 已提交
126 127 128 129
	return retcode;
}
EXPORT_SYMBOL(drm_open);

130 131 132 133 134 135 136 137 138 139 140
/**
 * File \c open operation.
 *
 * \param inode device inode.
 * \param filp file pointer.
 *
 * Puts the dev->fops corresponding to the device minor number into
 * \p filp, call the \c open method, and restore the file operations.
 */
int drm_stub_open(struct inode *inode, struct file *filp)
{
141
	struct drm_device *dev;
142
	struct drm_minor *minor;
143
	int err = -ENODEV;
144
	const struct file_operations *new_fops;
145 146 147

	DRM_DEBUG("\n");

A
Arnd Bergmann 已提交
148
	mutex_lock(&drm_global_mutex);
149 150 151
	minor = drm_minor_acquire(iminor(inode));
	if (IS_ERR(minor))
		goto out_unlock;
152

153
	dev = minor->dev;
154 155
	new_fops = fops_get(dev->driver->fops);
	if (!new_fops)
156
		goto out_release;
157

158 159 160
	replace_fops(filp, new_fops);
	if (filp->f_op->open)
		err = filp->f_op->open(inode, filp);
161 162 163 164

out_release:
	drm_minor_release(minor);
out_unlock:
A
Arnd Bergmann 已提交
165
	mutex_unlock(&drm_global_mutex);
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
	return err;
}

/**
 * Check whether DRI will run on this CPU.
 *
 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
 */
static int drm_cpu_valid(void)
{
#if defined(__i386__)
	if (boot_cpu_data.x86 == 3)
		return 0;	/* No cmpxchg on a 386 */
#endif
#if defined(__sparc__) && !defined(__sparc_v9__)
	return 0;		/* No cmpxchg before v9 sparc. */
#endif
	return 1;
}

/**
 * Called whenever a process opens /dev/drm.
 *
 * \param inode device inode.
 * \param filp file pointer.
191
 * \param minor acquired minor-object.
192 193 194 195 196 197
 * \return zero on success or a negative number on failure.
 *
 * Creates and initializes a drm_file structure for the file private data in \p
 * filp and add it into the double linked list in \p dev.
 */
static int drm_open_helper(struct inode *inode, struct file *filp,
198
			   struct drm_minor *minor)
199
{
200
	struct drm_device *dev = minor->dev;
201
	struct drm_file *priv;
202 203 204 205 206 207
	int ret;

	if (filp->f_flags & O_EXCL)
		return -EBUSY;	/* No exclusive opens */
	if (!drm_cpu_valid())
		return -EINVAL;
208
	if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
209
		return -EINVAL;
210

211
	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
212

J
Julia Lawall 已提交
213
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
214 215 216 217
	if (!priv)
		return -ENOMEM;

	filp->private_data = priv;
218
	priv->filp = filp;
219
	priv->uid = current_euid();
220
	priv->pid = get_pid(task_pid(current));
221
	priv->minor = minor;
222

223
	/* for compatibility root is always authenticated */
224 225
	priv->always_authenticated = capable(CAP_SYS_ADMIN);
	priv->authenticated = priv->always_authenticated;
226 227
	priv->lock_count = 0;

228
	INIT_LIST_HEAD(&priv->lhead);
D
Dave Airlie 已提交
229
	INIT_LIST_HEAD(&priv->fbs);
230
	mutex_init(&priv->fbs_lock);
231 232 233
	INIT_LIST_HEAD(&priv->event_list);
	init_waitqueue_head(&priv->event_wait);
	priv->event_space = 4096; /* set aside 4k for event buffer */
234

235 236 237
	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_open(dev, priv);

238 239 240
	if (drm_core_check_feature(dev, DRIVER_PRIME))
		drm_prime_init_file_private(&priv->prime);

241 242 243
	if (dev->driver->open) {
		ret = dev->driver->open(dev, priv);
		if (ret < 0)
244
			goto out_prime_destroy;
245 246
	}

247 248
	/* if there is no current master make this fd it, but do not create
	 * any master object for render clients */
D
Dave Airlie 已提交
249
	mutex_lock(&dev->struct_mutex);
250
	if (!priv->minor->master && !drm_is_render_client(priv)) {
251 252 253
		/* create a new master */
		priv->minor->master = drm_master_create(priv->minor);
		if (!priv->minor->master) {
254
			mutex_unlock(&dev->struct_mutex);
255
			ret = -ENOMEM;
256
			goto out_close;
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
		}

		priv->is_master = 1;
		/* take another reference for the copy in the local file priv */
		priv->master = drm_master_get(priv->minor->master);

		priv->authenticated = 1;

		mutex_unlock(&dev->struct_mutex);
		if (dev->driver->master_create) {
			ret = dev->driver->master_create(dev, priv->master);
			if (ret) {
				mutex_lock(&dev->struct_mutex);
				/* drop both references if this fails */
				drm_master_put(&priv->minor->master);
				drm_master_put(&priv->master);
				mutex_unlock(&dev->struct_mutex);
274
				goto out_close;
275 276
			}
		}
277 278 279 280 281 282 283 284
		mutex_lock(&dev->struct_mutex);
		if (dev->driver->master_set) {
			ret = dev->driver->master_set(dev, priv, true);
			if (ret) {
				/* drop both references if this fails */
				drm_master_put(&priv->minor->master);
				drm_master_put(&priv->master);
				mutex_unlock(&dev->struct_mutex);
285
				goto out_close;
286 287
			}
		}
288
	} else if (!drm_is_render_client(priv)) {
289 290 291
		/* get a reference to the master */
		priv->master = drm_master_get(priv->minor->master);
	}
292
	mutex_unlock(&dev->struct_mutex);
293

294
	mutex_lock(&dev->struct_mutex);
295
	list_add(&priv->lhead, &dev->filelist);
D
Dave Airlie 已提交
296
	mutex_unlock(&dev->struct_mutex);
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

#ifdef __alpha__
	/*
	 * Default the hose
	 */
	if (!dev->hose) {
		struct pci_dev *pci_dev;
		pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
		if (pci_dev) {
			dev->hose = pci_dev->sysdata;
			pci_dev_put(pci_dev);
		}
		if (!dev->hose) {
			struct pci_bus *b = pci_bus_b(pci_root_buses.next);
			if (b)
				dev->hose = b->sysdata;
		}
	}
#endif

	return 0;
318 319 320 321 322 323 324 325 326 327

out_close:
	if (dev->driver->postclose)
		dev->driver->postclose(dev, priv);
out_prime_destroy:
	if (drm_core_check_feature(dev, DRIVER_PRIME))
		drm_prime_destroy_file_private(&priv->prime);
	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_release(dev, priv);
	put_pid(priv->pid);
328
	kfree(priv);
329 330 331 332
	filp->private_data = NULL;
	return ret;
}

333 334 335 336 337 338 339 340 341 342 343 344
static void drm_master_release(struct drm_device *dev, struct file *filp)
{
	struct drm_file *file_priv = filp->private_data;

	if (drm_i_have_hw_lock(dev, file_priv)) {
		DRM_DEBUG("File %p released, freeing lock for context %d\n",
			  filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
		drm_lock_free(&file_priv->master->lock,
			      _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
	}
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
static void drm_events_release(struct drm_file *file_priv)
{
	struct drm_device *dev = file_priv->minor->dev;
	struct drm_pending_event *e, *et;
	struct drm_pending_vblank_event *v, *vt;
	unsigned long flags;

	spin_lock_irqsave(&dev->event_lock, flags);

	/* Remove pending flips */
	list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
		if (v->base.file_priv == file_priv) {
			list_del(&v->base.link);
			drm_vblank_put(dev, v->pipe);
			v->base.destroy(&v->base);
		}

	/* Remove unconsumed events */
363 364
	list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
		list_del(&e->link);
365
		e->destroy(e);
366
	}
367 368 369 370

	spin_unlock_irqrestore(&dev->event_lock, flags);
}

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
/**
 * drm_legacy_dev_reinit
 *
 * Reinitializes a legacy/ums drm device in it's lastclose function.
 */
static void drm_legacy_dev_reinit(struct drm_device *dev)
{
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return;

	dev->sigdata.lock = NULL;

	dev->context_flag = 0;
	dev->last_context = 0;
	dev->if_version = 0;
}

/**
 * Take down the DRM device.
 *
 * \param dev DRM device structure.
 *
 * Frees every resource in \p dev.
 *
 * \sa drm_device
 */
int drm_lastclose(struct drm_device * dev)
{
	struct drm_vma_entry *vma, *vma_temp;

	DRM_DEBUG("\n");

	if (dev->driver->lastclose)
		dev->driver->lastclose(dev);
	DRM_DEBUG("driver lastclose completed\n");

	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
		drm_irq_uninstall(dev);

	mutex_lock(&dev->struct_mutex);

	drm_agp_clear(dev);

	drm_legacy_sg_cleanup(dev);

	/* Clear vma list (only built for debugging) */
	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
		list_del(&vma->head);
		kfree(vma);
	}

	drm_legacy_dma_takedown(dev);

	dev->dev_mapping = NULL;
	mutex_unlock(&dev->struct_mutex);

	drm_legacy_dev_reinit(dev);

	DRM_DEBUG("lastclose completed\n");
	return 0;
}

L
Linus Torvalds 已提交
433 434 435 436
/**
 * Release file.
 *
 * \param inode device inode
437
 * \param file_priv DRM file private.
L
Linus Torvalds 已提交
438 439 440 441 442
 * \return zero on success or a negative number on failure.
 *
 * If the hardware lock is held then free it, and take it again for the kernel
 * context since it's necessary to reclaim buffers. Unlink the file private
 * data from its list and free it. Decreases the open count and if it reaches
443
 * zero calls drm_lastclose().
L
Linus Torvalds 已提交
444
 */
D
Dave Airlie 已提交
445
int drm_release(struct inode *inode, struct file *filp)
L
Linus Torvalds 已提交
446
{
447
	struct drm_file *file_priv = filp->private_data;
448 449
	struct drm_minor *minor = file_priv->minor;
	struct drm_device *dev = minor->dev;
L
Linus Torvalds 已提交
450 451
	int retcode = 0;

A
Arnd Bergmann 已提交
452
	mutex_lock(&drm_global_mutex);
L
Linus Torvalds 已提交
453

D
Dave Airlie 已提交
454
	DRM_DEBUG("open_count = %d\n", dev->open_count);
L
Linus Torvalds 已提交
455

456
	if (dev->driver->preclose)
457
		dev->driver->preclose(dev, file_priv);
L
Linus Torvalds 已提交
458 459 460 461 462

	/* ========================================================
	 * Begin inline drm_release
	 */

D
Dave Airlie 已提交
463
	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
464
		  task_pid_nr(current),
465
		  (long)old_encode_dev(file_priv->minor->kdev->devt),
D
Dave Airlie 已提交
466 467
		  dev->open_count);

468 469 470 471 472
	/* Release any auth tokens that might point to this file_priv,
	   (do that under the drm_global_mutex) */
	if (file_priv->magic)
		(void) drm_remove_magic(file_priv->master, file_priv->magic);

473 474 475
	/* if the master has gone away we can't do anything with the lock */
	if (file_priv->minor->master)
		drm_master_release(dev, filp);
L
Linus Torvalds 已提交
476

477 478 479
	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
		drm_core_reclaim_buffers(dev, file_priv);

480 481
	drm_events_release(file_priv);

482 483 484
	if (dev->driver->driver_features & DRIVER_MODESET)
		drm_fb_release(file_priv);

485 486 487
	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_release(dev, file_priv);

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
	mutex_lock(&dev->ctxlist_mutex);
	if (!list_empty(&dev->ctxlist)) {
		struct drm_ctx_list *pos, *n;

		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
			if (pos->tag == file_priv &&
			    pos->handle != DRM_KERNEL_CONTEXT) {
				if (dev->driver->context_dtor)
					dev->driver->context_dtor(dev,
								  pos->handle);

				drm_ctxbitmap_free(dev, pos->handle);

				list_del(&pos->head);
				kfree(pos);
			}
		}
	}
	mutex_unlock(&dev->ctxlist_mutex);
L
Linus Torvalds 已提交
507

D
Dave Airlie 已提交
508
	mutex_lock(&dev->struct_mutex);
509 510

	if (file_priv->is_master) {
511
		struct drm_master *master = file_priv->master;
512
		struct drm_file *temp;
513 514 515
		list_for_each_entry(temp, &dev->filelist, lhead) {
			if ((temp->master == file_priv->master) &&
			    (temp != file_priv))
516
				temp->authenticated = temp->always_authenticated;
517
		}
518

519 520 521 522 523 524 525 526 527 528 529 530 531
		/**
		 * Since the master is disappearing, so is the
		 * possibility to lock.
		 */

		if (master->lock.hw_lock) {
			if (dev->sigdata.lock == master->lock.hw_lock)
				dev->sigdata.lock = NULL;
			master->lock.hw_lock = NULL;
			master->lock.file_priv = NULL;
			wake_up_interruptible_all(&master->lock.lock_queue);
		}

532 533
		if (file_priv->minor->master == file_priv->master) {
			/* drop the reference held my the minor */
534 535
			if (dev->driver->master_drop)
				dev->driver->master_drop(dev, file_priv, true);
536 537
			drm_master_put(&file_priv->minor->master);
		}
L
Linus Torvalds 已提交
538
	}
539

540 541 542
	BUG_ON(dev->dev_mapping == NULL);
	iput(container_of(dev->dev_mapping, struct inode, i_data));

543
	/* drop the reference held my the file priv */
544 545
	if (file_priv->master)
		drm_master_put(&file_priv->master);
546
	file_priv->is_master = 0;
547
	list_del(&file_priv->lhead);
D
Dave Airlie 已提交
548
	mutex_unlock(&dev->struct_mutex);
D
Dave Airlie 已提交
549

550
	if (dev->driver->postclose)
551
		dev->driver->postclose(dev, file_priv);
552

553

554 555 556
	if (drm_core_check_feature(dev, DRIVER_PRIME))
		drm_prime_destroy_file_private(&file_priv->prime);

557
	put_pid(file_priv->pid);
558
	kfree(file_priv);
L
Linus Torvalds 已提交
559 560 561 562 563

	/* ========================================================
	 * End inline drm_release
	 */

D
Dave Airlie 已提交
564
	if (!--dev->open_count) {
565
		retcode = drm_lastclose(dev);
566 567
		if (drm_device_is_unplugged(dev))
			drm_put_dev(dev);
L
Linus Torvalds 已提交
568
	}
A
Arnd Bergmann 已提交
569
	mutex_unlock(&drm_global_mutex);
L
Linus Torvalds 已提交
570

571 572
	drm_minor_release(minor);

L
Linus Torvalds 已提交
573 574 575 576
	return retcode;
}
EXPORT_SYMBOL(drm_release);

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 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 632 633 634
static bool
drm_dequeue_event(struct drm_file *file_priv,
		  size_t total, size_t max, struct drm_pending_event **out)
{
	struct drm_device *dev = file_priv->minor->dev;
	struct drm_pending_event *e;
	unsigned long flags;
	bool ret = false;

	spin_lock_irqsave(&dev->event_lock, flags);

	*out = NULL;
	if (list_empty(&file_priv->event_list))
		goto out;
	e = list_first_entry(&file_priv->event_list,
			     struct drm_pending_event, link);
	if (e->event->length + total > max)
		goto out;

	file_priv->event_space += e->event->length;
	list_del(&e->link);
	*out = e;
	ret = true;

out:
	spin_unlock_irqrestore(&dev->event_lock, flags);
	return ret;
}

ssize_t drm_read(struct file *filp, char __user *buffer,
		 size_t count, loff_t *offset)
{
	struct drm_file *file_priv = filp->private_data;
	struct drm_pending_event *e;
	size_t total;
	ssize_t ret;

	ret = wait_event_interruptible(file_priv->event_wait,
				       !list_empty(&file_priv->event_list));
	if (ret < 0)
		return ret;

	total = 0;
	while (drm_dequeue_event(file_priv, total, count, &e)) {
		if (copy_to_user(buffer + total,
				 e->event, e->event->length)) {
			total = -EFAULT;
			break;
		}

		total += e->event->length;
		e->destroy(e);
	}

	return total;
}
EXPORT_SYMBOL(drm_read);

L
Linus Torvalds 已提交
635 636
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{
637 638 639 640 641 642 643 644 645
	struct drm_file *file_priv = filp->private_data;
	unsigned int mask = 0;

	poll_wait(filp, &file_priv->event_wait, wait);

	if (!list_empty(&file_priv->event_list))
		mask |= POLLIN | POLLRDNORM;

	return mask;
L
Linus Torvalds 已提交
646
}
D
Dave Airlie 已提交
647
EXPORT_SYMBOL(drm_poll);