linux/drivers/gpu/drm/via/via_mm.c
<<
>>
Prefs
   1/*
   2 * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
   3 * All rights reserved.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining a
   6 * copy of this software and associated documentation files (the "Software"),
   7 * to deal in the Software without restriction, including without limitation
   8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
   9 * and/or sell copies of the Software, and to permit persons to whom the
  10 * Software is furnished to do so, subject to the following conditions:
  11 *
  12 * The above copyright notice and this permission notice (including the
  13 * next paragraph) shall be included in all copies or substantial portions
  14 * of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22 * DEALINGS IN THE SOFTWARE.
  23 */
  24/*
  25 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
  26 */
  27
  28#include "drmP.h"
  29#include "via_drm.h"
  30#include "via_drv.h"
  31#include "drm_sman.h"
  32
  33#define VIA_MM_ALIGN_SHIFT 4
  34#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1)
  35
  36int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
  37{
  38        drm_via_agp_t *agp = data;
  39        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  40        int ret;
  41
  42        mutex_lock(&dev->struct_mutex);
  43        ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
  44                                 agp->size >> VIA_MM_ALIGN_SHIFT);
  45
  46        if (ret) {
  47                DRM_ERROR("AGP memory manager initialisation error\n");
  48                mutex_unlock(&dev->struct_mutex);
  49                return ret;
  50        }
  51
  52        dev_priv->agp_initialized = 1;
  53        dev_priv->agp_offset = agp->offset;
  54        mutex_unlock(&dev->struct_mutex);
  55
  56        DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
  57        return 0;
  58}
  59
  60int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
  61{
  62        drm_via_fb_t *fb = data;
  63        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  64        int ret;
  65
  66        mutex_lock(&dev->struct_mutex);
  67        ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
  68                                 fb->size >> VIA_MM_ALIGN_SHIFT);
  69
  70        if (ret) {
  71                DRM_ERROR("VRAM memory manager initialisation error\n");
  72                mutex_unlock(&dev->struct_mutex);
  73                return ret;
  74        }
  75
  76        dev_priv->vram_initialized = 1;
  77        dev_priv->vram_offset = fb->offset;
  78
  79        mutex_unlock(&dev->struct_mutex);
  80        DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
  81
  82        return 0;
  83
  84}
  85
  86int via_final_context(struct drm_device *dev, int context)
  87{
  88        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  89
  90        via_release_futex(dev_priv, context);
  91
  92        /* Linux specific until context tracking code gets ported to BSD */
  93        /* Last context, perform cleanup */
  94        if (dev->ctx_count == 1 && dev->dev_private) {
  95                DRM_DEBUG("Last Context\n");
  96                drm_irq_uninstall(dev);
  97                via_cleanup_futex(dev_priv);
  98                via_do_cleanup_map(dev);
  99        }
 100        return 1;
 101}
 102
 103void via_lastclose(struct drm_device *dev)
 104{
 105        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 106
 107        if (!dev_priv)
 108                return;
 109
 110        mutex_lock(&dev->struct_mutex);
 111        drm_sman_cleanup(&dev_priv->sman);
 112        dev_priv->vram_initialized = 0;
 113        dev_priv->agp_initialized = 0;
 114        mutex_unlock(&dev->struct_mutex);
 115}
 116
 117int via_mem_alloc(struct drm_device *dev, void *data,
 118                  struct drm_file *file_priv)
 119{
 120        drm_via_mem_t *mem = data;
 121        int retval = 0;
 122        struct drm_memblock_item *item;
 123        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 124        unsigned long tmpSize;
 125
 126        if (mem->type > VIA_MEM_AGP) {
 127                DRM_ERROR("Unknown memory type allocation\n");
 128                return -EINVAL;
 129        }
 130        mutex_lock(&dev->struct_mutex);
 131        if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
 132                      dev_priv->agp_initialized)) {
 133                DRM_ERROR
 134                    ("Attempt to allocate from uninitialized memory manager.\n");
 135                mutex_unlock(&dev->struct_mutex);
 136                return -EINVAL;
 137        }
 138
 139        tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
 140        item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0,
 141                              (unsigned long)file_priv);
 142        mutex_unlock(&dev->struct_mutex);
 143        if (item) {
 144                mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
 145                              dev_priv->vram_offset : dev_priv->agp_offset) +
 146                    (item->mm->
 147                     offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
 148                mem->index = item->user_hash.key;
 149        } else {
 150                mem->offset = 0;
 151                mem->size = 0;
 152                mem->index = 0;
 153                DRM_DEBUG("Video memory allocation failed\n");
 154                retval = -ENOMEM;
 155        }
 156
 157        return retval;
 158}
 159
 160int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 161{
 162        drm_via_private_t *dev_priv = dev->dev_private;
 163        drm_via_mem_t *mem = data;
 164        int ret;
 165
 166        mutex_lock(&dev->struct_mutex);
 167        ret = drm_sman_free_key(&dev_priv->sman, mem->index);
 168        mutex_unlock(&dev->struct_mutex);
 169        DRM_DEBUG("free = 0x%lx\n", mem->index);
 170
 171        return ret;
 172}
 173
 174
 175void via_reclaim_buffers_locked(struct drm_device *dev,
 176                                struct drm_file *file_priv)
 177{
 178        drm_via_private_t *dev_priv = dev->dev_private;
 179
 180        mutex_lock(&dev->struct_mutex);
 181        if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
 182                mutex_unlock(&dev->struct_mutex);
 183                return;
 184        }
 185
 186        if (dev->driver->dma_quiescent)
 187                dev->driver->dma_quiescent(dev);
 188
 189        drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
 190        mutex_unlock(&dev->struct_mutex);
 191        return;
 192}
 193