drm_context.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:20k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
  2.  * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
  3.  *
  4.  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25.  * OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  * Authors:
  28.  *    Rickard E. (Rik) Faith <faith@valinux.com>
  29.  *    Gareth Hughes <gareth@valinux.com>
  30.  * ChangeLog:
  31.  *  2001-11-16 Torsten Duwe <duwe@caldera.de>
  32.  * added context constructor/destructor hooks,
  33.  * needed by SiS driver's memory management.
  34.  */
  35. #define __NO_VERSION__
  36. #include "drmP.h"
  37. #if __HAVE_CTX_BITMAP
  38. /* ================================================================
  39.  * Context bitmap support
  40.  */
  41. void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
  42. {
  43. if ( ctx_handle < 0 ) goto failed;
  44. if ( !dev->ctx_bitmap ) goto failed;
  45. if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
  46. down(&dev->struct_sem);
  47. clear_bit( ctx_handle, dev->ctx_bitmap );
  48. dev->context_sareas[ctx_handle] = NULL;
  49. up(&dev->struct_sem);
  50. return;
  51. }
  52. failed:
  53.         DRM_ERROR( "Attempt to free invalid context handle: %dn",
  54.    ctx_handle );
  55.         return;
  56. }
  57. int DRM(ctxbitmap_next)( drm_device_t *dev )
  58. {
  59. int bit;
  60. if(!dev->ctx_bitmap) return -1;
  61. down(&dev->struct_sem);
  62. bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
  63. if ( bit < DRM_MAX_CTXBITMAP ) {
  64. set_bit( bit, dev->ctx_bitmap );
  65.     DRM_DEBUG( "drm_ctxbitmap_next bit : %dn", bit );
  66. if((bit+1) > dev->max_context) {
  67. dev->max_context = (bit+1);
  68. if(dev->context_sareas) {
  69. drm_map_t **ctx_sareas;
  70. ctx_sareas = DRM(realloc)(dev->context_sareas,
  71. (dev->max_context - 1) * 
  72. sizeof(*dev->context_sareas),
  73. dev->max_context * 
  74. sizeof(*dev->context_sareas),
  75. DRM_MEM_MAPS);
  76. if(!ctx_sareas) {
  77. clear_bit(bit, dev->ctx_bitmap);
  78. up(&dev->struct_sem);
  79. return -1;
  80. }
  81. dev->context_sareas = ctx_sareas;
  82. dev->context_sareas[bit] = NULL;
  83. } else {
  84. /* max_context == 1 at this point */
  85. dev->context_sareas = DRM(alloc)(
  86. dev->max_context * 
  87. sizeof(*dev->context_sareas),
  88. DRM_MEM_MAPS);
  89. if(!dev->context_sareas) {
  90. clear_bit(bit, dev->ctx_bitmap);
  91. up(&dev->struct_sem);
  92. return -1;
  93. }
  94. dev->context_sareas[bit] = NULL;
  95. }
  96. }
  97. up(&dev->struct_sem);
  98. return bit;
  99. }
  100. up(&dev->struct_sem);
  101. return -1;
  102. }
  103. int DRM(ctxbitmap_init)( drm_device_t *dev )
  104. {
  105. int i;
  106.     int temp;
  107. down(&dev->struct_sem);
  108. dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
  109. DRM_MEM_CTXBITMAP );
  110. if ( dev->ctx_bitmap == NULL ) {
  111. up(&dev->struct_sem);
  112. return -ENOMEM;
  113. }
  114. memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
  115. dev->context_sareas = NULL;
  116. dev->max_context = -1;
  117. up(&dev->struct_sem);
  118. for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
  119. temp = DRM(ctxbitmap_next)( dev );
  120.     DRM_DEBUG( "drm_ctxbitmap_init : %dn", temp );
  121. }
  122. return 0;
  123. }
  124. void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
  125. {
  126. down(&dev->struct_sem);
  127. if( dev->context_sareas ) DRM(free)( dev->context_sareas,
  128.      sizeof(*dev->context_sareas) * 
  129.      dev->max_context,
  130.      DRM_MEM_MAPS );
  131. DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
  132. up(&dev->struct_sem);
  133. }
  134. /* ================================================================
  135.  * Per Context SAREA Support
  136.  */
  137. int DRM(getsareactx)(struct inode *inode, struct file *filp,
  138.      unsigned int cmd, unsigned long arg)
  139. {
  140. drm_file_t *priv = filp->private_data;
  141. drm_device_t *dev = priv->dev;
  142. drm_ctx_priv_map_t request;
  143. drm_map_t *map;
  144. if (copy_from_user(&request,
  145.    (drm_ctx_priv_map_t *)arg,
  146.    sizeof(request)))
  147. return -EFAULT;
  148. down(&dev->struct_sem);
  149. if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
  150. up(&dev->struct_sem);
  151. return -EINVAL;
  152. }
  153. map = dev->context_sareas[request.ctx_id];
  154. up(&dev->struct_sem);
  155. request.handle = map->handle;
  156. if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request)))
  157. return -EFAULT;
  158. return 0;
  159. }
  160. int DRM(setsareactx)(struct inode *inode, struct file *filp,
  161.      unsigned int cmd, unsigned long arg)
  162. {
  163. drm_file_t *priv = filp->private_data;
  164. drm_device_t *dev = priv->dev;
  165. drm_ctx_priv_map_t request;
  166. drm_map_t *map = NULL;
  167. drm_map_list_t *r_list = NULL;
  168. struct list_head *list;
  169. if (copy_from_user(&request,
  170.    (drm_ctx_priv_map_t *)arg,
  171.    sizeof(request)))
  172. return -EFAULT;
  173. down(&dev->struct_sem);
  174. list_for_each(list, &dev->maplist->head) {
  175. r_list = (drm_map_list_t *)list;
  176. if(r_list->map &&
  177.    r_list->map->handle == request.handle)
  178. goto found;
  179. }
  180. bad:
  181. up(&dev->struct_sem);
  182. return -EINVAL;
  183. found:
  184. map = r_list->map;
  185. if (!map) goto bad;
  186. if (dev->max_context < 0)
  187. goto bad;
  188. if (request.ctx_id >= (unsigned) dev->max_context)
  189. goto bad;
  190. dev->context_sareas[request.ctx_id] = map;
  191. up(&dev->struct_sem);
  192. return 0;
  193. }
  194. /* ================================================================
  195.  * The actual DRM context handling routines
  196.  */
  197. int DRM(context_switch)( drm_device_t *dev, int old, int new )
  198. {
  199.         char buf[64];
  200.         if ( test_and_set_bit( 0, &dev->context_flag ) ) {
  201.                 DRM_ERROR( "Reentering -- FIXMEn" );
  202.                 return -EBUSY;
  203.         }
  204. #if __HAVE_DMA_HISTOGRAM
  205.         dev->ctx_start = get_cycles();
  206. #endif
  207.         DRM_DEBUG( "Context switch from %d to %dn", old, new );
  208.         if ( new == dev->last_context ) {
  209.                 clear_bit( 0, &dev->context_flag );
  210.                 return 0;
  211.         }
  212.         if ( DRM(flags) & DRM_FLAG_NOCTX ) {
  213.                 DRM(context_switch_complete)( dev, new );
  214.         } else {
  215.                 sprintf( buf, "C %d %dn", old, new );
  216.                 DRM(write_string)( dev, buf );
  217.         }
  218.         return 0;
  219. }
  220. int DRM(context_switch_complete)( drm_device_t *dev, int new )
  221. {
  222.         dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
  223.         dev->last_switch  = jiffies;
  224.         if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
  225.                 DRM_ERROR( "Lock isn't held after context switchn" );
  226.         }
  227. /* If a context switch is ever initiated
  228.                                    when the kernel holds the lock, release
  229.                                    that lock here. */
  230. #if __HAVE_DMA_HISTOGRAM
  231.         atomic_inc( &dev->histo.ctx[DRM(histogram_slot)(get_cycles()
  232. - dev->ctx_start)] );
  233. #endif
  234.         clear_bit( 0, &dev->context_flag );
  235.         wake_up( &dev->context_wait );
  236.         return 0;
  237. }
  238. int DRM(resctx)( struct inode *inode, struct file *filp,
  239.  unsigned int cmd, unsigned long arg )
  240. {
  241. drm_ctx_res_t res;
  242. drm_ctx_t ctx;
  243. int i;
  244. if ( copy_from_user( &res, (drm_ctx_res_t *)arg, sizeof(res) ) )
  245. return -EFAULT;
  246. if ( res.count >= DRM_RESERVED_CONTEXTS ) {
  247. memset( &ctx, 0, sizeof(ctx) );
  248. for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
  249. ctx.handle = i;
  250. if ( copy_to_user( &res.contexts[i],
  251.    &i, sizeof(i) ) )
  252. return -EFAULT;
  253. }
  254. }
  255. res.count = DRM_RESERVED_CONTEXTS;
  256. if ( copy_to_user( (drm_ctx_res_t *)arg, &res, sizeof(res) ) )
  257. return -EFAULT;
  258. return 0;
  259. }
  260. int DRM(addctx)( struct inode *inode, struct file *filp,
  261.  unsigned int cmd, unsigned long arg )
  262. {
  263. drm_file_t *priv = filp->private_data;
  264. drm_device_t *dev = priv->dev;
  265. drm_ctx_t ctx;
  266. if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
  267. return -EFAULT;
  268. ctx.handle = DRM(ctxbitmap_next)( dev );
  269. if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
  270. /* Skip kernel's context and get a new one. */
  271. ctx.handle = DRM(ctxbitmap_next)( dev );
  272. }
  273. DRM_DEBUG( "%dn", ctx.handle );
  274. if ( ctx.handle == -1 ) {
  275. DRM_DEBUG( "Not enough free contexts.n" );
  276. /* Should this return -EBUSY instead? */
  277. return -ENOMEM;
  278. }
  279. #ifdef DRIVER_CTX_CTOR
  280. if ( ctx.handle != DRM_KERNEL_CONTEXT )
  281. DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
  282. #endif
  283. if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
  284. return -EFAULT;
  285. return 0;
  286. }
  287. int DRM(modctx)( struct inode *inode, struct file *filp,
  288.  unsigned int cmd, unsigned long arg )
  289. {
  290. /* This does nothing */
  291. return 0;
  292. }
  293. int DRM(getctx)( struct inode *inode, struct file *filp,
  294.  unsigned int cmd, unsigned long arg )
  295. {
  296. drm_ctx_t ctx;
  297. if ( copy_from_user( &ctx, (drm_ctx_t*)arg, sizeof(ctx) ) )
  298. return -EFAULT;
  299. /* This is 0, because we don't handle any context flags */
  300. ctx.flags = 0;
  301. if ( copy_to_user( (drm_ctx_t*)arg, &ctx, sizeof(ctx) ) )
  302. return -EFAULT;
  303. return 0;
  304. }
  305. int DRM(switchctx)( struct inode *inode, struct file *filp,
  306.     unsigned int cmd, unsigned long arg )
  307. {
  308. drm_file_t *priv = filp->private_data;
  309. drm_device_t *dev = priv->dev;
  310. drm_ctx_t ctx;
  311. if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
  312. return -EFAULT;
  313. DRM_DEBUG( "%dn", ctx.handle );
  314. return DRM(context_switch)( dev, dev->last_context, ctx.handle );
  315. }
  316. int DRM(newctx)( struct inode *inode, struct file *filp,
  317.  unsigned int cmd, unsigned long arg )
  318. {
  319. drm_file_t *priv = filp->private_data;
  320. drm_device_t *dev = priv->dev;
  321. drm_ctx_t ctx;
  322. if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
  323. return -EFAULT;
  324. DRM_DEBUG( "%dn", ctx.handle );
  325. DRM(context_switch_complete)( dev, ctx.handle );
  326. return 0;
  327. }
  328. int DRM(rmctx)( struct inode *inode, struct file *filp,
  329. unsigned int cmd, unsigned long arg )
  330. {
  331. drm_file_t *priv = filp->private_data;
  332. drm_device_t *dev = priv->dev;
  333. drm_ctx_t ctx;
  334. if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
  335. return -EFAULT;
  336. DRM_DEBUG( "%dn", ctx.handle );
  337. if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
  338. priv->remove_auth_on_close = 1;
  339. }
  340. if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
  341. #ifdef DRIVER_CTX_DTOR
  342. DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
  343. #endif
  344. DRM(ctxbitmap_free)( dev, ctx.handle );
  345. }
  346. return 0;
  347. }
  348. #else /* __HAVE_CTX_BITMAP */
  349. /* ================================================================
  350.  * Old-style context support
  351.  */
  352. int DRM(context_switch)(drm_device_t *dev, int old, int new)
  353. {
  354. char     buf[64];
  355. drm_queue_t *q;
  356. #if 0
  357. atomic_inc(&dev->total_ctx);
  358. #endif
  359. if (test_and_set_bit(0, &dev->context_flag)) {
  360. DRM_ERROR("Reentering -- FIXMEn");
  361. return -EBUSY;
  362. }
  363. #if __HAVE_DMA_HISTOGRAM
  364. dev->ctx_start = get_cycles();
  365. #endif
  366. DRM_DEBUG("Context switch from %d to %dn", old, new);
  367. if (new >= dev->queue_count) {
  368. clear_bit(0, &dev->context_flag);
  369. return -EINVAL;
  370. }
  371. if (new == dev->last_context) {
  372. clear_bit(0, &dev->context_flag);
  373. return 0;
  374. }
  375. q = dev->queuelist[new];
  376. atomic_inc(&q->use_count);
  377. if (atomic_read(&q->use_count) == 1) {
  378. atomic_dec(&q->use_count);
  379. clear_bit(0, &dev->context_flag);
  380. return -EINVAL;
  381. }
  382. if (DRM(flags) & DRM_FLAG_NOCTX) {
  383. DRM(context_switch_complete)(dev, new);
  384. } else {
  385. sprintf(buf, "C %d %dn", old, new);
  386. DRM(write_string)(dev, buf);
  387. }
  388. atomic_dec(&q->use_count);
  389. return 0;
  390. }
  391. int DRM(context_switch_complete)(drm_device_t *dev, int new)
  392. {
  393. drm_device_dma_t *dma = dev->dma;
  394. dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
  395. dev->last_switch  = jiffies;
  396. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  397. DRM_ERROR("Lock isn't held after context switchn");
  398. }
  399. if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
  400. if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
  401.   DRM_KERNEL_CONTEXT)) {
  402. DRM_ERROR("Cannot free lockn");
  403. }
  404. }
  405. #if __HAVE_DMA_HISTOGRAM
  406. atomic_inc(&dev->histo.ctx[DRM(histogram_slot)(get_cycles()
  407.       - dev->ctx_start)]);
  408. #endif
  409. clear_bit(0, &dev->context_flag);
  410. wake_up_interruptible(&dev->context_wait);
  411. return 0;
  412. }
  413. static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
  414. {
  415. DRM_DEBUG("n");
  416. if (atomic_read(&q->use_count) != 1
  417.     || atomic_read(&q->finalization)
  418.     || atomic_read(&q->block_count)) {
  419. DRM_ERROR("New queue is already in use: u%d f%d b%dn",
  420.   atomic_read(&q->use_count),
  421.   atomic_read(&q->finalization),
  422.   atomic_read(&q->block_count));
  423. }
  424. atomic_set(&q->finalization,  0);
  425. atomic_set(&q->block_count,   0);
  426. atomic_set(&q->block_read,    0);
  427. atomic_set(&q->block_write,   0);
  428. atomic_set(&q->total_queued,  0);
  429. atomic_set(&q->total_flushed, 0);
  430. atomic_set(&q->total_locks,   0);
  431. init_waitqueue_head(&q->write_queue);
  432. init_waitqueue_head(&q->read_queue);
  433. init_waitqueue_head(&q->flush_queue);
  434. q->flags = ctx->flags;
  435. DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
  436. return 0;
  437. }
  438. /* drm_alloc_queue:
  439. PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
  440. disappear (so all deallocation must be done after IOCTLs are off)
  441.      2) dev->queue_count < dev->queue_slots
  442.      3) dev->queuelist[i].use_count == 0 and
  443. dev->queuelist[i].finalization == 0 if i not in use
  444. POST: 1) dev->queuelist[i].use_count == 1
  445.       2) dev->queue_count < dev->queue_slots */
  446. static int DRM(alloc_queue)(drm_device_t *dev)
  447. {
  448. int     i;
  449. drm_queue_t *queue;
  450. int     oldslots;
  451. int     newslots;
  452. /* Check for a free queue */
  453. for (i = 0; i < dev->queue_count; i++) {
  454. atomic_inc(&dev->queuelist[i]->use_count);
  455. if (atomic_read(&dev->queuelist[i]->use_count) == 1
  456.     && !atomic_read(&dev->queuelist[i]->finalization)) {
  457. DRM_DEBUG("%d (free)n", i);
  458. return i;
  459. }
  460. atomic_dec(&dev->queuelist[i]->use_count);
  461. }
  462. /* Allocate a new queue */
  463. down(&dev->struct_sem);
  464. queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES);
  465. memset(queue, 0, sizeof(*queue));
  466. atomic_set(&queue->use_count, 1);
  467. ++dev->queue_count;
  468. if (dev->queue_count >= dev->queue_slots) {
  469. oldslots = dev->queue_slots * sizeof(*dev->queuelist);
  470. if (!dev->queue_slots) dev->queue_slots = 1;
  471. dev->queue_slots *= 2;
  472. newslots = dev->queue_slots * sizeof(*dev->queuelist);
  473. dev->queuelist = DRM(realloc)(dev->queuelist,
  474.       oldslots,
  475.       newslots,
  476.       DRM_MEM_QUEUES);
  477. if (!dev->queuelist) {
  478. up(&dev->struct_sem);
  479. DRM_DEBUG("out of memoryn");
  480. return -ENOMEM;
  481. }
  482. }
  483. dev->queuelist[dev->queue_count-1] = queue;
  484. up(&dev->struct_sem);
  485. DRM_DEBUG("%d (new)n", dev->queue_count - 1);
  486. return dev->queue_count - 1;
  487. }
  488. int DRM(resctx)(struct inode *inode, struct file *filp,
  489. unsigned int cmd, unsigned long arg)
  490. {
  491. drm_ctx_res_t res;
  492. drm_ctx_t ctx;
  493. int i;
  494. DRM_DEBUG("%dn", DRM_RESERVED_CONTEXTS);
  495. if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
  496. return -EFAULT;
  497. if (res.count >= DRM_RESERVED_CONTEXTS) {
  498. memset(&ctx, 0, sizeof(ctx));
  499. for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
  500. ctx.handle = i;
  501. if (copy_to_user(&res.contexts[i],
  502.  &i,
  503.  sizeof(i)))
  504. return -EFAULT;
  505. }
  506. }
  507. res.count = DRM_RESERVED_CONTEXTS;
  508. if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
  509. return -EFAULT;
  510. return 0;
  511. }
  512. int DRM(addctx)(struct inode *inode, struct file *filp,
  513. unsigned int cmd, unsigned long arg)
  514. {
  515. drm_file_t *priv = filp->private_data;
  516. drm_device_t *dev = priv->dev;
  517. drm_ctx_t ctx;
  518. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  519. return -EFAULT;
  520. if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
  521. /* Init kernel's context and get a new one. */
  522. DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
  523. ctx.handle = DRM(alloc_queue)(dev);
  524. }
  525. DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
  526. DRM_DEBUG("%dn", ctx.handle);
  527. if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
  528. return -EFAULT;
  529. return 0;
  530. }
  531. int DRM(modctx)(struct inode *inode, struct file *filp,
  532. unsigned int cmd, unsigned long arg)
  533. {
  534. drm_file_t *priv = filp->private_data;
  535. drm_device_t *dev = priv->dev;
  536. drm_ctx_t ctx;
  537. drm_queue_t *q;
  538. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  539. return -EFAULT;
  540. DRM_DEBUG("%dn", ctx.handle);
  541. if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
  542. q = dev->queuelist[ctx.handle];
  543. atomic_inc(&q->use_count);
  544. if (atomic_read(&q->use_count) == 1) {
  545. /* No longer in use */
  546. atomic_dec(&q->use_count);
  547. return -EINVAL;
  548. }
  549. if (DRM_BUFCOUNT(&q->waitlist)) {
  550. atomic_dec(&q->use_count);
  551. return -EBUSY;
  552. }
  553. q->flags = ctx.flags;
  554. atomic_dec(&q->use_count);
  555. return 0;
  556. }
  557. int DRM(getctx)(struct inode *inode, struct file *filp,
  558. unsigned int cmd, unsigned long arg)
  559. {
  560. drm_file_t *priv = filp->private_data;
  561. drm_device_t *dev = priv->dev;
  562. drm_ctx_t ctx;
  563. drm_queue_t *q;
  564. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  565. return -EFAULT;
  566. DRM_DEBUG("%dn", ctx.handle);
  567. if (ctx.handle >= dev->queue_count) return -EINVAL;
  568. q = dev->queuelist[ctx.handle];
  569. atomic_inc(&q->use_count);
  570. if (atomic_read(&q->use_count) == 1) {
  571. /* No longer in use */
  572. atomic_dec(&q->use_count);
  573. return -EINVAL;
  574. }
  575. ctx.flags = q->flags;
  576. atomic_dec(&q->use_count);
  577. if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
  578. return -EFAULT;
  579. return 0;
  580. }
  581. int DRM(switchctx)(struct inode *inode, struct file *filp,
  582.    unsigned int cmd, unsigned long arg)
  583. {
  584. drm_file_t *priv = filp->private_data;
  585. drm_device_t *dev = priv->dev;
  586. drm_ctx_t ctx;
  587. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  588. return -EFAULT;
  589. DRM_DEBUG("%dn", ctx.handle);
  590. return DRM(context_switch)(dev, dev->last_context, ctx.handle);
  591. }
  592. int DRM(newctx)(struct inode *inode, struct file *filp,
  593. unsigned int cmd, unsigned long arg)
  594. {
  595. drm_file_t *priv = filp->private_data;
  596. drm_device_t *dev = priv->dev;
  597. drm_ctx_t ctx;
  598. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  599. return -EFAULT;
  600. DRM_DEBUG("%dn", ctx.handle);
  601. DRM(context_switch_complete)(dev, ctx.handle);
  602. return 0;
  603. }
  604. int DRM(rmctx)(struct inode *inode, struct file *filp,
  605.        unsigned int cmd, unsigned long arg)
  606. {
  607. drm_file_t *priv = filp->private_data;
  608. drm_device_t *dev = priv->dev;
  609. drm_ctx_t ctx;
  610. drm_queue_t *q;
  611. drm_buf_t *buf;
  612. if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
  613. return -EFAULT;
  614. DRM_DEBUG("%dn", ctx.handle);
  615. if (ctx.handle >= dev->queue_count) return -EINVAL;
  616. q = dev->queuelist[ctx.handle];
  617. atomic_inc(&q->use_count);
  618. if (atomic_read(&q->use_count) == 1) {
  619. /* No longer in use */
  620. atomic_dec(&q->use_count);
  621. return -EINVAL;
  622. }
  623. atomic_inc(&q->finalization); /* Mark queue in finalization state */
  624. atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
  625.  finalization) */
  626. while (test_and_set_bit(0, &dev->interrupt_flag)) {
  627. schedule();
  628. if (signal_pending(current)) {
  629. clear_bit(0, &dev->interrupt_flag);
  630. return -EINTR;
  631. }
  632. }
  633. /* Remove queued buffers */
  634. while ((buf = DRM(waitlist_get)(&q->waitlist))) {
  635. DRM(free_buffer)(dev, buf);
  636. }
  637. clear_bit(0, &dev->interrupt_flag);
  638. /* Wakeup blocked processes */
  639. wake_up_interruptible(&q->read_queue);
  640. wake_up_interruptible(&q->write_queue);
  641. wake_up_interruptible(&q->flush_queue);
  642. /* Finalization over.  Queue is made
  643.    available when both use_count and
  644.    finalization become 0, which won't
  645.    happen until all the waiting processes
  646.    stop waiting. */
  647. atomic_dec(&q->finalization);
  648. return 0;
  649. }
  650. #endif /* __HAVE_CTX_BITMAP */