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