196 lines
3.8 KiB
C
196 lines
3.8 KiB
C
/*
|
|
* 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
|