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