1*7c2d25f1SBen Skeggs /* SPDX-License-Identifier: MIT 2*7c2d25f1SBen Skeggs * 3*7c2d25f1SBen Skeggs * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. 4*7c2d25f1SBen Skeggs */ 5*7c2d25f1SBen Skeggs #include "engine.h" 6*7c2d25f1SBen Skeggs #include "gpu.h" 7*7c2d25f1SBen Skeggs 8*7c2d25f1SBen Skeggs #include <core/object.h> 9*7c2d25f1SBen Skeggs #include <engine/fifo/chan.h> 10*7c2d25f1SBen Skeggs 11*7c2d25f1SBen Skeggs struct nvkm_rm_engine { 12*7c2d25f1SBen Skeggs struct nvkm_engine engine; 13*7c2d25f1SBen Skeggs 14*7c2d25f1SBen Skeggs struct nvkm_engine_func func; 15*7c2d25f1SBen Skeggs }; 16*7c2d25f1SBen Skeggs 17*7c2d25f1SBen Skeggs struct nvkm_rm_engine_obj { 18*7c2d25f1SBen Skeggs struct nvkm_object object; 19*7c2d25f1SBen Skeggs struct nvkm_gsp_object rm; 20*7c2d25f1SBen Skeggs }; 21*7c2d25f1SBen Skeggs 22*7c2d25f1SBen Skeggs static void* 23*7c2d25f1SBen Skeggs nvkm_rm_engine_obj_dtor(struct nvkm_object *object) 24*7c2d25f1SBen Skeggs { 25*7c2d25f1SBen Skeggs struct nvkm_rm_engine_obj *obj = container_of(object, typeof(*obj), object); 26*7c2d25f1SBen Skeggs 27*7c2d25f1SBen Skeggs nvkm_gsp_rm_free(&obj->rm); 28*7c2d25f1SBen Skeggs return obj; 29*7c2d25f1SBen Skeggs } 30*7c2d25f1SBen Skeggs 31*7c2d25f1SBen Skeggs static const struct nvkm_object_func 32*7c2d25f1SBen Skeggs nvkm_rm_engine_obj = { 33*7c2d25f1SBen Skeggs .dtor = nvkm_rm_engine_obj_dtor, 34*7c2d25f1SBen Skeggs }; 35*7c2d25f1SBen Skeggs 36*7c2d25f1SBen Skeggs int 37*7c2d25f1SBen Skeggs nvkm_rm_engine_obj_new(struct nvkm_gsp_object *chan, int chid, const struct nvkm_oclass *oclass, 38*7c2d25f1SBen Skeggs struct nvkm_object **pobject) 39*7c2d25f1SBen Skeggs { 40*7c2d25f1SBen Skeggs struct nvkm_rm *rm = chan->client->gsp->rm; 41*7c2d25f1SBen Skeggs const int inst = oclass->engine->subdev.inst; 42*7c2d25f1SBen Skeggs const u32 class = oclass->base.oclass; 43*7c2d25f1SBen Skeggs const u32 handle = oclass->handle; 44*7c2d25f1SBen Skeggs struct nvkm_rm_engine_obj *obj; 45*7c2d25f1SBen Skeggs int ret; 46*7c2d25f1SBen Skeggs 47*7c2d25f1SBen Skeggs obj = kzalloc(sizeof(*obj), GFP_KERNEL); 48*7c2d25f1SBen Skeggs if (!obj) 49*7c2d25f1SBen Skeggs return -ENOMEM; 50*7c2d25f1SBen Skeggs 51*7c2d25f1SBen Skeggs switch (oclass->engine->subdev.type) { 52*7c2d25f1SBen Skeggs case NVKM_ENGINE_CE: 53*7c2d25f1SBen Skeggs ret = rm->api->ce->alloc(chan, handle, class, inst, &obj->rm); 54*7c2d25f1SBen Skeggs break; 55*7c2d25f1SBen Skeggs case NVKM_ENGINE_GR: 56*7c2d25f1SBen Skeggs ret = nvkm_gsp_rm_alloc(chan, handle, class, 0, &obj->rm); 57*7c2d25f1SBen Skeggs break; 58*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVDEC: 59*7c2d25f1SBen Skeggs ret = rm->api->nvdec->alloc(chan, handle, class, inst, &obj->rm); 60*7c2d25f1SBen Skeggs break; 61*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVENC: 62*7c2d25f1SBen Skeggs ret = rm->api->nvenc->alloc(chan, handle, class, inst, &obj->rm); 63*7c2d25f1SBen Skeggs break; 64*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVJPG: 65*7c2d25f1SBen Skeggs ret = rm->api->nvjpg->alloc(chan, handle, class, inst, &obj->rm); 66*7c2d25f1SBen Skeggs break; 67*7c2d25f1SBen Skeggs case NVKM_ENGINE_OFA: 68*7c2d25f1SBen Skeggs ret = rm->api->ofa->alloc(chan, handle, class, inst, &obj->rm); 69*7c2d25f1SBen Skeggs break; 70*7c2d25f1SBen Skeggs default: 71*7c2d25f1SBen Skeggs ret = -EINVAL; 72*7c2d25f1SBen Skeggs WARN_ON(1); 73*7c2d25f1SBen Skeggs break; 74*7c2d25f1SBen Skeggs } 75*7c2d25f1SBen Skeggs 76*7c2d25f1SBen Skeggs if (ret) { 77*7c2d25f1SBen Skeggs kfree(obj); 78*7c2d25f1SBen Skeggs return ret; 79*7c2d25f1SBen Skeggs } 80*7c2d25f1SBen Skeggs 81*7c2d25f1SBen Skeggs nvkm_object_ctor(&nvkm_rm_engine_obj, oclass, &obj->object); 82*7c2d25f1SBen Skeggs *pobject = &obj->object; 83*7c2d25f1SBen Skeggs return 0; 84*7c2d25f1SBen Skeggs } 85*7c2d25f1SBen Skeggs 86*7c2d25f1SBen Skeggs static int 87*7c2d25f1SBen Skeggs nvkm_rm_engine_obj_ctor(const struct nvkm_oclass *oclass, void *argv, u32 argc, 88*7c2d25f1SBen Skeggs struct nvkm_object **pobject) 89*7c2d25f1SBen Skeggs { 90*7c2d25f1SBen Skeggs struct nvkm_chan *chan = nvkm_uchan_chan(oclass->parent); 91*7c2d25f1SBen Skeggs 92*7c2d25f1SBen Skeggs return nvkm_rm_engine_obj_new(&chan->rm.object, chan->id, oclass, pobject); 93*7c2d25f1SBen Skeggs } 94*7c2d25f1SBen Skeggs 95*7c2d25f1SBen Skeggs static void * 96*7c2d25f1SBen Skeggs nvkm_rm_engine_dtor(struct nvkm_engine *engine) 97*7c2d25f1SBen Skeggs { 98*7c2d25f1SBen Skeggs kfree(engine->func); 99*7c2d25f1SBen Skeggs return engine; 100*7c2d25f1SBen Skeggs } 101*7c2d25f1SBen Skeggs 102*7c2d25f1SBen Skeggs int 103*7c2d25f1SBen Skeggs nvkm_rm_engine_ctor(void *(*dtor)(struct nvkm_engine *), struct nvkm_rm *rm, 104*7c2d25f1SBen Skeggs enum nvkm_subdev_type type, int inst, 105*7c2d25f1SBen Skeggs const u32 *class, int nclass, struct nvkm_engine *engine) 106*7c2d25f1SBen Skeggs { 107*7c2d25f1SBen Skeggs struct nvkm_engine_func *func; 108*7c2d25f1SBen Skeggs 109*7c2d25f1SBen Skeggs func = kzalloc(struct_size(func, sclass, nclass + 1), GFP_KERNEL); 110*7c2d25f1SBen Skeggs if (!func) 111*7c2d25f1SBen Skeggs return -ENOMEM; 112*7c2d25f1SBen Skeggs 113*7c2d25f1SBen Skeggs func->dtor = dtor; 114*7c2d25f1SBen Skeggs 115*7c2d25f1SBen Skeggs for (int i = 0; i < nclass; i++) { 116*7c2d25f1SBen Skeggs func->sclass[i].oclass = class[i]; 117*7c2d25f1SBen Skeggs func->sclass[i].minver = -1; 118*7c2d25f1SBen Skeggs func->sclass[i].maxver = 0; 119*7c2d25f1SBen Skeggs func->sclass[i].ctor = nvkm_rm_engine_obj_ctor; 120*7c2d25f1SBen Skeggs } 121*7c2d25f1SBen Skeggs 122*7c2d25f1SBen Skeggs nvkm_engine_ctor(func, rm->device, type, inst, true, engine); 123*7c2d25f1SBen Skeggs return 0; 124*7c2d25f1SBen Skeggs } 125*7c2d25f1SBen Skeggs 126*7c2d25f1SBen Skeggs static int 127*7c2d25f1SBen Skeggs nvkm_rm_engine_new_(struct nvkm_rm *rm, enum nvkm_subdev_type type, int inst, u32 class, 128*7c2d25f1SBen Skeggs struct nvkm_engine **pengine) 129*7c2d25f1SBen Skeggs { 130*7c2d25f1SBen Skeggs struct nvkm_engine *engine; 131*7c2d25f1SBen Skeggs int ret; 132*7c2d25f1SBen Skeggs 133*7c2d25f1SBen Skeggs engine = kzalloc(sizeof(*engine), GFP_KERNEL); 134*7c2d25f1SBen Skeggs if (!engine) 135*7c2d25f1SBen Skeggs return -ENOMEM; 136*7c2d25f1SBen Skeggs 137*7c2d25f1SBen Skeggs ret = nvkm_rm_engine_ctor(nvkm_rm_engine_dtor, rm, type, inst, &class, 1, engine); 138*7c2d25f1SBen Skeggs if (ret) { 139*7c2d25f1SBen Skeggs kfree(engine); 140*7c2d25f1SBen Skeggs return ret; 141*7c2d25f1SBen Skeggs } 142*7c2d25f1SBen Skeggs 143*7c2d25f1SBen Skeggs *pengine = engine; 144*7c2d25f1SBen Skeggs return 0; 145*7c2d25f1SBen Skeggs } 146*7c2d25f1SBen Skeggs 147*7c2d25f1SBen Skeggs int 148*7c2d25f1SBen Skeggs nvkm_rm_engine_new(struct nvkm_rm *rm, enum nvkm_subdev_type type, int inst) 149*7c2d25f1SBen Skeggs { 150*7c2d25f1SBen Skeggs const struct nvkm_rm_gpu *gpu = rm->gpu; 151*7c2d25f1SBen Skeggs struct nvkm_device *device = rm->device; 152*7c2d25f1SBen Skeggs 153*7c2d25f1SBen Skeggs switch (type) { 154*7c2d25f1SBen Skeggs case NVKM_ENGINE_CE: 155*7c2d25f1SBen Skeggs if (WARN_ON(inst >= ARRAY_SIZE(device->ce))) 156*7c2d25f1SBen Skeggs return -EINVAL; 157*7c2d25f1SBen Skeggs 158*7c2d25f1SBen Skeggs return nvkm_rm_engine_new_(rm, type, inst, gpu->ce.class, &device->ce[inst]); 159*7c2d25f1SBen Skeggs case NVKM_ENGINE_GR: 160*7c2d25f1SBen Skeggs if (inst != 0) 161*7c2d25f1SBen Skeggs return -ENODEV; /* MiG not supported, just ignore. */ 162*7c2d25f1SBen Skeggs 163*7c2d25f1SBen Skeggs return nvkm_rm_gr_new(rm); 164*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVDEC: 165*7c2d25f1SBen Skeggs if (WARN_ON(inst >= ARRAY_SIZE(device->nvdec))) 166*7c2d25f1SBen Skeggs return -EINVAL; 167*7c2d25f1SBen Skeggs 168*7c2d25f1SBen Skeggs return nvkm_rm_nvdec_new(rm, inst); 169*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVENC: 170*7c2d25f1SBen Skeggs if (WARN_ON(inst >= ARRAY_SIZE(device->nvenc))) 171*7c2d25f1SBen Skeggs return -EINVAL; 172*7c2d25f1SBen Skeggs 173*7c2d25f1SBen Skeggs return nvkm_rm_nvenc_new(rm, inst); 174*7c2d25f1SBen Skeggs case NVKM_ENGINE_NVJPG: 175*7c2d25f1SBen Skeggs if (WARN_ON(inst >= ARRAY_SIZE(device->nvjpg))) 176*7c2d25f1SBen Skeggs return -EINVAL; 177*7c2d25f1SBen Skeggs 178*7c2d25f1SBen Skeggs return nvkm_rm_engine_new_(rm, type, inst, gpu->nvjpg.class, &device->nvjpg[inst]); 179*7c2d25f1SBen Skeggs case NVKM_ENGINE_OFA: 180*7c2d25f1SBen Skeggs if (WARN_ON(inst >= ARRAY_SIZE(device->ofa))) 181*7c2d25f1SBen Skeggs return -EINVAL; 182*7c2d25f1SBen Skeggs 183*7c2d25f1SBen Skeggs return nvkm_rm_engine_new_(rm, type, inst, gpu->ofa.class, &device->ofa[inst]); 184*7c2d25f1SBen Skeggs default: 185*7c2d25f1SBen Skeggs break; 186*7c2d25f1SBen Skeggs } 187*7c2d25f1SBen Skeggs 188*7c2d25f1SBen Skeggs return -ENODEV; 189*7c2d25f1SBen Skeggs } 190