1/* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * 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 OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24#include <core/namedb.h> 25#include <core/gpuobj.h> 26#include <core/handle.h> 27 28static struct nvkm_handle * 29nvkm_namedb_lookup(struct nvkm_namedb *namedb, u32 name) 30{ 31 struct nvkm_handle *handle; 32 33 list_for_each_entry(handle, &namedb->list, node) { 34 if (handle->name == name) 35 return handle; 36 } 37 38 return NULL; 39} 40 41static struct nvkm_handle * 42nvkm_namedb_lookup_class(struct nvkm_namedb *namedb, u16 oclass) 43{ 44 struct nvkm_handle *handle; 45 46 list_for_each_entry(handle, &namedb->list, node) { 47 if (nv_mclass(handle->object) == oclass) 48 return handle; 49 } 50 51 return NULL; 52} 53 54static struct nvkm_handle * 55nvkm_namedb_lookup_vinst(struct nvkm_namedb *namedb, u64 vinst) 56{ 57 struct nvkm_handle *handle; 58 59 list_for_each_entry(handle, &namedb->list, node) { 60 if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { 61 if (nv_gpuobj(handle->object)->addr == vinst) 62 return handle; 63 } 64 } 65 66 return NULL; 67} 68 69static struct nvkm_handle * 70nvkm_namedb_lookup_cinst(struct nvkm_namedb *namedb, u32 cinst) 71{ 72 struct nvkm_handle *handle; 73 74 list_for_each_entry(handle, &namedb->list, node) { 75 if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { 76 if (nv_gpuobj(handle->object)->node && 77 nv_gpuobj(handle->object)->node->offset == cinst) 78 return handle; 79 } 80 } 81 82 return NULL; 83} 84 85int 86nvkm_namedb_insert(struct nvkm_namedb *namedb, u32 name, 87 struct nvkm_object *object, 88 struct nvkm_handle *handle) 89{ 90 int ret = -EEXIST; 91 write_lock_irq(&namedb->lock); 92 if (!nvkm_namedb_lookup(namedb, name)) { 93 nvkm_object_ref(object, &handle->object); 94 handle->namedb = namedb; 95 list_add(&handle->node, &namedb->list); 96 ret = 0; 97 } 98 write_unlock_irq(&namedb->lock); 99 return ret; 100} 101 102void 103nvkm_namedb_remove(struct nvkm_handle *handle) 104{ 105 struct nvkm_namedb *namedb = handle->namedb; 106 struct nvkm_object *object = handle->object; 107 write_lock_irq(&namedb->lock); 108 list_del(&handle->node); 109 write_unlock_irq(&namedb->lock); 110 nvkm_object_ref(NULL, &object); 111} 112 113struct nvkm_handle * 114nvkm_namedb_get(struct nvkm_namedb *namedb, u32 name) 115{ 116 struct nvkm_handle *handle; 117 read_lock(&namedb->lock); 118 handle = nvkm_namedb_lookup(namedb, name); 119 if (handle == NULL) 120 read_unlock(&namedb->lock); 121 return handle; 122} 123 124struct nvkm_handle * 125nvkm_namedb_get_class(struct nvkm_namedb *namedb, u16 oclass) 126{ 127 struct nvkm_handle *handle; 128 read_lock(&namedb->lock); 129 handle = nvkm_namedb_lookup_class(namedb, oclass); 130 if (handle == NULL) 131 read_unlock(&namedb->lock); 132 return handle; 133} 134 135struct nvkm_handle * 136nvkm_namedb_get_vinst(struct nvkm_namedb *namedb, u64 vinst) 137{ 138 struct nvkm_handle *handle; 139 read_lock(&namedb->lock); 140 handle = nvkm_namedb_lookup_vinst(namedb, vinst); 141 if (handle == NULL) 142 read_unlock(&namedb->lock); 143 return handle; 144} 145 146struct nvkm_handle * 147nvkm_namedb_get_cinst(struct nvkm_namedb *namedb, u32 cinst) 148{ 149 struct nvkm_handle *handle; 150 read_lock(&namedb->lock); 151 handle = nvkm_namedb_lookup_cinst(namedb, cinst); 152 if (handle == NULL) 153 read_unlock(&namedb->lock); 154 return handle; 155} 156 157void 158nvkm_namedb_put(struct nvkm_handle *handle) 159{ 160 if (handle) 161 read_unlock(&handle->namedb->lock); 162} 163 164int 165nvkm_namedb_create_(struct nvkm_object *parent, struct nvkm_object *engine, 166 struct nvkm_oclass *oclass, u32 pclass, 167 struct nvkm_oclass *sclass, u64 engcls, 168 int length, void **pobject) 169{ 170 struct nvkm_namedb *namedb; 171 int ret; 172 173 ret = nvkm_parent_create_(parent, engine, oclass, pclass | 174 NV_NAMEDB_CLASS, sclass, engcls, 175 length, pobject); 176 namedb = *pobject; 177 if (ret) 178 return ret; 179 180 rwlock_init(&namedb->lock); 181 INIT_LIST_HEAD(&namedb->list); 182 return 0; 183} 184 185int 186_nvkm_namedb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 187 struct nvkm_oclass *oclass, void *data, u32 size, 188 struct nvkm_object **pobject) 189{ 190 struct nvkm_namedb *object; 191 int ret; 192 193 ret = nvkm_namedb_create(parent, engine, oclass, 0, NULL, 0, &object); 194 *pobject = nv_object(object); 195 if (ret) 196 return ret; 197 198 return 0; 199} 200