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-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #ifndef	_SYS_RSM_RSMKA_PATH_INT_H
28 #define	_SYS_RSM_RSMKA_PATH_INT_H
29 
30 #ifdef	__cplusplus
31 extern "C" {
32 #endif
33 
34 #include <sys/rsm/rsm_common.h>
35 #include <sys/rsm/rsm.h>
36 #include <sys/rsm/rsmpi.h>
37 
38 /*
39  * Taskq setup
40  * Only one taskq thread is created and only one task is executed
41  * the task is executed as an infinite loop
42  */
43 #define	RSMKA_ONE_THREAD	1
44 #define	RSMKA_ONE_TASK		1
45 
46 /* Path (path_t) States */
47 #define	RSMKA_PATH_DOWN	1
48 #define	RSMKA_PATH_UP	2
49 #define	RSMKA_PATH_ACTIVE	3
50 #define	RSMKA_PATH_GOING_DOWN	4
51 
52 #define	RSMKA_OPCODE_TYPES	2
53 
54 /*
55  * Deferred Work Token Index
56  */
57 #define	RSMKA_IPC_DOWN_INDEX	0
58 #define	RSMKA_IPC_UP_INDEX	1
59 
60 /* Deferred Work Opcodes */
61 #define	RSMKA_IPC_DOWN	1
62 #define	RSMKA_IPC_UP	2
63 
64 /* Flags */
65 #define	RSMKA_NO_SLEEP			1
66 #define	RSMKA_USE_COOKIE		2
67 #define	RSMKA_NOHOLD			4
68 
69 
70 /*
71  * A work token is enqueued on the workqueue (singly linked list)
72  * when pathup or pathdown processing is to be done by the deferred work
73  * thread.  Token are enqueued at the end of the queue and processed
74  * from the front of the queue.
75  */
76 typedef struct work_token {
77 	struct work_token	*next;		/* pointer to next token */
78 	int			opcode;		/* opcode for work to do */
79 } work_token_t;
80 
81 typedef struct workqueue {
82 	work_token_t	*head;		/* start of work queue		*/
83 	work_token_t	*tail;		/* end of work queue		*/
84 	kmutex_t	work_mutex;	/* protects queue add/delete    */
85 	kcondvar_t	work_cv;	/* synchronize deferred thread  */
86 } work_queue_t;
87 
88 /*
89  * a pointer to srv_handler_arg is registered along with the handler
90  * and is passed to the rsm_srv_func - the service handler when it
91  * is invoked.
92  */
93 typedef struct srv_handler_arg {
94 	char		adapter_name[MAXNAMELEN];
95 	int		adapter_instance;
96 	rsm_addr_t	adapter_hwaddr;
97 } srv_handler_arg_t;
98 
99 typedef struct msgbuf_elem {
100 	boolean_t		active;
101 	rsmipc_request_t	msg;
102 } msgbuf_elem_t;
103 
104 /*
105  * receive buffer object
106  * procmsg_cnt - receivers count of messages processed since sending credits
107  * msgbuf_queue - an array-based circular queue of messages received
108  * msgbuf_head - index pointing to the head of msgbuf_queue
109  * msgbuf_head - index pointing to the tail of msgbuf_queue
110  * msgbuf_cnt - number of valid entries in msgbuf_queue
111  */
112 typedef struct recv_info {
113 	int				procmsg_cnt;
114 	int				rem_sendq_ready;
115 	taskq_t				*recv_taskq;
116 	msgbuf_elem_t			*msgbuf_queue;
117 	int				msgbuf_head;
118 	int				msgbuf_tail;
119 	int				msgbuf_cnt;
120 } recv_info_t;
121 
122 /*
123  * sendq_tokens are inserted in a circular list of the ipc_info descriptor
124  * when a path is added for a remote node.  When the path is active the
125  * rsmpi_sendq_handle will be valid and the sendq token can be used for
126  * ipc.  The sendq_tokens are used in a round robin fashion.
127  *
128  * msgbuf_avail - used by sender, number of avail slots in recvrs msgbuf_queue
129  */
130 typedef struct sendq_token {
131 	struct sendq_token		*next;
132 	rsm_send_q_handle_t		rsmpi_sendq_handle;
133 	int				ref_cnt;
134 	int				msgbuf_avail;
135 	kcondvar_t			sendq_cv;
136 }sendq_token_t;
137 
138 
139 
140 
141 typedef struct path {
142 	struct path		*next_path;
143 	rsm_node_id_t		remote_node;
144 	int			remote_devinst;
145 	rsm_addr_t		remote_hwaddr;
146 	int			state;
147 	int			flags;
148 #define	RSMKA_WAIT_FOR_SQACK	0x0001	/* waiting for SQREADY_ACK	*/
149 #define	RSMKA_SQCREATE_PENDING	0x0002	/* sendq_create is pending	*/
150 	kmutex_t		mutex;
151 	struct adapter		*local_adapter;
152 	sendq_token_t		sendq_token;
153 	work_token_t		work_token[RSMKA_OPCODE_TYPES];
154 	recv_info_t		recv_buffer;
155 #define	procmsg_cnt	recv_buffer.procmsg_cnt
156 #define	rem_sendq_ready	recv_buffer.rem_sendq_ready
157 #define	msgbuf_queue	recv_buffer.msgbuf_queue
158 #define	msgbuf_head	recv_buffer.msgbuf_head
159 #define	msgbuf_tail	recv_buffer.msgbuf_tail
160 #define	msgbuf_cnt	recv_buffer.msgbuf_cnt
161 #define	recv_taskq	recv_buffer.recv_taskq
162 	int64_t			local_incn;
163 	int64_t			remote_incn;
164 #define	RSM_UNKNOWN_INCN	0
165 	int			ref_cnt;
166 	kcondvar_t 		hold_cv;
167 } path_t;
168 
169 
170 typedef struct adapter {
171 	struct adapter		*next;
172 	struct adapter_listhead *listhead;
173 	int			ref_cnt;
174 	kmutex_t		mutex;
175 	int			instance;
176 	dev_info_t		*dip;
177 	rsm_addr_t		hwaddr;
178 	path_t			*next_path;
179 	rsm_controller_handle_t rsmpi_handle;
180 	rsm_controller_attr_t	rsm_attr;
181 	rsm_ops_t		*rsmpi_ops;
182 	srv_handler_arg_t	*hdlr_argp;
183 } adapter_t;
184 
185 
186 /*
187  * typedef struct {
188  *	adapter_t		*next_chunk;
189  *	int			base;
190  *	int			next_index;
191  *	int			used_count;
192  *	adapter_t		*phys_adapters[MAX_CHUNK_INDEX];
193  * } adapter_map_chunks_t;
194  */
195 
196 
197 /*
198  * There is one adapter_listhead for each adapter devname. This
199  * adapter_listhead stores the number of adapters belonging to
200  * it. It also stores the number of paths for all the adapters
201  * belonging to it.
202  */
203 typedef struct adapter_listhead {
204 	struct adapter_listhead	*next_listhead;
205 	char			adapter_devname[MAXNAMELEN];
206 	adapter_t		*next_adapter;
207 	int			ref_cnt;
208 	kmutex_t		mutex;
209 	int			adapter_count;
210 	int			path_count;
211 } adapter_listhead_t;
212 
213 
214 struct adapter_listhead_list {
215 	adapter_listhead_t	*next;
216 	kmutex_t		listlock;
217 };
218 
219 
220 /*
221  * One ipc_info descriptor for each remote node
222  */
223 typedef struct ipc_info {
224 	struct ipc_info			*next;
225 	rsm_node_id_t			remote_node;
226 	boolean_t			node_is_alive;
227 	sendq_token_t			*token_list;
228 	sendq_token_t			*current_token;
229 	kmutex_t			token_list_mutex;
230 	int				ref_cnt;
231 } ipc_info_t;
232 
233 
234 #define	SQ_TOKEN_TO_PATH(token) 	\
235 	((path_t *)((char *)(token) - ((char *)(&((path_t *)0)->sendq_token))))
236 
237 
238 
239 #define	WORK_TOKEN_TO_PATH(token, index) \
240 	((path_t *)((char *)(token) - 	\
241 		((char *)(&((path_t *)0)->work_token[(index)]))))
242 
243 
244 
245 
246 /*
247  * Descriptor Reference Count macros
248  */
249 
250 #define	ADAPTER_HOLD(adapter)	{	\
251 		mutex_enter(&((adapter)->mutex)); 	\
252 		(adapter)->ref_cnt++;		\
253 		ASSERT((adapter)->ref_cnt != 0);	\
254 		mutex_exit(&((adapter)->mutex));	\
255 }
256 
257 #define	ADAPTER_RELE(adapter)	{			\
258 		mutex_enter(&((adapter)->mutex)); 	\
259 		(adapter)->ref_cnt--;			\
260 		ASSERT((adapter)->ref_cnt >= 0);	\
261 		mutex_exit(&((adapter)->mutex));	\
262 }
263 
264 #define	ADAPTER_RELE_NOLOCK(adapter)	{		\
265 		ASSERT(MUTEX_HELD(&(adapter)->mutex));	\
266 		(adapter)->ref_cnt--;			\
267 		ASSERT((adapter)->ref_cnt >= 0);	\
268 }
269 
270 #define	PATH_HOLD(path)	{			\
271 		mutex_enter(&(path)->mutex); 	\
272 		(path)->ref_cnt++;		\
273 		ASSERT((path)->ref_cnt != 0);	\
274 		mutex_exit(&(path)->mutex);	\
275 }
276 
277 #define	PATH_HOLD_NOLOCK(path)	{			\
278 		ASSERT(MUTEX_HELD(&(path)->mutex));	\
279 		(path)->ref_cnt++;			\
280 		ASSERT((path)->ref_cnt != 0);		\
281 }
282 
283 #define	PATH_RELE(path)	{				\
284 		mutex_enter(&(path)->mutex); 		\
285 		(path)->ref_cnt--;			\
286 		ASSERT((path)->ref_cnt >= 0);		\
287 		if ((path)->ref_cnt == 0)		\
288 			cv_signal(&(path)->hold_cv);	\
289 		mutex_exit(&(path)->mutex);		\
290 }
291 
292 #define	PATH_RELE_NOLOCK(path)	{			\
293 		ASSERT(MUTEX_HELD(&(path)->mutex));	\
294 		(path)->ref_cnt--;			\
295 		ASSERT((path)->ref_cnt >= 0);		\
296 		if ((path)->ref_cnt == 0)		\
297 			cv_signal(&(path)->hold_cv);	\
298 }
299 
300 #define	SENDQ_TOKEN_HOLD(path)	{				\
301 		(path)->sendq_token.ref_cnt++;			\
302 		ASSERT((path)->sendq_token.ref_cnt != 0);	\
303 }
304 
305 #define	SENDQ_TOKEN_RELE(path)	{					\
306 		(path)->sendq_token.ref_cnt--;				\
307 		ASSERT((path)->sendq_token.ref_cnt >= 0);		\
308 		if ((path)->sendq_token.ref_cnt == 0)			\
309 			cv_signal(&(path)->sendq_token.sendq_cv);	\
310 }
311 
312 #define	IPCINFO_HOLD(ipc_info)	{			\
313 		mutex_enter(&ipc_info_lock); 		\
314 		(ipc_info)->ref_cnt++;			\
315 		ASSERT((ipc_info)->ref_cnt != 0); 	\
316 		mutex_exit(&ipc_info_lock);		\
317 }
318 
319 #define	IPCINFO_HOLD_NOLOCK(ipc_info)	{		\
320 		ASSERT(MUTEX_HELD(&ipc_info_lock));	\
321 		(ipc_info)->ref_cnt++;			\
322 		ASSERT((ipc_info)->ref_cnt != 0); 	\
323 }
324 
325 #define	IPCINFO_RELE(ipc_info)	{			\
326 		mutex_enter(&ipc_info_lock); 		\
327 		(ipc_info)->ref_cnt--;			\
328 		ASSERT((ipc_info)->ref_cnt >= 0); 	\
329 		mutex_exit(&ipc_info_lock);		\
330 }
331 
332 #define	IPCINFO_RELE_NOLOCK(ipc_info)	{		\
333 		ASSERT(MUTEX_HELD(&ipc_info_lock));	\
334 		(ipc_info)->ref_cnt--;			\
335 		ASSERT((ipc_info)->ref_cnt >= 0); 	\
336 }
337 /*
338  * Topology data structures - The primary structure is struct rsm_topology_t
339  * The key interconnect data required for segment operations includes the
340  * cluster nodeids and the controllers (name, hardware address); with
341  * the fundamental constraint that the controller specified for a segment
342  * import must have a physical connection with the contorller used in the
343  * export of the segment. To facilitate applications in the establishment
344  * of proper and efficient export and import policies, a delineation of the
345  * interconnect topology is provided by these data structures.
346  *
347  * A pointer to an instance of this structure type is returned by a call
348  * to rsm_get_interconnect_topology(). The application is responsible for
349  * calling rsm_free_interconnect_topology() to free the allocated memory.
350  *
351  * Note: the rsmka_connections_t structure should be always double-word
352  *	aligned.
353  */
354 
355 
356 #define	RSM_CONNECTION_ACTIVE	3
357 
358 
359 typedef struct {
360 	rsm_node_id_t		local_nodeid;
361 	int			local_cntlr_count;
362 } rsmka_topology_hdr_t;
363 
364 typedef struct {
365 	char		cntlr_name[MAXNAMELEN];
366 	rsm_addr_t	local_hwaddr;
367 	int		remote_cntlr_count;
368 } rsmka_connections_hdr_t;
369 
370 
371 /*
372  * An application must not attempt to use a connection unless the
373  * the connection_state element of struct remote_cntlr_t is equal to
374  * RSM_CONNECTION_ACTIVE
375  */
376 typedef struct {
377 	rsm_node_id_t		remote_nodeid;
378 	char			remote_cntlrname[MAXNAMELEN];
379 	rsm_addr_t		remote_hwaddr;
380 	uint_t			connection_state;
381 } rsmka_remote_cntlr_t;
382 
383 
384 /*
385  * The actual size of the remote_cntlr array is equal to the remote_cntlr_count
386  * of the connections_hdr_t struct.
387  */
388 typedef struct {
389 	rsmka_connections_hdr_t	hdr;
390 	rsmka_remote_cntlr_t	remote_cntlr[1];
391 } rsmka_connections_t;
392 
393 /*
394  * A pointer to an instance of this structure type is returned by a call
395  * to rsm_get_interconnect_topology().  The actual size of the connections
396  * array is equal to the local_cntlr_count of the topology_hdr_t struct.
397  */
398 typedef struct {
399 	rsmka_topology_hdr_t	topology_hdr;
400 	caddr_t			connections[1];
401 } rsmka_topology_t;
402 
403 #ifdef _SYSCALL32
404 typedef struct {
405 	rsmka_topology_hdr_t	topology_hdr;
406 	caddr32_t		connections[1];
407 } rsmka_topology32_t;
408 #endif
409 
410 #ifdef	__cplusplus
411 }
412 #endif
413 
414 #endif	/* _SYS_RSM_RSMKA_PATH_INT_H */
415