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
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _VIO_UTIL_H
#define _VIO_UTIL_H
#include <sys/stream.h>
#include <sys/vio_mailbox.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Helper routines for the Logical Domains (LDoms) drivers
*
* Note: The contents of this file are private to the implementation of the
* LDoms drivers and are subject to change at any time without notice.
*/
/*
* A message is composed of three structures. A message block (mblk_t), a
* data block to which it points and a data buffer. desballoc(9F) allows
* the caller to specify the data buffer and a free function which will
* be invoked when freeb(9F) is called to free the message. This allows
* the user to reclaim and reuse the data buffer, as opposed to using
* allocb(9F) where the message block, data block and data buffer are
* all destroyed by freeb().
*
* Note that even with desballoc the message and data blocks are destroyed
* by freeb() and must be recreated. It is only the data buffer which is
* preserved.
*
* The caller first creates a pool of vio_mblk_t's by invoking
* vio_create_mblks() and specifying the number of mblks and the size of the
* associated data buffers. Each vio_mblk_t contains a pointer to the
* mblk_t, a pointer to the data buffer and a function pointer to the
* reclaim function. The caller is returned a pointer to the pool which is
* used in subsequent allocation/destroy requests.
*
* The pool is managed as a circular queue with a head and tail pointer.
* Allocation requests result in the head index being incremented, mblks
* being returned to the pool result in the tail pointer being incremented.
*
* The pool can only be destroyed when all the mblks have been returned. It
* is the responsibility of the caller to ensure that all vio_allocb()
* requests have been completed before the pool is destroyed.
*
*
* vio_mblk_pool_t
* +-------------+
* | tail |--------------------------------+
* +-------------+ |
* | head |--------+ |
* +-------------+ | |
* ............... V V
* +-------------+ +-------+-------+-------+-------+
* | quep |---->| vmp_t | vmp_t | vmp_t | vmp_t |
* +-------------+ +-------+-------+-------+-------+
* | | | | | |
* ... | | | | +------------+
* | | | +-->| data block |
* | | | +------------+
* | | | +------------+
* | | +-->| data block |
* | | +------------+
* | | +------------+
* | +-->| data block |
* | +------------+
* | +------------+
* +-->| data block |
* +------------+
*
*/
/* mblk pool flags */
#define VMPL_FLAG_DESTROYING 0x1 /* pool is being destroyed */
#define VMPL_FLAG_CLIENT_DATA 0x2 /* pool data area provided by client */
struct vio_mblk_pool;
/* VIO mblk states */
typedef enum vio_mblk_state {
VIO_MBLK_FREE = 0x1, /* free to use */
VIO_MBLK_BOUND = 0x2, /* allocated/bound to a descriptor */
VIO_MBLK_HAS_DATA = 0x4 /* contains valid data */
} vio_mblk_state_t;
typedef struct vio_mblk {
uint8_t *datap; /* data buffer */
mblk_t *mp; /* mblk using datap */
frtn_t reclaim; /* mblk reclaim routine */
struct vio_mblk_pool *vmplp; /* pointer to parent pool */
uint_t index; /* index in the pool */
vio_mblk_state_t state; /* state flags */
} vio_mblk_t;
typedef struct vio_mblk_pool {
struct vio_mblk_pool *nextp; /* next in a list */
kmutex_t hlock; /* sync access to head */
kmutex_t tlock; /* sync access to tail */
vio_mblk_t *basep; /* base pointer to pool of vio_mblks */
vio_mblk_t **quep; /* queue of free vio_mblks */
uint8_t *datap; /* rx data buffer area */
uint32_t head; /* queue head */
uint32_t tail; /* queue tail */
uint64_t quelen; /* queue len (# mblks) */
uint64_t quemask; /* quelen - 1 */
size_t mblk_size; /* data buf size of each mblk */
uint32_t flag; /* pool-related flags */
} vio_mblk_pool_t;
typedef struct vio_multi_pool {
uint32_t num_pools; /* no. of vio mblk pools */
uint32_t tbsz; /* allocated buffer size */
uint32_t *bufsz_tbl; /* buffer sizes table */
uint32_t *nbuf_tbl; /* no. of buffers table */
vio_mblk_pool_t **vmpp; /* vio mblk pools */
} vio_multi_pool_t;
#define VIO_MBLK_DATA_OFF(vmp) ((vmp)->datap - ((vmp)->vmplp)->datap)
int vio_create_mblks(uint64_t num_mblks,
size_t mblk_size, uint8_t *mblk_datap,
vio_mblk_pool_t **poolp);
int vio_destroy_mblks(vio_mblk_pool_t *);
vio_mblk_t *vio_allocb(vio_mblk_pool_t *);
void vio_freeb(void *arg);
int vio_init_multipools(vio_multi_pool_t *vmultip, int num_pools, ...);
void vio_destroy_multipools(vio_multi_pool_t *vmultip, vio_mblk_pool_t **fvmp);
vio_mblk_t *vio_multipool_allocb(vio_multi_pool_t *vmultip, size_t size);
int vio_check_pending_pools(vio_multi_pool_t *vmultip);
void vio_clobber_pool(vio_mblk_pool_t *vmplp);
/* VIO versioning helpers */
#define VIO_VER_IS_NEGOTIATED(ver, maj, min) \
((ver.major == (maj)) && (ver.minor == (min)))
boolean_t vio_ver_is_supported(vio_ver_t ver, uint16_t maj, uint16_t min);
#ifdef __cplusplus
}
#endif
#endif /* _VIO_UTIL_H */
|