1 /*
2  * gh.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Copyright (C) 2005-2006 Texas Instruments, Inc.
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  */
16 
17 #include <linux/types.h>
18 
19 #include <dspbridge/host_os.h>
20 #include <dspbridge/gh.h>
21 
22 struct element {
23 	struct element *next;
24 	u8 data[1];
25 };
26 
27 struct gh_t_hash_tab {
28 	u16 max_bucket;
29 	u16 val_size;
30 	struct element **buckets;
31 	 u16(*hash) (void *, u16);
32 	 bool(*match) (void *, void *);
33 	void (*delete) (void *);
34 };
35 
36 static void noop(void *p);
37 
38 /*
39  *  ======== gh_create ========
40  */
41 
gh_create(u16 max_bucket,u16 val_size,u16 (* hash)(void *,u16),bool (* match)(void *,void *),void (* delete)(void *))42 struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size,
43 				u16(*hash) (void *, u16), bool(*match) (void *,
44 									void *),
45 				void (*delete) (void *))
46 {
47 	struct gh_t_hash_tab *hash_tab;
48 	u16 i;
49 	hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL);
50 	if (hash_tab == NULL)
51 		return NULL;
52 	hash_tab->max_bucket = max_bucket;
53 	hash_tab->val_size = val_size;
54 	hash_tab->hash = hash;
55 	hash_tab->match = match;
56 	hash_tab->delete = delete == NULL ? noop : delete;
57 
58 	hash_tab->buckets = (struct element **)
59 	    kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL);
60 	if (hash_tab->buckets == NULL) {
61 		gh_delete(hash_tab);
62 		return NULL;
63 	}
64 
65 	for (i = 0; i < max_bucket; i++)
66 		hash_tab->buckets[i] = NULL;
67 
68 	return hash_tab;
69 }
70 
71 /*
72  *  ======== gh_delete ========
73  */
gh_delete(struct gh_t_hash_tab * hash_tab)74 void gh_delete(struct gh_t_hash_tab *hash_tab)
75 {
76 	struct element *elem, *next;
77 	u16 i;
78 
79 	if (hash_tab != NULL) {
80 		if (hash_tab->buckets != NULL) {
81 			for (i = 0; i < hash_tab->max_bucket; i++) {
82 				for (elem = hash_tab->buckets[i]; elem != NULL;
83 				     elem = next) {
84 					next = elem->next;
85 					(*hash_tab->delete) (elem->data);
86 					kfree(elem);
87 				}
88 			}
89 
90 			kfree(hash_tab->buckets);
91 		}
92 
93 		kfree(hash_tab);
94 	}
95 }
96 
97 /*
98  *  ======== gh_exit ========
99  */
100 
gh_exit(void)101 void gh_exit(void)
102 {
103 	/* Do nothing */
104 }
105 
106 /*
107  *  ======== gh_find ========
108  */
109 
gh_find(struct gh_t_hash_tab * hash_tab,void * key)110 void *gh_find(struct gh_t_hash_tab *hash_tab, void *key)
111 {
112 	struct element *elem;
113 
114 	elem = hash_tab->buckets[(*hash_tab->hash) (key, hash_tab->max_bucket)];
115 
116 	for (; elem; elem = elem->next) {
117 		if ((*hash_tab->match) (key, elem->data))
118 			return elem->data;
119 	}
120 
121 	return NULL;
122 }
123 
124 /*
125  *  ======== gh_init ========
126  */
127 
gh_init(void)128 void gh_init(void)
129 {
130 	/* Do nothing */
131 }
132 
133 /*
134  *  ======== gh_insert ========
135  */
136 
gh_insert(struct gh_t_hash_tab * hash_tab,void * key,void * value)137 void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value)
138 {
139 	struct element *elem;
140 	u16 i;
141 	char *src, *dst;
142 
143 	elem = kzalloc(sizeof(struct element) - 1 + hash_tab->val_size,
144 			GFP_KERNEL);
145 	if (elem != NULL) {
146 
147 		dst = (char *)elem->data;
148 		src = (char *)value;
149 		for (i = 0; i < hash_tab->val_size; i++)
150 			*dst++ = *src++;
151 
152 		i = (*hash_tab->hash) (key, hash_tab->max_bucket);
153 		elem->next = hash_tab->buckets[i];
154 		hash_tab->buckets[i] = elem;
155 
156 		return elem->data;
157 	}
158 
159 	return NULL;
160 }
161 
162 /*
163  *  ======== noop ========
164  */
165 /* ARGSUSED */
noop(void * p)166 static void noop(void *p)
167 {
168 	p = p;			/* stifle compiler warning */
169 }
170 
171 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
172 /**
173  * gh_iterate() - This function goes through all the elements in the hash table
174  *		looking for the dsp symbols.
175  * @hash_tab:	Hash table
176  * @callback:	pointer to callback function
177  * @user_data:	User data, contains the find_symbol_context pointer
178  *
179  */
gh_iterate(struct gh_t_hash_tab * hash_tab,void (* callback)(void *,void *),void * user_data)180 void gh_iterate(struct gh_t_hash_tab *hash_tab,
181 		void (*callback)(void *, void *), void *user_data)
182 {
183 	struct element *elem;
184 	u32 i;
185 
186 	if (hash_tab && hash_tab->buckets)
187 		for (i = 0; i < hash_tab->max_bucket; i++) {
188 			elem = hash_tab->buckets[i];
189 			while (elem) {
190 				callback(&elem->data, user_data);
191 				elem = elem->next;
192 			}
193 		}
194 }
195 #endif
196