brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 390c265 Raw
301 lines · c
1/*2 * Copyright 2012 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Ben Skeggs23 */24#include <core/object.h>25#include <core/client.h>26#include <core/engine.h>27 28struct nvkm_object *29nvkm_object_search(struct nvkm_client *client, u64 handle,30		   const struct nvkm_object_func *func)31{32	struct nvkm_object *object;33	unsigned long flags;34 35	if (handle) {36		spin_lock_irqsave(&client->obj_lock, flags);37		struct rb_node *node = client->objroot.rb_node;38		while (node) {39			object = rb_entry(node, typeof(*object), node);40			if (handle < object->object)41				node = node->rb_left;42			else43			if (handle > object->object)44				node = node->rb_right;45			else {46				spin_unlock_irqrestore(&client->obj_lock, flags);47				goto done;48			}49		}50		spin_unlock_irqrestore(&client->obj_lock, flags);51		return ERR_PTR(-ENOENT);52	} else {53		object = &client->object;54	}55 56done:57	if (unlikely(func && object->func != func))58		return ERR_PTR(-EINVAL);59	return object;60}61 62void63nvkm_object_remove(struct nvkm_object *object)64{65	unsigned long flags;66 67	spin_lock_irqsave(&object->client->obj_lock, flags);68	if (!RB_EMPTY_NODE(&object->node))69		rb_erase(&object->node, &object->client->objroot);70	spin_unlock_irqrestore(&object->client->obj_lock, flags);71}72 73bool74nvkm_object_insert(struct nvkm_object *object)75{76	struct rb_node **ptr;77	struct rb_node *parent = NULL;78	unsigned long flags;79 80	spin_lock_irqsave(&object->client->obj_lock, flags);81	ptr = &object->client->objroot.rb_node;82	while (*ptr) {83		struct nvkm_object *this = rb_entry(*ptr, typeof(*this), node);84		parent = *ptr;85		if (object->object < this->object) {86			ptr = &parent->rb_left;87		} else if (object->object > this->object) {88			ptr = &parent->rb_right;89		} else {90			spin_unlock_irqrestore(&object->client->obj_lock, flags);91			return false;92		}93	}94 95	rb_link_node(&object->node, parent, ptr);96	rb_insert_color(&object->node, &object->client->objroot);97	spin_unlock_irqrestore(&object->client->obj_lock, flags);98	return true;99}100 101int102nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)103{104	if (likely(object->func->mthd))105		return object->func->mthd(object, mthd, data, size);106	return -ENODEV;107}108 109int110nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,111		 struct nvkm_event **pevent)112{113	if (likely(object->func->ntfy))114		return object->func->ntfy(object, mthd, pevent);115	return -ENODEV;116}117 118int119nvkm_object_map(struct nvkm_object *object, void *argv, u32 argc,120		enum nvkm_object_map *type, u64 *addr, u64 *size)121{122	if (likely(object->func->map))123		return object->func->map(object, argv, argc, type, addr, size);124	return -ENODEV;125}126 127int128nvkm_object_unmap(struct nvkm_object *object)129{130	if (likely(object->func->unmap))131		return object->func->unmap(object);132	return -ENODEV;133}134 135int136nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,137		 int align, struct nvkm_gpuobj **pgpuobj)138{139	if (object->func->bind)140		return object->func->bind(object, gpuobj, align, pgpuobj);141	return -ENODEV;142}143 144int145nvkm_object_fini(struct nvkm_object *object, bool suspend)146{147	const char *action = suspend ? "suspend" : "fini";148	struct nvkm_object *child;149	s64 time;150	int ret;151 152	nvif_debug(object, "%s children...\n", action);153	time = ktime_to_us(ktime_get());154	list_for_each_entry_reverse(child, &object->tree, head) {155		ret = nvkm_object_fini(child, suspend);156		if (ret && suspend)157			goto fail_child;158	}159 160	nvif_debug(object, "%s running...\n", action);161	if (object->func->fini) {162		ret = object->func->fini(object, suspend);163		if (ret) {164			nvif_error(object, "%s failed with %d\n", action, ret);165			if (suspend)166				goto fail;167		}168	}169 170	time = ktime_to_us(ktime_get()) - time;171	nvif_debug(object, "%s completed in %lldus\n", action, time);172	return 0;173 174fail:175	if (object->func->init) {176		int rret = object->func->init(object);177		if (rret)178			nvif_fatal(object, "failed to restart, %d\n", rret);179	}180fail_child:181	list_for_each_entry_continue_reverse(child, &object->tree, head) {182		nvkm_object_init(child);183	}184	return ret;185}186 187int188nvkm_object_init(struct nvkm_object *object)189{190	struct nvkm_object *child;191	s64 time;192	int ret;193 194	nvif_debug(object, "init running...\n");195	time = ktime_to_us(ktime_get());196	if (object->func->init) {197		ret = object->func->init(object);198		if (ret)199			goto fail;200	}201 202	nvif_debug(object, "init children...\n");203	list_for_each_entry(child, &object->tree, head) {204		ret = nvkm_object_init(child);205		if (ret)206			goto fail_child;207	}208 209	time = ktime_to_us(ktime_get()) - time;210	nvif_debug(object, "init completed in %lldus\n", time);211	return 0;212 213fail_child:214	list_for_each_entry_continue_reverse(child, &object->tree, head)215		nvkm_object_fini(child, false);216fail:217	nvif_error(object, "init failed with %d\n", ret);218	if (object->func->fini)219		object->func->fini(object, false);220	return ret;221}222 223void *224nvkm_object_dtor(struct nvkm_object *object)225{226	struct nvkm_object *child, *ctemp;227	void *data = object;228	s64 time;229 230	nvif_debug(object, "destroy children...\n");231	time = ktime_to_us(ktime_get());232	list_for_each_entry_safe(child, ctemp, &object->tree, head) {233		nvkm_object_del(&child);234	}235 236	nvif_debug(object, "destroy running...\n");237	nvkm_object_unmap(object);238	if (object->func->dtor)239		data = object->func->dtor(object);240	nvkm_engine_unref(&object->engine);241	time = ktime_to_us(ktime_get()) - time;242	nvif_debug(object, "destroy completed in %lldus...\n", time);243	return data;244}245 246void247nvkm_object_del(struct nvkm_object **pobject)248{249	struct nvkm_object *object = *pobject;250	if (object && !WARN_ON(!object->func)) {251		*pobject = nvkm_object_dtor(object);252		nvkm_object_remove(object);253		list_del(&object->head);254		kfree(*pobject);255		*pobject = NULL;256	}257}258 259void260nvkm_object_ctor(const struct nvkm_object_func *func,261		 const struct nvkm_oclass *oclass, struct nvkm_object *object)262{263	object->func = func;264	object->client = oclass->client;265	object->engine = nvkm_engine_ref(oclass->engine);266	object->oclass = oclass->base.oclass;267	object->handle = oclass->handle;268	object->object = oclass->object;269	INIT_LIST_HEAD(&object->head);270	INIT_LIST_HEAD(&object->tree);271	RB_CLEAR_NODE(&object->node);272	WARN_ON(IS_ERR(object->engine));273}274 275int276nvkm_object_new_(const struct nvkm_object_func *func,277		 const struct nvkm_oclass *oclass, void *data, u32 size,278		 struct nvkm_object **pobject)279{280	if (size == 0) {281		if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL)))282			return -ENOMEM;283		nvkm_object_ctor(func, oclass, *pobject);284		return 0;285	}286	return -ENOSYS;287}288 289static const struct nvkm_object_func290nvkm_object_func = {291};292 293int294nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,295		struct nvkm_object **pobject)296{297	const struct nvkm_object_func *func =298		oclass->base.func ? oclass->base.func : &nvkm_object_func;299	return nvkm_object_new_(func, oclass, data, size, pobject);300}301