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