Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
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 }