home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / include / drm / drm_memory_debug.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  8.2 KB  |  310 lines

  1. /**
  2.  * \file drm_memory_debug.h
  3.  * Memory management wrappers for DRM.
  4.  *
  5.  * \author Rickard E. (Rik) Faith <faith@valinux.com>
  6.  * \author Gareth Hughes <gareth@valinux.com>
  7.  */
  8.  
  9. /*
  10.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  11.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  12.  * All Rights Reserved.
  13.  *
  14.  * Permission is hereby granted, free of charge, to any person obtaining a
  15.  * copy of this software and associated documentation files (the "Software"),
  16.  * to deal in the Software without restriction, including without limitation
  17.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  18.  * and/or sell copies of the Software, and to permit persons to whom the
  19.  * Software is furnished to do so, subject to the following conditions:
  20.  *
  21.  * The above copyright notice and this permission notice (including the next
  22.  * paragraph) shall be included in all copies or substantial portions of the
  23.  * Software.
  24.  *
  25.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  26.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  27.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  28.  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  29.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  30.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  31.  * OTHER DEALINGS IN THE SOFTWARE.
  32.  */
  33.  
  34. #include "drmP.h"
  35.  
  36. typedef struct drm_mem_stats {
  37.     const char *name;
  38.     int succeed_count;
  39.     int free_count;
  40.     int fail_count;
  41.     unsigned long bytes_allocated;
  42.     unsigned long bytes_freed;
  43. } drm_mem_stats_t;
  44.  
  45. static DEFINE_SPINLOCK(drm_mem_lock);
  46. static unsigned long drm_ram_available = 0;    /* In pages */
  47. static unsigned long drm_ram_used = 0;
  48. static drm_mem_stats_t drm_mem_stats[] =
  49. {
  50.     [DRM_MEM_DMA] = {"dmabufs"},
  51.     [DRM_MEM_SAREA] = {"sareas"},
  52.     [DRM_MEM_DRIVER] = {"driver"},
  53.     [DRM_MEM_MAGIC] = {"magic"},
  54.     [DRM_MEM_IOCTLS] = {"ioctltab"},
  55.     [DRM_MEM_MAPS] = {"maplist"},
  56.     [DRM_MEM_VMAS] = {"vmalist"},
  57.     [DRM_MEM_BUFS] = {"buflist"},
  58.     [DRM_MEM_SEGS] = {"seglist"},
  59.     [DRM_MEM_PAGES] = {"pagelist"},
  60.     [DRM_MEM_FILES] = {"files"},
  61.     [DRM_MEM_QUEUES] = {"queues"},
  62.     [DRM_MEM_CMDS] = {"commands"},
  63.     [DRM_MEM_MAPPINGS] = {"mappings"},
  64.     [DRM_MEM_BUFLISTS] = {"buflists"},
  65.     [DRM_MEM_AGPLISTS] = {"agplist"},
  66.     [DRM_MEM_SGLISTS] = {"sglist"},
  67.     [DRM_MEM_TOTALAGP] = {"totalagp"},
  68.     [DRM_MEM_BOUNDAGP] = {"boundagp"},
  69.     [DRM_MEM_CTXBITMAP] = {"ctxbitmap"},
  70.     [DRM_MEM_CTXLIST] = {"ctxlist"},
  71.     [DRM_MEM_STUB] = {"stub"},
  72.     {NULL, 0,}        /* Last entry must be null */
  73. };
  74.  
  75. void drm_mem_init (void) {
  76.     drm_mem_stats_t *mem;
  77.     struct sysinfo si;
  78.  
  79.     for (mem = drm_mem_stats; mem->name; ++mem) {
  80.         mem->succeed_count = 0;
  81.         mem->free_count = 0;
  82.         mem->fail_count = 0;
  83.         mem->bytes_allocated = 0;
  84.         mem->bytes_freed = 0;
  85.     }
  86.  
  87.     si_meminfo(&si);
  88.     drm_ram_available = si.totalram;
  89.     drm_ram_used = 0;
  90. }
  91.  
  92. /* drm_mem_info is called whenever a process reads /dev/drm/mem. */
  93.  
  94. static int drm__mem_info (char *buf, char **start, off_t offset,
  95.                int request, int *eof, void *data) {
  96.     drm_mem_stats_t *pt;
  97.     int len = 0;
  98.  
  99.     if (offset > DRM_PROC_LIMIT) {
  100.         *eof = 1;
  101.         return 0;
  102.     }
  103.  
  104.     *eof = 0;
  105.     *start = &buf[offset];
  106.  
  107.     DRM_PROC_PRINT("          total counts            "
  108.                " |    outstanding  \n");
  109.     DRM_PROC_PRINT("type       alloc freed fail    bytes       freed"
  110.                " | allocs      bytes\n\n");
  111.     DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
  112.                "system", 0, 0, 0,
  113.                drm_ram_available << (PAGE_SHIFT - 10));
  114.     DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
  115.                "locked", 0, 0, 0, drm_ram_used >> 10);
  116.     DRM_PROC_PRINT("\n");
  117.     for (pt = drm_mem_stats; pt->name; pt++) {
  118.         DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
  119.                    pt->name,
  120.                    pt->succeed_count,
  121.                    pt->free_count,
  122.                    pt->fail_count,
  123.                    pt->bytes_allocated,
  124.                    pt->bytes_freed,
  125.                    pt->succeed_count - pt->free_count,
  126.                    (long)pt->bytes_allocated
  127.                    - (long)pt->bytes_freed);
  128.     }
  129.  
  130.     if (len > request + offset)
  131.         return request;
  132.     *eof = 1;
  133.     return len - offset;
  134. }
  135.  
  136. int drm_mem_info (char *buf, char **start, off_t offset,
  137.            int len, int *eof, void *data) {
  138.     int ret;
  139.  
  140.     spin_lock(&drm_mem_lock);
  141.     ret = drm__mem_info (buf, start, offset, len, eof, data);
  142.     spin_unlock(&drm_mem_lock);
  143.     return ret;
  144. }
  145.  
  146. void *drm_alloc (size_t size, int area) {
  147.     void *pt;
  148.  
  149.     if (!size) {
  150.         DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
  151.         return NULL;
  152.     }
  153.  
  154.     if (!(pt = kmalloc(size, GFP_KERNEL))) {
  155.         spin_lock(&drm_mem_lock);
  156.         ++drm_mem_stats[area].fail_count;
  157.         spin_unlock(&drm_mem_lock);
  158.         return NULL;
  159.     }
  160.     spin_lock(&drm_mem_lock);
  161.     ++drm_mem_stats[area].succeed_count;
  162.     drm_mem_stats[area].bytes_allocated += size;
  163.     spin_unlock(&drm_mem_lock);
  164.     return pt;
  165. }
  166.  
  167. void *drm_calloc (size_t nmemb, size_t size, int area) {
  168.     void *addr;
  169.  
  170.     addr = drm_alloc (nmemb * size, area);
  171.     if (addr != NULL)
  172.         memset((void *)addr, 0, size * nmemb);
  173.  
  174.     return addr;
  175. }
  176.  
  177. void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) {
  178.     void *pt;
  179.  
  180.     if (!(pt = drm_alloc (size, area)))
  181.         return NULL;
  182.     if (oldpt && oldsize) {
  183.         memcpy(pt, oldpt, oldsize);
  184.         drm_free (oldpt, oldsize, area);
  185.     }
  186.     return pt;
  187. }
  188.  
  189. void drm_free (void *pt, size_t size, int area) {
  190.     int alloc_count;
  191.     int free_count;
  192.  
  193.     if (!pt)
  194.         DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
  195.     else
  196.         kfree(pt);
  197.     spin_lock(&drm_mem_lock);
  198.     drm_mem_stats[area].bytes_freed += size;
  199.     free_count = ++drm_mem_stats[area].free_count;
  200.     alloc_count = drm_mem_stats[area].succeed_count;
  201.     spin_unlock(&drm_mem_lock);
  202.     if (free_count > alloc_count) {
  203.         DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
  204.                   free_count, alloc_count);
  205.     }
  206. }
  207.  
  208. #if __OS_HAS_AGP
  209.  
  210. DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
  211.     DRM_AGP_MEM *handle;
  212.  
  213.     if (!pages) {
  214.         DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
  215.         return NULL;
  216.     }
  217.  
  218.     if ((handle = drm_agp_allocate_memory (pages, type))) {
  219.         spin_lock(&drm_mem_lock);
  220.         ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
  221.         drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
  222.             += pages << PAGE_SHIFT;
  223.         spin_unlock(&drm_mem_lock);
  224.         return handle;
  225.     }
  226.     spin_lock(&drm_mem_lock);
  227.     ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
  228.     spin_unlock(&drm_mem_lock);
  229.     return NULL;
  230. }
  231.  
  232. int drm_free_agp (DRM_AGP_MEM * handle, int pages) {
  233.     int alloc_count;
  234.     int free_count;
  235.     int retval = -EINVAL;
  236.  
  237.     if (!handle) {
  238.         DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
  239.                   "Attempt to free NULL AGP handle\n");
  240.         return retval;
  241.     }
  242.  
  243.     if (drm_agp_free_memory (handle)) {
  244.         spin_lock(&drm_mem_lock);
  245.         free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;
  246.         alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
  247.         drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
  248.             += pages << PAGE_SHIFT;
  249.         spin_unlock(&drm_mem_lock);
  250.         if (free_count > alloc_count) {
  251.             DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
  252.                       "Excess frees: %d frees, %d allocs\n",
  253.                       free_count, alloc_count);
  254.         }
  255.         return 0;
  256.     }
  257.     return retval;
  258. }
  259.  
  260. int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) {
  261.     int retcode = -EINVAL;
  262.  
  263.     if (!handle) {
  264.         DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  265.                   "Attempt to bind NULL AGP handle\n");
  266.         return retcode;
  267.     }
  268.  
  269.     if (!(retcode = drm_agp_bind_memory (handle, start))) {
  270.         spin_lock(&drm_mem_lock);
  271.         ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
  272.         drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
  273.             += handle->page_count << PAGE_SHIFT;
  274.         spin_unlock(&drm_mem_lock);
  275.         return retcode;
  276.     }
  277.     spin_lock(&drm_mem_lock);
  278.     ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
  279.     spin_unlock(&drm_mem_lock);
  280.     return retcode;
  281. }
  282.  
  283. int drm_unbind_agp (DRM_AGP_MEM * handle) {
  284.     int alloc_count;
  285.     int free_count;
  286.     int retcode = -EINVAL;
  287.  
  288.     if (!handle) {
  289.         DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  290.                   "Attempt to unbind NULL AGP handle\n");
  291.         return retcode;
  292.     }
  293.  
  294.     if ((retcode = drm_agp_unbind_memory (handle)))
  295.         return retcode;
  296.     spin_lock(&drm_mem_lock);
  297.     free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;
  298.     alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
  299.     drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
  300.         += handle->page_count << PAGE_SHIFT;
  301.     spin_unlock(&drm_mem_lock);
  302.     if (free_count > alloc_count) {
  303.         DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  304.                   "Excess frees: %d frees, %d allocs\n",
  305.                   free_count, alloc_count);
  306.     }
  307.     return retcode;
  308. }
  309. #endif
  310.