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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * This header file contains definations for utility routines
28  * which can be used by all Solaris OFUV related kernel drivers
29  * and misc modules. The kernel modules using these APIs, should
30  * load sol_ofs using :
31  *	ld -r -N misc/sol_ofs
32  *
33  * The APIs defined are :
34  *	1. User Objects
35  *	2. Linked Lists
36  *	3. Debug Routines
37  */
38 #ifndef	_SYS_IB_CLIENTS_OF_SOL_OFS_SOL_OFS_COMMON_H
39 #define	_SYS_IB_CLIENTS_OF_SOL_OFS_SOL_OFS_COMMON_H
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 #include <sys/types.h>
46 #include <sys/ksynch.h>
47 
48 /*
49  * User Objects functions and structures.
50  */
51 typedef enum {
52 	/* User objects for sol_uverbs driver */
53 	SOL_UVERBS_UCTXT_UOBJ_TYPE	= 0,
54 	SOL_UVERBS_UPD_UOBJ_TYPE,
55 	SOL_UVERBS_UAH_UOBJ_TYPE,
56 	SOL_UVERBS_UMR_UOBJ_TYPE,
57 	SOL_UVERBS_UCQ_UOBJ_TYPE,
58 	SOL_UVERBS_USRQ_UOBJ_TYPE,
59 	SOL_UVERBS_UQP_UOBJ_TYPE,
60 	SOL_UVERBS_UFILE_UOBJ_TYPE,
61 
62 	/* User Objects for sol_ucma driver */
63 	SOL_UCMA_EVT_FILE_TYPE,
64 	SOL_UCMA_CM_ID_TYPE,
65 	SOL_UCMA_MCAST_TYPE
66 } sol_ofs_uobj_type_t;
67 
68 typedef struct {
69 	uint64_t		uo_user_handle;
70 	sol_ofs_uobj_type_t	uo_type;
71 	krwlock_t		uo_lock;
72 	uint32_t		uo_id;
73 	kmutex_t		uo_reflock;
74 	uint32_t		uo_refcnt;
75 	uint32_t		uo_live;
76 	size_t			uo_uobj_sz;
77 } sol_ofs_uobj_t;
78 
79 /*
80  * Objects are maintained in tables that allow an easy table ID to User Object
81  * mapping and can grow as resources are created.
82  */
83 #define	SOL_OFS_UO_BLKSZ	16
84 
85 typedef struct {
86 	int		ofs_uo_blk_avail;
87 	sol_ofs_uobj_t	*ofs_uoblk_blks[SOL_OFS_UO_BLKSZ];
88 } sol_ofs_uobj_blk_t;
89 
90 typedef struct {
91 	krwlock_t		uobj_tbl_lock;
92 	int			uobj_tbl_used_blks;
93 	uint_t			uobj_tbl_num_blks;
94 	size_t			uobj_tbl_uo_sz;
95 	int			uobj_tbl_uo_cnt;
96 	sol_ofs_uobj_blk_t	**uobj_tbl_uo_root;
97 } sol_ofs_uobj_table_t;
98 
99 /* User object table management routines */
100 void sol_ofs_uobj_tbl_init(sol_ofs_uobj_table_t *, size_t);
101 void sol_ofs_uobj_tbl_fini(sol_ofs_uobj_table_t *);
102 
103 void sol_ofs_uobj_init(sol_ofs_uobj_t *, uint64_t, sol_ofs_uobj_type_t);
104 void sol_ofs_uobj_ref(sol_ofs_uobj_t *);
105 void sol_ofs_uobj_deref(sol_ofs_uobj_t *,
106 void (*free_func)(sol_ofs_uobj_t *));
107 void sol_ofs_uobj_put(sol_ofs_uobj_t *);
108 void sol_ofs_uobj_free(sol_ofs_uobj_t *uobj);
109 
110 int sol_ofs_uobj_add(sol_ofs_uobj_table_t *, sol_ofs_uobj_t *);
111 sol_ofs_uobj_t	*sol_ofs_uobj_remove(sol_ofs_uobj_table_t *,
112     sol_ofs_uobj_t *);
113 sol_ofs_uobj_t	*sol_ofs_uobj_get_read(sol_ofs_uobj_table_t *, uint32_t);
114 sol_ofs_uobj_t	*sol_ofs_uobj_get_write(sol_ofs_uobj_table_t *, uint32_t);
115 
116 /*
117  * Generic linked list management functions
118  */
119 typedef uchar_t		bool;
120 #define	FALSE		0
121 #define	TRUE		1
122 #define	INVALID_HANDLE	0xFFFFFFFF
123 #define	MAX_HASH_SIZE	1024
124 
125 /*
126  * Simple doubly linked list for opaque addresses.  Protection must occur
127  * outside of the list.  These behavior very much like the linux kernel
128  * lists, hence the familiar look of the API; but note there are
129  * some signficant differences, mainly the list header is not embedded
130  * in the element, so the container (typeof) constructs are not required.
131  */
132 typedef struct llist_head {
133 	struct llist_head	*prv;
134 	struct llist_head	*nxt;
135 	void			*ptr;
136 } llist_head_t;
137 
138 
139 #define	LLIST_HEAD_INIT(x) { &(x), &(x), NULL }
140 
llist_head_init(llist_head_t * list,void * ptr)141 static inline void llist_head_init(llist_head_t *list, void *ptr)
142 {
143 	list->prv = list->nxt = list;
144 	list->ptr = ptr;
145 }
146 
__llist_add(llist_head_t * new,llist_head_t * prv,llist_head_t * nxt)147 static inline void __llist_add(llist_head_t  *new, llist_head_t  *prv,
148 							llist_head_t  *nxt)
149 {
150 	nxt->prv   = new;
151 	new->nxt   = nxt;
152 	new->prv   = prv;
153 	prv->nxt   = new;
154 }
llist_add(llist_head_t * new,llist_head_t * head)155 static inline void llist_add(llist_head_t *new, llist_head_t *head)
156 {
157 	__llist_add(new, head, head->nxt);
158 }
159 
llist_add_tail(llist_head_t * new,llist_head_t * head)160 static inline void llist_add_tail(llist_head_t *new, llist_head_t *head)
161 {
162 	__llist_add(new, head->prv, head);
163 }
164 
llist_del(llist_head_t * entry)165 static inline void llist_del(llist_head_t *entry)
166 {
167 	entry->nxt->prv = entry->prv;
168 	entry->prv->nxt = entry->nxt;
169 }
170 
llist_is_last(llist_head_t * list,llist_head_t * head)171 static inline int llist_is_last(llist_head_t *list, llist_head_t *head)
172 {
173 	return (list->nxt == head);
174 }
175 
llist_empty(llist_head_t * head)176 static inline int llist_empty(llist_head_t *head)
177 {
178 	return (head->nxt == head);
179 }
180 
181 #define	list_for_each(_pos, _head)                 \
182 	for (_pos = (_head)->nxt; _pos != (_head); _pos = _pos->nxt)
183 #define	list_for_each_safe(_pos, n, _head) \
184 	for (_pos = (_head)->nxt, n = _pos->nxt; _pos != (_head); \
185 		_pos = n, n = _pos->nxt)
186 
187 /*
188  * Doubly linked per user context IB resource list definitions
189  * Protection must occur * outside of the list.
190  */
191 typedef struct genlist_entry_s {
192 	uintptr_t		data;
193 	void			*data_context;
194 	struct genlist_entry_s	*next;
195 	struct genlist_entry_s	*prev;
196 } genlist_entry_t;
197 
198 typedef struct genlist_s {
199 	uint32_t	count;
200 	genlist_entry_t	*head;
201 	genlist_entry_t	*tail;
202 } genlist_t;
203 
204 
205 genlist_entry_t *add_genlist(genlist_t *list, uintptr_t data,
206     void *data_context);
207 
208 #define	genlist_for_each(_pos, _head)	\
209 	for (_pos = (_head)->head; _pos; _pos = _pos->next)
210 
211 void delete_genlist(genlist_t *list, genlist_entry_t *entry);
212 
213 genlist_entry_t *remove_genlist_head(genlist_t *list);
214 
215 void insert_genlist_tail(genlist_t *list, genlist_entry_t *entry);
216 
217 void flush_genlist(genlist_t *list);
218 
219 bool genlist_empty(genlist_t *list);
220 
init_genlist(genlist_t * list)221 static inline void init_genlist(genlist_t *list)
222 {
223 	list->head = list->tail = NULL;
224 	list->count = 0;
225 }
226 
227 
228 /*
229  * Debug printfs defines
230  */
231 void sol_ofs_dprintf_l5(char *name, char *fmt, ...);
232 void sol_ofs_dprintf_l4(char *name, char *fmt, ...);
233 void sol_ofs_dprintf_l3(char *name, char *fmt, ...);
234 void sol_ofs_dprintf_l2(char *name, char *fmt, ...);
235 void sol_ofs_dprintf_l1(char *name, char *fmt, ...);
236 void sol_ofs_dprintf_l0(char *name, char *fmt, ...);
237 
238 #define	SOL_OFS_DPRINTF_L5	sol_ofs_dprintf_l5
239 #define	SOL_OFS_DPRINTF_L4	sol_ofs_dprintf_l4
240 #define	SOL_OFS_DPRINTF_L3	sol_ofs_dprintf_l3
241 #define	SOL_OFS_DPRINTF_L2	sol_ofs_dprintf_l2
242 #define	SOL_OFS_DPRINTF_L1	sol_ofs_dprintf_l1
243 #define	SOL_OFS_DPRINTF_L0	sol_ofs_dprintf_l0
244 
245 /* Misc */
246 #define	SOL_OFS_DRV_NAME_LEN	64
247 
248 #ifdef __cplusplus
249 }
250 #endif
251 
252 #endif /* _SYS_IB_CLIENTS_OF_SOL_OFS_SOL_OFS_COMMON_H */
253