blob: cd725033f274cf3d7b745faa0b4268f158a500f2 [file] [log] [blame]
/*
* 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 = (struct element **)
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_exit ========
*/
void gh_exit(void)
{
/* Do nothing */
}
/*
* ======== 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_init ========
*/
void gh_init(void)
{
/* Do nothing */
}
/*
* ======== 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