/* * 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 <linux/types.h> #include <dspbridge/host_os.h> #include <dspbridge/gh.h> struct element { struct element *next; u8 data[1]; }; struct gh_t_hash_tab { u16 max_bucket; u16 val_size; struct element **buckets; u16(*hash) (void *, u16); bool(*match) (void *, void *); void (*delete) (void *); }; static void noop(void *p); /* * ======== gh_create ======== */ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, u16(*hash) (void *, u16), bool(*match) (void *, void *), void (*delete) (void *)) { struct gh_t_hash_tab *hash_tab; u16 i; hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL); if (hash_tab == NULL) return NULL; hash_tab->max_bucket = max_bucket; hash_tab->val_size = val_size; hash_tab->hash = hash; hash_tab->match = match; hash_tab->delete = delete == NULL ? noop : delete; hash_tab->buckets = kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL); if (hash_tab->buckets == NULL) { gh_delete(hash_tab); return NULL; } for (i = 0; i < max_bucket; i++) hash_tab->buckets[i] = NULL; return hash_tab; } /* * ======== gh_delete ======== */ void gh_delete(struct gh_t_hash_tab *hash_tab) { struct element *elem, *next; u16 i; if (hash_tab != NULL) { if (hash_tab->buckets != NULL) { for (i = 0; i < hash_tab->max_bucket; i++) { for (elem = hash_tab->buckets[i]; elem != NULL; elem = next) { next = elem->next; (*hash_tab->delete) (elem->data); kfree(elem); } } kfree(hash_tab->buckets); } kfree(hash_tab); } } /* * ======== gh_find ======== */ void *gh_find(struct gh_t_hash_tab *hash_tab, void *key) { struct element *elem; elem = hash_tab->buckets[(*hash_tab->hash) (key, hash_tab->max_bucket)]; for (; elem; elem = elem->next) { if ((*hash_tab->match) (key, elem->data)) return elem->data; } return NULL; } /* * ======== gh_insert ======== */ void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value) { struct element *elem; u16 i; char *src, *dst; elem = kzalloc(sizeof(struct element) - 1 + hash_tab->val_size, GFP_KERNEL); if (elem != NULL) { dst = (char *)elem->data; src = (char *)value; for (i = 0; i < hash_tab->val_size; i++) *dst++ = *src++; i = (*hash_tab->hash) (key, hash_tab->max_bucket); elem->next = hash_tab->buckets[i]; hash_tab->buckets[i] = elem; return elem->data; } return NULL; } /* * ======== noop ======== */ /* ARGSUSED */ static void noop(void *p) { p = p; /* stifle compiler warning */ } #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 element *elem; u32 i; if (hash_tab && hash_tab->buckets) for (i = 0; i < hash_tab->max_bucket; i++) { elem = hash_tab->buckets[i]; while (elem) { callback(&elem->data, user_data); elem = elem->next; } } } #endif