These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / core / object.c
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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 }