• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <core/object.h>
25 #include <core/client.h>
26 #include <core/engine.h>
27 
28 int
nvkm_object_mthd(struct nvkm_object * object,u32 mthd,void * data,u32 size)29 nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
30 {
31 	if (likely(object->func->mthd))
32 		return object->func->mthd(object, mthd, data, size);
33 	return -ENODEV;
34 }
35 
36 int
nvkm_object_ntfy(struct nvkm_object * object,u32 mthd,struct nvkm_event ** pevent)37 nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,
38 		 struct nvkm_event **pevent)
39 {
40 	if (likely(object->func->ntfy))
41 		return object->func->ntfy(object, mthd, pevent);
42 	return -ENODEV;
43 }
44 
45 int
nvkm_object_map(struct nvkm_object * object,u64 * addr,u32 * size)46 nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size)
47 {
48 	if (likely(object->func->map))
49 		return object->func->map(object, addr, size);
50 	return -ENODEV;
51 }
52 
53 int
nvkm_object_rd08(struct nvkm_object * object,u64 addr,u8 * data)54 nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data)
55 {
56 	if (likely(object->func->rd08))
57 		return object->func->rd08(object, addr, data);
58 	return -ENODEV;
59 }
60 
61 int
nvkm_object_rd16(struct nvkm_object * object,u64 addr,u16 * data)62 nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data)
63 {
64 	if (likely(object->func->rd16))
65 		return object->func->rd16(object, addr, data);
66 	return -ENODEV;
67 }
68 
69 int
nvkm_object_rd32(struct nvkm_object * object,u64 addr,u32 * data)70 nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data)
71 {
72 	if (likely(object->func->rd32))
73 		return object->func->rd32(object, addr, data);
74 	return -ENODEV;
75 }
76 
77 int
nvkm_object_wr08(struct nvkm_object * object,u64 addr,u8 data)78 nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data)
79 {
80 	if (likely(object->func->wr08))
81 		return object->func->wr08(object, addr, data);
82 	return -ENODEV;
83 }
84 
85 int
nvkm_object_wr16(struct nvkm_object * object,u64 addr,u16 data)86 nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data)
87 {
88 	if (likely(object->func->wr16))
89 		return object->func->wr16(object, addr, data);
90 	return -ENODEV;
91 }
92 
93 int
nvkm_object_wr32(struct nvkm_object * object,u64 addr,u32 data)94 nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data)
95 {
96 	if (likely(object->func->wr32))
97 		return object->func->wr32(object, addr, data);
98 	return -ENODEV;
99 }
100 
101 int
nvkm_object_bind(struct nvkm_object * object,struct nvkm_gpuobj * gpuobj,int align,struct nvkm_gpuobj ** pgpuobj)102 nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
103 		 int align, struct nvkm_gpuobj **pgpuobj)
104 {
105 	if (object->func->bind)
106 		return object->func->bind(object, gpuobj, align, pgpuobj);
107 	return -ENODEV;
108 }
109 
110 int
nvkm_object_fini(struct nvkm_object * object,bool suspend)111 nvkm_object_fini(struct nvkm_object *object, bool suspend)
112 {
113 	const char *action = suspend ? "suspend" : "fini";
114 	struct nvkm_object *child;
115 	s64 time;
116 	int ret;
117 
118 	nvif_debug(object, "%s children...\n", action);
119 	time = ktime_to_us(ktime_get());
120 	list_for_each_entry(child, &object->tree, head) {
121 		ret = nvkm_object_fini(child, suspend);
122 		if (ret && suspend)
123 			goto fail_child;
124 	}
125 
126 	nvif_debug(object, "%s running...\n", action);
127 	if (object->func->fini) {
128 		ret = object->func->fini(object, suspend);
129 		if (ret) {
130 			nvif_error(object, "%s failed with %d\n", action, ret);
131 			if (suspend)
132 				goto fail;
133 		}
134 	}
135 
136 	time = ktime_to_us(ktime_get()) - time;
137 	nvif_debug(object, "%s completed in %lldus\n", action, time);
138 	return 0;
139 
140 fail:
141 	if (object->func->init) {
142 		int rret = object->func->init(object);
143 		if (rret)
144 			nvif_fatal(object, "failed to restart, %d\n", rret);
145 	}
146 fail_child:
147 	list_for_each_entry_continue_reverse(child, &object->tree, head) {
148 		nvkm_object_init(child);
149 	}
150 	return ret;
151 }
152 
153 int
nvkm_object_init(struct nvkm_object * object)154 nvkm_object_init(struct nvkm_object *object)
155 {
156 	struct nvkm_object *child;
157 	s64 time;
158 	int ret;
159 
160 	nvif_debug(object, "init running...\n");
161 	time = ktime_to_us(ktime_get());
162 	if (object->func->init) {
163 		ret = object->func->init(object);
164 		if (ret)
165 			goto fail;
166 	}
167 
168 	nvif_debug(object, "init children...\n");
169 	list_for_each_entry(child, &object->tree, head) {
170 		ret = nvkm_object_init(child);
171 		if (ret)
172 			goto fail_child;
173 	}
174 
175 	time = ktime_to_us(ktime_get()) - time;
176 	nvif_debug(object, "init completed in %lldus\n", time);
177 	return 0;
178 
179 fail_child:
180 	list_for_each_entry_continue_reverse(child, &object->tree, head)
181 		nvkm_object_fini(child, false);
182 fail:
183 	nvif_error(object, "init failed with %d\n", ret);
184 	if (object->func->fini)
185 		object->func->fini(object, false);
186 	return ret;
187 }
188 
189 void *
nvkm_object_dtor(struct nvkm_object * object)190 nvkm_object_dtor(struct nvkm_object *object)
191 {
192 	struct nvkm_object *child, *ctemp;
193 	void *data = object;
194 	s64 time;
195 
196 	nvif_debug(object, "destroy children...\n");
197 	time = ktime_to_us(ktime_get());
198 	list_for_each_entry_safe(child, ctemp, &object->tree, head) {
199 		nvkm_object_del(&child);
200 	}
201 
202 	nvif_debug(object, "destroy running...\n");
203 	if (object->func->dtor)
204 		data = object->func->dtor(object);
205 	nvkm_engine_unref(&object->engine);
206 	time = ktime_to_us(ktime_get()) - time;
207 	nvif_debug(object, "destroy completed in %lldus...\n", time);
208 	return data;
209 }
210 
211 void
nvkm_object_del(struct nvkm_object ** pobject)212 nvkm_object_del(struct nvkm_object **pobject)
213 {
214 	struct nvkm_object *object = *pobject;
215 	if (object && !WARN_ON(!object->func)) {
216 		*pobject = nvkm_object_dtor(object);
217 		nvkm_client_remove(object->client, object);
218 		list_del(&object->head);
219 		kfree(*pobject);
220 		*pobject = NULL;
221 	}
222 }
223 
224 void
nvkm_object_ctor(const struct nvkm_object_func * func,const struct nvkm_oclass * oclass,struct nvkm_object * object)225 nvkm_object_ctor(const struct nvkm_object_func *func,
226 		 const struct nvkm_oclass *oclass, struct nvkm_object *object)
227 {
228 	object->func = func;
229 	object->client = oclass->client;
230 	object->engine = nvkm_engine_ref(oclass->engine);
231 	object->oclass = oclass->base.oclass;
232 	object->handle = oclass->handle;
233 	INIT_LIST_HEAD(&object->head);
234 	INIT_LIST_HEAD(&object->tree);
235 	RB_CLEAR_NODE(&object->node);
236 	WARN_ON(oclass->engine && !object->engine);
237 }
238 
239 int
nvkm_object_new_(const struct nvkm_object_func * func,const struct nvkm_oclass * oclass,void * data,u32 size,struct nvkm_object ** pobject)240 nvkm_object_new_(const struct nvkm_object_func *func,
241 		 const struct nvkm_oclass *oclass, void *data, u32 size,
242 		 struct nvkm_object **pobject)
243 {
244 	if (size == 0) {
245 		if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL)))
246 			return -ENOMEM;
247 		nvkm_object_ctor(func, oclass, *pobject);
248 		return 0;
249 	}
250 	return -ENOSYS;
251 }
252 
253 static const struct nvkm_object_func
254 nvkm_object_func = {
255 };
256 
257 int
nvkm_object_new(const struct nvkm_oclass * oclass,void * data,u32 size,struct nvkm_object ** pobject)258 nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
259 		struct nvkm_object **pobject)
260 {
261 	const struct nvkm_object_func *func =
262 		oclass->base.func ? oclass->base.func : &nvkm_object_func;
263 	return nvkm_object_new_(func, oclass, data, size, pobject);
264 }
265