xref: /onnv-gate/usr/src/lib/fm/topo/modules/common/pcibus/did_hash.c (revision 3062:46d280f5351d)
1*3062Scindi /*
2*3062Scindi  * CDDL HEADER START
3*3062Scindi  *
4*3062Scindi  * The contents of this file are subject to the terms of the
5*3062Scindi  * Common Development and Distribution License (the "License").
6*3062Scindi  * You may not use this file except in compliance with the License.
7*3062Scindi  *
8*3062Scindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3062Scindi  * or http://www.opensolaris.org/os/licensing.
10*3062Scindi  * See the License for the specific language governing permissions
11*3062Scindi  * and limitations under the License.
12*3062Scindi  *
13*3062Scindi  * When distributing Covered Code, include this CDDL HEADER in each
14*3062Scindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3062Scindi  * If applicable, add the following below this CDDL HEADER, with the
16*3062Scindi  * fields enclosed by brackets "[]" replaced with your own identifying
17*3062Scindi  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3062Scindi  *
19*3062Scindi  * CDDL HEADER END
20*3062Scindi  */
21*3062Scindi 
22*3062Scindi /*
23*3062Scindi  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*3062Scindi  * Use is subject to license terms.
25*3062Scindi  */
26*3062Scindi 
27*3062Scindi #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*3062Scindi 
29*3062Scindi #include <stdio.h>
30*3062Scindi #include <stdlib.h>
31*3062Scindi #include <assert.h>
32*3062Scindi #include <sys/types.h>
33*3062Scindi #include <libdevinfo.h>
34*3062Scindi #include <fm/topo_mod.h>
35*3062Scindi #include <pcibus.h>
36*3062Scindi #include <did.h>
37*3062Scindi 
38*3062Scindi #include "did_impl.h"
39*3062Scindi #include "did_props.h"
40*3062Scindi 
41*3062Scindi static did_hash_t *did_hash_create(topo_mod_t *);
42*3062Scindi static void did_hash_destroy(did_hash_t *);
43*3062Scindi 
44*3062Scindi int
did_hash_init(topo_mod_t * hdl)45*3062Scindi did_hash_init(topo_mod_t *hdl)
46*3062Scindi {
47*3062Scindi 	did_hash_t *dh = did_hash_create(hdl);
48*3062Scindi 
49*3062Scindi 	if (dh != NULL) {
50*3062Scindi 		topo_mod_setspecific(hdl, (void *) dh);
51*3062Scindi 		return (0);
52*3062Scindi 	} else {
53*3062Scindi 		return (-1);
54*3062Scindi 	}
55*3062Scindi }
56*3062Scindi 
57*3062Scindi void
did_hash_fini(topo_mod_t * mod)58*3062Scindi did_hash_fini(topo_mod_t *mod)
59*3062Scindi {
60*3062Scindi 	did_hash_t *dh = (did_hash_t *)topo_mod_getspecific(mod);
61*3062Scindi 
62*3062Scindi 	topo_mod_setspecific(mod, NULL);
63*3062Scindi 	if (dh == NULL)
64*3062Scindi 		return;
65*3062Scindi 	did_hash_destroy(dh);
66*3062Scindi }
67*3062Scindi 
68*3062Scindi static uint64_t
did_dnhash(di_node_t key)69*3062Scindi did_dnhash(di_node_t key)
70*3062Scindi {
71*3062Scindi 	static uint64_t key_divisor = 0;
72*3062Scindi 	uint64_t keyn;
73*3062Scindi 
74*3062Scindi 	/*
75*3062Scindi 	 * A bit naughty here, we're aware that a di_info_t is a
76*3062Scindi 	 * pointer to a struct.  For our hashing, we want use the size
77*3062Scindi 	 * of that struct, which we determine here, somewhat
78*3062Scindi 	 * impolitely.
79*3062Scindi 	 */
80*3062Scindi 	if (key_divisor == 0)
81*3062Scindi 		key_divisor = sizeof (*key);
82*3062Scindi 
83*3062Scindi 	keyn = (uintptr_t)key;
84*3062Scindi 
85*3062Scindi 	return (keyn / key_divisor);
86*3062Scindi }
87*3062Scindi 
88*3062Scindi static did_hash_t *
did_hash_create(topo_mod_t * hdl)89*3062Scindi did_hash_create(topo_mod_t *hdl)
90*3062Scindi {
91*3062Scindi 	did_hash_t *r = topo_mod_zalloc(hdl, sizeof (did_hash_t));
92*3062Scindi 
93*3062Scindi 	if (r == NULL) {
94*3062Scindi 		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
95*3062Scindi 		return (NULL);
96*3062Scindi 	}
97*3062Scindi 	r->dph_mod = hdl;
98*3062Scindi 	r->dph_hashlen = REC_HASHLEN;
99*3062Scindi 	r->dph_hash = topo_mod_zalloc(hdl,
100*3062Scindi 	    r->dph_hashlen * sizeof (did_t *));
101*3062Scindi 	if (r->dph_hash == NULL) {
102*3062Scindi 		topo_mod_free(hdl, r, sizeof (did_hash_t));
103*3062Scindi 		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
104*3062Scindi 		return (NULL);
105*3062Scindi 	}
106*3062Scindi 	return (r);
107*3062Scindi }
108*3062Scindi 
109*3062Scindi static void
did_hash_destroy(did_hash_t * ht)110*3062Scindi did_hash_destroy(did_hash_t *ht)
111*3062Scindi {
112*3062Scindi 	did_t *e, *n;
113*3062Scindi 	int idx;
114*3062Scindi 
115*3062Scindi 	if (ht == NULL)
116*3062Scindi 		return;
117*3062Scindi 	for (idx = 0; idx < ht->dph_hashlen; idx++) {
118*3062Scindi 		for (e = ht->dph_hash[idx]; e != NULL; ) {
119*3062Scindi 			n = e->dp_next;
120*3062Scindi 			did_destroy(e);
121*3062Scindi 			e = n;
122*3062Scindi 		}
123*3062Scindi 	}
124*3062Scindi 	topo_mod_free(ht->dph_mod,
125*3062Scindi 	    ht->dph_hash, ht->dph_hashlen * sizeof (did_t *));
126*3062Scindi 	topo_mod_free(ht->dph_mod, ht, sizeof (did_hash_t));
127*3062Scindi }
128*3062Scindi 
129*3062Scindi void
did_hash_insert(topo_mod_t * mp,di_node_t key,did_t * new)130*3062Scindi did_hash_insert(topo_mod_t *mp, di_node_t key, did_t *new)
131*3062Scindi {
132*3062Scindi 	did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mp);
133*3062Scindi 	did_t *assertchk;
134*3062Scindi 	int idx = did_dnhash(key) % tab->dph_hashlen;
135*3062Scindi 
136*3062Scindi 	tab->dph_nelems++;
137*3062Scindi 	did_hold(new);
138*3062Scindi 	topo_mod_dprintf(tab->dph_mod, "Insert [key=%p] into %p, bucket %d\n",
139*3062Scindi 	    key, (void *)tab, idx);
140*3062Scindi 	if (tab->dph_hash[idx] == NULL) {
141*3062Scindi 		tab->dph_hash[idx] = new;
142*3062Scindi 		topo_mod_dprintf(tab->dph_mod, "first entry.\n");
143*3062Scindi 	} else {
144*3062Scindi 		/*
145*3062Scindi 		 * We should not be putting in a duplicate entry
146*3062Scindi 		 */
147*3062Scindi 		for (assertchk = tab->dph_hash[idx];
148*3062Scindi 		    assertchk != NULL;
149*3062Scindi 		    assertchk = assertchk->dp_next)
150*3062Scindi 			assert(assertchk->dp_src != key);
151*3062Scindi 		new->dp_next = tab->dph_hash[idx];
152*3062Scindi 		tab->dph_hash[idx] = new;
153*3062Scindi 	}
154*3062Scindi }
155*3062Scindi 
156*3062Scindi did_t *
did_hash_lookup(topo_mod_t * mp,di_node_t key)157*3062Scindi did_hash_lookup(topo_mod_t *mp, di_node_t key)
158*3062Scindi {
159*3062Scindi 	did_t *e;
160*3062Scindi 	did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mp);
161*3062Scindi 	int idx = did_dnhash(key) % tab->dph_hashlen;
162*3062Scindi 
163*3062Scindi 	e = tab->dph_hash[idx];
164*3062Scindi 	while (e != NULL) {
165*3062Scindi 		if (e->dp_src == key) {
166*3062Scindi 			did_hold(e);
167*3062Scindi 			return (e);
168*3062Scindi 		}
169*3062Scindi 		e = e->dp_next;
170*3062Scindi 	}
171*3062Scindi 	return (NULL);
172*3062Scindi }
173