Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
namedb.c
Go to the documentation of this file.
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24 
25 #include <core/object.h>
26 #include <core/namedb.h>
27 #include <core/handle.h>
28 #include <core/gpuobj.h>
29 
30 static struct nouveau_handle *
31 nouveau_namedb_lookup(struct nouveau_namedb *namedb, u32 name)
32 {
33  struct nouveau_handle *handle;
34 
35  list_for_each_entry(handle, &namedb->list, node) {
36  if (handle->name == name)
37  return handle;
38  }
39 
40  return NULL;
41 }
42 
43 static struct nouveau_handle *
44 nouveau_namedb_lookup_class(struct nouveau_namedb *namedb, u16 oclass)
45 {
46  struct nouveau_handle *handle;
47 
48  list_for_each_entry(handle, &namedb->list, node) {
49  if (nv_mclass(handle->object) == oclass)
50  return handle;
51  }
52 
53  return NULL;
54 }
55 
56 static struct nouveau_handle *
57 nouveau_namedb_lookup_vinst(struct nouveau_namedb *namedb, u64 vinst)
58 {
59  struct nouveau_handle *handle;
60 
61  list_for_each_entry(handle, &namedb->list, node) {
62  if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
63  if (nv_gpuobj(handle->object)->addr == vinst)
64  return handle;
65  }
66  }
67 
68  return NULL;
69 }
70 
71 static struct nouveau_handle *
72 nouveau_namedb_lookup_cinst(struct nouveau_namedb *namedb, u32 cinst)
73 {
74  struct nouveau_handle *handle;
75 
76  list_for_each_entry(handle, &namedb->list, node) {
77  if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
78  if (nv_gpuobj(handle->object)->node &&
79  nv_gpuobj(handle->object)->node->offset == cinst)
80  return handle;
81  }
82  }
83 
84  return NULL;
85 }
86 
87 int
89  struct nouveau_object *object,
90  struct nouveau_handle *handle)
91 {
92  int ret = -EEXIST;
93  write_lock_irq(&namedb->lock);
94  if (!nouveau_namedb_lookup(namedb, name)) {
95  nouveau_object_ref(object, &handle->object);
96  handle->namedb = namedb;
97  list_add(&handle->node, &namedb->list);
98  ret = 0;
99  }
100  write_unlock_irq(&namedb->lock);
101  return ret;
102 }
103 
104 void
106 {
107  struct nouveau_namedb *namedb = handle->namedb;
108  struct nouveau_object *object = handle->object;
109  write_lock_irq(&namedb->lock);
110  list_del(&handle->node);
111  write_unlock_irq(&namedb->lock);
112  nouveau_object_ref(NULL, &object);
113 }
114 
115 struct nouveau_handle *
116 nouveau_namedb_get(struct nouveau_namedb *namedb, u32 name)
117 {
118  struct nouveau_handle *handle;
119  read_lock(&namedb->lock);
120  handle = nouveau_namedb_lookup(namedb, name);
121  if (handle == NULL)
122  read_unlock(&namedb->lock);
123  return handle;
124 }
125 
126 struct nouveau_handle *
128 {
129  struct nouveau_handle *handle;
130  read_lock(&namedb->lock);
131  handle = nouveau_namedb_lookup_class(namedb, oclass);
132  if (handle == NULL)
133  read_unlock(&namedb->lock);
134  return handle;
135 }
136 
137 struct nouveau_handle *
139 {
140  struct nouveau_handle *handle;
141  read_lock(&namedb->lock);
142  handle = nouveau_namedb_lookup_vinst(namedb, vinst);
143  if (handle == NULL)
144  read_unlock(&namedb->lock);
145  return handle;
146 }
147 
148 struct nouveau_handle *
150 {
151  struct nouveau_handle *handle;
152  read_lock(&namedb->lock);
153  handle = nouveau_namedb_lookup_cinst(namedb, cinst);
154  if (handle == NULL)
155  read_unlock(&namedb->lock);
156  return handle;
157 }
158 
159 void
161 {
162  if (handle)
163  read_unlock(&handle->namedb->lock);
164 }
165 
166 int
168  struct nouveau_object *engine,
169  struct nouveau_oclass *oclass, u32 pclass,
170  struct nouveau_oclass *sclass, u32 engcls,
171  int length, void **pobject)
172 {
173  struct nouveau_namedb *namedb;
174  int ret;
175 
176  ret = nouveau_parent_create_(parent, engine, oclass, pclass |
177  NV_NAMEDB_CLASS, sclass, engcls,
178  length, pobject);
179  namedb = *pobject;
180  if (ret)
181  return ret;
182 
183  rwlock_init(&namedb->lock);
184  INIT_LIST_HEAD(&namedb->list);
185  return 0;
186 }
187 
188 int
190  struct nouveau_object *engine,
191  struct nouveau_oclass *oclass, void *data, u32 size,
192  struct nouveau_object **pobject)
193 {
194  struct nouveau_namedb *object;
195  int ret;
196 
197  ret = nouveau_namedb_create(parent, engine, oclass, 0, NULL, 0, &object);
198  *pobject = nv_object(object);
199  if (ret)
200  return ret;
201 
202  return 0;
203 }