/* * gh.c * * DSP-BIOS Bridge driver support functions for TI OMAP processors. * * Copyright (C) 2005-2006 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include struct gh_node { struct hlist_node hl; u8 data[0]; }; #define GH_HASH_ORDER 8 struct gh_t_hash_tab { u32 val_size; DECLARE_HASHTABLE(hash_table, GH_HASH_ORDER); u32 (*hash)(const void *key); bool (*match)(const void *key, const void *value); void (*delete)(void *key); }; /* * ======== gh_create ======== */ struct gh_t_hash_tab *gh_create(u32 val_size, u32 (*hash)(const void *), bool (*match)(const void *, const void *), void (*delete)(void *)) { struct gh_t_hash_tab *hash_tab; hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL); if (!hash_tab) return ERR_PTR(-ENOMEM); hash_init(hash_tab->hash_table); hash_tab->val_size = val_size; hash_tab->hash = hash; hash_tab->match = match; hash_tab->delete = delete; return hash_tab; } /* * ======== gh_delete ======== */ void gh_delete(struct gh_t_hash_tab *hash_tab) { struct gh_node *n; struct hlist_node *tmp; u32 i; if (hash_tab) { hash_for_each_safe(hash_tab->hash_table, i, tmp, n, hl) { hash_del(&n->hl); if (hash_tab->delete) hash_tab->delete(n->data); kfree(n); } kfree(hash_tab); } } /* * ======== gh_find ======== */ void *gh_find(struct gh_t_hash_tab *hash_tab, const void *key) { struct gh_node *n; u32 key_hash = hash_tab->hash(key); hash_for_each_possible(hash_tab->hash_table, n, hl, key_hash) { if (hash_tab->match(key, n->data)) return n->data; } return ERR_PTR(-ENODATA); } /* * ======== gh_insert ======== */ void *gh_insert(struct gh_t_hash_tab *hash_tab, const void *key, const void *value) { struct gh_node *n; n = kmalloc(sizeof(struct gh_node) + hash_tab->val_size, GFP_KERNEL); if (!n) return ERR_PTR(-ENOMEM); INIT_HLIST_NODE(&n->hl); hash_add(hash_tab->hash_table, &n->hl, hash_tab->hash(key)); memcpy(n->data, value, hash_tab->val_size); return n->data; } #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE /** * gh_iterate() - This function goes through all the elements in the hash table * looking for the dsp symbols. * @hash_tab: Hash table * @callback: pointer to callback function * @user_data: User data, contains the find_symbol_context pointer * */ void gh_iterate(struct gh_t_hash_tab *hash_tab, void (*callback)(void *, void *), void *user_data) { struct gh_node *n; u32 i; if (!hash_tab) return; hash_for_each(hash_tab->hash_table, i, n, hl) callback(&n->data, user_data); } #endif