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