xref: /dflybsd-src/sys/dev/drm/drm_hashtab.c (revision 3f6063cc01b519b28ab36c05951d44c32dbf6a51)
1*3f6063ccSDavid Shao /**************************************************************************
2*3f6063ccSDavid Shao  *
3*3f6063ccSDavid Shao  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
4*3f6063ccSDavid Shao  * All Rights Reserved.
5*3f6063ccSDavid Shao  *
6*3f6063ccSDavid Shao  * Permission is hereby granted, free of charge, to any person obtaining a
7*3f6063ccSDavid Shao  * copy of this software and associated documentation files (the
8*3f6063ccSDavid Shao  * "Software"), to deal in the Software without restriction, including
9*3f6063ccSDavid Shao  * without limitation the rights to use, copy, modify, merge, publish,
10*3f6063ccSDavid Shao  * distribute, sub license, and/or sell copies of the Software, and to
11*3f6063ccSDavid Shao  * permit persons to whom the Software is furnished to do so, subject to
12*3f6063ccSDavid Shao  * the following conditions:
13*3f6063ccSDavid Shao  *
14*3f6063ccSDavid Shao  * The above copyright notice and this permission notice (including the
15*3f6063ccSDavid Shao  * next paragraph) shall be included in all copies or substantial portions
16*3f6063ccSDavid Shao  * of the Software.
17*3f6063ccSDavid Shao  *
18*3f6063ccSDavid Shao  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*3f6063ccSDavid Shao  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*3f6063ccSDavid Shao  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21*3f6063ccSDavid Shao  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22*3f6063ccSDavid Shao  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23*3f6063ccSDavid Shao  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24*3f6063ccSDavid Shao  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25*3f6063ccSDavid Shao  *
26*3f6063ccSDavid Shao  *
27*3f6063ccSDavid Shao  * __FBSDID("$FreeBSD: src/sys/dev/drm/drm_hashtab.c,v 1.1 2010/01/31 14:25:29 rnoland Exp $");
28*3f6063ccSDavid Shao  **************************************************************************/
29*3f6063ccSDavid Shao 
30*3f6063ccSDavid Shao /*
31*3f6063ccSDavid Shao  * Simple open hash tab implementation.
32*3f6063ccSDavid Shao  *
33*3f6063ccSDavid Shao  * Authors:
34*3f6063ccSDavid Shao  * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
35*3f6063ccSDavid Shao  */
36*3f6063ccSDavid Shao 
37*3f6063ccSDavid Shao #include "dev/drm/drmP.h"
38*3f6063ccSDavid Shao #include "dev/drm/drm_hashtab.h"
39*3f6063ccSDavid Shao 
40*3f6063ccSDavid Shao #if defined(__DragonFly__)
41*3f6063ccSDavid Shao #include "dev/drm/drm_priv_hash.h"
42*3f6063ccSDavid Shao #else
43*3f6063ccSDavid Shao #include <sys/hash.h>
44*3f6063ccSDavid Shao #endif
45*3f6063ccSDavid Shao 
46*3f6063ccSDavid Shao int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
47*3f6063ccSDavid Shao {
48*3f6063ccSDavid Shao 	ht->size = 1 << order;
49*3f6063ccSDavid Shao 	ht->order = order;
50*3f6063ccSDavid Shao 	ht->table = NULL;
51*3f6063ccSDavid Shao 	ht->table = drm_hashinit(ht->size, DRM_MEM_HASHTAB, &ht->mask);
52*3f6063ccSDavid Shao 	if (!ht->table) {
53*3f6063ccSDavid Shao 		DRM_ERROR("Out of memory for hash table\n");
54*3f6063ccSDavid Shao 		return -ENOMEM;
55*3f6063ccSDavid Shao 	}
56*3f6063ccSDavid Shao 	return 0;
57*3f6063ccSDavid Shao }
58*3f6063ccSDavid Shao 
59*3f6063ccSDavid Shao void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
60*3f6063ccSDavid Shao {
61*3f6063ccSDavid Shao 	struct drm_hash_item *entry;
62*3f6063ccSDavid Shao 	struct drm_hash_item_list *h_list;
63*3f6063ccSDavid Shao 	unsigned int hashed_key;
64*3f6063ccSDavid Shao 	int count = 0;
65*3f6063ccSDavid Shao 
66*3f6063ccSDavid Shao 	hashed_key = hash32_buf(&key, sizeof(key), ht->order);
67*3f6063ccSDavid Shao 	DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
68*3f6063ccSDavid Shao 	h_list = &ht->table[hashed_key & ht->mask];
69*3f6063ccSDavid Shao 	LIST_FOREACH(entry, h_list, head)
70*3f6063ccSDavid Shao 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
71*3f6063ccSDavid Shao }
72*3f6063ccSDavid Shao 
73*3f6063ccSDavid Shao static struct drm_hash_item *
74*3f6063ccSDavid Shao drm_ht_find_key(struct drm_open_hash *ht, unsigned long key)
75*3f6063ccSDavid Shao {
76*3f6063ccSDavid Shao 	struct drm_hash_item *entry;
77*3f6063ccSDavid Shao 	struct drm_hash_item_list *h_list;
78*3f6063ccSDavid Shao 	unsigned int hashed_key;
79*3f6063ccSDavid Shao 
80*3f6063ccSDavid Shao 	hashed_key = hash32_buf(&key, sizeof(key), ht->order);
81*3f6063ccSDavid Shao 	h_list = &ht->table[hashed_key & ht->mask];
82*3f6063ccSDavid Shao 	LIST_FOREACH(entry, h_list, head) {
83*3f6063ccSDavid Shao 		if (entry->key == key)
84*3f6063ccSDavid Shao 			return entry;
85*3f6063ccSDavid Shao 		if (entry->key > key)
86*3f6063ccSDavid Shao 			break;
87*3f6063ccSDavid Shao 	}
88*3f6063ccSDavid Shao 	return NULL;
89*3f6063ccSDavid Shao }
90*3f6063ccSDavid Shao 
91*3f6063ccSDavid Shao 
92*3f6063ccSDavid Shao int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
93*3f6063ccSDavid Shao {
94*3f6063ccSDavid Shao 	struct drm_hash_item *entry, *parent;
95*3f6063ccSDavid Shao 	struct drm_hash_item_list *h_list;
96*3f6063ccSDavid Shao 	unsigned int hashed_key;
97*3f6063ccSDavid Shao 	unsigned long key = item->key;
98*3f6063ccSDavid Shao 
99*3f6063ccSDavid Shao 	hashed_key = hash32_buf(&key, sizeof(key), ht->order);
100*3f6063ccSDavid Shao 	h_list = &ht->table[hashed_key & ht->mask];
101*3f6063ccSDavid Shao 	parent = NULL;
102*3f6063ccSDavid Shao 	LIST_FOREACH(entry, h_list, head) {
103*3f6063ccSDavid Shao 		if (entry->key == key)
104*3f6063ccSDavid Shao 			return -EINVAL;
105*3f6063ccSDavid Shao 		if (entry->key > key)
106*3f6063ccSDavid Shao 			break;
107*3f6063ccSDavid Shao 		parent = entry;
108*3f6063ccSDavid Shao 	}
109*3f6063ccSDavid Shao 	if (parent) {
110*3f6063ccSDavid Shao 		LIST_INSERT_AFTER(parent, item, head);
111*3f6063ccSDavid Shao 	} else {
112*3f6063ccSDavid Shao 		LIST_INSERT_HEAD(h_list, item, head);
113*3f6063ccSDavid Shao 	}
114*3f6063ccSDavid Shao 	return 0;
115*3f6063ccSDavid Shao }
116*3f6063ccSDavid Shao 
117*3f6063ccSDavid Shao /*
118*3f6063ccSDavid Shao  * Just insert an item and return any "bits" bit key that hasn't been
119*3f6063ccSDavid Shao  * used before.
120*3f6063ccSDavid Shao  */
121*3f6063ccSDavid Shao int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
122*3f6063ccSDavid Shao 			      unsigned long seed, int bits, int shift,
123*3f6063ccSDavid Shao 			      unsigned long add)
124*3f6063ccSDavid Shao {
125*3f6063ccSDavid Shao 	int ret;
126*3f6063ccSDavid Shao 	unsigned long mask = (1 << bits) - 1;
127*3f6063ccSDavid Shao 	unsigned long first, unshifted_key = 0;
128*3f6063ccSDavid Shao 
129*3f6063ccSDavid Shao 	unshifted_key = hash32_buf(&seed, sizeof(seed), unshifted_key);
130*3f6063ccSDavid Shao 	first = unshifted_key;
131*3f6063ccSDavid Shao 	do {
132*3f6063ccSDavid Shao 		item->key = (unshifted_key << shift) + add;
133*3f6063ccSDavid Shao 		ret = drm_ht_insert_item(ht, item);
134*3f6063ccSDavid Shao 		if (ret)
135*3f6063ccSDavid Shao 			unshifted_key = (unshifted_key + 1) & mask;
136*3f6063ccSDavid Shao 	} while(ret && (unshifted_key != first));
137*3f6063ccSDavid Shao 
138*3f6063ccSDavid Shao 	if (ret) {
139*3f6063ccSDavid Shao 		DRM_ERROR("Available key bit space exhausted\n");
140*3f6063ccSDavid Shao 		return -EINVAL;
141*3f6063ccSDavid Shao 	}
142*3f6063ccSDavid Shao 	return 0;
143*3f6063ccSDavid Shao }
144*3f6063ccSDavid Shao 
145*3f6063ccSDavid Shao int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
146*3f6063ccSDavid Shao 		     struct drm_hash_item **item)
147*3f6063ccSDavid Shao {
148*3f6063ccSDavid Shao 	struct drm_hash_item *entry;
149*3f6063ccSDavid Shao 
150*3f6063ccSDavid Shao 	entry = drm_ht_find_key(ht, key);
151*3f6063ccSDavid Shao 	if (!entry)
152*3f6063ccSDavid Shao 		return -EINVAL;
153*3f6063ccSDavid Shao 
154*3f6063ccSDavid Shao 	*item = entry;
155*3f6063ccSDavid Shao 	return 0;
156*3f6063ccSDavid Shao }
157*3f6063ccSDavid Shao 
158*3f6063ccSDavid Shao int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
159*3f6063ccSDavid Shao {
160*3f6063ccSDavid Shao 	struct drm_hash_item *entry;
161*3f6063ccSDavid Shao 
162*3f6063ccSDavid Shao 	entry = drm_ht_find_key(ht, key);
163*3f6063ccSDavid Shao 	if (entry) {
164*3f6063ccSDavid Shao 		LIST_REMOVE(entry, head);
165*3f6063ccSDavid Shao 		return 0;
166*3f6063ccSDavid Shao 	}
167*3f6063ccSDavid Shao 	return -EINVAL;
168*3f6063ccSDavid Shao }
169*3f6063ccSDavid Shao 
170*3f6063ccSDavid Shao int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
171*3f6063ccSDavid Shao {
172*3f6063ccSDavid Shao 	LIST_REMOVE(item, head);
173*3f6063ccSDavid Shao 	return 0;
174*3f6063ccSDavid Shao }
175*3f6063ccSDavid Shao 
176*3f6063ccSDavid Shao void drm_ht_remove(struct drm_open_hash *ht)
177*3f6063ccSDavid Shao {
178*3f6063ccSDavid Shao 	if (ht->table) {
179*3f6063ccSDavid Shao 		drm_hashdestroy(ht->table, DRM_MEM_HASHTAB, ht->mask);
180*3f6063ccSDavid Shao 		ht->table = NULL;
181*3f6063ccSDavid Shao 	}
182*3f6063ccSDavid Shao }
183