1/*
2 * Copyright 2015 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 <bskeggs@redhat.com>
23 */
24#include <core/oproxy.h>
25
26static int
27nvkm_oproxy_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
28{
29	return nvkm_object_mthd(nvkm_oproxy(object)->object, mthd, data, size);
30}
31
32static int
33nvkm_oproxy_ntfy(struct nvkm_object *object, u32 mthd,
34		 struct nvkm_event **pevent)
35{
36	return nvkm_object_ntfy(nvkm_oproxy(object)->object, mthd, pevent);
37}
38
39static int
40nvkm_oproxy_map(struct nvkm_object *object, void *argv, u32 argc,
41		enum nvkm_object_map *type, u64 *addr, u64 *size)
42{
43	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
44	return nvkm_object_map(oproxy->object, argv, argc, type, addr, size);
45}
46
47static int
48nvkm_oproxy_unmap(struct nvkm_object *object)
49{
50	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
51
52	if (unlikely(!oproxy->object))
53		return 0;
54
55	return nvkm_object_unmap(oproxy->object);
56}
57
58static int
59nvkm_oproxy_rd08(struct nvkm_object *object, u64 addr, u8 *data)
60{
61	return nvkm_object_rd08(nvkm_oproxy(object)->object, addr, data);
62}
63
64static int
65nvkm_oproxy_rd16(struct nvkm_object *object, u64 addr, u16 *data)
66{
67	return nvkm_object_rd16(nvkm_oproxy(object)->object, addr, data);
68}
69
70static int
71nvkm_oproxy_rd32(struct nvkm_object *object, u64 addr, u32 *data)
72{
73	return nvkm_object_rd32(nvkm_oproxy(object)->object, addr, data);
74}
75
76static int
77nvkm_oproxy_wr08(struct nvkm_object *object, u64 addr, u8 data)
78{
79	return nvkm_object_wr08(nvkm_oproxy(object)->object, addr, data);
80}
81
82static int
83nvkm_oproxy_wr16(struct nvkm_object *object, u64 addr, u16 data)
84{
85	return nvkm_object_wr16(nvkm_oproxy(object)->object, addr, data);
86}
87
88static int
89nvkm_oproxy_wr32(struct nvkm_object *object, u64 addr, u32 data)
90{
91	return nvkm_object_wr32(nvkm_oproxy(object)->object, addr, data);
92}
93
94static int
95nvkm_oproxy_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
96		 int align, struct nvkm_gpuobj **pgpuobj)
97{
98	return nvkm_object_bind(nvkm_oproxy(object)->object,
99				parent, align, pgpuobj);
100}
101
102static int
103nvkm_oproxy_sclass(struct nvkm_object *object, int index,
104		   struct nvkm_oclass *oclass)
105{
106	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
107	oclass->parent = oproxy->object;
108	if (!oproxy->object->func->sclass)
109		return -ENODEV;
110	return oproxy->object->func->sclass(oproxy->object, index, oclass);
111}
112
113static int
114nvkm_oproxy_uevent(struct nvkm_object *object, void *argv, u32 argc,
115		   struct nvkm_uevent *uevent)
116{
117	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
118
119	if (!oproxy->object->func->uevent)
120		return -ENOSYS;
121
122	return oproxy->object->func->uevent(oproxy->object, argv, argc, uevent);
123}
124
125static int
126nvkm_oproxy_fini(struct nvkm_object *object, bool suspend)
127{
128	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
129	int ret;
130
131	if (oproxy->func->fini[0]) {
132		ret = oproxy->func->fini[0](oproxy, suspend);
133		if (ret && suspend)
134			return ret;
135	}
136
137	if (oproxy->object->func->fini) {
138		ret = oproxy->object->func->fini(oproxy->object, suspend);
139		if (ret && suspend)
140			return ret;
141	}
142
143	if (oproxy->func->fini[1]) {
144		ret = oproxy->func->fini[1](oproxy, suspend);
145		if (ret && suspend)
146			return ret;
147	}
148
149	return 0;
150}
151
152static int
153nvkm_oproxy_init(struct nvkm_object *object)
154{
155	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
156	int ret;
157
158	if (oproxy->func->init[0]) {
159		ret = oproxy->func->init[0](oproxy);
160		if (ret)
161			return ret;
162	}
163
164	if (oproxy->object->func->init) {
165		ret = oproxy->object->func->init(oproxy->object);
166		if (ret)
167			return ret;
168	}
169
170	if (oproxy->func->init[1]) {
171		ret = oproxy->func->init[1](oproxy);
172		if (ret)
173			return ret;
174	}
175
176	return 0;
177}
178
179static void *
180nvkm_oproxy_dtor(struct nvkm_object *object)
181{
182	struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
183	if (oproxy->func->dtor[0])
184		oproxy->func->dtor[0](oproxy);
185	nvkm_object_del(&oproxy->object);
186	if (oproxy->func->dtor[1])
187		oproxy->func->dtor[1](oproxy);
188	return oproxy;
189}
190
191static const struct nvkm_object_func
192nvkm_oproxy_func = {
193	.dtor = nvkm_oproxy_dtor,
194	.init = nvkm_oproxy_init,
195	.fini = nvkm_oproxy_fini,
196	.mthd = nvkm_oproxy_mthd,
197	.ntfy = nvkm_oproxy_ntfy,
198	.map = nvkm_oproxy_map,
199	.unmap = nvkm_oproxy_unmap,
200	.rd08 = nvkm_oproxy_rd08,
201	.rd16 = nvkm_oproxy_rd16,
202	.rd32 = nvkm_oproxy_rd32,
203	.wr08 = nvkm_oproxy_wr08,
204	.wr16 = nvkm_oproxy_wr16,
205	.wr32 = nvkm_oproxy_wr32,
206	.bind = nvkm_oproxy_bind,
207	.sclass = nvkm_oproxy_sclass,
208	.uevent = nvkm_oproxy_uevent,
209};
210
211void
212nvkm_oproxy_ctor(const struct nvkm_oproxy_func *func,
213		 const struct nvkm_oclass *oclass, struct nvkm_oproxy *oproxy)
214{
215	nvkm_object_ctor(&nvkm_oproxy_func, oclass, &oproxy->base);
216	oproxy->func = func;
217}
218
219int
220nvkm_oproxy_new_(const struct nvkm_oproxy_func *func,
221		 const struct nvkm_oclass *oclass, struct nvkm_oproxy **poproxy)
222{
223	if (!(*poproxy = kzalloc(sizeof(**poproxy), GFP_KERNEL)))
224		return -ENOMEM;
225	nvkm_oproxy_ctor(func, oclass, *poproxy);
226	return 0;
227}
228