0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/slab.h>
0029
0030 #include <drm/drm_device.h>
0031 #include <drm/drm_file.h>
0032 #include <drm/via_drm.h>
0033
0034 #include "via_drv.h"
0035
0036 #define VIA_MM_ALIGN_SHIFT 4
0037 #define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1)
0038
0039 struct via_memblock {
0040 struct drm_mm_node mm_node;
0041 struct list_head owner_list;
0042 };
0043
0044 int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
0045 {
0046 drm_via_agp_t *agp = data;
0047 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0048
0049 mutex_lock(&dev->struct_mutex);
0050 drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT);
0051
0052 dev_priv->agp_initialized = 1;
0053 dev_priv->agp_offset = agp->offset;
0054 mutex_unlock(&dev->struct_mutex);
0055
0056 DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
0057 return 0;
0058 }
0059
0060 int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
0061 {
0062 drm_via_fb_t *fb = data;
0063 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0064
0065 mutex_lock(&dev->struct_mutex);
0066 drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT);
0067
0068 dev_priv->vram_initialized = 1;
0069 dev_priv->vram_offset = fb->offset;
0070
0071 mutex_unlock(&dev->struct_mutex);
0072 DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
0073
0074 return 0;
0075
0076 }
0077
0078 int via_final_context(struct drm_device *dev, int context)
0079 {
0080 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0081
0082 via_release_futex(dev_priv, context);
0083
0084
0085
0086 if (list_is_singular(&dev->ctxlist)) {
0087 DRM_DEBUG("Last Context\n");
0088 drm_legacy_irq_uninstall(dev);
0089 via_cleanup_futex(dev_priv);
0090 via_do_cleanup_map(dev);
0091 }
0092 return 1;
0093 }
0094
0095 void via_lastclose(struct drm_device *dev)
0096 {
0097 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0098
0099 if (!dev_priv)
0100 return;
0101
0102 mutex_lock(&dev->struct_mutex);
0103 if (dev_priv->vram_initialized) {
0104 drm_mm_takedown(&dev_priv->vram_mm);
0105 dev_priv->vram_initialized = 0;
0106 }
0107 if (dev_priv->agp_initialized) {
0108 drm_mm_takedown(&dev_priv->agp_mm);
0109 dev_priv->agp_initialized = 0;
0110 }
0111 mutex_unlock(&dev->struct_mutex);
0112 }
0113
0114 int via_mem_alloc(struct drm_device *dev, void *data,
0115 struct drm_file *file)
0116 {
0117 drm_via_mem_t *mem = data;
0118 int retval = 0, user_key;
0119 struct via_memblock *item;
0120 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0121 struct via_file_private *file_priv = file->driver_priv;
0122 unsigned long tmpSize;
0123
0124 if (mem->type > VIA_MEM_AGP) {
0125 DRM_ERROR("Unknown memory type allocation\n");
0126 return -EINVAL;
0127 }
0128 mutex_lock(&dev->struct_mutex);
0129 if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
0130 dev_priv->agp_initialized)) {
0131 mutex_unlock(&dev->struct_mutex);
0132 DRM_ERROR
0133 ("Attempt to allocate from uninitialized memory manager.\n");
0134 return -EINVAL;
0135 }
0136
0137 item = kzalloc(sizeof(*item), GFP_KERNEL);
0138 if (!item) {
0139 retval = -ENOMEM;
0140 goto fail_alloc;
0141 }
0142
0143 tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
0144 if (mem->type == VIA_MEM_AGP)
0145 retval = drm_mm_insert_node(&dev_priv->agp_mm,
0146 &item->mm_node,
0147 tmpSize);
0148 else
0149 retval = drm_mm_insert_node(&dev_priv->vram_mm,
0150 &item->mm_node,
0151 tmpSize);
0152 if (retval)
0153 goto fail_alloc;
0154
0155 retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
0156 if (retval < 0)
0157 goto fail_idr;
0158 user_key = retval;
0159
0160 list_add(&item->owner_list, &file_priv->obj_list);
0161 mutex_unlock(&dev->struct_mutex);
0162
0163 mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
0164 dev_priv->vram_offset : dev_priv->agp_offset) +
0165 ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT);
0166 mem->index = user_key;
0167
0168 return 0;
0169
0170 fail_idr:
0171 drm_mm_remove_node(&item->mm_node);
0172 fail_alloc:
0173 kfree(item);
0174 mutex_unlock(&dev->struct_mutex);
0175
0176 mem->offset = 0;
0177 mem->size = 0;
0178 mem->index = 0;
0179 DRM_DEBUG("Video memory allocation failed\n");
0180
0181 return retval;
0182 }
0183
0184 int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
0185 {
0186 drm_via_private_t *dev_priv = dev->dev_private;
0187 drm_via_mem_t *mem = data;
0188 struct via_memblock *obj;
0189
0190 mutex_lock(&dev->struct_mutex);
0191 obj = idr_find(&dev_priv->object_idr, mem->index);
0192 if (obj == NULL) {
0193 mutex_unlock(&dev->struct_mutex);
0194 return -EINVAL;
0195 }
0196
0197 idr_remove(&dev_priv->object_idr, mem->index);
0198 list_del(&obj->owner_list);
0199 drm_mm_remove_node(&obj->mm_node);
0200 kfree(obj);
0201 mutex_unlock(&dev->struct_mutex);
0202
0203 DRM_DEBUG("free = 0x%lx\n", mem->index);
0204
0205 return 0;
0206 }
0207
0208
0209 void via_reclaim_buffers_locked(struct drm_device *dev,
0210 struct drm_file *file)
0211 {
0212 struct via_file_private *file_priv = file->driver_priv;
0213 struct via_memblock *entry, *next;
0214
0215 if (!(dev->master && file->master->lock.hw_lock))
0216 return;
0217
0218 drm_legacy_idlelock_take(&file->master->lock);
0219
0220 mutex_lock(&dev->struct_mutex);
0221 if (list_empty(&file_priv->obj_list)) {
0222 mutex_unlock(&dev->struct_mutex);
0223 drm_legacy_idlelock_release(&file->master->lock);
0224
0225 return;
0226 }
0227
0228 via_driver_dma_quiescent(dev);
0229
0230 list_for_each_entry_safe(entry, next, &file_priv->obj_list,
0231 owner_list) {
0232 list_del(&entry->owner_list);
0233 drm_mm_remove_node(&entry->mm_node);
0234 kfree(entry);
0235 }
0236 mutex_unlock(&dev->struct_mutex);
0237
0238 drm_legacy_idlelock_release(&file->master->lock);
0239
0240 return;
0241 }