xref: /linux/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.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 #include "runl.h"
23 #include "chan.h"
24 #include "chid.h"
25 #include "priv.h"
26 
27 void
28 nvkm_runl_del(struct nvkm_runl *runl)
29 {
30 	struct nvkm_engn *engn, *engt;
31 
32 	list_for_each_entry_safe(engn, engt, &runl->engns, head) {
33 		list_del(&engn->head);
34 		kfree(engn);
35 	}
36 
37 	nvkm_chid_unref(&runl->chid);
38 	nvkm_chid_unref(&runl->cgid);
39 
40 	list_del(&runl->head);
41 	mutex_destroy(&runl->mutex);
42 	kfree(runl);
43 }
44 
45 struct nvkm_engn *
46 nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *func,
47 	      enum nvkm_subdev_type type, int inst)
48 {
49 	struct nvkm_device *device = runl->fifo->engine.subdev.device;
50 	struct nvkm_engine *engine;
51 	struct nvkm_engn *engn;
52 
53 	engine = nvkm_device_engine(device, type, inst);
54 	if (!engine) {
55 		RUNL_DEBUG(runl, "engn %d.%d[%s] not found", engi, inst, nvkm_subdev_type[type]);
56 		return NULL;
57 	}
58 
59 	if (!(engn = kzalloc(sizeof(*engn), GFP_KERNEL)))
60 		return NULL;
61 
62 	engn->func = func;
63 	engn->runl = runl;
64 	engn->id = engi;
65 	engn->engine = engine;
66 	list_add_tail(&engn->head, &runl->engns);
67 	return engn;
68 }
69 
70 struct nvkm_runl *
71 nvkm_runl_get(struct nvkm_fifo *fifo, int runi, u32 addr)
72 {
73 	struct nvkm_runl *runl;
74 
75 	nvkm_runl_foreach(runl, fifo) {
76 		if ((runi >= 0 && runl->id == runi) || (runi < 0 && runl->addr == addr))
77 			return runl;
78 	}
79 
80 	return NULL;
81 }
82 
83 struct nvkm_runl *
84 nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr)
85 {
86 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
87 	struct nvkm_runl *runl;
88 	int ret;
89 
90 	if (!(runl = kzalloc(sizeof(*runl), GFP_KERNEL)))
91 		return NULL;
92 
93 	runl->func = fifo->func->runl;
94 	runl->fifo = fifo;
95 	runl->id = runi;
96 	runl->addr = addr;
97 	INIT_LIST_HEAD(&runl->engns);
98 	INIT_LIST_HEAD(&runl->cgrps);
99 	mutex_init(&runl->mutex);
100 	list_add_tail(&runl->head, &fifo->runls);
101 
102 	if (!fifo->chid) {
103 		if ((ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->cgid)) ||
104 		    (ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->chid))) {
105 			RUNL_ERROR(runl, "cgid/chid: %d", ret);
106 			nvkm_runl_del(runl);
107 			return NULL;
108 		}
109 	} else {
110 		runl->cgid = nvkm_chid_ref(fifo->cgid);
111 		runl->chid = nvkm_chid_ref(fifo->chid);
112 	}
113 
114 	return runl;
115 }
116