xref: /titanic_50/usr/src/uts/sun4u/starfire/sys/idn_smr.h (revision e07d9cb85217949d497b02d7211de8a197d2f2eb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  *
26  * Inter-Domain Network - SMR support.
27  */
28 
29 #ifndef	_SYS_IDN_SMR_H
30 #define	_SYS_IDN_SMR_H
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #include <sys/sysmacros.h>
35 
36 #ifdef	__cplusplus
37 extern "C" {
38 #endif
39 
40 typedef uint_t	smr_offset_t;
41 
42 #define	IDN_NIL_SMROFFSET		((smr_offset_t)-1)
43 
44 /*
45  * ---------------------------------------------------------------------
46  * Data in the SMR is automatically aligned on 64 byte boundaries due
47  * to the large IDN_SMR_BUFSIZE, however the streams buffers may not be
48  * so we bump them in order to allow us to align appropriately and thus
49  * maximize bcopy performance.
50  * ---------------------------------------------------------------------
51  */
52 #define	IDN_ALIGNSIZE		64
53 /*
54  * Align the pointer "p" to the same relative offset as the reference
55  * pointer "r" within IDN_ALIGNSIZE bytes.
56  */
57 #define	IDN_ALIGNPTR(p, r)	((uintptr_t)(p) + (((uintptr_t)(r) - \
58 					(uintptr_t)(p)) & \
59 					(uintptr_t)(IDN_ALIGNSIZE - 1)))
60 
61 #define	IDN_OFFSET2ADDR(off)	((caddr_t)((uintptr_t)(off) + \
62 					(uintptr_t)idn.smr.vaddr))
63 #define	IDN_ADDR2OFFSET(va)	((smr_offset_t)((caddr_t)(va) - idn.smr.vaddr))
64 #define	IDN_BUF2DATA(b, o)	((caddr_t)((uintptr_t)(b) + (uintptr_t)(o)))
65 #define	IDN_BUF2HDR(b)		((smr_pkthdr_t *)(b))
66 
67 #define	IDN_CKSUM_PKT_COUNT	(((int)&((smr_pkthdr_t *)(0))->b_cksum) / 2)
68 #define	IDN_CKSUM_PKT(h)	\
69 		(IDN_CHECKSUM ? \
70 		idn_cksum((ushort_t *)(h), IDN_CKSUM_PKT_COUNT) : 0)
71 
72 typedef struct smr_pkthdr {
73 	uint_t		b_netaddr;
74 	uint_t		b_netports;
75 	smr_offset_t	b_offset;
76 	int		b_length;
77 
78 	ushort_t	b_rawio;
79 	ushort_t	b_cksum;
80 	smr_offset_t	b_next;		/* used during reclamation */
81 } smr_pkthdr_t;
82 
83 /*
84  * ---------------------------------------------------------------------
85  * IDN Slab related definitions.
86  *
87  * Domains are allocated SMR buffers in slabs.  Slaves keep track of
88  * their own slabs in their respective idn_domain entry.  The Master
89  * keeps track of slave slabs via their respective idn_domain entry.
90  * The global slab pools representing all of the SMR and managed by
91  * the master are maintained in the idn_global structure.
92  *
93  * The minimum number of slabs is chosen so that there is at least
94  * one slab available for every possible domain that might be attached.
95  *
96  * NOTE: idn_slab_bufcount * idn_smr_bufsize should be on a 64-byte
97  *	 (IDN_ALIGNSIZE) boundary for maximum bcopy performance.
98  * ---------------------------------------------------------------------
99  */
100 #define	IDN_SLAB_BUFCOUNT	idn_slab_bufcount
101 #define	IDN_SLAB_SIZE		(IDN_SLAB_BUFCOUNT * IDN_SMR_BUFSIZE)
102 #define	IDN_SLAB_MAXNUM		(idn.slabpool->ntotslabs)
103 #define	IDN_SLAB_MINPERPOOL	3
104 #define	IDN_SLAB_MINTOTAL	idn_slab_mintotal
105 #define	IDN_SLAB_PREALLOC	idn_slab_prealloc
106 
107 /*
108  * ---------------------------------------------------------------------
109  * Maximum number of slabs per domain the master will
110  * allow to be allocated.  Further requests simply result
111  * in a failed allocation.
112  * Nominal value is 1/6 of the total available (~10).
113  * Maximum number of bufs a domain can expect based on
114  * IDN_SLAB_MAXPERDOMAIN.
115  * ---------------------------------------------------------------------
116  */
117 #define	IDN_SLAB_MAXPERDOMAIN	idn_slab_maxperdomain
118 #define	IDN_BUF_MAXPERDOMAIN	(IDN_SLAB_MAXPERDOMAIN * IDN_SLAB_BUFCOUNT)
119 /*
120  * ---------------------------------------------------------------------
121  * If the total number of available slabs managed by the master
122  * goes below this minimum total threshold, then the master kicks
123  * off a reap request to all domains to check for free slabs and
124  * to give them up.  For performance reasons, domains do not
125  * automatically flush out free slabs.  They rely on the master
126  * to tell them to look for some.
127  * ---------------------------------------------------------------------
128  */
129 #define	IDN_SLAB_THRESHOLD	MIN(MAX_DOMAINS, \
130 					(IDN_SLAB_MINTOTAL + \
131 					(IDN_SLAB_MINTOTAL / 5)))
132 #define	IDN_REAP_INTERVAL	(2 * hz)
133 
134 #define	SMR_SLABPOOL_HASH(d)		((d) % idn.slabpool->npools)
135 #define	SMR_SLABPOOL_HASHSTEP(p)	(((p)+4) % idn.slabpool->npools)
136 #define	SMR_SLAB_HASH(p, d) \
137 				((d) % idn.slabpool->pool[p].nslabs)
138 #define	SMR_SLAB_HASHSTEP(p, s) \
139 				(((s)+1) % idn.slabpool->pool[p].nslabs)
140 
141 /*
142  * ---------------------------------------------------------------------
143  * There is one smr_slabbuf for each buffer in the respective slab.
144  *
145  * sb_domid	Domainid currently owning respective buffer.
146  *		Local domains use this field to determine what buffers
147  *		are outstanding at which domains.  The master uses this
148  *		field to know which domain owns given slab.
149  * sb_bufp	Actual pointer to (VA) buffer.
150  * sb_next	Used to manage free and in-use lists.
151  * ---------------------------------------------------------------------
152  */
153 typedef struct smr_slabbuf {
154 	int		sb_domid;
155 	caddr_t		sb_bufp;
156 	struct smr_slabbuf	*sb_next;
157 } smr_slabbuf_t;
158 
159 /*
160  * ---------------------------------------------------------------------
161  * There is one smr_slab per slab of buffers.
162  *
163  * sl_next	List of slabs allocated to same requester.
164  * sl_start	Base virtual address (SMR) of slab.
165  * sl_end	Points to byte immediately following end of slab.
166  * sl_lock	Atomic lock used to manage free/inuse lists.
167  * sl_domid	Used by Master to indicate which slave owns
168  *		respective slab.
169  * sl_free	Freelist of available buffers.
170  * sl_inuse	List of buffers currently allocated and in-use.
171  * sl_head	Pointer to memory allocated to hold smr_slabbuf_t's.
172  * ---------------------------------------------------------------------
173  */
174 typedef struct smr_slab {
175 	struct smr_slab	*sl_next;
176 	caddr_t		sl_start,
177 			sl_end;
178 	lock_t		sl_lock;
179 
180 	union {
181 		int	_sl_domid;
182 		struct {
183 			smr_slabbuf_t	*_sl_free;
184 			smr_slabbuf_t	*_sl_inuse;
185 			smr_slabbuf_t	*_sl_head;
186 		} _s;
187 	} _u;
188 } smr_slab_t;
189 
190 #define	sl_domid	_u._sl_domid
191 #define	sl_free		_u._s._sl_free
192 #define	sl_inuse	_u._s._sl_inuse
193 #define	sl_head		_u._s._sl_head
194 
195 /*
196  * ---------------------------------------------------------------------
197  * io/idn_smr.c
198  * ---------------------------------------------------------------------
199  */
200 extern void	smr_slab_reap(int domid, int *nslabs);
201 extern int	smr_slab_alloc(int domid, smr_slab_t **spp);
202 extern void 	smr_slab_free(int domid, smr_slab_t *sp);
203 extern void	smr_slab_garbage_collection(smr_slab_t *sp);
204 extern int	smr_slab_busy(smr_slab_t *sp);
205 extern int 	smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp);
206 extern int 	smr_buf_free(int domid, caddr_t bufp, uint_t len);
207 extern int	smr_buf_free_locked(int domid, caddr_t bufp, uint_t len);
208 extern int 	smr_buf_free_all(int domid);
209 extern int 	smr_buf_reclaim(int domid, int nbufs);
210 extern int 	smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag,
211 					int serrno);
212 extern void	smr_alloc_buflist(smr_slab_t *sp);
213 extern void	smr_free_buflist(smr_slab_t *sp);
214 extern int	smr_slabwaiter_init();
215 extern void	smr_slabwaiter_deinit();
216 extern int	smr_slabwaiter_abort(int domid, int serrno);
217 extern smr_slab_t *smr_slaballoc_get(int domid, caddr_t bufp,
218 					caddr_t ebufp);
219 extern int	smr_slabpool_init(size_t reserved_size,
220 					caddr_t *reserved_area);
221 extern void 	smr_slabpool_deinit();
222 extern void	smr_remap(struct as *as, register caddr_t vaddr,
223 					register pfn_t new_pfn, uint_t mblen);
224 
225 extern int	idn_slab_prealloc;
226 
227 #ifdef	__cplusplus
228 }
229 #endif
230 
231 #endif /* _SYS_IDN_SMR_H */
232