blob: 936470cb608e4e1c422ab13494dab3d4204a63cd [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/err.h>
#include <linux/hashtable.h>
#include <linux/slab.h>
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