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