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/object.h>
0025 #include <core/client.h>
0026 #include <core/engine.h>
0027
0028 struct nvkm_object *
0029 nvkm_object_search(struct nvkm_client *client, u64 handle,
0030 const struct nvkm_object_func *func)
0031 {
0032 struct nvkm_object *object;
0033
0034 if (handle) {
0035 struct rb_node *node = client->objroot.rb_node;
0036 while (node) {
0037 object = rb_entry(node, typeof(*object), node);
0038 if (handle < object->object)
0039 node = node->rb_left;
0040 else
0041 if (handle > object->object)
0042 node = node->rb_right;
0043 else
0044 goto done;
0045 }
0046 return ERR_PTR(-ENOENT);
0047 } else {
0048 object = &client->object;
0049 }
0050
0051 done:
0052 if (unlikely(func && object->func != func))
0053 return ERR_PTR(-EINVAL);
0054 return object;
0055 }
0056
0057 void
0058 nvkm_object_remove(struct nvkm_object *object)
0059 {
0060 if (!RB_EMPTY_NODE(&object->node))
0061 rb_erase(&object->node, &object->client->objroot);
0062 }
0063
0064 bool
0065 nvkm_object_insert(struct nvkm_object *object)
0066 {
0067 struct rb_node **ptr = &object->client->objroot.rb_node;
0068 struct rb_node *parent = NULL;
0069
0070 while (*ptr) {
0071 struct nvkm_object *this = rb_entry(*ptr, typeof(*this), node);
0072 parent = *ptr;
0073 if (object->object < this->object)
0074 ptr = &parent->rb_left;
0075 else
0076 if (object->object > this->object)
0077 ptr = &parent->rb_right;
0078 else
0079 return false;
0080 }
0081
0082 rb_link_node(&object->node, parent, ptr);
0083 rb_insert_color(&object->node, &object->client->objroot);
0084 return true;
0085 }
0086
0087 int
0088 nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
0089 {
0090 if (likely(object->func->mthd))
0091 return object->func->mthd(object, mthd, data, size);
0092 return -ENODEV;
0093 }
0094
0095 int
0096 nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,
0097 struct nvkm_event **pevent)
0098 {
0099 if (likely(object->func->ntfy))
0100 return object->func->ntfy(object, mthd, pevent);
0101 return -ENODEV;
0102 }
0103
0104 int
0105 nvkm_object_map(struct nvkm_object *object, void *argv, u32 argc,
0106 enum nvkm_object_map *type, u64 *addr, u64 *size)
0107 {
0108 if (likely(object->func->map))
0109 return object->func->map(object, argv, argc, type, addr, size);
0110 return -ENODEV;
0111 }
0112
0113 int
0114 nvkm_object_unmap(struct nvkm_object *object)
0115 {
0116 if (likely(object->func->unmap))
0117 return object->func->unmap(object);
0118 return -ENODEV;
0119 }
0120
0121 int
0122 nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data)
0123 {
0124 if (likely(object->func->rd08))
0125 return object->func->rd08(object, addr, data);
0126 return -ENODEV;
0127 }
0128
0129 int
0130 nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data)
0131 {
0132 if (likely(object->func->rd16))
0133 return object->func->rd16(object, addr, data);
0134 return -ENODEV;
0135 }
0136
0137 int
0138 nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data)
0139 {
0140 if (likely(object->func->rd32))
0141 return object->func->rd32(object, addr, data);
0142 return -ENODEV;
0143 }
0144
0145 int
0146 nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data)
0147 {
0148 if (likely(object->func->wr08))
0149 return object->func->wr08(object, addr, data);
0150 return -ENODEV;
0151 }
0152
0153 int
0154 nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data)
0155 {
0156 if (likely(object->func->wr16))
0157 return object->func->wr16(object, addr, data);
0158 return -ENODEV;
0159 }
0160
0161 int
0162 nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data)
0163 {
0164 if (likely(object->func->wr32))
0165 return object->func->wr32(object, addr, data);
0166 return -ENODEV;
0167 }
0168
0169 int
0170 nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
0171 int align, struct nvkm_gpuobj **pgpuobj)
0172 {
0173 if (object->func->bind)
0174 return object->func->bind(object, gpuobj, align, pgpuobj);
0175 return -ENODEV;
0176 }
0177
0178 int
0179 nvkm_object_fini(struct nvkm_object *object, bool suspend)
0180 {
0181 const char *action = suspend ? "suspend" : "fini";
0182 struct nvkm_object *child;
0183 s64 time;
0184 int ret;
0185
0186 nvif_debug(object, "%s children...\n", action);
0187 time = ktime_to_us(ktime_get());
0188 list_for_each_entry(child, &object->tree, head) {
0189 ret = nvkm_object_fini(child, suspend);
0190 if (ret && suspend)
0191 goto fail_child;
0192 }
0193
0194 nvif_debug(object, "%s running...\n", action);
0195 if (object->func->fini) {
0196 ret = object->func->fini(object, suspend);
0197 if (ret) {
0198 nvif_error(object, "%s failed with %d\n", action, ret);
0199 if (suspend)
0200 goto fail;
0201 }
0202 }
0203
0204 time = ktime_to_us(ktime_get()) - time;
0205 nvif_debug(object, "%s completed in %lldus\n", action, time);
0206 return 0;
0207
0208 fail:
0209 if (object->func->init) {
0210 int rret = object->func->init(object);
0211 if (rret)
0212 nvif_fatal(object, "failed to restart, %d\n", rret);
0213 }
0214 fail_child:
0215 list_for_each_entry_continue_reverse(child, &object->tree, head) {
0216 nvkm_object_init(child);
0217 }
0218 return ret;
0219 }
0220
0221 int
0222 nvkm_object_init(struct nvkm_object *object)
0223 {
0224 struct nvkm_object *child;
0225 s64 time;
0226 int ret;
0227
0228 nvif_debug(object, "init running...\n");
0229 time = ktime_to_us(ktime_get());
0230 if (object->func->init) {
0231 ret = object->func->init(object);
0232 if (ret)
0233 goto fail;
0234 }
0235
0236 nvif_debug(object, "init children...\n");
0237 list_for_each_entry(child, &object->tree, head) {
0238 ret = nvkm_object_init(child);
0239 if (ret)
0240 goto fail_child;
0241 }
0242
0243 time = ktime_to_us(ktime_get()) - time;
0244 nvif_debug(object, "init completed in %lldus\n", time);
0245 return 0;
0246
0247 fail_child:
0248 list_for_each_entry_continue_reverse(child, &object->tree, head)
0249 nvkm_object_fini(child, false);
0250 fail:
0251 nvif_error(object, "init failed with %d\n", ret);
0252 if (object->func->fini)
0253 object->func->fini(object, false);
0254 return ret;
0255 }
0256
0257 void *
0258 nvkm_object_dtor(struct nvkm_object *object)
0259 {
0260 struct nvkm_object *child, *ctemp;
0261 void *data = object;
0262 s64 time;
0263
0264 nvif_debug(object, "destroy children...\n");
0265 time = ktime_to_us(ktime_get());
0266 list_for_each_entry_safe(child, ctemp, &object->tree, head) {
0267 nvkm_object_del(&child);
0268 }
0269
0270 nvif_debug(object, "destroy running...\n");
0271 nvkm_object_unmap(object);
0272 if (object->func->dtor)
0273 data = object->func->dtor(object);
0274 nvkm_engine_unref(&object->engine);
0275 time = ktime_to_us(ktime_get()) - time;
0276 nvif_debug(object, "destroy completed in %lldus...\n", time);
0277 return data;
0278 }
0279
0280 void
0281 nvkm_object_del(struct nvkm_object **pobject)
0282 {
0283 struct nvkm_object *object = *pobject;
0284 if (object && !WARN_ON(!object->func)) {
0285 *pobject = nvkm_object_dtor(object);
0286 nvkm_object_remove(object);
0287 list_del(&object->head);
0288 kfree(*pobject);
0289 *pobject = NULL;
0290 }
0291 }
0292
0293 void
0294 nvkm_object_ctor(const struct nvkm_object_func *func,
0295 const struct nvkm_oclass *oclass, struct nvkm_object *object)
0296 {
0297 object->func = func;
0298 object->client = oclass->client;
0299 object->engine = nvkm_engine_ref(oclass->engine);
0300 object->oclass = oclass->base.oclass;
0301 object->handle = oclass->handle;
0302 object->route = oclass->route;
0303 object->token = oclass->token;
0304 object->object = oclass->object;
0305 INIT_LIST_HEAD(&object->head);
0306 INIT_LIST_HEAD(&object->tree);
0307 RB_CLEAR_NODE(&object->node);
0308 WARN_ON(IS_ERR(object->engine));
0309 }
0310
0311 int
0312 nvkm_object_new_(const struct nvkm_object_func *func,
0313 const struct nvkm_oclass *oclass, void *data, u32 size,
0314 struct nvkm_object **pobject)
0315 {
0316 if (size == 0) {
0317 if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL)))
0318 return -ENOMEM;
0319 nvkm_object_ctor(func, oclass, *pobject);
0320 return 0;
0321 }
0322 return -ENOSYS;
0323 }
0324
0325 static const struct nvkm_object_func
0326 nvkm_object_func = {
0327 };
0328
0329 int
0330 nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
0331 struct nvkm_object **pobject)
0332 {
0333 const struct nvkm_object_func *func =
0334 oclass->base.func ? oclass->base.func : &nvkm_object_func;
0335 return nvkm_object_new_(func, oclass, data, size, pobject);
0336 }