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