The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/drm_context.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  *
   31  * $FreeBSD: releng/5.0/sys/dev/drm/drm_context.h 95693 2002-04-29 00:25:10Z anholt $
   32  */
   33 
   34 #define __NO_VERSION__
   35 #include "dev/drm/drmP.h"
   36 
   37 #if __HAVE_CTX_BITMAP
   38 
   39 /* ================================================================
   40  * Context bitmap support
   41  */
   42 
   43 void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
   44 {
   45         if ( ctx_handle < 0 ) goto failed;
   46         if ( !dev->ctx_bitmap ) goto failed;
   47 
   48         if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
   49                 DRM_OS_LOCK;
   50                 clear_bit( ctx_handle, dev->ctx_bitmap );
   51                 dev->context_sareas[ctx_handle] = NULL;
   52                 DRM_OS_UNLOCK;
   53                 return;
   54         }
   55 failed:
   56         DRM_ERROR( "Attempt to free invalid context handle: %d\n",
   57                    ctx_handle );
   58         return;
   59 }
   60 
   61 int DRM(ctxbitmap_next)( drm_device_t *dev )
   62 {
   63         int bit;
   64 
   65         if(!dev->ctx_bitmap) return -1;
   66 
   67         DRM_OS_LOCK;
   68         bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
   69         if ( bit < DRM_MAX_CTXBITMAP ) {
   70                 set_bit( bit, dev->ctx_bitmap );
   71                 DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
   72                 if((bit+1) > dev->max_context) {
   73                         dev->max_context = (bit+1);
   74                         if(dev->context_sareas) {
   75                                 drm_map_t **ctx_sareas;
   76 
   77                                 ctx_sareas = DRM(realloc)(dev->context_sareas,
   78                                                 (dev->max_context - 1) * 
   79                                                 sizeof(*dev->context_sareas),
   80                                                 dev->max_context * 
   81                                                 sizeof(*dev->context_sareas),
   82                                                 DRM_MEM_MAPS);
   83                                 if(!ctx_sareas) {
   84                                         clear_bit(bit, dev->ctx_bitmap);
   85                                         DRM_OS_UNLOCK;
   86                                         return -1;
   87                                 }
   88                                 dev->context_sareas = ctx_sareas;
   89                                 dev->context_sareas[bit] = NULL;
   90                         } else {
   91                                 /* max_context == 1 at this point */
   92                                 dev->context_sareas = DRM(alloc)(
   93                                                 dev->max_context * 
   94                                                 sizeof(*dev->context_sareas),
   95                                                 DRM_MEM_MAPS);
   96                                 if(!dev->context_sareas) {
   97                                         clear_bit(bit, dev->ctx_bitmap);
   98                                         DRM_OS_UNLOCK;
   99                                         return -1;
  100                                 }
  101                                 dev->context_sareas[bit] = NULL;
  102                         }
  103                 }
  104                 DRM_OS_UNLOCK;
  105                 return bit;
  106         }
  107         DRM_OS_UNLOCK;
  108         return -1;
  109 }
  110 
  111 int DRM(ctxbitmap_init)( drm_device_t *dev )
  112 {
  113         int i;
  114         int temp;
  115 
  116         DRM_OS_LOCK;
  117         dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
  118                                                         DRM_MEM_CTXBITMAP );
  119         if ( dev->ctx_bitmap == NULL ) {
  120                 DRM_OS_UNLOCK;
  121                 return DRM_OS_ERR(ENOMEM);
  122         }
  123         memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
  124         dev->context_sareas = NULL;
  125         dev->max_context = -1;
  126         DRM_OS_UNLOCK;
  127 
  128         for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
  129                 temp = DRM(ctxbitmap_next)( dev );
  130                 DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
  131         }
  132 
  133         return 0;
  134 }
  135 
  136 void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
  137 {
  138         DRM_OS_LOCK;
  139         if( dev->context_sareas ) DRM(free)( dev->context_sareas,
  140                                              sizeof(*dev->context_sareas) * 
  141                                              dev->max_context,
  142                                              DRM_MEM_MAPS );
  143         DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
  144         DRM_OS_UNLOCK;
  145 }
  146 
  147 /* ================================================================
  148  * Per Context SAREA Support
  149  */
  150 
  151 int DRM(getsareactx)( DRM_OS_IOCTL )
  152 {
  153         DRM_OS_DEVICE;
  154         drm_ctx_priv_map_t request;
  155         drm_map_t *map;
  156 
  157         DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data, 
  158                            sizeof(request) );
  159 
  160         DRM_OS_LOCK;
  161         if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
  162                 DRM_OS_UNLOCK;
  163                 return DRM_OS_ERR(EINVAL);
  164         }
  165 
  166         map = dev->context_sareas[request.ctx_id];
  167         DRM_OS_UNLOCK;
  168 
  169         request.handle = map->handle;
  170 
  171         DRM_OS_KRNTOUSR( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
  172 
  173         return 0;
  174 }
  175 
  176 int DRM(setsareactx)( DRM_OS_IOCTL )
  177 {
  178         DRM_OS_DEVICE;
  179         drm_ctx_priv_map_t request;
  180         drm_map_t *map = NULL;
  181 #ifdef __linux__
  182         drm_map_list_t *r_list = NULL;
  183         struct list_head *list;
  184 #endif /* __linux__ */
  185 #ifdef __FreeBSD__
  186         drm_map_list_entry_t *list;
  187 #endif /* __FreeBSD__ */
  188 
  189         DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data,
  190                            sizeof(request) );
  191 
  192         DRM_OS_LOCK;
  193 #ifdef __linux__
  194         list_for_each(list, &dev->maplist->head) {
  195                 r_list = (drm_map_list_t *)list;
  196                 if(r_list->map &&
  197                    r_list->map->handle == request.handle) 
  198                         goto found;
  199         }
  200 #endif /* __linux__ */
  201 #ifdef __FreeBSD__
  202         TAILQ_FOREACH(list, dev->maplist, link) {
  203                 map=list->map;
  204                 if(map->handle == request.handle) 
  205                         goto found;
  206         }
  207 #endif /* __FreeBSD__ */
  208 
  209 bad:
  210         DRM_OS_UNLOCK;
  211         return DRM_OS_ERR(EINVAL);
  212 
  213 found:
  214 #ifdef __linux__
  215         map = r_list->map;
  216 #endif /* __linux__ */
  217 #ifdef __FreeBSD__
  218         map = list->map;
  219 #endif /* __FreeBSD__ */
  220         if (!map) goto bad;
  221         if (dev->max_context < 0)
  222                 goto bad;
  223         if (request.ctx_id >= (unsigned) dev->max_context)
  224                 goto bad;
  225         dev->context_sareas[request.ctx_id] = map;
  226         DRM_OS_UNLOCK;
  227         return 0;
  228 }
  229 
  230 /* ================================================================
  231  * The actual DRM context handling routines
  232  */
  233 
  234 int DRM(context_switch)( drm_device_t *dev, int old, int new )
  235 {
  236         char buf[64];
  237 
  238         if ( test_and_set_bit( 0, &dev->context_flag ) ) {
  239                 DRM_ERROR( "Reentering -- FIXME\n" );
  240                 return DRM_OS_ERR(EBUSY);
  241         }
  242 
  243 #if __HAVE_DMA_HISTOGRAM
  244         dev->ctx_start = get_cycles();
  245 #endif
  246 
  247         DRM_DEBUG( "Context switch from %d to %d\n", old, new );
  248 
  249         if ( new == dev->last_context ) {
  250                 clear_bit( 0, &dev->context_flag );
  251                 return 0;
  252         }
  253 
  254         if ( DRM(flags) & DRM_FLAG_NOCTX ) {
  255                 DRM(context_switch_complete)( dev, new );
  256         } else {
  257                 sprintf( buf, "C %d %d\n", old, new );
  258                 DRM(write_string)( dev, buf );
  259         }
  260 
  261         return 0;
  262 }
  263 
  264 int DRM(context_switch_complete)( drm_device_t *dev, int new )
  265 {
  266         dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
  267         dev->last_switch  = jiffies;
  268 
  269         if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
  270                 DRM_ERROR( "Lock isn't held after context switch\n" );
  271         }
  272 
  273                                 /* If a context switch is ever initiated
  274                                    when the kernel holds the lock, release
  275                                    that lock here. */
  276 #if __HAVE_DMA_HISTOGRAM
  277         atomic_inc( &dev->histo.ctx[DRM(histogram_slot)(get_cycles()
  278                                                         - dev->ctx_start)] );
  279 
  280 #endif
  281         clear_bit( 0, &dev->context_flag );
  282         DRM_OS_WAKEUP( &dev->context_wait );
  283 
  284         return 0;
  285 }
  286 
  287 int DRM(resctx)( DRM_OS_IOCTL )
  288 {
  289         drm_ctx_res_t res;
  290         drm_ctx_t ctx;
  291         int i;
  292 
  293         DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) );
  294 
  295         if ( res.count >= DRM_RESERVED_CONTEXTS ) {
  296                 memset( &ctx, 0, sizeof(ctx) );
  297                 for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
  298                         ctx.handle = i;
  299                         if ( DRM_OS_COPYTOUSR( &res.contexts[i],
  300                                            &i, sizeof(i) ) )
  301                                 return DRM_OS_ERR(EFAULT);
  302                 }
  303         }
  304         res.count = DRM_RESERVED_CONTEXTS;
  305 
  306         DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) );
  307 
  308         return 0;
  309 }
  310 
  311 int DRM(addctx)( DRM_OS_IOCTL )
  312 {
  313         DRM_OS_DEVICE;
  314         drm_ctx_t ctx;
  315 
  316         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  317 
  318         ctx.handle = DRM(ctxbitmap_next)( dev );
  319         if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
  320                                 /* Skip kernel's context and get a new one. */
  321                 ctx.handle = DRM(ctxbitmap_next)( dev );
  322         }
  323         DRM_DEBUG( "%d\n", ctx.handle );
  324         if ( ctx.handle == -1 ) {
  325                 DRM_DEBUG( "Not enough free contexts.\n" );
  326                                 /* Should this return -EBUSY instead? */
  327                 return DRM_OS_ERR(ENOMEM);
  328         }
  329 
  330         DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
  331 
  332         return 0;
  333 }
  334 
  335 int DRM(modctx)( DRM_OS_IOCTL )
  336 {
  337         /* This does nothing */
  338         return 0;
  339 }
  340 
  341 int DRM(getctx)( DRM_OS_IOCTL )
  342 {
  343         drm_ctx_t ctx;
  344 
  345         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  346 
  347         /* This is 0, because we don't handle any context flags */
  348         ctx.flags = 0;
  349 
  350         DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
  351 
  352         return 0;
  353 }
  354 
  355 int DRM(switchctx)( DRM_OS_IOCTL )
  356 {
  357         DRM_OS_DEVICE;
  358         drm_ctx_t ctx;
  359 
  360         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  361 
  362         DRM_DEBUG( "%d\n", ctx.handle );
  363         return DRM(context_switch)( dev, dev->last_context, ctx.handle );
  364 }
  365 
  366 int DRM(newctx)( DRM_OS_IOCTL )
  367 {
  368         DRM_OS_DEVICE;
  369         drm_ctx_t ctx;
  370 
  371         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  372 
  373         DRM_DEBUG( "%d\n", ctx.handle );
  374         DRM(context_switch_complete)( dev, ctx.handle );
  375 
  376         return 0;
  377 }
  378 
  379 int DRM(rmctx)( DRM_OS_IOCTL )
  380 {
  381         DRM_OS_DEVICE;
  382         drm_ctx_t ctx;
  383 
  384         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  385 
  386         DRM_DEBUG( "%d\n", ctx.handle );
  387 #ifdef __linux__
  388         if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
  389                 priv->remove_auth_on_close = 1;
  390         }
  391 #endif /* __linux__ */
  392         if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
  393                 DRM(ctxbitmap_free)( dev, ctx.handle );
  394         }
  395 
  396         return 0;
  397 }
  398 
  399 
  400 #else /* __HAVE_CTX_BITMAP */
  401 
  402 /* ================================================================
  403  * Old-style context support
  404  */
  405 
  406 
  407 int DRM(context_switch)(drm_device_t *dev, int old, int new)
  408 {
  409         char        buf[64];
  410         drm_queue_t *q;
  411 
  412 #if 0
  413         atomic_inc(&dev->total_ctx);
  414 #endif
  415 
  416         if (test_and_set_bit(0, &dev->context_flag)) {
  417                 DRM_ERROR("Reentering -- FIXME\n");
  418                 return DRM_OS_ERR(EBUSY);
  419         }
  420 
  421 #if __HAVE_DMA_HISTOGRAM
  422         dev->ctx_start = get_cycles();
  423 #endif
  424 
  425         DRM_DEBUG("Context switch from %d to %d\n", old, new);
  426 
  427         if (new >= dev->queue_count) {
  428                 clear_bit(0, &dev->context_flag);
  429                 return DRM_OS_ERR(EINVAL);
  430         }
  431 
  432         if (new == dev->last_context) {
  433                 clear_bit(0, &dev->context_flag);
  434                 return 0;
  435         }
  436 
  437         q = dev->queuelist[new];
  438         atomic_inc(&q->use_count);
  439         if (atomic_read(&q->use_count) == 1) {
  440                 atomic_dec(&q->use_count);
  441                 clear_bit(0, &dev->context_flag);
  442                 return DRM_OS_ERR(EINVAL);
  443         }
  444 
  445         if (DRM(flags) & DRM_FLAG_NOCTX) {
  446                 DRM(context_switch_complete)(dev, new);
  447         } else {
  448                 sprintf(buf, "C %d %d\n", old, new);
  449                 DRM(write_string)(dev, buf);
  450         }
  451 
  452         atomic_dec(&q->use_count);
  453 
  454         return 0;
  455 }
  456 
  457 int DRM(context_switch_complete)(drm_device_t *dev, int new)
  458 {
  459         drm_device_dma_t *dma = dev->dma;
  460 
  461         dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
  462         dev->last_switch  = jiffies;
  463 
  464         if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  465                 DRM_ERROR("Lock isn't held after context switch\n");
  466         }
  467 
  468         if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
  469                 if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
  470                                   DRM_KERNEL_CONTEXT)) {
  471                         DRM_ERROR("Cannot free lock\n");
  472                 }
  473         }
  474 
  475 #if __HAVE_DMA_HISTOGRAM
  476         atomic_inc(&dev->histo.ctx[DRM(histogram_slot)(get_cycles()
  477                                                       - dev->ctx_start)]);
  478 
  479 #endif
  480         clear_bit(0, &dev->context_flag);
  481         DRM_OS_WAKEUP_INT(&dev->context_wait);
  482 
  483         return 0;
  484 }
  485 
  486 static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
  487 {
  488         DRM_DEBUG("\n");
  489 
  490         if (atomic_read(&q->use_count) != 1
  491             || atomic_read(&q->finalization)
  492             || atomic_read(&q->block_count)) {
  493                 DRM_ERROR("New queue is already in use: u%ld f%ld b%ld\n",
  494                           (unsigned long)atomic_read(&q->use_count),
  495                           (unsigned long)atomic_read(&q->finalization),
  496                           (unsigned long)atomic_read(&q->block_count));
  497         }
  498 
  499         atomic_set(&q->finalization,  0);
  500         atomic_set(&q->block_count,   0);
  501         atomic_set(&q->block_read,    0);
  502         atomic_set(&q->block_write,   0);
  503         atomic_set(&q->total_queued,  0);
  504         atomic_set(&q->total_flushed, 0);
  505         atomic_set(&q->total_locks,   0);
  506 
  507 #ifdef __linux__
  508         init_waitqueue_head(&q->write_queue);
  509         init_waitqueue_head(&q->read_queue);
  510         init_waitqueue_head(&q->flush_queue);
  511 #endif /* __linux__ */
  512 #ifdef __FreeBSD__
  513         q->write_queue = 0;
  514         q->read_queue = 0;
  515         q->flush_queue = 0;
  516 #endif /* __FreeBSD__ */
  517 
  518         q->flags = ctx->flags;
  519 
  520         DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
  521 
  522         return 0;
  523 }
  524 
  525 
  526 /* drm_alloc_queue:
  527 PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
  528         disappear (so all deallocation must be done after IOCTLs are off)
  529      2) dev->queue_count < dev->queue_slots
  530      3) dev->queuelist[i].use_count == 0 and
  531         dev->queuelist[i].finalization == 0 if i not in use
  532 POST: 1) dev->queuelist[i].use_count == 1
  533       2) dev->queue_count < dev->queue_slots */
  534 
  535 static int DRM(alloc_queue)(drm_device_t *dev)
  536 {
  537         int         i;
  538         drm_queue_t *queue;
  539         int         oldslots;
  540         int         newslots;
  541                                 /* Check for a free queue */
  542         for (i = 0; i < dev->queue_count; i++) {
  543                 atomic_inc(&dev->queuelist[i]->use_count);
  544                 if (atomic_read(&dev->queuelist[i]->use_count) == 1
  545                     && !atomic_read(&dev->queuelist[i]->finalization)) {
  546                         DRM_DEBUG("%d (free)\n", i);
  547                         return i;
  548                 }
  549                 atomic_dec(&dev->queuelist[i]->use_count);
  550         }
  551                                 /* Allocate a new queue */
  552         DRM_OS_LOCK;
  553 
  554         queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES);
  555         memset(queue, 0, sizeof(*queue));
  556         atomic_set(&queue->use_count, 1);
  557 
  558         ++dev->queue_count;
  559         if (dev->queue_count >= dev->queue_slots) {
  560                 oldslots = dev->queue_slots * sizeof(*dev->queuelist);
  561                 if (!dev->queue_slots) dev->queue_slots = 1;
  562                 dev->queue_slots *= 2;
  563                 newslots = dev->queue_slots * sizeof(*dev->queuelist);
  564 
  565                 dev->queuelist = DRM(realloc)(dev->queuelist,
  566                                               oldslots,
  567                                               newslots,
  568                                               DRM_MEM_QUEUES);
  569                 if (!dev->queuelist) {
  570                         DRM_OS_UNLOCK;
  571                         DRM_DEBUG("out of memory\n");
  572                         return DRM_OS_ERR(ENOMEM);
  573                 }
  574         }
  575         dev->queuelist[dev->queue_count-1] = queue;
  576 
  577         DRM_OS_UNLOCK;
  578         DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
  579         return dev->queue_count - 1;
  580 }
  581 
  582 int DRM(resctx)( DRM_OS_IOCTL )
  583 {
  584         drm_ctx_res_t   res;
  585         drm_ctx_t       ctx;
  586         int             i;
  587 
  588         DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
  589         
  590         DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) );
  591 
  592         if (res.count >= DRM_RESERVED_CONTEXTS) {
  593                 memset(&ctx, 0, sizeof(ctx));
  594                 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
  595                         ctx.handle = i;
  596                         if (DRM_OS_COPYTOUSR(&res.contexts[i],
  597                                          &i,
  598                                          sizeof(i)))
  599                                 return DRM_OS_ERR(EFAULT);
  600                 }
  601         }
  602         res.count = DRM_RESERVED_CONTEXTS;
  603 
  604         DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) );
  605 
  606         return 0;
  607 }
  608 
  609 int DRM(addctx)( DRM_OS_IOCTL )
  610 {
  611         DRM_OS_DEVICE;
  612         drm_ctx_t       ctx;
  613 
  614         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  615 
  616         if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
  617                                 /* Init kernel's context and get a new one. */
  618                 DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
  619                 ctx.handle = DRM(alloc_queue)(dev);
  620         }
  621         DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
  622         DRM_DEBUG("%d\n", ctx.handle);
  623         
  624         DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
  625 
  626         return 0;
  627 }
  628 
  629 int DRM(modctx)( DRM_OS_IOCTL )
  630 {
  631         DRM_OS_DEVICE;
  632         drm_ctx_t       ctx;
  633         drm_queue_t     *q;
  634 
  635         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  636 
  637         DRM_DEBUG("%d\n", ctx.handle);
  638 
  639         if (ctx.handle < 0 || ctx.handle >= dev->queue_count) 
  640                 return DRM_OS_ERR(EINVAL);
  641         q = dev->queuelist[ctx.handle];
  642 
  643         atomic_inc(&q->use_count);
  644         if (atomic_read(&q->use_count) == 1) {
  645                                 /* No longer in use */
  646                 atomic_dec(&q->use_count);
  647                 return DRM_OS_ERR(EINVAL);
  648         }
  649 
  650         if (DRM_BUFCOUNT(&q->waitlist)) {
  651                 atomic_dec(&q->use_count);
  652                 return DRM_OS_ERR(EBUSY);
  653         }
  654 
  655         q->flags = ctx.flags;
  656 
  657         atomic_dec(&q->use_count);
  658         return 0;
  659 }
  660 
  661 int DRM(getctx)( DRM_OS_IOCTL )
  662 {
  663         DRM_OS_DEVICE;
  664         drm_ctx_t       ctx;
  665         drm_queue_t     *q;
  666 
  667         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  668 
  669         DRM_DEBUG("%d\n", ctx.handle);
  670 
  671         if (ctx.handle >= dev->queue_count) 
  672                 return DRM_OS_ERR(EINVAL);
  673         q = dev->queuelist[ctx.handle];
  674 
  675         atomic_inc(&q->use_count);
  676         if (atomic_read(&q->use_count) == 1) {
  677                                 /* No longer in use */
  678                 atomic_dec(&q->use_count);
  679                 return DRM_OS_ERR(EINVAL);
  680         }
  681 
  682         ctx.flags = q->flags;
  683         atomic_dec(&q->use_count);
  684 
  685         DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
  686 
  687         return 0;
  688 }
  689 
  690 int DRM(switchctx)( DRM_OS_IOCTL )
  691 {
  692         DRM_OS_DEVICE;
  693         drm_ctx_t       ctx;
  694 
  695         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  696 
  697         DRM_DEBUG("%d\n", ctx.handle);
  698         return DRM(context_switch)(dev, dev->last_context, ctx.handle);
  699 }
  700 
  701 int DRM(newctx)( DRM_OS_IOCTL )
  702 {
  703         DRM_OS_DEVICE;
  704         drm_ctx_t       ctx;
  705 
  706         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  707 
  708         DRM_DEBUG("%d\n", ctx.handle);
  709         DRM(context_switch_complete)(dev, ctx.handle);
  710 
  711         return 0;
  712 }
  713 
  714 int DRM(rmctx)( DRM_OS_IOCTL )
  715 {
  716         DRM_OS_DEVICE;
  717         drm_ctx_t       ctx;
  718         drm_queue_t     *q;
  719         drm_buf_t       *buf;
  720 
  721         DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
  722 
  723         DRM_DEBUG("%d\n", ctx.handle);
  724 
  725         if (ctx.handle >= dev->queue_count) return DRM_OS_ERR(EINVAL);
  726         q = dev->queuelist[ctx.handle];
  727 
  728         atomic_inc(&q->use_count);
  729         if (atomic_read(&q->use_count) == 1) {
  730                                 /* No longer in use */
  731                 atomic_dec(&q->use_count);
  732                 return DRM_OS_ERR(EINVAL);
  733         }
  734 
  735         atomic_inc(&q->finalization); /* Mark queue in finalization state */
  736         atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
  737                                          finalization) */
  738 
  739         while (test_and_set_bit(0, &dev->interrupt_flag)) {
  740 #ifdef __linux__
  741                 schedule();
  742                 if (signal_pending(current)) {
  743                         clear_bit(0, &dev->interrupt_flag);
  744                         return DRM_OS_ERR(EINTR);
  745                 }
  746 #endif /* __linux__ */
  747 #ifdef __FreeBSD__
  748                 static int never;
  749                 int retcode;
  750                 retcode = tsleep(&never, PZERO|PCATCH, "never", 1);
  751                 if (retcode)
  752                         return retcode;
  753 #endif /* __FreeBSD__ */
  754         }
  755                                 /* Remove queued buffers */
  756         while ((buf = DRM(waitlist_get)(&q->waitlist))) {
  757                 DRM(free_buffer)(dev, buf);
  758         }
  759         clear_bit(0, &dev->interrupt_flag);
  760 
  761                                 /* Wakeup blocked processes */
  762 #ifdef __linux__
  763         wake_up_interruptible(&q->read_queue);
  764         wake_up_interruptible(&q->write_queue);
  765 #endif /* __linux__ */
  766 #ifdef __FreeBSD__
  767         wakeup( &q->block_read );
  768         wakeup( &q->block_write );
  769 #endif /* __FreeBSD__ */
  770         DRM_OS_WAKEUP_INT( &q->flush_queue );
  771                                 /* Finalization over.  Queue is made
  772                                    available when both use_count and
  773                                    finalization become 0, which won't
  774                                    happen until all the waiting processes
  775                                    stop waiting. */
  776         atomic_dec(&q->finalization);
  777         return 0;
  778 }
  779 
  780 #endif /* __HAVE_CTX_BITMAP */

Cache object: 5f1f9b87c8362c08739e41f1a5ac5c9b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.