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_lists.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_lists.h -- Buffer list handling routines -*- linux-c -*-
    2  * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
    3  *
    4  * Copyright 1999 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_lists.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_DMA_WAITLIST
   38 
   39 int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
   40 {
   41         if (bl->count)
   42                 return DRM_OS_ERR(EINVAL);
   43 
   44         bl->bufs       = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
   45                                     DRM_MEM_BUFLISTS);
   46 
   47         if(!bl->bufs) return DRM_OS_ERR(ENOMEM);
   48 
   49         bl->count      = count;
   50         bl->rp         = bl->bufs;
   51         bl->wp         = bl->bufs;
   52         bl->end        = &bl->bufs[bl->count+1];
   53         DRM_OS_SPININIT( bl->write_lock, "writelock" );
   54         DRM_OS_SPININIT( bl->read_lock, "readlock" );
   55         return 0;
   56 }
   57 
   58 int DRM(waitlist_destroy)(drm_waitlist_t *bl)
   59 {
   60         if (bl->rp != bl->wp)
   61                 return DRM_OS_ERR(EINVAL);
   62         if (bl->bufs) DRM(free)(bl->bufs,
   63                                 (bl->count + 2) * sizeof(*bl->bufs),
   64                                 DRM_MEM_BUFLISTS);
   65         bl->count = 0;
   66         bl->bufs  = NULL;
   67         bl->rp    = NULL;
   68         bl->wp    = NULL;
   69         bl->end   = NULL;
   70         return 0;
   71 }
   72 
   73 int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
   74 {
   75         int           left;
   76 #ifdef __linux__
   77         unsigned long flags;
   78 #endif /* __linux__ */
   79 #ifdef __FreeBSD__
   80         int             s;
   81 #endif /* __FreeBSD__ */
   82         left = DRM_LEFTCOUNT(bl);
   83         if (!left) {
   84                 DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
   85                           buf->idx, buf->pid);
   86                 return DRM_OS_ERR(EINVAL);
   87         }
   88 #if __HAVE_DMA_HISTOGRAM
   89 #ifdef __linux__
   90         buf->time_queued = get_cycles();
   91 #endif /* __linux__ */
   92 #ifdef __FreeBSD__
   93         getnanotime(&buf->time_queued);
   94 #endif /* __FreeBSD__ */
   95 #endif
   96         buf->list        = DRM_LIST_WAIT;
   97 
   98 #ifdef __linux__
   99         spin_lock_irqsave(&bl->write_lock, flags);
  100 #endif /* __linux__ */
  101 #ifdef __FreeBSD__
  102         DRM_OS_SPINLOCK(&bl->write_lock);
  103         s = spldrm();
  104 #endif /* __FreeBSD__ */
  105         *bl->wp = buf;
  106         if (++bl->wp >= bl->end) bl->wp = bl->bufs;
  107 #ifdef __linux__
  108         spin_unlock_irqrestore(&bl->write_lock, flags);
  109 #endif /* __linux__ */
  110 #ifdef __FreeBSD__
  111         splx(s);
  112         DRM_OS_SPINUNLOCK(&bl->write_lock);
  113 #endif /* __FreeBSD__ */
  114 
  115         return 0;
  116 }
  117 
  118 drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
  119 {
  120         drm_buf_t     *buf;
  121 #ifdef __linux__
  122         unsigned long flags;
  123 #endif /* __linux__ */
  124 #ifdef __FreeBSD__
  125         int             s;
  126 #endif /* __FreeBSD__ */
  127 
  128 #ifdef __linux__
  129         spin_lock_irqsave(&bl->read_lock, flags);
  130         buf = *bl->rp;
  131         if (bl->rp == bl->wp) {
  132                 spin_unlock_irqrestore(&bl->read_lock, flags);
  133                 return NULL;
  134         }
  135         if (++bl->rp >= bl->end) bl->rp = bl->bufs;
  136         spin_unlock_irqrestore(&bl->read_lock, flags);
  137 #endif /* __linux__ */
  138 #ifdef __FreeBSD__
  139         DRM_OS_SPINLOCK(&bl->read_lock);
  140         s = spldrm();
  141         buf = *bl->rp;
  142         if (bl->rp == bl->wp) {
  143                 splx(s);
  144                 DRM_OS_SPINUNLOCK(&bl->read_lock);
  145                 return NULL;
  146         }                                    
  147         if (++bl->rp >= bl->end) bl->rp = bl->bufs;
  148         splx(s);
  149         DRM_OS_SPINUNLOCK(&bl->read_lock);
  150 #endif /* __FreeBSD__ */
  151         
  152         return buf;
  153 }
  154 
  155 #endif /* __HAVE_DMA_WAITLIST */
  156 
  157 
  158 #if __HAVE_DMA_FREELIST
  159 
  160 int DRM(freelist_create)(drm_freelist_t *bl, int count)
  161 {
  162         atomic_set(&bl->count, 0);
  163         bl->next      = NULL;
  164 #ifdef __linux__
  165         init_waitqueue_head(&bl->waiting);
  166 #endif /* __linux__ */
  167 #ifdef __FreeBSD__
  168         bl->waiting = 0;
  169 #endif /* __FreeBSD__ */
  170 
  171         bl->low_mark  = 0;
  172         bl->high_mark = 0;
  173         atomic_set(&bl->wfh,   0);
  174         DRM_OS_SPININIT( bl->lock, "freelistlock" );
  175         ++bl->initialized;
  176         return 0;
  177 }
  178 
  179 int DRM(freelist_destroy)(drm_freelist_t *bl)
  180 {
  181         atomic_set(&bl->count, 0);
  182         bl->next = NULL;
  183         return 0;
  184 }
  185 
  186 int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
  187 {
  188         drm_device_dma_t *dma  = dev->dma;
  189 
  190         if (!dma) {
  191                 DRM_ERROR("No DMA support\n");
  192                 return 1;
  193         }
  194 
  195         if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
  196                 DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
  197                           buf->idx, buf->waiting, buf->pending, buf->list);
  198         }
  199         if (!bl) return 1;
  200 #if __HAVE_DMA_HISTOGRAM
  201 #ifdef __linux__
  202         buf->time_freed = get_cycles();
  203 #endif /* __linux__ */
  204 #ifdef __FreeBSD__
  205         getnanotime(&buf->time_queued);
  206 #endif /* __FreeBSD__ */
  207         DRM(histogram_compute)(dev, buf);
  208 #endif
  209         buf->list       = DRM_LIST_FREE;
  210 
  211         DRM_OS_SPINLOCK( &bl->lock );
  212         buf->next       = bl->next;
  213         bl->next        = buf;
  214         DRM_OS_SPINUNLOCK( &bl->lock );
  215 
  216         atomic_inc(&bl->count);
  217         if (atomic_read(&bl->count) > dma->buf_count) {
  218                 DRM_ERROR("%ld of %d buffers free after addition of %d\n",
  219                           (unsigned long)atomic_read(&bl->count), 
  220                                 dma->buf_count, buf->idx);
  221                 return 1;
  222         }
  223                                 /* Check for high water mark */
  224         if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
  225                 atomic_set(&bl->wfh, 0);
  226                 DRM_OS_WAKEUP_INT(&bl->waiting);
  227         }
  228         return 0;
  229 }
  230 
  231 static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
  232 {
  233         drm_buf_t         *buf;
  234 
  235         if (!bl) return NULL;
  236 
  237                                 /* Get buffer */
  238         DRM_OS_SPINLOCK(&bl->lock);
  239         if (!bl->next) {
  240                 DRM_OS_SPINUNLOCK(&bl->lock);
  241                 return NULL;
  242         }
  243         buf       = bl->next;
  244         bl->next  = bl->next->next;
  245         DRM_OS_SPINUNLOCK(&bl->lock);
  246 
  247         atomic_dec(&bl->count);
  248         buf->next = NULL;
  249         buf->list = DRM_LIST_NONE;
  250         if (buf->waiting || buf->pending) {
  251                 DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
  252                           buf->idx, buf->waiting, buf->pending, buf->list);
  253         }
  254 
  255         return buf;
  256 }
  257 
  258 drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
  259 {
  260         drm_buf_t         *buf  = NULL;
  261 #ifdef __linux__
  262         DECLARE_WAITQUEUE(entry, current);
  263 #endif /* __linux__ */
  264 #ifdef __FreeBSD__
  265         int     error;
  266 #endif /* __FreeBSD__ */
  267 
  268         if (!bl || !bl->initialized) return NULL;
  269 
  270                                 /* Check for low water mark */
  271         if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
  272                 atomic_set(&bl->wfh, 1);
  273         if (atomic_read(&bl->wfh)) {
  274                 if (block) {
  275 #ifdef __linux__
  276                         add_wait_queue(&bl->waiting, &entry);
  277                         for (;;) {
  278                                 current->state = TASK_INTERRUPTIBLE;
  279                                 if (!atomic_read(&bl->wfh)
  280                                     && (buf = DRM(freelist_try)(bl))) break;
  281                                 schedule();
  282                                 if (signal_pending(current)) break;
  283                         }
  284                         current->state = TASK_RUNNING;
  285                         remove_wait_queue(&bl->waiting, &entry);
  286 #endif /* __linux__ */
  287 #ifdef __FreeBSD__
  288                         for (;;) {
  289                                 if (!atomic_read(&bl->wfh)
  290                                     && (buf = DRM(freelist_try(bl)))) break;
  291                                 error = tsleep(&bl->waiting, PZERO|PCATCH,
  292                                                "drmfg", 0);
  293                                 if (error)
  294                                         break;
  295                         }
  296 #endif /* __FreeBSD__ */
  297                 }
  298                 return buf;
  299         }
  300 
  301         return DRM(freelist_try)(bl);
  302 }
  303 
  304 #endif /* __HAVE_DMA_FREELIST */

Cache object: 22eb16fd7a723fbdb647848a24d82121


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