Blame view
drivers/gpu/drm/drm_fops.c
16.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/** |
b5e89ed53 drm: lindent the ... |
2 |
* \file drm_fops.c |
1da177e4c Linux-2.6.12-rc2 |
3 |
* File operations for DRM |
b5e89ed53 drm: lindent the ... |
4 |
* |
1da177e4c Linux-2.6.12-rc2 |
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 38 |
* \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. */ #include "drmP.h" #include <linux/poll.h> |
5a0e3ad6a include cleanup: ... |
39 |
#include <linux/slab.h> |
e0cd36081 gpu: add module.h... |
40 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
41 |
|
58374713c drm: kill BKL fro... |
42 43 |
/* from BKL pushdown: note that nothing else serializes idr_find() */ DEFINE_MUTEX(drm_global_mutex); |
e3461a2bc drm: export drm_g... |
44 |
EXPORT_SYMBOL(drm_global_mutex); |
58374713c drm: kill BKL fro... |
45 |
|
b5e89ed53 drm: lindent the ... |
46 |
static int drm_open_helper(struct inode *inode, struct file *filp, |
84b1fd103 drm: remove drm_f... |
47 |
struct drm_device * dev); |
c94f70298 drm: misc cleanup |
48 |
|
84b1fd103 drm: remove drm_f... |
49 |
static int drm_setup(struct drm_device * dev) |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 |
{ int i; int ret; |
22eae947b drm: rename drive... |
53 54 |
if (dev->driver->firstopen) { ret = dev->driver->firstopen(dev); |
b5e89ed53 drm: lindent the ... |
55 |
if (ret != 0) |
1da177e4c Linux-2.6.12-rc2 |
56 57 |
return ret; } |
b5e89ed53 drm: lindent the ... |
58 59 |
atomic_set(&dev->ioctl_count, 0); atomic_set(&dev->vma_count, 0); |
1da177e4c Linux-2.6.12-rc2 |
60 |
|
f453ba046 DRM: add mode set... |
61 62 63 64 |
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !drm_core_check_feature(dev, DRIVER_MODESET)) { dev->buf_use = 0; atomic_set(&dev->buf_alloc, 0); |
b5e89ed53 drm: lindent the ... |
65 66 |
i = drm_dma_setup(dev); if (i < 0) |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
return i; } |
3d77461ec drm: cleanup old ... |
69 |
for (i = 0; i < ARRAY_SIZE(dev->counts); i++) |
b5e89ed53 drm: lindent the ... |
70 |
atomic_set(&dev->counts[i], 0); |
1da177e4c Linux-2.6.12-rc2 |
71 |
|
11d9c2fd0 drm: fix crash wi... |
72 |
dev->sigdata.lock = NULL; |
7c1c2871a drm: move to kref... |
73 |
|
1da177e4c Linux-2.6.12-rc2 |
74 75 76 77 |
dev->queue_count = 0; dev->queue_reserved = 0; dev->queue_slots = 0; dev->queuelist = NULL; |
1da177e4c Linux-2.6.12-rc2 |
78 79 80 81 82 83 |
dev->context_flag = 0; dev->interrupt_flag = 0; dev->dma_flag = 0; dev->last_context = 0; dev->last_switch = 0; dev->last_checked = 0; |
b5e89ed53 drm: lindent the ... |
84 |
init_waitqueue_head(&dev->context_wait); |
1da177e4c Linux-2.6.12-rc2 |
85 86 87 88 |
dev->if_version = 0; dev->ctx_start = 0; dev->lck_start = 0; |
1da177e4c Linux-2.6.12-rc2 |
89 |
dev->buf_async = NULL; |
b5e89ed53 drm: lindent the ... |
90 91 |
init_waitqueue_head(&dev->buf_readers); init_waitqueue_head(&dev->buf_writers); |
1da177e4c Linux-2.6.12-rc2 |
92 |
|
b5e89ed53 drm: lindent the ... |
93 94 |
DRM_DEBUG(" "); |
1da177e4c Linux-2.6.12-rc2 |
95 96 97 |
/* * The kernel's context could be created here, but is now created |
b5e89ed53 drm: lindent the ... |
98 |
* in drm_dma_enqueue. This is more resource-efficient for |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 102 |
* hardware that does not do DMA, but may mean that * drm_select_queue fails between the time the interrupt is * initialized and the time the queues are initialized. */ |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 106 107 108 |
return 0; } /** * Open file. |
b5e89ed53 drm: lindent the ... |
109 |
* |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 113 114 115 116 117 |
* \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(). */ |
b5e89ed53 drm: lindent the ... |
118 |
int drm_open(struct inode *inode, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
119 |
{ |
84b1fd103 drm: remove drm_f... |
120 |
struct drm_device *dev = NULL; |
2c14f28be drm: reorganise m... |
121 122 |
int minor_id = iminor(inode); struct drm_minor *minor; |
1da177e4c Linux-2.6.12-rc2 |
123 |
int retcode = 0; |
2c14f28be drm: reorganise m... |
124 125 |
minor = idr_find(&drm_minors_idr, minor_id); if (!minor) |
1da177e4c Linux-2.6.12-rc2 |
126 |
return -ENODEV; |
b5e89ed53 drm: lindent the ... |
127 |
|
2c14f28be drm: reorganise m... |
128 |
if (!(dev = minor->dev)) |
1da177e4c Linux-2.6.12-rc2 |
129 |
return -ENODEV; |
b5e89ed53 drm: lindent the ... |
130 131 132 133 |
retcode = drm_open_helper(inode, filp, dev); if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
1a72d65d6 drm: Remove count... |
134 |
if (!dev->open_count++) |
a2c0a97b7 drm: GEM mmap sup... |
135 |
retcode = drm_setup(dev); |
1da177e4c Linux-2.6.12-rc2 |
136 |
} |
da5840586 drm: Return ENODE... |
137 138 139 140 141 142 143 144 145 |
if (!retcode) { mutex_lock(&dev->struct_mutex); if (minor->type == DRM_MINOR_LEGACY) { if (dev->dev_mapping == NULL) dev->dev_mapping = inode->i_mapping; else if (dev->dev_mapping != inode->i_mapping) retcode = -ENODEV; } mutex_unlock(&dev->struct_mutex); |
f453ba046 DRM: add mode set... |
146 |
} |
a2c0a97b7 drm: GEM mmap sup... |
147 |
|
1da177e4c Linux-2.6.12-rc2 |
148 149 150 151 152 |
return retcode; } EXPORT_SYMBOL(drm_open); /** |
d985c1088 drm: major update... |
153 154 155 156 157 158 159 160 161 162 |
* 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) { |
84b1fd103 drm: remove drm_f... |
163 |
struct drm_device *dev = NULL; |
2c14f28be drm: reorganise m... |
164 165 |
struct drm_minor *minor; int minor_id = iminor(inode); |
d985c1088 drm: major update... |
166 |
int err = -ENODEV; |
99ac48f54 [PATCH] mark f_op... |
167 |
const struct file_operations *old_fops; |
d985c1088 drm: major update... |
168 169 170 |
DRM_DEBUG(" "); |
58374713c drm: kill BKL fro... |
171 |
mutex_lock(&drm_global_mutex); |
2c14f28be drm: reorganise m... |
172 173 |
minor = idr_find(&drm_minors_idr, minor_id); if (!minor) |
70ffa16e6 drm: cdev lock_ke... |
174 |
goto out; |
d985c1088 drm: major update... |
175 |
|
2c14f28be drm: reorganise m... |
176 |
if (!(dev = minor->dev)) |
70ffa16e6 drm: cdev lock_ke... |
177 |
goto out; |
d985c1088 drm: major update... |
178 179 |
old_fops = filp->f_op; |
e08e96de9 drm: Make the per... |
180 |
filp->f_op = fops_get(dev->driver->fops); |
f41ced8f1 Check fops_get() ... |
181 182 183 184 |
if (filp->f_op == NULL) { filp->f_op = old_fops; goto out; } |
d985c1088 drm: major update... |
185 186 187 188 189 |
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { fops_put(filp->f_op); filp->f_op = fops_get(old_fops); } fops_put(old_fops); |
70ffa16e6 drm: cdev lock_ke... |
190 |
out: |
58374713c drm: kill BKL fro... |
191 |
mutex_unlock(&drm_global_mutex); |
d985c1088 drm: major update... |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
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. * \param dev device. * \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, |
84b1fd103 drm: remove drm_f... |
224 |
struct drm_device * dev) |
d985c1088 drm: major update... |
225 |
{ |
2c14f28be drm: reorganise m... |
226 |
int minor_id = iminor(inode); |
84b1fd103 drm: remove drm_f... |
227 |
struct drm_file *priv; |
d985c1088 drm: major update... |
228 229 230 231 232 233 |
int ret; if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */ if (!drm_cpu_valid()) return -EINVAL; |
5bcf719b7 drm/switcheroo: t... |
234 235 |
if (dev->switch_power_state != DRM_SWITCH_POWER_ON) return -EINVAL; |
d985c1088 drm: major update... |
236 |
|
2c14f28be drm: reorganise m... |
237 238 |
DRM_DEBUG("pid = %d, minor = %d ", task_pid_nr(current), minor_id); |
d985c1088 drm: major update... |
239 |
|
6ebc22e6d drivers/gpu/drm: ... |
240 |
priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
d985c1088 drm: major update... |
241 242 |
if (!priv) return -ENOMEM; |
d985c1088 drm: major update... |
243 |
filp->private_data = priv; |
6c340eac0 drm: Replace filp... |
244 |
priv->filp = filp; |
2df68b439 drm/cred: wrap ta... |
245 |
priv->uid = current_euid(); |
ba25f9dcc Use helpers to ob... |
246 |
priv->pid = task_pid_nr(current); |
2c14f28be drm: reorganise m... |
247 |
priv->minor = idr_find(&drm_minors_idr, minor_id); |
d985c1088 drm: major update... |
248 249 250 251 |
priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); priv->lock_count = 0; |
bd1b331fa drm: cleanup use ... |
252 |
INIT_LIST_HEAD(&priv->lhead); |
f453ba046 DRM: add mode set... |
253 |
INIT_LIST_HEAD(&priv->fbs); |
c9a9c5e02 drm: Add async ev... |
254 255 256 |
INIT_LIST_HEAD(&priv->event_list); init_waitqueue_head(&priv->event_wait); priv->event_space = 4096; /* set aside 4k for event buffer */ |
bd1b331fa drm: cleanup use ... |
257 |
|
673a394b1 drm: Add GEM ("gr... |
258 259 |
if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); |
d985c1088 drm: major update... |
260 261 262 263 264 |
if (dev->driver->open) { ret = dev->driver->open(dev, priv); if (ret < 0) goto out_free; } |
7c1c2871a drm: move to kref... |
265 266 |
/* if there is no current master make this fd it */ |
30e2fb188 sem2mutex: driver... |
267 |
mutex_lock(&dev->struct_mutex); |
7c1c2871a drm: move to kref... |
268 269 270 271 |
if (!priv->minor->master) { /* create a new master */ priv->minor->master = drm_master_create(priv->minor); if (!priv->minor->master) { |
dba5ed0cd drm: drm_fops.c u... |
272 |
mutex_unlock(&dev->struct_mutex); |
7c1c2871a drm: move to kref... |
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
ret = -ENOMEM; goto out_free; } 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); goto out_free; } } |
862302ffe drm: Add support ... |
295 296 297 298 299 300 301 302 303 304 305 306 |
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); goto out_free; } } mutex_unlock(&dev->struct_mutex); |
7c1c2871a drm: move to kref... |
307 308 309 310 311 |
} else { /* get a reference to the master */ priv->master = drm_master_get(priv->minor->master); mutex_unlock(&dev->struct_mutex); } |
bd1b331fa drm: cleanup use ... |
312 |
|
7c1c2871a drm: move to kref... |
313 |
mutex_lock(&dev->struct_mutex); |
bd1b331fa drm: cleanup use ... |
314 |
list_add(&priv->lhead, &dev->filelist); |
30e2fb188 sem2mutex: driver... |
315 |
mutex_unlock(&dev->struct_mutex); |
d985c1088 drm: major update... |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
#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; out_free: |
9a298b2ac drm: Remove memor... |
338 |
kfree(priv); |
d985c1088 drm: major update... |
339 340 341 342 343 344 345 |
filp->private_data = NULL; return ret; } /** No-op. */ int drm_fasync(int fd, struct file *filp, int on) { |
84b1fd103 drm: remove drm_f... |
346 |
struct drm_file *priv = filp->private_data; |
2c14f28be drm: reorganise m... |
347 |
struct drm_device *dev = priv->minor->dev; |
d985c1088 drm: major update... |
348 349 350 |
DRM_DEBUG("fd = %d, device = 0x%lx ", fd, |
2c14f28be drm: reorganise m... |
351 |
(long)old_encode_dev(priv->minor->device)); |
60aa49243 Rationalize fasyn... |
352 |
return fasync_helper(fd, filp, on, &dev->buf_async); |
d985c1088 drm: major update... |
353 354 |
} EXPORT_SYMBOL(drm_fasync); |
7c1c2871a drm: move to kref... |
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 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 |
/* * Reclaim locked buffers; note that this may be a bad idea if the current * context doesn't have the hw lock... */ static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) { struct drm_file *file_priv = f->private_data; if (drm_i_have_hw_lock(dev, file_priv)) { dev->driver->reclaim_buffers_locked(dev, file_priv); } else { unsigned long _end = jiffies + 3 * DRM_HZ; int locked = 0; drm_idlelock_take(&file_priv->master->lock); /* * Wait for a while. */ do { spin_lock_bh(&file_priv->master->lock.spinlock); locked = file_priv->master->lock.idle_has_lock; spin_unlock_bh(&file_priv->master->lock.spinlock); if (locked) break; schedule(); } while (!time_after_eq(jiffies, _end)); if (!locked) { DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this " "\tdriver to use reclaim_buffers_idlelocked() instead. " "\tI will go on reclaiming the buffers anyway. "); } dev->driver->reclaim_buffers_locked(dev, file_priv); drm_idlelock_release(&file_priv->master->lock); } } static void drm_master_release(struct drm_device *dev, struct file *filp) { struct drm_file *file_priv = filp->private_data; if (dev->driver->reclaim_buffers_locked && file_priv->master->lock.hw_lock) drm_reclaim_locked_buffers(dev, filp); if (dev->driver->reclaim_buffers_idlelocked && file_priv->master->lock.hw_lock) { drm_idlelock_take(&file_priv->master->lock); dev->driver->reclaim_buffers_idlelocked(dev, file_priv); drm_idlelock_release(&file_priv->master->lock); } if (drm_i_have_hw_lock(dev, file_priv)) { DRM_DEBUG("File %p released, freeing lock for context %d ", 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)); } if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->reclaim_buffers_locked) { dev->driver->reclaim_buffers(dev, file_priv); } } |
c9a9c5e02 drm: Add async ev... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
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 */ list_for_each_entry_safe(e, et, &file_priv->event_list, link) e->destroy(e); spin_unlock_irqrestore(&dev->event_lock, flags); } |
d985c1088 drm: major update... |
449 |
/** |
1da177e4c Linux-2.6.12-rc2 |
450 451 452 |
* Release file. * * \param inode device inode |
6c340eac0 drm: Replace filp... |
453 |
* \param file_priv DRM file private. |
1da177e4c Linux-2.6.12-rc2 |
454 455 456 457 458 |
* \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 |
22eae947b drm: rename drive... |
459 |
* zero calls drm_lastclose(). |
1da177e4c Linux-2.6.12-rc2 |
460 |
*/ |
b5e89ed53 drm: lindent the ... |
461 |
int drm_release(struct inode *inode, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
462 |
{ |
6c340eac0 drm: Replace filp... |
463 |
struct drm_file *file_priv = filp->private_data; |
2c14f28be drm: reorganise m... |
464 |
struct drm_device *dev = file_priv->minor->dev; |
1da177e4c Linux-2.6.12-rc2 |
465 |
int retcode = 0; |
58374713c drm: kill BKL fro... |
466 |
mutex_lock(&drm_global_mutex); |
1da177e4c Linux-2.6.12-rc2 |
467 |
|
b5e89ed53 drm: lindent the ... |
468 469 |
DRM_DEBUG("open_count = %d ", dev->open_count); |
1da177e4c Linux-2.6.12-rc2 |
470 |
|
22eae947b drm: rename drive... |
471 |
if (dev->driver->preclose) |
6c340eac0 drm: Replace filp... |
472 |
dev->driver->preclose(dev, file_priv); |
1da177e4c Linux-2.6.12-rc2 |
473 474 475 476 |
/* ======================================================== * Begin inline drm_release */ |
b5e89ed53 drm: lindent the ... |
477 478 |
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d ", |
ba25f9dcc Use helpers to ob... |
479 |
task_pid_nr(current), |
2c14f28be drm: reorganise m... |
480 |
(long)old_encode_dev(file_priv->minor->device), |
b5e89ed53 drm: lindent the ... |
481 |
dev->open_count); |
7c1c2871a drm: move to kref... |
482 483 484 |
/* if the master has gone away we can't do anything with the lock */ if (file_priv->minor->master) drm_master_release(dev, filp); |
1da177e4c Linux-2.6.12-rc2 |
485 |
|
c9a9c5e02 drm: Add async ev... |
486 |
drm_events_release(file_priv); |
673a394b1 drm: Add GEM ("gr... |
487 488 |
if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); |
ea39f8351 drm: Release user... |
489 490 |
if (dev->driver->driver_features & DRIVER_MODESET) drm_fb_release(file_priv); |
30e2fb188 sem2mutex: driver... |
491 |
mutex_lock(&dev->ctxlist_mutex); |
bd1b331fa drm: cleanup use ... |
492 |
if (!list_empty(&dev->ctxlist)) { |
55910517a drm: detypedeffin... |
493 |
struct drm_ctx_list *pos, *n; |
1da177e4c Linux-2.6.12-rc2 |
494 |
|
bd1b331fa drm: cleanup use ... |
495 |
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { |
6c340eac0 drm: Replace filp... |
496 |
if (pos->tag == file_priv && |
b5e89ed53 drm: lindent the ... |
497 |
pos->handle != DRM_KERNEL_CONTEXT) { |
1da177e4c Linux-2.6.12-rc2 |
498 |
if (dev->driver->context_dtor) |
b5e89ed53 drm: lindent the ... |
499 500 |
dev->driver->context_dtor(dev, pos->handle); |
1da177e4c Linux-2.6.12-rc2 |
501 |
|
b5e89ed53 drm: lindent the ... |
502 |
drm_ctxbitmap_free(dev, pos->handle); |
1da177e4c Linux-2.6.12-rc2 |
503 |
|
b5e89ed53 drm: lindent the ... |
504 |
list_del(&pos->head); |
9a298b2ac drm: Remove memor... |
505 |
kfree(pos); |
1da177e4c Linux-2.6.12-rc2 |
506 507 508 509 |
--dev->ctx_count; } } } |
30e2fb188 sem2mutex: driver... |
510 |
mutex_unlock(&dev->ctxlist_mutex); |
1da177e4c Linux-2.6.12-rc2 |
511 |
|
30e2fb188 sem2mutex: driver... |
512 |
mutex_lock(&dev->struct_mutex); |
7c1c2871a drm: move to kref... |
513 514 |
if (file_priv->is_master) { |
fda714c29 drm: Avoid client... |
515 |
struct drm_master *master = file_priv->master; |
84b1fd103 drm: remove drm_f... |
516 |
struct drm_file *temp; |
7c1c2871a drm: move to kref... |
517 518 519 520 521 |
list_for_each_entry(temp, &dev->filelist, lhead) { if ((temp->master == file_priv->master) && (temp != file_priv)) temp->authenticated = 0; } |
bd1b331fa drm: cleanup use ... |
522 |
|
fda714c29 drm: Avoid client... |
523 524 525 526 527 528 529 530 531 532 533 534 |
/** * 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); } |
7c1c2871a drm: move to kref... |
535 536 |
if (file_priv->minor->master == file_priv->master) { /* drop the reference held my the minor */ |
862302ffe drm: Add support ... |
537 538 |
if (dev->driver->master_drop) dev->driver->master_drop(dev, file_priv, true); |
7c1c2871a drm: move to kref... |
539 540 |
drm_master_put(&file_priv->minor->master); } |
1da177e4c Linux-2.6.12-rc2 |
541 |
} |
7c1c2871a drm: move to kref... |
542 543 544 545 |
/* drop the reference held my the file priv */ drm_master_put(&file_priv->master); file_priv->is_master = 0; |
6c340eac0 drm: Replace filp... |
546 |
list_del(&file_priv->lhead); |
30e2fb188 sem2mutex: driver... |
547 |
mutex_unlock(&dev->struct_mutex); |
b5e89ed53 drm: lindent the ... |
548 |
|
22eae947b drm: rename drive... |
549 |
if (dev->driver->postclose) |
6c340eac0 drm: Replace filp... |
550 |
dev->driver->postclose(dev, file_priv); |
9a298b2ac drm: Remove memor... |
551 |
kfree(file_priv); |
1da177e4c Linux-2.6.12-rc2 |
552 553 554 555 |
/* ======================================================== * End inline drm_release */ |
b5e89ed53 drm: lindent the ... |
556 |
atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); |
b5e89ed53 drm: lindent the ... |
557 |
if (!--dev->open_count) { |
7c1c2871a drm: move to kref... |
558 559 560 561 |
if (atomic_read(&dev->ioctl_count)) { DRM_ERROR("Device busy: %d ", atomic_read(&dev->ioctl_count)); |
58374713c drm: kill BKL fro... |
562 |
retcode = -EBUSY; |
1a72d65d6 drm: Remove count... |
563 564 |
} else retcode = drm_lastclose(dev); |
1da177e4c Linux-2.6.12-rc2 |
565 |
} |
58374713c drm: kill BKL fro... |
566 |
mutex_unlock(&drm_global_mutex); |
1da177e4c Linux-2.6.12-rc2 |
567 568 569 570 |
return retcode; } EXPORT_SYMBOL(drm_release); |
c9a9c5e02 drm: Add async ev... |
571 572 573 574 575 576 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 |
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); |
1da177e4c Linux-2.6.12-rc2 |
628 629 |
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) { |
c9a9c5e02 drm: Add async ev... |
630 631 632 633 634 635 636 637 638 |
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; |
1da177e4c Linux-2.6.12-rc2 |
639 |
} |
b5e89ed53 drm: lindent the ... |
640 |
EXPORT_SYMBOL(drm_poll); |