1/* $NetBSD: nouveau_core_namedb.c,v 1.1.1.1 2014/08/06 12:36:23 riastradh Exp $ */
2
3/*
4 * Copyright 2012 Red Hat Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions 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 NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * 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
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Ben Skeggs
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: nouveau_core_namedb.c,v 1.1.1.1 2014/08/06 12:36:23 riastradh Exp $");
29
30#include <core/object.h>
31#include <core/namedb.h>
32#include <core/handle.h>
33#include <core/gpuobj.h>
34
35static struct nouveau_handle *
36nouveau_namedb_lookup(struct nouveau_namedb *namedb, u32 name)
37{
38 struct nouveau_handle *handle;
39
40 list_for_each_entry(handle, &namedb->list, node) {
41 if (handle->name == name)
42 return handle;
43 }
44
45 return NULL;
46}
47
48static struct nouveau_handle *
49nouveau_namedb_lookup_class(struct nouveau_namedb *namedb, u16 oclass)
50{
51 struct nouveau_handle *handle;
52
53 list_for_each_entry(handle, &namedb->list, node) {
54 if (nv_mclass(handle->object) == oclass)
55 return handle;
56 }
57
58 return NULL;
59}
60
61static struct nouveau_handle *
62nouveau_namedb_lookup_vinst(struct nouveau_namedb *namedb, u64 vinst)
63{
64 struct nouveau_handle *handle;
65
66 list_for_each_entry(handle, &namedb->list, node) {
67 if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
68 if (nv_gpuobj(handle->object)->addr == vinst)
69 return handle;
70 }
71 }
72
73 return NULL;
74}
75
76static struct nouveau_handle *
77nouveau_namedb_lookup_cinst(struct nouveau_namedb *namedb, u32 cinst)
78{
79 struct nouveau_handle *handle;
80
81 list_for_each_entry(handle, &namedb->list, node) {
82 if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
83 if (nv_gpuobj(handle->object)->node &&
84 nv_gpuobj(handle->object)->node->offset == cinst)
85 return handle;
86 }
87 }
88
89 return NULL;
90}
91
92int
93nouveau_namedb_insert(struct nouveau_namedb *namedb, u32 name,
94 struct nouveau_object *object,
95 struct nouveau_handle *handle)
96{
97 int ret = -EEXIST;
98 write_lock_irq(&namedb->lock);
99 if (!nouveau_namedb_lookup(namedb, name)) {
100 nouveau_object_ref(object, &handle->object);
101 handle->namedb = namedb;
102 list_add(&handle->node, &namedb->list);
103 ret = 0;
104 }
105 write_unlock_irq(&namedb->lock);
106 return ret;
107}
108
109void
110nouveau_namedb_remove(struct nouveau_handle *handle)
111{
112 struct nouveau_namedb *namedb = handle->namedb;
113 struct nouveau_object *object = handle->object;
114 write_lock_irq(&namedb->lock);
115 list_del(&handle->node);
116 write_unlock_irq(&namedb->lock);
117 nouveau_object_ref(NULL, &object);
118}
119
120struct nouveau_handle *
121nouveau_namedb_get(struct nouveau_namedb *namedb, u32 name)
122{
123 struct nouveau_handle *handle;
124 read_lock(&namedb->lock);
125 handle = nouveau_namedb_lookup(namedb, name);
126 if (handle == NULL)
127 read_unlock(&namedb->lock);
128 return handle;
129}
130
131struct nouveau_handle *
132nouveau_namedb_get_class(struct nouveau_namedb *namedb, u16 oclass)
133{
134 struct nouveau_handle *handle;
135 read_lock(&namedb->lock);
136 handle = nouveau_namedb_lookup_class(namedb, oclass);
137 if (handle == NULL)
138 read_unlock(&namedb->lock);
139 return handle;
140}
141
142struct nouveau_handle *
143nouveau_namedb_get_vinst(struct nouveau_namedb *namedb, u64 vinst)
144{
145 struct nouveau_handle *handle;
146 read_lock(&namedb->lock);
147 handle = nouveau_namedb_lookup_vinst(namedb, vinst);
148 if (handle == NULL)
149 read_unlock(&namedb->lock);
150 return handle;
151}
152
153struct nouveau_handle *
154nouveau_namedb_get_cinst(struct nouveau_namedb *namedb, u32 cinst)
155{
156 struct nouveau_handle *handle;
157 read_lock(&namedb->lock);
158 handle = nouveau_namedb_lookup_cinst(namedb, cinst);
159 if (handle == NULL)
160 read_unlock(&namedb->lock);
161 return handle;
162}
163
164void
165nouveau_namedb_put(struct nouveau_handle *handle)
166{
167 if (handle)
168 read_unlock(&handle->namedb->lock);
169}
170
171int
172nouveau_namedb_create_(struct nouveau_object *parent,
173 struct nouveau_object *engine,
174 struct nouveau_oclass *oclass, u32 pclass,
175 struct nouveau_oclass *sclass, u64 engcls,
176 int length, void **pobject)
177{
178 struct nouveau_namedb *namedb;
179 int ret;
180
181 ret = nouveau_parent_create_(parent, engine, oclass, pclass |
182 NV_NAMEDB_CLASS, sclass, engcls,
183 length, pobject);
184 namedb = *pobject;
185 if (ret)
186 return ret;
187
188 rwlock_init(&namedb->lock);
189 INIT_LIST_HEAD(&namedb->list);
190 return 0;
191}
192
193int
194_nouveau_namedb_ctor(struct nouveau_object *parent,
195 struct nouveau_object *engine,
196 struct nouveau_oclass *oclass, void *data, u32 size,
197 struct nouveau_object **pobject)
198{
199 struct nouveau_namedb *object;
200 int ret;
201
202 ret = nouveau_namedb_create(parent, engine, oclass, 0, NULL, 0, &object);
203 *pobject = nv_object(object);
204 if (ret)
205 return ret;
206
207 return 0;
208}
209