summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4u/starfire/sys/idn_smr.h
blob: 8a0e4cddb24f6ad8799d3c647d58cbd70e3491c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * Inter-Domain Network - SMR support.
 */

#ifndef	_SYS_IDN_SMR_H
#define	_SYS_IDN_SMR_H

#include <sys/sysmacros.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef uint_t	smr_offset_t;

#define	IDN_NIL_SMROFFSET		((smr_offset_t)-1)

/*
 * ---------------------------------------------------------------------
 * Data in the SMR is automatically aligned on 64 byte boundaries due
 * to the large IDN_SMR_BUFSIZE, however the streams buffers may not be
 * so we bump them in order to allow us to align appropriately and thus
 * maximize bcopy performance.
 * ---------------------------------------------------------------------
 */
#define	IDN_ALIGNSIZE		64
/*
 * Align the pointer "p" to the same relative offset as the reference
 * pointer "r" within IDN_ALIGNSIZE bytes.
 */
#define	IDN_ALIGNPTR(p, r)	((uintptr_t)(p) + (((uintptr_t)(r) - \
					(uintptr_t)(p)) & \
					(uintptr_t)(IDN_ALIGNSIZE - 1)))

#define	IDN_OFFSET2ADDR(off)	((caddr_t)((uintptr_t)(off) + \
					(uintptr_t)idn.smr.vaddr))
#define	IDN_ADDR2OFFSET(va)	((smr_offset_t)((caddr_t)(va) - idn.smr.vaddr))
#define	IDN_BUF2DATA(b, o)	((caddr_t)((uintptr_t)(b) + (uintptr_t)(o)))
#define	IDN_BUF2HDR(b)		((smr_pkthdr_t *)(b))

#define	IDN_CKSUM_PKT_COUNT	(offsetof(smr_pkthdr_t, b_cksum) / 2)

#define	IDN_CKSUM_PKT(h)	\
		(IDN_CHECKSUM ? \
		idn_cksum((ushort_t *)(h), IDN_CKSUM_PKT_COUNT) : 0)

typedef struct smr_pkthdr {
	uint_t		b_netaddr;
	uint_t		b_netports;
	smr_offset_t	b_offset;
	int		b_length;

	ushort_t	b_rawio;
	ushort_t	b_cksum;
	smr_offset_t	b_next;		/* used during reclamation */
} smr_pkthdr_t;

/*
 * ---------------------------------------------------------------------
 * IDN Slab related definitions.
 *
 * Domains are allocated SMR buffers in slabs.  Slaves keep track of
 * their own slabs in their respective idn_domain entry.  The Master
 * keeps track of slave slabs via their respective idn_domain entry.
 * The global slab pools representing all of the SMR and managed by
 * the master are maintained in the idn_global structure.
 *
 * The minimum number of slabs is chosen so that there is at least
 * one slab available for every possible domain that might be attached.
 *
 * NOTE: idn_slab_bufcount * idn_smr_bufsize should be on a 64-byte
 *	 (IDN_ALIGNSIZE) boundary for maximum bcopy performance.
 * ---------------------------------------------------------------------
 */
#define	IDN_SLAB_BUFCOUNT	idn_slab_bufcount
#define	IDN_SLAB_SIZE		(IDN_SLAB_BUFCOUNT * IDN_SMR_BUFSIZE)
#define	IDN_SLAB_MAXNUM		(idn.slabpool->ntotslabs)
#define	IDN_SLAB_MINPERPOOL	3
#define	IDN_SLAB_MINTOTAL	idn_slab_mintotal
#define	IDN_SLAB_PREALLOC	idn_slab_prealloc

/*
 * ---------------------------------------------------------------------
 * Maximum number of slabs per domain the master will
 * allow to be allocated.  Further requests simply result
 * in a failed allocation.
 * Nominal value is 1/6 of the total available (~10).
 * Maximum number of bufs a domain can expect based on
 * IDN_SLAB_MAXPERDOMAIN.
 * ---------------------------------------------------------------------
 */
#define	IDN_SLAB_MAXPERDOMAIN	idn_slab_maxperdomain
#define	IDN_BUF_MAXPERDOMAIN	(IDN_SLAB_MAXPERDOMAIN * IDN_SLAB_BUFCOUNT)
/*
 * ---------------------------------------------------------------------
 * If the total number of available slabs managed by the master
 * goes below this minimum total threshold, then the master kicks
 * off a reap request to all domains to check for free slabs and
 * to give them up.  For performance reasons, domains do not
 * automatically flush out free slabs.  They rely on the master
 * to tell them to look for some.
 * ---------------------------------------------------------------------
 */
#define	IDN_SLAB_THRESHOLD	MIN(MAX_DOMAINS, \
					(IDN_SLAB_MINTOTAL + \
					(IDN_SLAB_MINTOTAL / 5)))
#define	IDN_REAP_INTERVAL	(2 * hz)

#define	SMR_SLABPOOL_HASH(d)		((d) % idn.slabpool->npools)
#define	SMR_SLABPOOL_HASHSTEP(p)	(((p)+4) % idn.slabpool->npools)
#define	SMR_SLAB_HASH(p, d) \
				((d) % idn.slabpool->pool[p].nslabs)
#define	SMR_SLAB_HASHSTEP(p, s) \
				(((s)+1) % idn.slabpool->pool[p].nslabs)

/*
 * ---------------------------------------------------------------------
 * There is one smr_slabbuf for each buffer in the respective slab.
 *
 * sb_domid	Domainid currently owning respective buffer.
 *		Local domains use this field to determine what buffers
 *		are outstanding at which domains.  The master uses this
 *		field to know which domain owns given slab.
 * sb_bufp	Actual pointer to (VA) buffer.
 * sb_next	Used to manage free and in-use lists.
 * ---------------------------------------------------------------------
 */
typedef struct smr_slabbuf {
	int		sb_domid;
	caddr_t		sb_bufp;
	struct smr_slabbuf	*sb_next;
} smr_slabbuf_t;

/*
 * ---------------------------------------------------------------------
 * There is one smr_slab per slab of buffers.
 *
 * sl_next	List of slabs allocated to same requester.
 * sl_start	Base virtual address (SMR) of slab.
 * sl_end	Points to byte immediately following end of slab.
 * sl_lock	Atomic lock used to manage free/inuse lists.
 * sl_domid	Used by Master to indicate which slave owns
 *		respective slab.
 * sl_free	Freelist of available buffers.
 * sl_inuse	List of buffers currently allocated and in-use.
 * sl_head	Pointer to memory allocated to hold smr_slabbuf_t's.
 * ---------------------------------------------------------------------
 */
typedef struct smr_slab {
	struct smr_slab	*sl_next;
	caddr_t		sl_start,
			sl_end;
	lock_t		sl_lock;

	union {
		int	_sl_domid;
		struct {
			smr_slabbuf_t	*_sl_free;
			smr_slabbuf_t	*_sl_inuse;
			smr_slabbuf_t	*_sl_head;
		} _s;
	} _u;
} smr_slab_t;

#define	sl_domid	_u._sl_domid
#define	sl_free		_u._s._sl_free
#define	sl_inuse	_u._s._sl_inuse
#define	sl_head		_u._s._sl_head

/*
 * ---------------------------------------------------------------------
 * io/idn_smr.c
 * ---------------------------------------------------------------------
 */
extern void	smr_slab_reap(int domid, int *nslabs);
extern int	smr_slab_alloc(int domid, smr_slab_t **spp);
extern void 	smr_slab_free(int domid, smr_slab_t *sp);
extern void	smr_slab_garbage_collection(smr_slab_t *sp);
extern int	smr_slab_busy(smr_slab_t *sp);
extern int 	smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp);
extern int 	smr_buf_free(int domid, caddr_t bufp, uint_t len);
extern int	smr_buf_free_locked(int domid, caddr_t bufp, uint_t len);
extern int 	smr_buf_free_all(int domid);
extern int 	smr_buf_reclaim(int domid, int nbufs);
extern int 	smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag,
					int serrno);
extern void	smr_alloc_buflist(smr_slab_t *sp);
extern void	smr_free_buflist(smr_slab_t *sp);
extern int	smr_slabwaiter_init();
extern void	smr_slabwaiter_deinit();
extern int	smr_slabwaiter_abort(int domid, int serrno);
extern smr_slab_t *smr_slaballoc_get(int domid, caddr_t bufp,
					caddr_t ebufp);
extern int	smr_slabpool_init(size_t reserved_size,
					caddr_t *reserved_area);
extern void 	smr_slabpool_deinit();
extern void	smr_remap(struct as *as, register caddr_t vaddr,
					register pfn_t new_pfn, uint_t mblen);

extern int	idn_slab_prealloc;

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_IDN_SMR_H */