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