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