Commit | Line | Data |
---|---|---|
479dcaea | 1 | /* |
ebb945a9 | 2 | * Copyright 2012 Red Hat Inc. |
479dcaea BS |
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. | |
479dcaea | 21 | */ |
02a841d4 | 22 | #include <core/ramht.h> |
245dcfe9 | 23 | #include <core/engine.h> |
ebb945a9 | 24 | |
dac79008 | 25 | static u32 |
5025407b | 26 | nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) |
479dcaea | 27 | { |
dac79008 | 28 | u32 hash = 0; |
479dcaea | 29 | |
ebb945a9 | 30 | while (handle) { |
e05c5a31 BS |
31 | hash ^= (handle & ((1 << ramht->bits) - 1)); |
32 | handle >>= ramht->bits; | |
479dcaea BS |
33 | } |
34 | ||
ebb945a9 | 35 | hash ^= chid << (ramht->bits - 4); |
479dcaea BS |
36 | return hash; |
37 | } | |
38 | ||
1d2a1e53 BS |
39 | struct nvkm_gpuobj * |
40 | nvkm_ramht_search(struct nvkm_ramht *ramht, int chid, u32 handle) | |
479dcaea | 41 | { |
ebb945a9 | 42 | u32 co, ho; |
dac79008 | 43 | |
5025407b | 44 | co = ho = nvkm_ramht_hash(ramht, chid, handle); |
479dcaea | 45 | do { |
1d2a1e53 BS |
46 | if (ramht->data[co].chid == chid) { |
47 | if (ramht->data[co].handle == handle) | |
48 | return ramht->data[co].inst; | |
479dcaea | 49 | } |
479dcaea | 50 | |
1d2a1e53 | 51 | if (++co >= ramht->size) |
479dcaea BS |
52 | co = 0; |
53 | } while (co != ho); | |
54 | ||
1d2a1e53 BS |
55 | return NULL; |
56 | } | |
57 | ||
58 | static int | |
59 | nvkm_ramht_update(struct nvkm_ramht *ramht, int co, struct nvkm_object *object, | |
60 | int chid, int addr, u32 handle, u32 context) | |
61 | { | |
62 | struct nvkm_ramht_data *data = &ramht->data[co]; | |
63 | u64 inst = 0x00000040; /* just non-zero for <=g8x fifo ramht */ | |
64 | int ret; | |
65 | ||
66 | nvkm_gpuobj_del(&data->inst); | |
67 | data->chid = chid; | |
68 | data->handle = handle; | |
69 | ||
68f3f702 BS |
70 | if (object) { |
71 | ret = nvkm_object_bind(object, ramht->parent, 16, &data->inst); | |
72 | if (ret) { | |
73 | if (ret != -ENODEV) { | |
74 | data->chid = -1; | |
75 | return ret; | |
76 | } | |
77 | data->inst = NULL; | |
78 | } | |
1d2a1e53 | 79 | |
68f3f702 BS |
80 | if (data->inst) { |
81 | if (ramht->device->card_type >= NV_50) | |
82 | inst = data->inst->node->offset; | |
83 | else | |
84 | inst = data->inst->addr; | |
1d2a1e53 | 85 | } |
1d2a1e53 | 86 | |
68f3f702 BS |
87 | if (addr < 0) context |= inst << -addr; |
88 | else context |= inst >> addr; | |
1d2a1e53 BS |
89 | } |
90 | ||
1d2a1e53 BS |
91 | nvkm_kmap(ramht->gpuobj); |
92 | nvkm_wo32(ramht->gpuobj, (co << 3) + 0, handle); | |
93 | nvkm_wo32(ramht->gpuobj, (co << 3) + 4, context); | |
94 | nvkm_done(ramht->gpuobj); | |
95 | return co + 1; | |
479dcaea BS |
96 | } |
97 | ||
ebb945a9 | 98 | void |
5025407b | 99 | nvkm_ramht_remove(struct nvkm_ramht *ramht, int cookie) |
dac79008 | 100 | { |
1d2a1e53 BS |
101 | if (--cookie >= 0) |
102 | nvkm_ramht_update(ramht, cookie, NULL, -1, 0, 0, 0); | |
dac79008 BS |
103 | } |
104 | ||
1d2a1e53 BS |
105 | int |
106 | nvkm_ramht_insert(struct nvkm_ramht *ramht, struct nvkm_object *object, | |
107 | int chid, int addr, u32 handle, u32 context) | |
108 | { | |
109 | u32 co, ho; | |
110 | ||
111 | if (nvkm_ramht_search(ramht, chid, handle)) | |
112 | return -EEXIST; | |
113 | ||
114 | co = ho = nvkm_ramht_hash(ramht, chid, handle); | |
115 | do { | |
116 | if (ramht->data[co].chid < 0) { | |
117 | return nvkm_ramht_update(ramht, co, object, chid, | |
118 | addr, handle, context); | |
119 | } | |
120 | ||
121 | if (++co >= ramht->size) | |
122 | co = 0; | |
123 | } while (co != ho); | |
124 | ||
125 | return -ENOSPC; | |
126 | } | |
127 | ||
128 | void | |
129 | nvkm_ramht_del(struct nvkm_ramht **pramht) | |
130 | { | |
131 | struct nvkm_ramht *ramht = *pramht; | |
132 | if (ramht) { | |
133 | nvkm_gpuobj_del(&ramht->gpuobj); | |
78a121d8 | 134 | vfree(*pramht); |
1d2a1e53 BS |
135 | *pramht = NULL; |
136 | } | |
137 | } | |
a8eaebc6 BS |
138 | |
139 | int | |
1d2a1e53 BS |
140 | nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align, |
141 | struct nvkm_gpuobj *parent, struct nvkm_ramht **pramht) | |
a8eaebc6 | 142 | { |
5025407b | 143 | struct nvkm_ramht *ramht; |
1d2a1e53 | 144 | int ret, i; |
a8eaebc6 | 145 | |
78a121d8 IM |
146 | if (!(ramht = *pramht = vzalloc(sizeof(*ramht) + |
147 | (size >> 3) * sizeof(*ramht->data)))) | |
1d2a1e53 BS |
148 | return -ENOMEM; |
149 | ||
150 | ramht->device = device; | |
151 | ramht->parent = parent; | |
152 | ramht->size = size >> 3; | |
153 | ramht->bits = order_base_2(ramht->size); | |
154 | for (i = 0; i < ramht->size; i++) | |
155 | ramht->data[i].chid = -1; | |
a8eaebc6 | 156 | |
1d2a1e53 BS |
157 | ret = nvkm_gpuobj_new(ramht->device, size, align, true, |
158 | ramht->parent, &ramht->gpuobj); | |
159 | if (ret) | |
160 | nvkm_ramht_del(pramht); | |
161 | return ret; | |
479dcaea | 162 | } |