UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / gpu / drm / via / via_mm.c
CommitLineData
22f579c6 1/*
ce65a44d
TH
2 * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
3 * All rights reserved.
22f579c6
DA
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
ce65a44d
TH
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,
22f579c6
DA
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
ce65a44d 24/*
96de0e25 25 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
ce65a44d
TH
26 */
27
760285e7
DH
28#include <drm/drmP.h>
29#include <drm/via_drm.h>
22f579c6 30#include "via_drv.h"
22f579c6 31
ce65a44d 32#define VIA_MM_ALIGN_SHIFT 4
58c1e85a 33#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1)
22f579c6 34
977b4f6e
DV
35struct via_memblock {
36 struct drm_mm_node mm_node;
37 struct list_head owner_list;
38};
39
c153f45f 40int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
22f579c6 41{
c153f45f 42 drm_via_agp_t *agp = data;
ce65a44d 43 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
22f579c6 44
ce65a44d 45 mutex_lock(&dev->struct_mutex);
977b4f6e 46 drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT);
22f579c6 47
d40c8533 48 dev_priv->agp_initialized = 1;
c153f45f 49 dev_priv->agp_offset = agp->offset;
ce65a44d 50 mutex_unlock(&dev->struct_mutex);
22f579c6 51
3e684eae 52 DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
22f579c6
DA
53 return 0;
54}
55
c153f45f 56int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
22f579c6 57{
c153f45f 58 drm_via_fb_t *fb = data;
ce65a44d 59 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
22f579c6 60
ce65a44d 61 mutex_lock(&dev->struct_mutex);
977b4f6e 62 drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT);
22f579c6 63
d40c8533 64 dev_priv->vram_initialized = 1;
c153f45f 65 dev_priv->vram_offset = fb->offset;
22f579c6 66
ce65a44d 67 mutex_unlock(&dev->struct_mutex);
3e684eae 68 DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
ce65a44d
TH
69
70 return 0;
22f579c6 71
22f579c6
DA
72}
73
74int via_final_context(struct drm_device *dev, int context)
b5e89ed5 75{
22f579c6
DA
76 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
77
b5e89ed5
DA
78 via_release_futex(dev_priv, context);
79
22f579c6
DA
80 /* Linux specific until context tracking code gets ported to BSD */
81 /* Last context, perform cleanup */
82 if (dev->ctx_count == 1 && dev->dev_private) {
b5e89ed5 83 DRM_DEBUG("Last Context\n");
9bfbd5cb 84 drm_irq_uninstall(dev);
22f579c6
DA
85 via_cleanup_futex(dev_priv);
86 via_do_cleanup_map(dev);
87 }
22f579c6
DA
88 return 1;
89}
90
ce65a44d
TH
91void via_lastclose(struct drm_device *dev)
92{
93 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
94
95 if (!dev_priv)
96 return;
97
98 mutex_lock(&dev->struct_mutex);
977b4f6e
DV
99 if (dev_priv->vram_initialized) {
100 drm_mm_takedown(&dev_priv->vram_mm);
101 dev_priv->vram_initialized = 0;
102 }
103 if (dev_priv->agp_initialized) {
104 drm_mm_takedown(&dev_priv->agp_mm);
105 dev_priv->agp_initialized = 0;
106 }
ce65a44d 107 mutex_unlock(&dev->struct_mutex);
bc5f4523 108}
ce65a44d 109
c153f45f 110int via_mem_alloc(struct drm_device *dev, void *data,
c828e204 111 struct drm_file *file)
22f579c6 112{
c153f45f 113 drm_via_mem_t *mem = data;
77ee8f38 114 int retval = 0, user_key;
977b4f6e 115 struct via_memblock *item;
ce65a44d 116 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
c828e204 117 struct via_file_private *file_priv = file->driver_priv;
ce65a44d 118 unsigned long tmpSize;
22f579c6 119
c153f45f 120 if (mem->type > VIA_MEM_AGP) {
ce65a44d 121 DRM_ERROR("Unknown memory type allocation\n");
20caafa6 122 return -EINVAL;
22f579c6 123 }
ce65a44d 124 mutex_lock(&dev->struct_mutex);
c153f45f 125 if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
ce65a44d
TH
126 dev_priv->agp_initialized)) {
127 DRM_ERROR
128 ("Attempt to allocate from uninitialized memory manager.\n");
129 mutex_unlock(&dev->struct_mutex);
20caafa6 130 return -EINVAL;
22f579c6
DA
131 }
132
977b4f6e 133 item = kzalloc(sizeof(*item), GFP_KERNEL);
77ee8f38
DV
134 if (!item) {
135 retval = -ENOMEM;
136 goto fail_alloc;
137 }
c828e204 138
977b4f6e
DV
139 tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
140 if (mem->type == VIA_MEM_AGP)
141 retval = drm_mm_insert_node(&dev_priv->agp_mm,
142 &item->mm_node,
143 tmpSize, 0);
144 else
145 retval = drm_mm_insert_node(&dev_priv->vram_mm,
146 &item->mm_node,
147 tmpSize, 0);
148 if (retval)
149 goto fail_alloc;
150
77ee8f38
DV
151again:
152 if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) {
20caafa6 153 retval = -ENOMEM;
77ee8f38 154 goto fail_idr;
22f579c6 155 }
77ee8f38
DV
156
157 retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key);
158 if (retval == -EAGAIN)
159 goto again;
160 if (retval)
161 goto fail_idr;
162
163 list_add(&item->owner_list, &file_priv->obj_list);
c828e204 164 mutex_unlock(&dev->struct_mutex);
22f579c6 165
77ee8f38
DV
166 mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
167 dev_priv->vram_offset : dev_priv->agp_offset) +
977b4f6e 168 ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT);
77ee8f38
DV
169 mem->index = user_key;
170
171 return 0;
172
173fail_idr:
977b4f6e 174 drm_mm_remove_node(&item->mm_node);
77ee8f38 175fail_alloc:
977b4f6e 176 kfree(item);
77ee8f38
DV
177 mutex_unlock(&dev->struct_mutex);
178
179 mem->offset = 0;
180 mem->size = 0;
181 mem->index = 0;
182 DRM_DEBUG("Video memory allocation failed\n");
183
22f579c6
DA
184 return retval;
185}
186
c153f45f 187int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
22f579c6 188{
ce65a44d 189 drm_via_private_t *dev_priv = dev->dev_private;
c153f45f 190 drm_via_mem_t *mem = data;
977b4f6e 191 struct via_memblock *obj;
22f579c6 192
ce65a44d 193 mutex_lock(&dev->struct_mutex);
77ee8f38
DV
194 obj = idr_find(&dev_priv->object_idr, mem->index);
195 if (obj == NULL) {
196 mutex_unlock(&dev->struct_mutex);
197 return -EINVAL;
198 }
199
200 idr_remove(&dev_priv->object_idr, mem->index);
977b4f6e
DV
201 list_del(&obj->owner_list);
202 drm_mm_remove_node(&obj->mm_node);
203 kfree(obj);
ce65a44d 204 mutex_unlock(&dev->struct_mutex);
77ee8f38 205
c153f45f 206 DRM_DEBUG("free = 0x%lx\n", mem->index);
22f579c6 207
b5215ef1 208 return 0;
22f579c6
DA
209}
210
22f579c6 211
58c1e85a 212void via_reclaim_buffers_locked(struct drm_device *dev,
c828e204 213 struct drm_file *file)
22f579c6 214{
c828e204 215 struct via_file_private *file_priv = file->driver_priv;
977b4f6e 216 struct via_memblock *entry, *next;
22f579c6 217
834859c3
DV
218 if (!(file->minor->master && file->master->lock.hw_lock))
219 return;
220
221 drm_idlelock_take(&file->master->lock);
222
ce65a44d 223 mutex_lock(&dev->struct_mutex);
c828e204 224 if (list_empty(&file_priv->obj_list)) {
ce65a44d 225 mutex_unlock(&dev->struct_mutex);
834859c3
DV
226 drm_idlelock_release(&file->master->lock);
227
ce65a44d 228 return;
22f579c6
DA
229 }
230
834859c3 231 via_driver_dma_quiescent(dev);
22f579c6 232
c828e204
DV
233 list_for_each_entry_safe(entry, next, &file_priv->obj_list,
234 owner_list) {
977b4f6e
DV
235 list_del(&entry->owner_list);
236 drm_mm_remove_node(&entry->mm_node);
237 kfree(entry);
c828e204 238 }
ce65a44d 239 mutex_unlock(&dev->struct_mutex);
834859c3
DV
240
241 drm_idlelock_release(&file->master->lock);
242
ce65a44d 243 return;
22f579c6 244}