aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_fops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_fops.c')
-rw-r--r--drivers/char/drm/drm_fops.c317
1 files changed, 180 insertions, 137 deletions
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index bf0a740122bf..403f44a1bf01 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -35,6 +35,7 @@
35 */ 35 */
36 36
37#include "drmP.h" 37#include "drmP.h"
38#include "drm_sarea.h"
38#include <linux/poll.h> 39#include <linux/poll.h>
39 40
40static int drm_open_helper(struct inode *inode, struct file *filp, 41static int drm_open_helper(struct inode *inode, struct file *filp,
@@ -42,15 +43,21 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
42 43
43static int drm_setup(drm_device_t * dev) 44static int drm_setup(drm_device_t * dev)
44{ 45{
46 drm_local_map_t *map;
45 int i; 47 int i;
46 int ret; 48 int ret;
47 49
48 if (dev->driver->presetup) { 50 if (dev->driver->firstopen) {
49 ret = dev->driver->presetup(dev); 51 ret = dev->driver->firstopen(dev);
50 if (ret != 0) 52 if (ret != 0)
51 return ret; 53 return ret;
52 } 54 }
53 55
56 /* prebuild the SAREA */
57 i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
58 if (i != 0)
59 return i;
60
54 atomic_set(&dev->ioctl_count, 0); 61 atomic_set(&dev->ioctl_count, 0);
55 atomic_set(&dev->vma_count, 0); 62 atomic_set(&dev->vma_count, 0);
56 dev->buf_use = 0; 63 dev->buf_use = 0;
@@ -109,8 +116,6 @@ static int drm_setup(drm_device_t * dev)
109 * drm_select_queue fails between the time the interrupt is 116 * drm_select_queue fails between the time the interrupt is
110 * initialized and the time the queues are initialized. 117 * initialized and the time the queues are initialized.
111 */ 118 */
112 if (dev->driver->postsetup)
113 dev->driver->postsetup(dev);
114 119
115 return 0; 120 return 0;
116} 121}
@@ -154,10 +159,168 @@ int drm_open(struct inode *inode, struct file *filp)
154 159
155 return retcode; 160 return retcode;
156} 161}
157
158EXPORT_SYMBOL(drm_open); 162EXPORT_SYMBOL(drm_open);
159 163
160/** 164/**
165 * File \c open operation.
166 *
167 * \param inode device inode.
168 * \param filp file pointer.
169 *
170 * Puts the dev->fops corresponding to the device minor number into
171 * \p filp, call the \c open method, and restore the file operations.
172 */
173int drm_stub_open(struct inode *inode, struct file *filp)
174{
175 drm_device_t *dev = NULL;
176 int minor = iminor(inode);
177 int err = -ENODEV;
178 struct file_operations *old_fops;
179
180 DRM_DEBUG("\n");
181
182 if (!((minor >= 0) && (minor < drm_cards_limit)))
183 return -ENODEV;
184
185 if (!drm_heads[minor])
186 return -ENODEV;
187
188 if (!(dev = drm_heads[minor]->dev))
189 return -ENODEV;
190
191 old_fops = filp->f_op;
192 filp->f_op = fops_get(&dev->driver->fops);
193 if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
194 fops_put(filp->f_op);
195 filp->f_op = fops_get(old_fops);
196 }
197 fops_put(old_fops);
198
199 return err;
200}
201
202/**
203 * Check whether DRI will run on this CPU.
204 *
205 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
206 */
207static int drm_cpu_valid(void)
208{
209#if defined(__i386__)
210 if (boot_cpu_data.x86 == 3)
211 return 0; /* No cmpxchg on a 386 */
212#endif
213#if defined(__sparc__) && !defined(__sparc_v9__)
214 return 0; /* No cmpxchg before v9 sparc. */
215#endif
216 return 1;
217}
218
219/**
220 * Called whenever a process opens /dev/drm.
221 *
222 * \param inode device inode.
223 * \param filp file pointer.
224 * \param dev device.
225 * \return zero on success or a negative number on failure.
226 *
227 * Creates and initializes a drm_file structure for the file private data in \p
228 * filp and add it into the double linked list in \p dev.
229 */
230static int drm_open_helper(struct inode *inode, struct file *filp,
231 drm_device_t * dev)
232{
233 int minor = iminor(inode);
234 drm_file_t *priv;
235 int ret;
236
237 if (filp->f_flags & O_EXCL)
238 return -EBUSY; /* No exclusive opens */
239 if (!drm_cpu_valid())
240 return -EINVAL;
241
242 DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
243
244 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
245 if (!priv)
246 return -ENOMEM;
247
248 memset(priv, 0, sizeof(*priv));
249 filp->private_data = priv;
250 priv->uid = current->euid;
251 priv->pid = current->pid;
252 priv->minor = minor;
253 priv->head = drm_heads[minor];
254 priv->ioctl_count = 0;
255 /* for compatibility root is always authenticated */
256 priv->authenticated = capable(CAP_SYS_ADMIN);
257 priv->lock_count = 0;
258
259 if (dev->driver->open) {
260 ret = dev->driver->open(dev, priv);
261 if (ret < 0)
262 goto out_free;
263 }
264
265 down(&dev->struct_sem);
266 if (!dev->file_last) {
267 priv->next = NULL;
268 priv->prev = NULL;
269 dev->file_first = priv;
270 dev->file_last = priv;
271 /* first opener automatically becomes master */
272 priv->master = 1;
273 } else {
274 priv->next = NULL;
275 priv->prev = dev->file_last;
276 dev->file_last->next = priv;
277 dev->file_last = priv;
278 }
279 up(&dev->struct_sem);
280
281#ifdef __alpha__
282 /*
283 * Default the hose
284 */
285 if (!dev->hose) {
286 struct pci_dev *pci_dev;
287 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
288 if (pci_dev) {
289 dev->hose = pci_dev->sysdata;
290 pci_dev_put(pci_dev);
291 }
292 if (!dev->hose) {
293 struct pci_bus *b = pci_bus_b(pci_root_buses.next);
294 if (b)
295 dev->hose = b->sysdata;
296 }
297 }
298#endif
299
300 return 0;
301 out_free:
302 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
303 filp->private_data = NULL;
304 return ret;
305}
306
307/** No-op. */
308int drm_fasync(int fd, struct file *filp, int on)
309{
310 drm_file_t *priv = filp->private_data;
311 drm_device_t *dev = priv->head->dev;
312 int retcode;
313
314 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
315 (long)old_encode_dev(priv->head->device));
316 retcode = fasync_helper(fd, filp, on, &dev->buf_async);
317 if (retcode < 0)
318 return retcode;
319 return 0;
320}
321EXPORT_SYMBOL(drm_fasync);
322
323/**
161 * Release file. 324 * Release file.
162 * 325 *
163 * \param inode device inode 326 * \param inode device inode
@@ -167,7 +330,7 @@ EXPORT_SYMBOL(drm_open);
167 * If the hardware lock is held then free it, and take it again for the kernel 330 * If the hardware lock is held then free it, and take it again for the kernel
168 * context since it's necessary to reclaim buffers. Unlink the file private 331 * context since it's necessary to reclaim buffers. Unlink the file private
169 * data from its list and free it. Decreases the open count and if it reaches 332 * data from its list and free it. Decreases the open count and if it reaches
170 * zero calls takedown(). 333 * zero calls drm_lastclose().
171 */ 334 */
172int drm_release(struct inode *inode, struct file *filp) 335int drm_release(struct inode *inode, struct file *filp)
173{ 336{
@@ -180,8 +343,8 @@ int drm_release(struct inode *inode, struct file *filp)
180 343
181 DRM_DEBUG("open_count = %d\n", dev->open_count); 344 DRM_DEBUG("open_count = %d\n", dev->open_count);
182 345
183 if (dev->driver->prerelease) 346 if (dev->driver->preclose)
184 dev->driver->prerelease(dev, filp); 347 dev->driver->preclose(dev, filp);
185 348
186 /* ======================================================== 349 /* ========================================================
187 * Begin inline drm_release 350 * Begin inline drm_release
@@ -197,8 +360,8 @@ int drm_release(struct inode *inode, struct file *filp)
197 DRM_DEBUG("File %p released, freeing lock for context %d\n", 360 DRM_DEBUG("File %p released, freeing lock for context %d\n",
198 filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 361 filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
199 362
200 if (dev->driver->release) 363 if (dev->driver->reclaim_buffers_locked)
201 dev->driver->release(dev, filp); 364 dev->driver->reclaim_buffers_locked(dev, filp);
202 365
203 drm_lock_free(dev, &dev->lock.hw_lock->lock, 366 drm_lock_free(dev, &dev->lock.hw_lock->lock,
204 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 367 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@@ -207,7 +370,7 @@ int drm_release(struct inode *inode, struct file *filp)
207 hardware at this point, possibly 370 hardware at this point, possibly
208 processed via a callback to the X 371 processed via a callback to the X
209 server. */ 372 server. */
210 } else if (dev->driver->release && priv->lock_count 373 } else if (dev->driver->reclaim_buffers_locked && priv->lock_count
211 && dev->lock.hw_lock) { 374 && dev->lock.hw_lock) {
212 /* The lock is required to reclaim buffers */ 375 /* The lock is required to reclaim buffers */
213 DECLARE_WAITQUEUE(entry, current); 376 DECLARE_WAITQUEUE(entry, current);
@@ -237,15 +400,14 @@ int drm_release(struct inode *inode, struct file *filp)
237 __set_current_state(TASK_RUNNING); 400 __set_current_state(TASK_RUNNING);
238 remove_wait_queue(&dev->lock.lock_queue, &entry); 401 remove_wait_queue(&dev->lock.lock_queue, &entry);
239 if (!retcode) { 402 if (!retcode) {
240 if (dev->driver->release) 403 dev->driver->reclaim_buffers_locked(dev, filp);
241 dev->driver->release(dev, filp);
242 drm_lock_free(dev, &dev->lock.hw_lock->lock, 404 drm_lock_free(dev, &dev->lock.hw_lock->lock,
243 DRM_KERNEL_CONTEXT); 405 DRM_KERNEL_CONTEXT);
244 } 406 }
245 } 407 }
246 408
247 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) 409 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
248 && !dev->driver->release) { 410 !dev->driver->reclaim_buffers_locked) {
249 dev->driver->reclaim_buffers(dev, filp); 411 dev->driver->reclaim_buffers(dev, filp);
250 } 412 }
251 413
@@ -292,9 +454,8 @@ int drm_release(struct inode *inode, struct file *filp)
292 } 454 }
293 up(&dev->struct_sem); 455 up(&dev->struct_sem);
294 456
295 if (dev->driver->free_filp_priv) 457 if (dev->driver->postclose)
296 dev->driver->free_filp_priv(dev, priv); 458 dev->driver->postclose(dev, priv);
297
298 drm_free(priv, sizeof(*priv), DRM_MEM_FILES); 459 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
299 460
300 /* ======================================================== 461 /* ========================================================
@@ -313,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
313 } 474 }
314 spin_unlock(&dev->count_lock); 475 spin_unlock(&dev->count_lock);
315 unlock_kernel(); 476 unlock_kernel();
316 return drm_takedown(dev); 477 return drm_lastclose(dev);
317 } 478 }
318 spin_unlock(&dev->count_lock); 479 spin_unlock(&dev->count_lock);
319 480
@@ -321,129 +482,11 @@ int drm_release(struct inode *inode, struct file *filp)
321 482
322 return retcode; 483 return retcode;
323} 484}
324
325EXPORT_SYMBOL(drm_release); 485EXPORT_SYMBOL(drm_release);
326 486
327/**
328 * Called whenever a process opens /dev/drm.
329 *
330 * \param inode device inode.
331 * \param filp file pointer.
332 * \param dev device.
333 * \return zero on success or a negative number on failure.
334 *
335 * Creates and initializes a drm_file structure for the file private data in \p
336 * filp and add it into the double linked list in \p dev.
337 */
338static int drm_open_helper(struct inode *inode, struct file *filp,
339 drm_device_t * dev)
340{
341 int minor = iminor(inode);
342 drm_file_t *priv;
343 int ret;
344
345 if (filp->f_flags & O_EXCL)
346 return -EBUSY; /* No exclusive opens */
347 if (!drm_cpu_valid())
348 return -EINVAL;
349
350 DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
351
352 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
353 if (!priv)
354 return -ENOMEM;
355
356 memset(priv, 0, sizeof(*priv));
357 filp->private_data = priv;
358 priv->uid = current->euid;
359 priv->pid = current->pid;
360 priv->minor = minor;
361 priv->head = drm_heads[minor];
362 priv->ioctl_count = 0;
363 priv->authenticated = capable(CAP_SYS_ADMIN);
364 priv->lock_count = 0;
365
366 if (dev->driver->open_helper) {
367 ret = dev->driver->open_helper(dev, priv);
368 if (ret < 0)
369 goto out_free;
370 }
371
372 down(&dev->struct_sem);
373 if (!dev->file_last) {
374 priv->next = NULL;
375 priv->prev = NULL;
376 dev->file_first = priv;
377 dev->file_last = priv;
378 } else {
379 priv->next = NULL;
380 priv->prev = dev->file_last;
381 dev->file_last->next = priv;
382 dev->file_last = priv;
383 }
384 up(&dev->struct_sem);
385
386#ifdef __alpha__
387 /*
388 * Default the hose
389 */
390 if (!dev->hose) {
391 struct pci_dev *pci_dev;
392 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
393 if (pci_dev) {
394 dev->hose = pci_dev->sysdata;
395 pci_dev_put(pci_dev);
396 }
397 if (!dev->hose) {
398 struct pci_bus *b = pci_bus_b(pci_root_buses.next);
399 if (b)
400 dev->hose = b->sysdata;
401 }
402 }
403#endif
404
405 return 0;
406 out_free:
407 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
408 filp->private_data = NULL;
409 return ret;
410}
411
412/** No-op. */
413int drm_flush(struct file *filp)
414{
415 drm_file_t *priv = filp->private_data;
416 drm_device_t *dev = priv->head->dev;
417
418 DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
419 current->pid, (long)old_encode_dev(priv->head->device),
420 dev->open_count);
421 return 0;
422}
423
424EXPORT_SYMBOL(drm_flush);
425
426/** No-op. */
427int drm_fasync(int fd, struct file *filp, int on)
428{
429 drm_file_t *priv = filp->private_data;
430 drm_device_t *dev = priv->head->dev;
431 int retcode;
432
433 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
434 (long)old_encode_dev(priv->head->device));
435 retcode = fasync_helper(fd, filp, on, &dev->buf_async);
436 if (retcode < 0)
437 return retcode;
438 return 0;
439}
440
441EXPORT_SYMBOL(drm_fasync);
442
443/** No-op. */ 487/** No-op. */
444unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) 488unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
445{ 489{
446 return 0; 490 return 0;
447} 491}
448
449EXPORT_SYMBOL(drm_poll); 492EXPORT_SYMBOL(drm_poll);