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.c

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 /*-
    2  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
    3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
    4  * All Rights Reserved.
    5  *
    6  * Permission is hereby granted, free of charge, to any person obtaining a
    7  * copy of this software and associated documentation files (the "Software"),
    8  * to deal in the Software without restriction, including without limitation
    9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   10  * and/or sell copies of the Software, and to permit persons to whom the
   11  * Software is furnished to do so, subject to the following conditions:
   12  *
   13  * The above copyright notice and this permission notice (including the next
   14  * paragraph) shall be included in all copies or substantial portions of the
   15  * Software.
   16  *
   17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   23  * OTHER DEALINGS IN THE SOFTWARE.
   24  *
   25  * Authors:
   26  *    Rickard E. (Rik) Faith <faith@valinux.com>
   27  *    Gareth Hughes <gareth@valinux.com>
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/9.0/sys/dev/drm/drm_context.c 207066 2010-04-22 18:21:25Z rnoland $");
   33 
   34 /** @file drm_context.c
   35  * Implementation of the context management ioctls.
   36  */
   37 
   38 #include "dev/drm/drmP.h"
   39 
   40 /* ================================================================
   41  * Context bitmap support
   42  */
   43 
   44 void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
   45 {
   46         if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP || 
   47             dev->ctx_bitmap == NULL) {
   48                 DRM_ERROR("Attempt to free invalid context handle: %d\n",
   49                    ctx_handle);
   50                 return;
   51         }
   52 
   53         DRM_LOCK();
   54         clear_bit(ctx_handle, dev->ctx_bitmap);
   55         dev->context_sareas[ctx_handle] = NULL;
   56         DRM_UNLOCK();
   57         return;
   58 }
   59 
   60 int drm_ctxbitmap_next(struct drm_device *dev)
   61 {
   62         int bit;
   63 
   64         if (dev->ctx_bitmap == NULL)
   65                 return -1;
   66 
   67         DRM_LOCK();
   68         bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
   69         if (bit >= DRM_MAX_CTXBITMAP) {
   70                 DRM_UNLOCK();
   71                 return -1;
   72         }
   73 
   74         set_bit(bit, dev->ctx_bitmap);
   75         DRM_DEBUG("bit : %d\n", bit);
   76         if ((bit+1) > dev->max_context) {
   77                 drm_local_map_t **ctx_sareas;
   78                 int max_ctx = (bit+1);
   79 
   80                 ctx_sareas = realloc(dev->context_sareas,
   81                     max_ctx * sizeof(*dev->context_sareas),
   82                     DRM_MEM_SAREA, M_NOWAIT);
   83                 if (ctx_sareas == NULL) {
   84                         clear_bit(bit, dev->ctx_bitmap);
   85                         DRM_DEBUG("failed to allocate bit : %d\n", bit);
   86                         DRM_UNLOCK();
   87                         return -1;
   88                 }
   89                 dev->max_context = max_ctx;
   90                 dev->context_sareas = ctx_sareas;
   91                 dev->context_sareas[bit] = NULL;
   92         }
   93         DRM_UNLOCK();
   94         return bit;
   95 }
   96 
   97 int drm_ctxbitmap_init(struct drm_device *dev)
   98 {
   99         int i;
  100         int temp;
  101 
  102         DRM_LOCK();
  103         dev->ctx_bitmap = malloc(PAGE_SIZE, DRM_MEM_CTXBITMAP,
  104             M_NOWAIT | M_ZERO);
  105         if (dev->ctx_bitmap == NULL) {
  106                 DRM_UNLOCK();
  107                 return ENOMEM;
  108         }
  109         dev->context_sareas = NULL;
  110         dev->max_context = -1;
  111         DRM_UNLOCK();
  112 
  113         for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
  114                 temp = drm_ctxbitmap_next(dev);
  115                 DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
  116         }
  117 
  118         return 0;
  119 }
  120 
  121 void drm_ctxbitmap_cleanup(struct drm_device *dev)
  122 {
  123         DRM_LOCK();
  124         if (dev->context_sareas != NULL)
  125                 free(dev->context_sareas, DRM_MEM_SAREA);
  126         free(dev->ctx_bitmap, DRM_MEM_CTXBITMAP);
  127         DRM_UNLOCK();
  128 }
  129 
  130 /* ================================================================
  131  * Per Context SAREA Support
  132  */
  133 
  134 int drm_getsareactx(struct drm_device *dev, void *data,
  135                     struct drm_file *file_priv)
  136 {
  137         struct drm_ctx_priv_map *request = data;
  138         drm_local_map_t *map;
  139 
  140         DRM_LOCK();
  141         if (dev->max_context < 0 ||
  142             request->ctx_id >= (unsigned) dev->max_context) {
  143                 DRM_UNLOCK();
  144                 return EINVAL;
  145         }
  146 
  147         map = dev->context_sareas[request->ctx_id];
  148         DRM_UNLOCK();
  149 
  150         request->handle = (void *)map->handle;
  151 
  152         return 0;
  153 }
  154 
  155 int drm_setsareactx(struct drm_device *dev, void *data,
  156                     struct drm_file *file_priv)
  157 {
  158         struct drm_ctx_priv_map *request = data;
  159         drm_local_map_t *map = NULL;
  160 
  161         DRM_LOCK();
  162         TAILQ_FOREACH(map, &dev->maplist, link) {
  163                 if (map->handle == request->handle) {
  164                         if (dev->max_context < 0)
  165                                 goto bad;
  166                         if (request->ctx_id >= (unsigned) dev->max_context)
  167                                 goto bad;
  168                         dev->context_sareas[request->ctx_id] = map;
  169                         DRM_UNLOCK();
  170                         return 0;
  171                 }
  172         }
  173 
  174 bad:
  175         DRM_UNLOCK();
  176         return EINVAL;
  177 }
  178 
  179 /* ================================================================
  180  * The actual DRM context handling routines
  181  */
  182 
  183 int drm_context_switch(struct drm_device *dev, int old, int new)
  184 {
  185         if (test_and_set_bit(0, &dev->context_flag)) {
  186                 DRM_ERROR("Reentering -- FIXME\n");
  187                 return EBUSY;
  188         }
  189 
  190         DRM_DEBUG("Context switch from %d to %d\n", old, new);
  191 
  192         if (new == dev->last_context) {
  193                 clear_bit(0, &dev->context_flag);
  194                 return 0;
  195         }
  196 
  197         return 0;
  198 }
  199 
  200 int drm_context_switch_complete(struct drm_device *dev, int new)
  201 {
  202         dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
  203 
  204         if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  205                 DRM_ERROR("Lock isn't held after context switch\n");
  206         }
  207 
  208         /* If a context switch is ever initiated
  209            when the kernel holds the lock, release
  210            that lock here. */
  211         clear_bit(0, &dev->context_flag);
  212 
  213         return 0;
  214 }
  215 
  216 int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  217 {
  218         struct drm_ctx_res *res = data;
  219         struct drm_ctx ctx;
  220         int i;
  221 
  222         if (res->count >= DRM_RESERVED_CONTEXTS) {
  223                 bzero(&ctx, sizeof(ctx));
  224                 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
  225                         ctx.handle = i;
  226                         if (DRM_COPY_TO_USER(&res->contexts[i],
  227                             &ctx, sizeof(ctx)))
  228                                 return EFAULT;
  229                 }
  230         }
  231         res->count = DRM_RESERVED_CONTEXTS;
  232 
  233         return 0;
  234 }
  235 
  236 int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  237 {
  238         struct drm_ctx *ctx = data;
  239 
  240         ctx->handle = drm_ctxbitmap_next(dev);
  241         if (ctx->handle == DRM_KERNEL_CONTEXT) {
  242                 /* Skip kernel's context and get a new one. */
  243                 ctx->handle = drm_ctxbitmap_next(dev);
  244         }
  245         DRM_DEBUG("%d\n", ctx->handle);
  246         if (ctx->handle == -1) {
  247                 DRM_DEBUG("Not enough free contexts.\n");
  248                 /* Should this return -EBUSY instead? */
  249                 return ENOMEM;
  250         }
  251 
  252         if (dev->driver->context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
  253                 DRM_LOCK();
  254                 dev->driver->context_ctor(dev, ctx->handle);
  255                 DRM_UNLOCK();
  256         }
  257 
  258         return 0;
  259 }
  260 
  261 int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  262 {
  263         /* This does nothing */
  264         return 0;
  265 }
  266 
  267 int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  268 {
  269         struct drm_ctx *ctx = data;
  270 
  271         /* This is 0, because we don't handle any context flags */
  272         ctx->flags = 0;
  273 
  274         return 0;
  275 }
  276 
  277 int drm_switchctx(struct drm_device *dev, void *data,
  278                   struct drm_file *file_priv)
  279 {
  280         struct drm_ctx *ctx = data;
  281 
  282         DRM_DEBUG("%d\n", ctx->handle);
  283         return drm_context_switch(dev, dev->last_context, ctx->handle);
  284 }
  285 
  286 int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  287 {
  288         struct drm_ctx *ctx = data;
  289 
  290         DRM_DEBUG("%d\n", ctx->handle);
  291         drm_context_switch_complete(dev, ctx->handle);
  292 
  293         return 0;
  294 }
  295 
  296 int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
  297 {
  298         struct drm_ctx *ctx = data;
  299 
  300         DRM_DEBUG("%d\n", ctx->handle);
  301         if (ctx->handle != DRM_KERNEL_CONTEXT) {
  302                 if (dev->driver->context_dtor) {
  303                         DRM_LOCK();
  304                         dev->driver->context_dtor(dev, ctx->handle);
  305                         DRM_UNLOCK();
  306                 }
  307 
  308                 drm_ctxbitmap_free(dev, ctx->handle);
  309         }
  310 
  311         return 0;
  312 }

Cache object: 09151a248bc04cc867fbe7e16815e3fb


[ 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.