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