diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 14:54:17 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 12:37:39 +1000 |
commit | b9977d2d78f05350be659cb2b76d5e9f455099e5 (patch) | |
tree | d9c28e548d431d4d4233ad182795af2f6f1fe2e3 /drm/nouveau/nvkm/core | |
parent | 541f14853e44c2934afd49c597b36768823ee84d (diff) | |
download | nouveau-b9977d2d78f05350be659cb2b76d5e9f455099e5.tar.gz |
ramht: remove dependence on namedb
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drm/nouveau/nvkm/core')
-rw-r--r-- | drm/nouveau/nvkm/core/ramht.c | 157 |
1 files changed, 113 insertions, 44 deletions
diff --git a/drm/nouveau/nvkm/core/ramht.c b/drm/nouveau/nvkm/core/ramht.c index 061adedc6..307d53269 100644 --- a/drm/nouveau/nvkm/core/ramht.c +++ b/drm/nouveau/nvkm/core/ramht.c @@ -33,74 +33,143 @@ nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) } hash ^= chid << (ramht->bits - 4); - hash = hash << 3; return hash; } -int -nvkm_ramht_insert(struct nvkm_ramht *ramht, int chid, u32 handle, u32 context) +struct nvkm_gpuobj * +nvkm_ramht_search(struct nvkm_ramht *ramht, int chid, u32 handle) { - struct nvkm_gpuobj *gpuobj = &ramht->gpuobj; - int ret = -ENOSPC; u32 co, ho; co = ho = nvkm_ramht_hash(ramht, chid, handle); - nvkm_kmap(gpuobj); do { - if (!nvkm_ro32(gpuobj, co + 4)) { - nvkm_wo32(gpuobj, co + 0, handle); - nvkm_wo32(gpuobj, co + 4, context); - ret = co; - break; + if (ramht->data[co].chid == chid) { + if (ramht->data[co].handle == handle) + return ramht->data[co].inst; } - co += 8; - if (co >= nv_gpuobj(ramht)->size) + if (++co >= ramht->size) co = 0; } while (co != ho); - nvkm_done(gpuobj); - return ret; + return NULL; +} + +static int +nvkm_ramht_update(struct nvkm_ramht *ramht, int co, struct nvkm_object *object, + int chid, int addr, u32 handle, u32 context) +{ + struct nvkm_ramht_data *data = &ramht->data[co]; + u64 inst = 0x00000040; /* just non-zero for <=g8x fifo ramht */ + int ret; + + nvkm_gpuobj_del(&data->inst); + data->chid = chid; + data->handle = handle; + + if (!object) { + inst = 0; + goto done; + } + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) { + struct nvkm_gpuobj *gpuobj = nv_gpuobj(object); + if (ramht->device->card_type >= NV_50) + inst = gpuobj->node->offset; + else + inst = gpuobj->addr; + goto done; + } + + ret = nvkm_object_bind(object, ramht->parent, 16, &data->inst); + if (ret) { + if (ret != -ENODEV) { + data->chid = -1; + return ret; + } + data->inst = NULL; + } + + if (data->inst) { + if (ramht->device->card_type >= NV_50) + inst = data->inst->node->offset; + else + inst = data->inst->addr; + } + +done: + if (addr < 0) context |= inst << -addr; + else context |= inst >> addr; + + nvkm_kmap(ramht->gpuobj); + nvkm_wo32(ramht->gpuobj, (co << 3) + 0, handle); + nvkm_wo32(ramht->gpuobj, (co << 3) + 4, context); + nvkm_done(ramht->gpuobj); + return co + 1; } void nvkm_ramht_remove(struct nvkm_ramht *ramht, int cookie) { - struct nvkm_gpuobj *gpuobj = &ramht->gpuobj; - nvkm_kmap(gpuobj); - nvkm_wo32(gpuobj, cookie + 0, 0x00000000); - nvkm_wo32(gpuobj, cookie + 4, 0x00000000); - nvkm_done(gpuobj); + if (--cookie >= 0) + nvkm_ramht_update(ramht, cookie, NULL, -1, 0, 0, 0); } -static struct nvkm_oclass -nvkm_ramht_oclass = { - .handle = 0x0000abcd, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = NULL, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, - }, -}; +int +nvkm_ramht_insert(struct nvkm_ramht *ramht, struct nvkm_object *object, + int chid, int addr, u32 handle, u32 context) +{ + u32 co, ho; + + if (nvkm_ramht_search(ramht, chid, handle)) + return -EEXIST; + + co = ho = nvkm_ramht_hash(ramht, chid, handle); + do { + if (ramht->data[co].chid < 0) { + return nvkm_ramht_update(ramht, co, object, chid, + addr, handle, context); + } + + if (++co >= ramht->size) + co = 0; + } while (co != ho); + + return -ENOSPC; +} + +void +nvkm_ramht_del(struct nvkm_ramht **pramht) +{ + struct nvkm_ramht *ramht = *pramht; + if (ramht) { + nvkm_gpuobj_del(&ramht->gpuobj); + kfree(*pramht); + *pramht = NULL; + } +} int -nvkm_ramht_new(struct nvkm_object *parent, struct nvkm_object *pargpu, - u32 size, u32 align, struct nvkm_ramht **pramht) +nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align, + struct nvkm_gpuobj *parent, struct nvkm_ramht **pramht) { struct nvkm_ramht *ramht; - int ret; + int ret, i; - ret = nvkm_gpuobj_create(parent, parent->engine ? - &parent->engine->subdev.object : NULL, /* <nv50 ramht */ - &nvkm_ramht_oclass, 0, pargpu, size, - align, NVOBJ_FLAG_ZERO_ALLOC, &ramht); - *pramht = ramht; - if (ret) - return ret; + if (!(ramht = *pramht = kzalloc(sizeof(*ramht) + (size >> 3) * + sizeof(*ramht->data), GFP_KERNEL))) + return -ENOMEM; + + ramht->device = device; + ramht->parent = parent; + ramht->size = size >> 3; + ramht->bits = order_base_2(ramht->size); + for (i = 0; i < ramht->size; i++) + ramht->data[i].chid = -1; - ramht->bits = order_base_2(nv_gpuobj(ramht)->size >> 3); - return 0; + ret = nvkm_gpuobj_new(ramht->device, size, align, true, + ramht->parent, &ramht->gpuobj); + if (ret) + nvkm_ramht_del(pramht); + return ret; } |