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 #include <core/ramht.h>
0023 #include <core/engine.h>
0024 #include <core/object.h>
0025 
0026 static u32
0027 nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle)
0028 {
0029     u32 hash = 0;
0030 
0031     while (handle) {
0032         hash ^= (handle & ((1 << ramht->bits) - 1));
0033         handle >>= ramht->bits;
0034     }
0035 
0036     hash ^= chid << (ramht->bits - 4);
0037     return hash;
0038 }
0039 
0040 struct nvkm_gpuobj *
0041 nvkm_ramht_search(struct nvkm_ramht *ramht, int chid, u32 handle)
0042 {
0043     u32 co, ho;
0044 
0045     co = ho = nvkm_ramht_hash(ramht, chid, handle);
0046     do {
0047         if (ramht->data[co].chid == chid) {
0048             if (ramht->data[co].handle == handle)
0049                 return ramht->data[co].inst;
0050         }
0051 
0052         if (++co >= ramht->size)
0053             co = 0;
0054     } while (co != ho);
0055 
0056     return NULL;
0057 }
0058 
0059 static int
0060 nvkm_ramht_update(struct nvkm_ramht *ramht, int co, struct nvkm_object *object,
0061           int chid, int addr, u32 handle, u32 context)
0062 {
0063     struct nvkm_ramht_data *data = &ramht->data[co];
0064     u64 inst = 0x00000040; /* just non-zero for <=g8x fifo ramht */
0065     int ret;
0066 
0067     nvkm_gpuobj_del(&data->inst);
0068     data->chid = chid;
0069     data->handle = handle;
0070 
0071     if (object) {
0072         ret = nvkm_object_bind(object, ramht->parent, 16, &data->inst);
0073         if (ret) {
0074             if (ret != -ENODEV) {
0075                 data->chid = -1;
0076                 return ret;
0077             }
0078             data->inst = NULL;
0079         }
0080 
0081         if (data->inst) {
0082             if (ramht->device->card_type >= NV_50)
0083                 inst = data->inst->node->offset;
0084             else
0085                 inst = data->inst->addr;
0086         }
0087 
0088         if (addr < 0) context |= inst << -addr;
0089         else          context |= inst >>  addr;
0090     }
0091 
0092     nvkm_kmap(ramht->gpuobj);
0093     nvkm_wo32(ramht->gpuobj, (co << 3) + 0, handle);
0094     nvkm_wo32(ramht->gpuobj, (co << 3) + 4, context);
0095     nvkm_done(ramht->gpuobj);
0096     return co + 1;
0097 }
0098 
0099 void
0100 nvkm_ramht_remove(struct nvkm_ramht *ramht, int cookie)
0101 {
0102     if (--cookie >= 0)
0103         nvkm_ramht_update(ramht, cookie, NULL, -1, 0, 0, 0);
0104 }
0105 
0106 int
0107 nvkm_ramht_insert(struct nvkm_ramht *ramht, struct nvkm_object *object,
0108           int chid, int addr, u32 handle, u32 context)
0109 {
0110     u32 co, ho;
0111 
0112     if (nvkm_ramht_search(ramht, chid, handle))
0113         return -EEXIST;
0114 
0115     co = ho = nvkm_ramht_hash(ramht, chid, handle);
0116     do {
0117         if (ramht->data[co].chid < 0) {
0118             return nvkm_ramht_update(ramht, co, object, chid,
0119                          addr, handle, context);
0120         }
0121 
0122         if (++co >= ramht->size)
0123             co = 0;
0124     } while (co != ho);
0125 
0126     return -ENOSPC;
0127 }
0128 
0129 void
0130 nvkm_ramht_del(struct nvkm_ramht **pramht)
0131 {
0132     struct nvkm_ramht *ramht = *pramht;
0133     if (ramht) {
0134         nvkm_gpuobj_del(&ramht->gpuobj);
0135         vfree(*pramht);
0136         *pramht = NULL;
0137     }
0138 }
0139 
0140 int
0141 nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align,
0142            struct nvkm_gpuobj *parent, struct nvkm_ramht **pramht)
0143 {
0144     struct nvkm_ramht *ramht;
0145     int ret, i;
0146 
0147     if (!(ramht = *pramht = vzalloc(struct_size(ramht, data, (size >> 3)))))
0148         return -ENOMEM;
0149 
0150     ramht->device = device;
0151     ramht->parent = parent;
0152     ramht->size = size >> 3;
0153     ramht->bits = order_base_2(ramht->size);
0154     for (i = 0; i < ramht->size; i++)
0155         ramht->data[i].chid = -1;
0156 
0157     ret = nvkm_gpuobj_new(ramht->device, size, align, true,
0158                   ramht->parent, &ramht->gpuobj);
0159     if (ret)
0160         nvkm_ramht_del(pramht);
0161     return ret;
0162 }