xref: /linux/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c (revision 2fc71a0566f63ac3cd43d7cf2d5efbbab6293c5f)
1 /*
2  * Copyright 2021 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 #define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object)
23 #include "cgrp.h"
24 #include "chan.h"
25 #include "runl.h"
26 
27 #include <core/oproxy.h>
28 
29 #include <nvif/if0020.h>
30 
31 #include "gk104.h"
32 
33 struct nvkm_uchan {
34 	struct nvkm_object object;
35 	struct nvkm_chan *chan;
36 };
37 
38 static int
39 nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
40 {
41 	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
42 	union nvif_chan_event_args *args = argv;
43 
44 	if (!uevent)
45 		return 0;
46 	if (argc != sizeof(args->v0) || args->v0.version != 0)
47 		return -ENOSYS;
48 
49 	switch (args->v0.type) {
50 	case NVIF_CHAN_EVENT_V0_NON_STALL_INTR:
51 	case NVIF_CHAN_EVENT_V0_KILLED:
52 		return chan->object.func->uevent(&chan->object, argv, argc, uevent);
53 	default:
54 		break;
55 	}
56 
57 	return -ENOSYS;
58 }
59 
60 struct nvkm_uobj {
61 	struct nvkm_oproxy oproxy;
62 	struct nvkm_chan *chan;
63 };
64 
65 static const struct nvkm_oproxy_func
66 nvkm_uchan_object = {
67 };
68 
69 static int
70 nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
71 		      struct nvkm_object **pobject)
72 {
73 	struct nvkm_chan *chan = nvkm_uchan(oclass->parent)->chan;
74 	struct nvkm_uobj *uobj;
75 	struct nvkm_oclass _oclass;
76 
77 	if (!(uobj = kzalloc(sizeof(*uobj), GFP_KERNEL)))
78 		return -ENOMEM;
79 
80 	nvkm_oproxy_ctor(&nvkm_uchan_object, oclass, &uobj->oproxy);
81 	uobj->chan = chan;
82 	*pobject = &uobj->oproxy.base;
83 
84 	_oclass = *oclass;
85 	_oclass.parent = &chan->object;
86 	return nvkm_fifo_chan_child_new(&_oclass, argv, argc, &uobj->oproxy.object);
87 }
88 
89 static int
90 nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
91 {
92 	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
93 	struct nvkm_engn *engn;
94 	int ret;
95 
96 	nvkm_runl_foreach_engn(engn, chan->cgrp->runl) {
97 		struct nvkm_engine *engine = engn->engine;
98 		int c = 0;
99 
100 		oclass->engine = engine;
101 		oclass->base.oclass = 0;
102 
103 		if (engine->func->fifo.sclass) {
104 			ret = engine->func->fifo.sclass(oclass, index);
105 			if (oclass->base.oclass) {
106 				if (!oclass->base.ctor)
107 					oclass->base.ctor = nvkm_object_new;
108 				oclass->ctor = nvkm_uchan_object_new;
109 				return 0;
110 			}
111 
112 			index -= ret;
113 			continue;
114 		}
115 
116 		while (engine->func->sclass[c].oclass) {
117 			if (c++ == index) {
118 				oclass->base = engine->func->sclass[index];
119 				if (!oclass->base.ctor)
120 					oclass->base.ctor = nvkm_object_new;
121 				oclass->ctor = nvkm_uchan_object_new;
122 				return 0;
123 			}
124 		}
125 
126 		index -= c;
127 	}
128 
129 	return -EINVAL;
130 }
131 
132 static int
133 nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc,
134 	       enum nvkm_object_map *type, u64 *addr, u64 *size)
135 {
136 	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
137 
138 	return chan->object.func->map(&chan->object, argv, argc, type, addr, size);
139 }
140 
141 static int
142 nvkm_uchan_fini(struct nvkm_object *object, bool suspend)
143 {
144 	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
145 	int ret;
146 
147 	ret = chan->object.func->fini(&chan->object, suspend);
148 	if (ret && suspend)
149 		return ret;
150 
151 	return 0;
152 }
153 
154 static int
155 nvkm_uchan_init(struct nvkm_object *object)
156 {
157 	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
158 
159 	return chan->object.func->init(&chan->object);
160 }
161 
162 static void *
163 nvkm_uchan_dtor(struct nvkm_object *object)
164 {
165 	struct nvkm_uchan *uchan = nvkm_uchan(object);
166 
167 	nvkm_chan_del(&uchan->chan);
168 	return uchan;
169 }
170 
171 static const struct nvkm_object_func
172 nvkm_uchan = {
173 	.dtor = nvkm_uchan_dtor,
174 	.init = nvkm_uchan_init,
175 	.fini = nvkm_uchan_fini,
176 	.map = nvkm_uchan_map,
177 	.sclass = nvkm_uchan_sclass,
178 	.uevent = nvkm_uchan_uevent,
179 };
180 
181 int
182 nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm_oclass *oclass,
183 	       void *argv, u32 argc, struct nvkm_object **pobject)
184 {
185 	struct nvkm_object *object = NULL;
186 	struct nvkm_uchan *uchan;
187 	int ret;
188 
189 	if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL)))
190 		return -ENOMEM;
191 
192 	nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object);
193 	*pobject = &uchan->object;
194 
195 	if (fifo->func->chan.ctor)
196 		ret = fifo->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object);
197 	else
198 		ret = fifo->func->chan.oclass->ctor(fifo, oclass, argv, argc, &object);
199 	if (!object)
200 		return ret;
201 
202 	uchan->chan = container_of(object, typeof(*uchan->chan), object);
203 	return ret;
204 }
205