0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <core/engine.h>
0025 #include <core/device.h>
0026 #include <core/option.h>
0027
0028 #include <subdev/fb.h>
0029
0030 bool
0031 nvkm_engine_chsw_load(struct nvkm_engine *engine)
0032 {
0033 if (engine->func->chsw_load)
0034 return engine->func->chsw_load(engine);
0035 return false;
0036 }
0037
0038 void
0039 nvkm_engine_unref(struct nvkm_engine **pengine)
0040 {
0041 struct nvkm_engine *engine = *pengine;
0042 if (engine) {
0043 if (refcount_dec_and_mutex_lock(&engine->use.refcount, &engine->use.mutex)) {
0044 nvkm_subdev_fini(&engine->subdev, false);
0045 engine->use.enabled = false;
0046 mutex_unlock(&engine->use.mutex);
0047 }
0048 *pengine = NULL;
0049 }
0050 }
0051
0052 struct nvkm_engine *
0053 nvkm_engine_ref(struct nvkm_engine *engine)
0054 {
0055 int ret;
0056 if (engine) {
0057 if (!refcount_inc_not_zero(&engine->use.refcount)) {
0058 mutex_lock(&engine->use.mutex);
0059 if (!refcount_inc_not_zero(&engine->use.refcount)) {
0060 engine->use.enabled = true;
0061 if ((ret = nvkm_subdev_init(&engine->subdev))) {
0062 engine->use.enabled = false;
0063 mutex_unlock(&engine->use.mutex);
0064 return ERR_PTR(ret);
0065 }
0066 refcount_set(&engine->use.refcount, 1);
0067 }
0068 mutex_unlock(&engine->use.mutex);
0069 }
0070 }
0071 return engine;
0072 }
0073
0074 void
0075 nvkm_engine_tile(struct nvkm_engine *engine, int region)
0076 {
0077 struct nvkm_fb *fb = engine->subdev.device->fb;
0078 if (engine->func->tile)
0079 engine->func->tile(engine, region, &fb->tile.region[region]);
0080 }
0081
0082 static void
0083 nvkm_engine_intr(struct nvkm_subdev *subdev)
0084 {
0085 struct nvkm_engine *engine = nvkm_engine(subdev);
0086 if (engine->func->intr)
0087 engine->func->intr(engine);
0088 }
0089
0090 static int
0091 nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
0092 {
0093 struct nvkm_engine *engine = nvkm_engine(subdev);
0094 if (engine->func->info) {
0095 if (!IS_ERR((engine = nvkm_engine_ref(engine)))) {
0096 int ret = engine->func->info(engine, mthd, data);
0097 nvkm_engine_unref(&engine);
0098 return ret;
0099 }
0100 return PTR_ERR(engine);
0101 }
0102 return -ENOSYS;
0103 }
0104
0105 static int
0106 nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend)
0107 {
0108 struct nvkm_engine *engine = nvkm_engine(subdev);
0109 if (engine->func->fini)
0110 return engine->func->fini(engine, suspend);
0111 return 0;
0112 }
0113
0114 static int
0115 nvkm_engine_init(struct nvkm_subdev *subdev)
0116 {
0117 struct nvkm_engine *engine = nvkm_engine(subdev);
0118 struct nvkm_fb *fb = subdev->device->fb;
0119 int ret = 0, i;
0120 s64 time;
0121
0122 if (!engine->use.enabled) {
0123 nvkm_trace(subdev, "init skipped, engine has no users\n");
0124 return ret;
0125 }
0126
0127 if (engine->func->oneinit && !engine->subdev.oneinit) {
0128 nvkm_trace(subdev, "one-time init running...\n");
0129 time = ktime_to_us(ktime_get());
0130 ret = engine->func->oneinit(engine);
0131 if (ret) {
0132 nvkm_trace(subdev, "one-time init failed, %d\n", ret);
0133 return ret;
0134 }
0135
0136 engine->subdev.oneinit = true;
0137 time = ktime_to_us(ktime_get()) - time;
0138 nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
0139 }
0140
0141 if (engine->func->init)
0142 ret = engine->func->init(engine);
0143
0144 for (i = 0; fb && i < fb->tile.regions; i++)
0145 nvkm_engine_tile(engine, i);
0146 return ret;
0147 }
0148
0149 static int
0150 nvkm_engine_preinit(struct nvkm_subdev *subdev)
0151 {
0152 struct nvkm_engine *engine = nvkm_engine(subdev);
0153 if (engine->func->preinit)
0154 engine->func->preinit(engine);
0155 return 0;
0156 }
0157
0158 static void *
0159 nvkm_engine_dtor(struct nvkm_subdev *subdev)
0160 {
0161 struct nvkm_engine *engine = nvkm_engine(subdev);
0162 if (engine->func->dtor)
0163 return engine->func->dtor(engine);
0164 mutex_destroy(&engine->use.mutex);
0165 return engine;
0166 }
0167
0168 const struct nvkm_subdev_func
0169 nvkm_engine = {
0170 .dtor = nvkm_engine_dtor,
0171 .preinit = nvkm_engine_preinit,
0172 .init = nvkm_engine_init,
0173 .fini = nvkm_engine_fini,
0174 .info = nvkm_engine_info,
0175 .intr = nvkm_engine_intr,
0176 };
0177
0178 int
0179 nvkm_engine_ctor(const struct nvkm_engine_func *func, struct nvkm_device *device,
0180 enum nvkm_subdev_type type, int inst, bool enable, struct nvkm_engine *engine)
0181 {
0182 nvkm_subdev_ctor(&nvkm_engine, device, type, inst, &engine->subdev);
0183 engine->func = func;
0184 refcount_set(&engine->use.refcount, 0);
0185 mutex_init(&engine->use.mutex);
0186
0187 if (!nvkm_boolopt(device->cfgopt, engine->subdev.name, enable)) {
0188 nvkm_debug(&engine->subdev, "disabled\n");
0189 return -ENODEV;
0190 }
0191
0192 spin_lock_init(&engine->lock);
0193 return 0;
0194 }
0195
0196 int
0197 nvkm_engine_new_(const struct nvkm_engine_func *func, struct nvkm_device *device,
0198 enum nvkm_subdev_type type, int inst, bool enable,
0199 struct nvkm_engine **pengine)
0200 {
0201 if (!(*pengine = kzalloc(sizeof(**pengine), GFP_KERNEL)))
0202 return -ENOMEM;
0203 return nvkm_engine_ctor(func, device, type, inst, enable, *pengine);
0204 }