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/parent.h> 25#include <core/client.h> 26#include <core/engine.h> 27 28int 29nvkm_parent_sclass(struct nvkm_object *parent, u16 handle, 30 struct nvkm_object **pengine, 31 struct nvkm_oclass **poclass) 32{ 33 struct nvkm_sclass *sclass; 34 struct nvkm_engine *engine; 35 struct nvkm_oclass *oclass; 36 u64 mask; 37 38 sclass = nv_parent(parent)->sclass; 39 while (sclass) { 40 if ((sclass->oclass->handle & 0xffff) == handle) { 41 *pengine = &parent->engine->subdev.object; 42 *poclass = sclass->oclass; 43 return 0; 44 } 45 46 sclass = sclass->sclass; 47 } 48 49 mask = nv_parent(parent)->engine; 50 while (mask) { 51 int i = __ffs64(mask); 52 53 if (nv_iclass(parent, NV_CLIENT_CLASS)) 54 engine = nv_engine(nv_client(parent)->device); 55 else 56 engine = nvkm_engine(parent, i); 57 58 if (engine) { 59 oclass = engine->sclass; 60 while (oclass->ofuncs) { 61 if ((oclass->handle & 0xffff) == handle) { 62 *pengine = nv_object(engine); 63 *poclass = oclass; 64 return 0; 65 } 66 oclass++; 67 } 68 } 69 70 mask &= ~(1ULL << i); 71 } 72 73 return -EINVAL; 74} 75 76int 77nvkm_parent_lclass(struct nvkm_object *parent, u32 *lclass, int size) 78{ 79 struct nvkm_sclass *sclass; 80 struct nvkm_engine *engine; 81 struct nvkm_oclass *oclass; 82 int nr = -1, i; 83 u64 mask; 84 85 sclass = nv_parent(parent)->sclass; 86 while (sclass) { 87 if (++nr < size) 88 lclass[nr] = sclass->oclass->handle & 0xffff; 89 sclass = sclass->sclass; 90 } 91 92 mask = nv_parent(parent)->engine; 93 while (i = __ffs64(mask), mask) { 94 engine = nvkm_engine(parent, i); 95 if (engine && (oclass = engine->sclass)) { 96 while (oclass->ofuncs) { 97 if (++nr < size) 98 lclass[nr] = oclass->handle & 0xffff; 99 oclass++; 100 } 101 } 102 103 mask &= ~(1ULL << i); 104 } 105 106 return nr + 1; 107} 108 109int 110nvkm_parent_create_(struct nvkm_object *parent, struct nvkm_object *engine, 111 struct nvkm_oclass *oclass, u32 pclass, 112 struct nvkm_oclass *sclass, u64 engcls, 113 int size, void **pobject) 114{ 115 struct nvkm_parent *object; 116 struct nvkm_sclass *nclass; 117 int ret; 118 119 ret = nvkm_object_create_(parent, engine, oclass, pclass | 120 NV_PARENT_CLASS, size, pobject); 121 object = *pobject; 122 if (ret) 123 return ret; 124 125 while (sclass && sclass->ofuncs) { 126 nclass = kzalloc(sizeof(*nclass), GFP_KERNEL); 127 if (!nclass) 128 return -ENOMEM; 129 130 nclass->sclass = object->sclass; 131 object->sclass = nclass; 132 nclass->engine = engine ? nv_engine(engine) : NULL; 133 nclass->oclass = sclass; 134 sclass++; 135 } 136 137 object->engine = engcls; 138 return 0; 139} 140 141void 142nvkm_parent_destroy(struct nvkm_parent *parent) 143{ 144 struct nvkm_sclass *sclass; 145 146 while ((sclass = parent->sclass)) { 147 parent->sclass = sclass->sclass; 148 kfree(sclass); 149 } 150 151 nvkm_object_destroy(&parent->object); 152} 153 154 155void 156_nvkm_parent_dtor(struct nvkm_object *object) 157{ 158 nvkm_parent_destroy(nv_parent(object)); 159} 160