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
33extern "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 */
78typedef 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
83typedef 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 */
95typedef 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
101typedef 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 */
114typedef 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 */
132typedef 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
143typedef 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
172typedef 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 */
205typedef 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
216struct 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 */
225typedef 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
361typedef struct {
362	rsm_node_id_t		local_nodeid;
363	int			local_cntlr_count;
364} rsmka_topology_hdr_t;
365
366typedef 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 */
378typedef 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 */
390typedef 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 */
400typedef struct {
401	rsmka_topology_hdr_t	topology_hdr;
402	caddr_t			connections[1];
403} rsmka_topology_t;
404
405#ifdef _SYSCALL32
406typedef 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