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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Inter-Domain Network 27 */ 28 29 #ifndef _SYS_IDN_H 30 #define _SYS_IDN_H 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #ifndef _ASM 35 36 #ifdef _KERNEL 37 38 #include <sys/note.h> 39 40 #include <sys/cmn_err.h> 41 #include <sys/dditypes.h> 42 #include <sys/stream.h> 43 #include <sys/machsystm.h> 44 #include <sys/ethernet.h> 45 #include <sys/dlpi.h> 46 #include <sys/time.h> 47 #include <sys/kmem.h> 48 #include <sys/atomic.h> 49 #include <sys/cpuvar.h> 50 51 #include <sys/idn_sigb.h> 52 #include <sys/idn_smr.h> 53 #endif /* _KERNEL */ 54 55 #ifdef __cplusplus 56 extern "C" { 57 #endif 58 59 typedef const char * const procname_t; 60 61 #define MB2B(m) ((size_t)(m) << 20) /* MBytes to Bytes */ 62 #define B2MB(b) ((uint_t)((b) >> 20)) /* Bytes to MBytes */ 63 64 #ifdef _KERNEL 65 66 /* 67 * IDN_PROP_SMRSIZE - User specified size in MBytes. 68 * IDN_PROP_SMRADDR - OBP's internal physical address of the region. 69 * 70 * OBP properties of "memory" node that define the SMR space. 71 */ 72 #define IDN_PROP_SMRSIZE "idn-smr-size" 73 #define IDN_PROP_SMRADDR "idn-smr-addr" 74 75 /* 76 * IDN_AWOLMSG_INTERVAL (driver.conf) 77 * 78 * Number of seconds between AWOL messages on a per-domain basis. 79 * The purpose is to throttle the frequency at which these 80 * messages appear. 81 * 82 * IDN_MSGWAIT_NEGO (driver.conf) 83 * IDN_MSGWAIT_CFG 84 * IDN_MSGWAIT_CON 85 * IDN_MSGWAIT_FIN 86 * IDN_MSGWAIT_CMD 87 * IDN_MSGWAIT_DATA 88 * 89 * Number of seconds to wait for response to respective 90 * message type. 91 * 92 * IDN_RETRYFREQ_NEGO (driver.conf) 93 * IDN_RETRYFREQ_CON 94 * IDN_RETRYFREQ_FIN 95 * 96 * Number of seconds to wait between retries of the respective 97 * message type. 98 * 99 * IDN_SMR_ALIGN (not tunable) 100 * 101 * The hardware registers that describe the SMR are based on a 64K 102 * aligned physical address. 103 * 104 * IDN_SMR_SIZE (OBP [only]) 105 * 106 * Total size of the SMR (Shared Memory Region) in bytes. 107 * 108 * IDN_NWR_SIZE (driver.conf) 109 * 110 * Total size of the NWR (NetWork Region) portion of the SMR which 111 * is actually used to support network activity. The NWR is managed 112 * as simply a pool of I/O buffers which are distributed by the 113 * Master domain to the Slaves for the purpose of communicating 114 * between each other. If not set then the entire SMR is used 115 * as the NWR. 116 * Req: IDN_NWR_SIZE <= IDN_SMR_SIZE 117 * 118 * IDN_SMR_BUFSIZE (driver.conf) 119 * 120 * Size of individual SMR buffers. The SMR is divided into chunks 121 * of IDN_SMR_BUFSIZE bytes. The IDN_MTU is based on this size 122 * and thus the IDN_SMR_BUFSIZE should be chosen based on performance. 123 * 124 * IDN_DATA_SIZE (NOT tunable) 125 * 126 * Portion of IDN_SMR_BUFSIZE that can contain raw non-IDN dependent 127 * data. We subtract IDN_ALIGNSIZE bytes to allow for fast bcopy 128 * alignment. 129 * Req: IDN_DATA_SIZE <= 130 * (IDN_SMR_BUFSIZE - sizeof (smr_pkthdr_t) - IDN_ALIGNSIZE) 131 * 132 * IDN_MTU (indirectly tunable via IDN_SMR_BUFSIZE) 133 * 134 * This size represents the portion of an SMR I/O buffers that can 135 * contain (ethernet headerless) data. 136 * Req: IDN_MTU <= IDN_DATA_SIZE - sizeof (ether_header) 137 * 138 * IDN_WINDOW_MAX (driver.conf) 139 * 140 * Maximum number of outstanding packets that are allowed per 141 * domain. If this value is exceeded for a particular domain 142 * no further I/Os will be transmitted to that domain until it 143 * has acknowledged enough of the previous transmission to bring 144 * down its outstanding I/O count (idn_domain.dio) below this 145 * value. In addition, if this value is exceeded then a Timer 146 * is scheduled to check for any response from the remote domain. 147 * 148 * IDN_WINDOW_INCR (driver.conf) 149 * 150 * As more channels/nets are activated on a particular domain 151 * the greater the number of possible outstanding data packets 152 * that can be outstanding to a given domain. Since this natural 153 * occurence can result in the outstanding-I/O count to a given 154 * domain to increase we run the risk of dropping into the 155 * IDN_WINDOW_MAX region even though the receiving domain 156 * may be fine with handling the load. In order to compensate 157 * for this increased activity and to not incur unjustified 158 * slips into the IDN_WINDOW_MAX region, the IDN_WINDOW_MAX 159 * value is adjusted by IDN_WINDOW_INCR for each channel/net 160 * that is activated for a given domain. 161 * 162 * IDN_WINDOW_EMAX (not tunable) 163 * 164 * The effective value of IDN_WINDOW_MAX once it has 165 * been adjusted by IDN_WINDOW_INCR. 166 * 167 * IDN_RECLAIM_MIN (driver.conf) 168 * 169 * Minimum number of outstanding packets that our allowed 170 * before subsequent sends will attempt to reclaim some number 171 * of outstanding data packets. 172 * 173 * IDN_RECLAIM_MAX (driver.conf) 174 * This value represents the maximum number of outstanding 175 * packets we will try to reclaim during a send once we've 176 * passed the IDN_RECLAIM_MIN boundary. 177 * 178 * IDN_MODUNLOADABLE (ndd) 179 * 180 * By default the IDN driver is unloadable. Setting this 181 * variable will allow the IDN driver to be unloaded provided 182 * it's not in use. 183 * 184 * IDN_LOWAT/IDN_HIWAT (driver.conf) 185 * 186 * Low/High water marks for the STREAM interface to IDN. 187 * 188 * IDN_MBOX_PER_NET (driver.conf) 189 * 190 * Number of mailbox entries that are allocated per channel/net. 191 * This value effectively represents the amount of outstanding 192 * activity that can reside at a domain. Increasing this value 193 * allows more packets to be in transit to a domain, however 194 * at some point there are diminishing returns since the receiver 195 * can only consume packets so fast. 196 * 197 * IDN_MAX_NETS (driver.conf) 198 * 199 * Maximum number of network interfaces (channels) that IDN 200 * is currently configured to allow. The absolute max is 201 * IDN_MAXMAX_NETS. We don't automatically default IDN_MAX_NETS 202 * to IDN_MAXMAX_NETS because it would mean wasted space in 203 * the mailbox region having to reserve mailboxes that will 204 * very likely go unused. The smaller this value the fewer 205 * the number of mailboxes in the SMR and thus the greater the 206 * number of possible I/O buffers available. 207 * Req: IDN_MAX_NETS <= IDN_MAXMAX_NETS 208 * 209 * IDN_CHECKSUM (driver.conf) 210 * 211 * If enabled, IDN validates the smr_pkthdr_t of incoming packets 212 * via a checksum, and calculates the checksum for outgoing packets. 213 * Only the first 3 fields of smr_pkthdr_t are checksummed and 214 * must be set to their expected values prior to calculating the 215 * checksum. Turned OFF by default when compiled DEBUG. 216 * 217 * IDN_SMR_MAXSIZE (not tunable) 218 * 219 * The absolute maximum size of the SMR region that we'll allow. 220 * Note that the virtual address space comes out kernelmap. 221 */ 222 #define IDN_AWOLMSG_INTERVAL 60 /* seconds */ 223 #define IDN_MSGWAIT_NEGO 20 /* seconds */ 224 #define IDN_MSGWAIT_CFG 40 225 #define IDN_MSGWAIT_CON 20 226 #define IDN_MSGWAIT_FIN 40 227 #define IDN_MSGWAIT_CMD 40 228 #define IDN_MSGWAIT_DATA 30 229 #define IDN_RETRYFREQ_NEGO 2 230 #define IDN_RETRYFREQ_CON 2 231 #define IDN_RETRYFREQ_FIN 3 232 233 #define IDN_SMR_BUFSIZE_MIN 512 234 #define IDN_SMR_BUFSIZE_MAX (512*1024) 235 #define IDN_SMR_BUFSIZE_DEF (16*1024) 236 237 #define IDN_SMR_SHIFT (16) 238 #define IDN_SMR_ALIGN (1 << IDN_SMR_SHIFT) /* 64K */ 239 #define IDN_SMR_SIZE idn_smr_size 240 #define IDN_NWR_SIZE idn_nwr_size 241 #define IDN_SMR_BUFSIZE idn_smr_bufsize 242 #define IDN_DATA_SIZE (IDN_SMR_BUFSIZE \ 243 - sizeof (smr_pkthdr_t) \ 244 - IDN_ALIGNSIZE) 245 #define IDN_MTU (IDN_DATA_SIZE - sizeof (struct ether_header)) 246 #define IDN_WINDOW_MAX idn_window_max 247 #define IDN_WINDOW_INCR idn_window_incr 248 #define IDN_WINDOW_EMAX idn_window_emax 249 #define IDN_RECLAIM_MIN idn_reclaim_min 250 #define IDN_RECLAIM_MAX idn_reclaim_max 251 #define IDN_MODUNLOADABLE idn_modunloadable 252 #define IDN_LOWAT idn_lowat 253 #define IDN_HIWAT idn_hiwat 254 #define IDN_MBOX_PER_NET idn_mbox_per_net 255 #define IDN_MAX_NETS idn_max_nets 256 #define IDN_CHECKSUM idn_checksum 257 #define IDN_SMR_MAXSIZE 96 258 #define _IDN_SMR_SIZE 32 /* 32M */ 259 #define _IDN_NWR_SIZE _IDN_SMR_SIZE /* 32M */ 260 #define _IDN_SMR_BUFSIZE (16 * 1024) /* 16K */ 261 262 263 #define IDN_TUNEVAR_NAME(v) (*(char **)((ulong_t)&(v)+(sizeof (ulong_t)))) 264 #define IDN_TUNEVAR_VALUE(v) (v) 265 266 /* 267 * History structure to support problem analysis. 268 */ 269 #define IDN_HISTORY_NUM 1024 270 #define IDN_HISTORY_LOG(op, d0, d1, d2) \ 271 if (idn_history) { \ 272 mutex_enter(&idnhlog.h_mutex); \ 273 idnhlog.h_log[idnhlog.h_index].e_time = TIMESTAMP(); \ 274 idnhlog.h_log[idnhlog.h_index].e_op = (ushort_t)(op); \ 275 idnhlog.h_log[idnhlog.h_index].e_data[0] = (ushort_t)(d0); \ 276 idnhlog.h_log[idnhlog.h_index].e_data[1] = (ushort_t)(d1); \ 277 idnhlog.h_log[idnhlog.h_index].e_data[2] = (ushort_t)(d2); \ 278 idnhlog.h_index++; \ 279 idnhlog.h_index &= (IDN_HISTORY_NUM - 1); \ 280 mutex_exit(&idnhlog.h_mutex); \ 281 } 282 283 #define IDNH_GSTATE 0x0001 /* d0=gstate, d1=, d2= */ 284 #define IDNH_DSTATE 0x0002 /* d0=domid, d1=dstate, d2=cpuid */ 285 #define IDNH_AWOL 0x0003 /* d0=domid, d1=dstate, d2=cpuid */ 286 #define IDNH_MASTERID 0x0004 /* d0=masterid, d1=oldid, d2= */ 287 #define IDNH_NEGO 0x0005 /* d0=domid, d1=ds_trans_on, d2=ds_connected */ 288 #define IDNH_FIN 0x0006 /* d0=domid, d1=finstate, d2= */ 289 #define IDNH_RELINK 0x0007 /* d0=domid, d1=dstate, d2=ds_relink */ 290 291 struct idn_h_entry { 292 hrtime_t e_time; 293 ushort_t e_op; 294 ushort_t e_data[3]; 295 }; 296 297 struct idn_history { 298 kmutex_t h_mutex; 299 int h_index; 300 struct idn_h_entry h_log[IDN_HISTORY_NUM]; 301 }; 302 #endif /* _KERNEL */ 303 304 /* 305 * IDN_SIGBPIL - Interrupt level at which IDN driver 306 * wakes up idn_sigbhandler_thread 307 */ 308 #define IDN_SIGBPIL PIL_3 309 310 /* 311 * Definition of sigbintr.sb_busy values which 312 * represents state of idn_sigbhandler. 313 */ 314 #define IDNSIGB_NOTREADY ((uchar_t)0) 315 #define IDNSIGB_INACTIVE ((uchar_t)1) 316 #define IDNSIGB_STARTED ((uchar_t)2) 317 #define IDNSIGB_ACTIVE ((uchar_t)3) 318 #define IDNSIGB_DIE ((uchar_t)4) 319 320 /* 321 * Some Xfire based macros that assume 4 cpus per board. 322 */ 323 #define CPUID_TO_BOARDID(c) ((c) >> 2) 324 #define MAX_CPU_PER_BRD 4 325 #define CPUSET_TO_BOARDSET(cset, bset) \ 326 { \ 327 register int c, b; \ 328 (bset) = 0; \ 329 for (b = 0; b < MAX_BOARDS; b++) \ 330 for (c = 0; c < MAX_CPU_PER_BRD; c++) \ 331 if (CPU_IN_SET((cset), \ 332 (b * MAX_CPU_PER_BRD) + c)) \ 333 (bset) |= 1 << b; \ 334 } 335 336 /* 337 * Macros to manipulate boardset and domainset masks. 338 */ 339 typedef ushort_t boardset_t; /* assumes max of 16 boards */ 340 typedef ushort_t domainset_t; /* assumes max of 16 domains */ 341 342 #define BOARDSET(brd) ((boardset_t)(1 << (brd))) 343 #define BOARDSET_ALL ((boardset_t)~0) 344 #define BOARD_IN_SET(set, brd) ((set) & BOARDSET(brd)) 345 #define BOARDSET_ADD(set, brd) ((set) |= BOARDSET(brd)) 346 #define BOARDSET_DEL(set, brd) ((set) &= ~BOARDSET(brd)) 347 #define DOMAINSET(d) ((domainset_t)1 << (d)) 348 #define DOMAINSET_ALL ((domainset_t)~0) 349 #define DOMAIN_IN_SET(s, d) ((s) & DOMAINSET(d)) 350 #define DOMAINSET_ADD(s, d) ((s) |= DOMAINSET(d)) 351 #define DOMAINSET_DEL(s, d) ((s) &= ~DOMAINSET(d)) 352 353 /* 354 * PFN_TO_SMADDR macro converts a PFN to a IDN_SMR_ALIGN'ed 355 * address suitable for the CIC bar/lar registers. 356 */ 357 #if (IDN_SMR_SHIFT <= MMU_PAGESHIFT) 358 #define PFN_TO_SMADDR(pfn) ((pfn) << (MMU_PAGESHIFT - IDN_SMR_SHIFT)) 359 #else 360 #define PFN_TO_SMADDR(pfn) ((pfn) >> (IDN_SMR_SHIFT - MMU_PAGESHIFT)) 361 #endif 362 363 /* 364 * Translate a physical address to a unique domain identifier. 365 * IMPORTANT - Assumes each board's memory is configured on a 8GB 366 * boundary. PA(8G) = PFN(1M). 367 */ 368 #define MEM8G_SHIFT 33 /* (1 << 33) == 8G */ 369 #define PADDR_TO_DOMAINID(paddr) ((int)((paddr) >> MEM8G_SHIFT) & 0xf) 370 371 #define VALID_NWROFFSET(off, align) \ 372 (((uint_t)(off) >= 0) && \ 373 ((size_t)(off) < MB2B(IDN_NWR_SIZE)) && \ 374 !((uint_t)(off) & ((align) - 1))) 375 #define VALID_NWRADDR(addr, align) \ 376 (((caddr_t)(addr) >= idn.smr.vaddr) && \ 377 VALID_NWROFFSET(((caddr_t)(addr) - idn.smr.vaddr), (align))) 378 #define VALID_DOMAINID(d) (((d) >= 0) && ((d) < MAX_DOMAINS)) 379 #define VALID_UDOMAINID(d) ((d) < MAX_DOMAINS) 380 #define VALID_CPUID(c) (((c) >= 0) && ((c) < NCPU)) 381 #define VALID_CHANNEL(c) (((c) >= 0) && ((c) < IDN_MAX_NETS)) 382 #define VALID_UCHANNEL(c) ((c) < IDN_MAX_NETS) 383 384 /* 385 * The following are bit values of idn_debug, currently 386 * only useful if compiled with DEBUG. 387 */ 388 #ifdef DEBUG 389 #define STRING(sss) char sss[20] 390 #define INUM2STR(mm, ss) inum2str((mm), (ss)) 391 392 #define IDNDBG_XDC 0x00000001 393 #define IDNDBG_XF 0x00000002 394 #define IDNDBG_REGS 0x00000004 395 #define IDNDBG_SMR 0x00000008 396 #define IDNDBG_PROTO 0x00000010 397 #define IDNDBG_STR 0x00000020 398 #define IDNDBG_DRV 0x00000040 399 #define IDNDBG_DATA 0x00000080 400 #define IDNDBG_STATE 0x00000100 401 #define IDNDBG_DLPI 0x00000200 402 #define IDNDBG_KERN 0x00000400 403 #define IDNDBG_ALLOC 0x00000800 404 #define IDNDBG_REMAP 0x00001000 405 #define IDNDBG_TIMER 0x00002000 406 #define IDNDBG_CHAN 0x00004000 407 #define IDNDBG_AWOL 0x00008000 408 #define IDNDBG_SYNC 0x00010000 409 #define _IDNDBG_UNUSED0 0x00020000 410 #define IDNDBG_HITLIST 0x00040000 411 #define IDNDBG_XMON 0x00080000 412 #define IDNDBG_TEST 0x80000000 413 #define IDNDBG_ALL ((uint_t)-1) 414 415 #define PR_ALL if (idn_debug) printf 416 #define PR_XDC if (idn_debug & IDNDBG_XDC) printf 417 #define PR_XF if (idn_debug & IDNDBG_XF) printf 418 #define PR_REGS if (idn_debug & IDNDBG_REGS) printf 419 #define PR_SMR if (idn_debug & IDNDBG_SMR) printf 420 #define PR_PROTO if (idn_debug & IDNDBG_PROTO) printf 421 #define PR_STR if (idn_debug & IDNDBG_STR) printf 422 #define PR_DRV if (idn_debug & IDNDBG_DRV) printf 423 #define PR_DATA if (idn_debug & IDNDBG_DATA) printf 424 #define PR_STATE if (idn_debug & IDNDBG_STATE) printf 425 #define PR_DLPI if (idn_debug & IDNDBG_DLPI) printf 426 #define PR_KERN if (idn_debug & IDNDBG_KERN) printf 427 #define PR_ALLOC if (idn_debug & IDNDBG_ALLOC) printf 428 #define PR_REMAP if (idn_debug & (IDNDBG_SMR|IDNDBG_REMAP)) printf 429 #define PR_TIMER if (idn_debug & IDNDBG_TIMER) printf 430 #define PR_CHAN if (idn_debug & IDNDBG_CHAN) printf 431 #define PR_AWOL if (idn_debug & (IDNDBG_PROTO|IDNDBG_AWOL)) printf 432 #define PR_SYNC if (idn_debug & IDNDBG_SYNC) printf 433 #define _PR_UNUSED0 if (idn_debug & _IDNDBG_UNUSED0) printf 434 #define PR_HITLIST if (idn_debug & IDNDBG_HITLIST) printf 435 #define PR_XMON if (idn_debug & IDNDBG_XMON) printf 436 #define PR_TEST if (idn_debug & IDNDBG_TEST) printf 437 #else 438 #define STRING(sss) char *sss = "" 439 #define INUM2STR(mm, ss) 440 441 #define PR_ALL if (0) printf 442 #define PR_XDC PR_ALL 443 #define PR_XF PR_ALL 444 #define PR_REGS PR_ALL 445 #define PR_SMR PR_ALL 446 #define PR_PROTO PR_ALL 447 #define PR_STR PR_ALL 448 #define PR_DRV PR_ALL 449 #define PR_DATA PR_ALL 450 #define PR_STATE PR_ALL 451 #define PR_DLPI PR_ALL 452 #define PR_KERN PR_ALL 453 #define PR_ALLOC PR_ALL 454 #define PR_REMAP PR_ALL 455 #define PR_TIMER PR_ALL 456 #define PR_CHAN PR_ALL 457 #define PR_AWOL PR_ALL 458 #define PR_SYNC PR_ALL 459 #define PR_SNOOP PR_ALL 460 #define PR_HITLIST PR_ALL 461 #define PR_XMON PR_ALL 462 #define PR_TEST PR_ALL 463 #endif /* DEBUG */ 464 465 #ifdef _KERNEL 466 /* 467 * IDN drivers fields. 468 * 469 * IDNMINPSZ Minimum packet size the IDN supports. 470 * 471 * IDNMAXPSZ Maximum packet size that IDN supports from upper 472 * layers. Is equal to IDN_MTU + ether_header. Note 473 * that the IDN driver could support larger packets 474 * however the infrastructure to support fragmentation 475 * does not (and should not) exist with respect to 476 * ethernet packet types. 477 */ 478 #ifdef DEBUG 479 #define IDNDESC "Inter-Domain Network (DEBUG)" 480 #else 481 #define IDNDESC "Inter-Domain Network" 482 #endif /* DEBUG */ 483 484 #define IDNIDNUM 8264 485 #define IDNNAME "idn" 486 #define IDNMINPSZ 0 /* set at idnopen() */ 487 #define IDNMAXPSZ 0 /* set at idnopen() */ 488 489 #endif /* _KERNEL */ 490 491 /* 492 * IDN Global States. 493 */ 494 typedef enum { 495 /* 0 */ IDNGS_OFFLINE = 0, /* idle */ 496 /* 1 */ IDNGS_CONNECT, /* connecting initial domain */ 497 /* 2 */ IDNGS_ONLINE, /* master selected */ 498 /* 3 */ IDNGS_DISCONNECT, /* local is unlinking */ 499 /* 4 */ IDNGS_RECONFIG, /* selecting new master */ 500 /* 5 */ _IDNGS_UNUNSED5, 501 /* 6 */ _IDNGS_UNUNSED6, 502 /* 7 */ _IDNGS_UNUNSED7, 503 /* 8 */ _IDNGS_UNUNSED8, 504 /* 9 */ _IDNGS_UNUNSED9, 505 /* 10 */ IDNGS_IGNORE /* ignore requests (fault injection) */ 506 } idn_gstate_t; 507 508 #ifdef _KERNEL 509 510 #define TIMESTAMP() (gethrtime() / 1000000ull) 511 512 /* 513 * Spaced defined in: 514 * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1. 515 */ 516 #define IDNSB_GSTATE_NEW 0 517 #define IDNSB_GSTATE_OLD 1 518 #define IDNSB_MASTERCPU 2 519 #define IDNSB_RESERVED 3 520 521 #define IDNSB_HWCHKPT_MAX 4 522 523 #define IDNSB_SIZE 72 524 /* 525 * This structure gets overlay onto: 526 * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1. 527 * 528 * This structure must be exactly IDNSB_SIZE bytes. 529 */ 530 typedef struct idnsb { 531 uchar_t id_gstate; 532 uchar_t id_pgstate; 533 uchar_t id_master_board; 534 uchar_t id_pmaster_board; 535 536 uchar_t reserved_DO_NOT_USE[24]; /* idnevent_t field */ 537 538 struct { 539 uchar_t d_board; 540 uchar_t d_state; 541 } id_status[MAX_DOMAINS]; 542 uint_t id_hwstate; 543 ushort_t id_hwchkpt[IDNSB_HWCHKPT_MAX]; 544 } idnsb_t; /* sizeof = 72 (0x48) 18X bytes */ 545 546 547 #define IDNSB_DOMAIN_UPDATE(dp) \ 548 { \ 549 mutex_enter(&idn.idnsb_mutex); \ 550 if (idn.idnsb) { \ 551 int domid = (dp)->domid; \ 552 if ((dp)->dcpu == IDN_NIL_DCPU) \ 553 idn.idnsb->id_status[domid].d_board = \ 554 (uchar_t)0xff; \ 555 else if ((dp)->dvote.v.board == 0) \ 556 idn.idnsb->id_status[domid].d_board = \ 557 (uchar_t)CPUID_TO_BOARDID((dp)->dcpu); \ 558 else \ 559 idn.idnsb->id_status[domid].d_board = \ 560 (uchar_t)(dp)->dvote.v.board; \ 561 idn.idnsb->id_status[domid].d_state = \ 562 (uchar_t)(dp)->dstate; \ 563 } \ 564 mutex_exit(&idn.idnsb_mutex); \ 565 } 566 /* 567 * The following definitions and macros pertain to the 568 * id_hwstate and id_hwchkpt[] fields. 569 * 570 * id_hwstate (m = mark: 1=open, 2=close) 571 * 0 1 2 3 4 5 6 7 572 * --------------------------------- 573 * | m | m | m | m | XX unused XXX | 574 * --------------------------------- 575 * | | | | 576 * | | | +- CACHE 577 * | | +- CHAN 578 * | +- LINK 579 * +- SMR 580 * 581 * Note that nibble 4 is used in DEBUG for noting cache 582 * flush progress through idnxf_flushall_ecache(). This 583 * will override id_hwchkpt[] since it only has room for 584 * 4 items, however the BBSRAM space is there and 585 * unofficially available :-o 586 * 587 * id_hwchkpt[0] = SMR boardset 588 * id_hwchkpt[1] = LINK boardset 589 * id_hwchkpt[2] = CHAN boardset 590 * id_hwchkpt[3] = CACHE boardset. 591 */ 592 #define IDNSB_CHKPT_SMR 0 593 #define IDNSB_CHKPT_LINK 1 594 #define IDNSB_CHKPT_CHAN 2 595 #define IDNSB_CHKPT_CACHE 3 596 #define IDNSB_CHKPT_UNUSED 4 /* This is the max you can have */ 597 598 #define _CHKPT_MARKIT(item, mark) \ 599 { \ 600 uint_t mk = (((uint_t)((mark) & 0xf)) << \ 601 (((sizeof (uint_t) << 1) - 1 - (item)) << 2)); \ 602 uint_t *sp = &idn.idnsb->id_hwstate; \ 603 ASSERT(idn.idnsb); \ 604 *sp &= ~(((uint_t)0xf) << (((sizeof (uint_t) << 1) \ 605 - 1 - (item)) << 2)); \ 606 *sp |= mk; \ 607 } 608 609 #define CHECKPOINT_OPENED(item, bset, mark) \ 610 { \ 611 mutex_enter(&idn.idnsb_mutex); \ 612 if (idn.idnsb) { \ 613 ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ 614 _CHKPT_MARKIT((item), (mark)); \ 615 sp[item] |= ((ushort_t)(bset)); \ 616 } \ 617 mutex_exit(&idn.idnsb_mutex); \ 618 } 619 620 #define CHECKPOINT_CLOSED(item, bset, mark) \ 621 { \ 622 mutex_enter(&idn.idnsb_mutex); \ 623 if (idn.idnsb) { \ 624 ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ 625 _CHKPT_MARKIT((item), (mark)); \ 626 sp[item] &= (ushort_t)~(bset); \ 627 } \ 628 mutex_exit(&idn.idnsb_mutex); \ 629 } 630 631 #define CHECKPOINT_CLEAR(item, mark) \ 632 { \ 633 mutex_enter(&idn.idnsb_mutex); \ 634 if (idn.idnsb) { \ 635 ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ 636 _CHKPT_MARKIT((item), (mark)); \ 637 sp[item] = 0; \ 638 } \ 639 mutex_exit(&idn.idnsb_mutex); \ 640 } 641 #ifdef DEBUG 642 #define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) \ 643 CHECKPOINT_CLEAR(IDNSB_CHKPT_UNUSED, (mark)) 644 #define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) \ 645 CHECKPOINT_OPENED(IDNSB_CHKPT_UNUSED, (bset), (mark)) 646 #else 647 #define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) 648 #define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) 649 #endif /* DEBUG */ 650 651 652 #ifdef DEBUG 653 #define IDN_GSTATE_TRANSITION(ns) \ 654 { \ 655 hrtime_t tstamp; \ 656 /*LINTED*/ \ 657 IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \ 658 tstamp = TIMESTAMP(); \ 659 ASSERT(IDN_GLOCK_IS_EXCL()); \ 660 PR_STATE("GSTATE:%ld: (l=%d) %s(%d) -> %s(%d)\n", \ 661 (uint64_t)tstamp, __LINE__, \ 662 idngs_str[idn.state], idn.state, \ 663 idngs_str[ns], (ns)); \ 664 mutex_enter(&idn.idnsb_mutex); \ 665 if (idn.idnsb) { \ 666 idn.idnsb->id_pgstate = (uchar_t)idn.state; \ 667 idn.idnsb->id_gstate = (uchar_t)(ns); \ 668 } \ 669 mutex_exit(&idn.idnsb_mutex); \ 670 idn.state = (ns); \ 671 } 672 #else 673 #define IDN_GSTATE_TRANSITION(ns) \ 674 { \ 675 IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \ 676 mutex_enter(&idn.idnsb_mutex); \ 677 if (idn.idnsb) { \ 678 idn.idnsb->id_pgstate = (uchar_t)idn.state; \ 679 idn.idnsb->id_gstate = (uchar_t)(ns); \ 680 } \ 681 mutex_exit(&idn.idnsb_mutex); \ 682 idn.state = (ns); \ 683 } 684 #endif /* DEBUG */ 685 686 /* 687 * IDN link/unlink operations occur asynchronously with respect to the 688 * caller. The following definitions are to support the return of 689 * success/failure back to the original requesting thread. It's 690 * unlikely to have multiple outstanding link/unlink requests so we 691 * just provide a very small cache of waiting list entries. If the 692 * cache becomes exhausted then additional ones are kmem_alloc'd. 693 */ 694 #define IDNOP_CACHE_SIZE 3 695 #define IDNOP_IN_CACHE(dwl) \ 696 (((dwl) >= &idn.dopers->_dop_wcache[0]) && \ 697 ((dwl) < &idn.dopers->_dop_wcache[IDNOP_CACHE_SIZE])) 698 699 typedef struct dop_waitlist { 700 struct dop_waitlist *dw_next; 701 domainset_t dw_reqset; 702 domainset_t dw_domset; 703 short dw_op; 704 domainset_t dw_errset; 705 idnsb_error_t *dw_idnerr; 706 short dw_errors[MAX_DOMAINS]; 707 } dop_waitlist_t; 708 709 typedef uint_t idn_xdcargs_t[4]; 710 typedef uint_t idn_chanset_t; 711 712 /* 713 * Types of synchronization zones which a connection 714 * could be in. 715 */ 716 typedef enum { 717 IDNSYNC_NIL, 718 IDNSYNC_CONNECT, 719 IDNSYNC_DISCONNECT 720 } idn_synccmd_t; 721 722 /* 723 * Type of sync-registration that is being requested. 724 */ 725 typedef enum { 726 IDNSYNC_REG_REG, 727 IDNSYNC_REG_NEW, 728 IDNSYNC_REG_QUERY 729 } idn_syncreg_t; 730 731 #define IDN_SYNC_NUMZONE 3 732 #define IDN_SYNC_GETZONE(s) ((((s) != IDNSYNC_CONNECT) && \ 733 ((s) != IDNSYNC_DISCONNECT)) ? \ 734 -1 : (int)(s) - 1) 735 #define IDN_SYNC_GETTRANS(s) (((s) == IDNSYNC_CONNECT) ? \ 736 idn.domset.ds_trans_on : \ 737 ((s) == IDNSYNC_DISCONNECT) ? \ 738 idn.domset.ds_trans_off : 0) 739 740 /* 741 * Generic states when in a state transition region. 742 * These ultimately map to domain states via 743 * a idn_xphase_t definition. General model: 744 * 745 * PEND 746 * /\ 747 * / \ 748 * | | 749 * V V 750 * SENT--->RCVD 751 * \ / 752 * \ / 753 * VV 754 * FINAL 755 * 756 * Start these types with PEND = 0 so that they're 757 * compatible with idnxs_state_table[] and idn_xphase_t 758 * phases that use the value as an index. 759 */ 760 typedef enum { 761 /* 0 */ IDNXS_PEND = 0, 762 /* 1 */ IDNXS_SENT, 763 /* 2 */ IDNXS_RCVD, 764 /* 3 */ IDNXS_FINAL, 765 /* 4 */ IDNXS_NIL 766 } idn_xstate_t; 767 768 /* 769 * Locking protocol: 770 * 771 * Each routine is called with SYNC_LOCK and 772 * the respective domain's DLOCK(EXCL) held. 773 * The routines must return with these locks 774 * still held. 775 */ 776 struct idn_msgtype; 777 778 typedef struct { 779 int t_state; 780 int (*t_check)(int domid, struct idn_msgtype *mtp, 781 idn_xdcargs_t xargs); 782 void (*t_action)(int domid, struct idn_msgtype *mtp, 783 idn_xdcargs_t xargs); 784 void (*t_error)(int domid, struct idn_msgtype *mtp, 785 idn_xdcargs_t xargs); 786 } idn_trans_t; 787 788 /* 789 * The callback routines (xt_final & xt_exit) are called with 790 * DLOCK and SYNC_LOCK held and they are required to return 791 * with these locks still held. 792 */ 793 typedef struct { 794 uint_t xt_msgtype; 795 idn_trans_t xt_trans[4]; 796 void (*xt_final)(int domid); 797 void (*xt_exit)(int domid, uint_t msgtype); 798 } idn_xphase_t; 799 800 /* 801 * Synchronization entry representing the synchronization 802 * state with respect to a given domain for a given zone. 803 */ 804 typedef struct idn_syncop { 805 struct idn_syncop *s_next; 806 int s_domid; 807 idn_synccmd_t s_cmd; 808 int s_msg; 809 810 domainset_t s_set_exp; 811 domainset_t s_set_rdy; 812 int (*s_transfunc)(int domid, void *arg); 813 void *s_transarg; 814 #ifdef DEBUG 815 int s_query[MAX_DOMAINS]; 816 #endif /* DEBUG */ 817 } idn_syncop_t; 818 819 #ifdef DEBUG 820 #define IDN_SYNC_QUERY_INIT(d) \ 821 (bzero((caddr_t)idn_domain[d].dsync.s_query, \ 822 sizeof (idn_domain[d].dsync.s_query))) 823 #define IDN_SYNC_QUERY_UPDATE(md, sd) (idn_domain[md].dsync.s_query[sd]++) 824 #else /* DEBUG */ 825 #define IDN_SYNC_QUERY_INIT(d) 826 #define IDN_SYNC_QUERY_UPDATE(md, sd) 827 #endif /* DEBUG */ 828 829 typedef struct { 830 idn_syncop_t *sc_op; 831 int sc_cnt; 832 } idn_synczone_t; 833 834 #endif /* _KERNEL */ 835 836 /* 837 * Vote Ticket used during negotiations and elections. 838 * 839 * 31 0 840 * ----------------------------------------- 841 * |m...|....|pppp|....|Cbbb|bccc|cccB|BBB1| 842 * ----------------------------------------- 843 * m [31] = master/slave 844 * . [30:24] = unused 845 * p [23:20] = priority 846 * . [19:16] = unused 847 * C [15] = connected (has master) 848 * b [14:11] = nmembrds-1 849 * c [10:5] = ncpus-1 850 * B [4:1] = board_id 851 * 1 [0] = one 852 */ 853 typedef union { 854 struct { 855 uint_t master :1; 856 uint_t unused0 :7; 857 uint_t priority :4; 858 uint_t unused1 :4; 859 uint_t connected :1; 860 uint_t nmembrds :4; 861 uint_t ncpus :6; 862 uint_t board :4; 863 uint_t one :1; 864 } v; 865 uint_t ticket; 866 } idn_vote_t; 867 868 #define IDNVOTE_PRI_MASK 0xf 869 #define IDNVOTE_MAXPRI 0xf 870 #define IDNVOTE_MINPRI 0 871 #define IDNVOTE_DEFPRI 1 /* must be larger than MINPRI */ 872 /* 873 * Initially: 874 * vote.v.priority = IDNVOTE_DEFPRI 875 * vote.v.one = 1 876 */ 877 #define IDNVOTE_INITIAL_TICKET ((IDNVOTE_DEFPRI << 20) | 1) 878 #define IDNVOTE_PRIVALUE(vvv) \ 879 ((int)vvv.v.priority + ((int)vvv.v.master ? IDNVOTE_MAXPRI : 0)) 880 881 /* 882 * During elections we only use the "elect" attributes of the 883 * election ticket, i.e. those physical attributes pertaining 884 * to the individual domain (priority, nboards, ncpus, board). 885 */ 886 #define IDNVOTE_ELECT_MASK 0x00f07fff 887 #define IDNVOTE_ELECT(tkt) ((tkt).ticket & IDNVOTE_ELECT_MASK) 888 #define IDNVOTE_BASICS_MASK 0x00f0ffff 889 #define IDNVOTE_BASICS(tkt) ((tkt).ticket & IDNVOTE_BASICS_MASK) 890 891 /* 892 * Values used in idn_select_master(). 893 */ 894 #define MASTER_IS_NONE 0 /* index into master_select_table */ 895 #define MASTER_IS_OTHER 1 896 #define MASTER_IS_LOCAL 2 897 #define MASTER_IS_REMOTE 3 898 899 typedef enum { 900 MASTER_SELECT_VOTE, 901 MASTER_SELECT_VOTE_RCFG, 902 MASTER_SELECT_CONNECT, 903 MASTER_SELECT_REMOTE, 904 MASTER_SELECT_LOCAL, 905 MASTER_SELECT_WAIT, 906 MASTER_SELECT_ERROR 907 } idn_master_select_t; 908 909 /* 910 * Used to synchronize completion of link/unlink with respect to 911 * the original requester (user). Necessary since link establishment 912 * occurs asynchronously. 913 */ 914 typedef enum { 915 /* 0 */ IDNOP_DISCONNECTED, /* successfully disconnected */ 916 /* 1 */ IDNOP_CONNECTED, /* successfully established */ 917 /* 2 */ IDNOP_ERROR /* error trying to link/unlink */ 918 } idn_opflag_t; 919 920 /* 921 * IDN Protocol Messages. 922 * These are IDN version (IDN_VERSION) dependent. 923 * 924 * ----- 7, --- 6,5.................0 925 * | ack | nack | IDN message type | 926 * ---------------------------------- 927 */ 928 #define IDN_VERSION 1 929 930 /* 931 * Must be no more than 6-bits. See DMV private data. 932 */ 933 #define IDNP_ACK 0x20 934 #define IDNP_NACK 0x10 935 #define IDNP_NULL 0x00 936 #define IDNP_NEGO 0x01 937 #define IDNP_CON 0x02 938 #define IDNP_CFG 0x03 939 #define IDNP_FIN 0x04 940 #define IDNP_CMD 0x05 941 #define IDNP_DATA 0x06 942 943 #define IDN_NUM_MSGTYPES 7 944 #define IDNP_ACKNACK_MASK (IDNP_ACK | IDNP_NACK) 945 #define IDNP_MSGTYPE_MASK 0x0f 946 #define VALID_MSGTYPE(m) (((m) >= IDNP_NEGO) && ((m) < IDN_NUM_MSGTYPES)) 947 948 typedef struct idn_msgtype { 949 ushort_t mt_mtype; 950 ushort_t mt_atype; 951 ushort_t mt_cookie; 952 } idn_msgtype_t; 953 954 /* 955 * IDN private data section of DMV layout (48 bits). 956 * 957 * 47......40,39.....34,33.....28,27..24,23......16,15..............0 958 * | version | msgtype | acktype | did | cpuid | cookie | 959 * ------------------------------------------------------------------ 960 * 961 * version Local domain's version of IDN software. 962 * msgtype Type of IDN message, e.g. nego, syn, etc. 963 * acktype If msgtype is a ACK or NACK, then acktype is the 964 * type of ack that we're receiving, e.g. ack/nego|ack. 965 * did Local domain's ID (netid) - system-wide unique. 966 * cpuid Local domain's CPU->cpu_id that sending message. 967 * cookie Cookie assigned by remote domain for authentication. 968 * For NEGO & NEGO+ACK messages, it's the cookie that 969 * the sender expects the receiver to use in subsequent 970 * messages. The upper-eight bits represent a timer 971 * cookie to associate timers with expected messages. 972 */ 973 #endif /* !_ASM */ 974 975 #ifdef _KERNEL 976 977 #define _IDNPD_COOKIE_MASK 0xffff 978 #define _IDNPD_COOKIE_SHIFT 32 979 #define _IDNPD_VER_MASK 0xff 980 #define _IDNPD_VER_SHIFT 24 981 #define _IDNPD_MTYPE_MASK 0x3f 982 #define _IDNPD_MTYPE_SHIFT 18 983 #define _IDNPD_ATYPE_MASK 0x3f 984 #define _IDNPD_ATYPE_SHIFT 12 985 #define _IDNPD_DOMID_MASK 0xf 986 #define _IDNPD_DOMID_SHIFT 8 987 #define _IDNPD_CPUID_MASK 0xff 988 #define _IDNPD_CPUID_SHIFT 0 989 990 #define _IDNPD_COOKIE_LEN 16 991 992 #ifndef _ASM 993 994 #define IDN_PD2COOKIE(pdata) \ 995 (((uint_t)((pdata) >> _IDNPD_COOKIE_SHIFT)) & _IDNPD_COOKIE_MASK) 996 #define IDN_PD2VER(pdata) \ 997 (((uint_t)((pdata) >> _IDNPD_VER_SHIFT)) & _IDNPD_VER_MASK) 998 #define IDN_PD2MTYPE(pdata) \ 999 (((uint_t)((pdata) >> _IDNPD_MTYPE_SHIFT)) & _IDNPD_MTYPE_MASK) 1000 #define IDN_PD2ATYPE(pdata) \ 1001 (((uint_t)((pdata) >> _IDNPD_ATYPE_SHIFT)) & _IDNPD_ATYPE_MASK) 1002 #define IDN_PD2DOMID(pdata) \ 1003 (((uint_t)((pdata) >> _IDNPD_DOMID_SHIFT)) & _IDNPD_DOMID_MASK) 1004 #define IDN_PD2CPUID(pdata) \ 1005 (((uint_t)((pdata) >> _IDNPD_CPUID_SHIFT)) & _IDNPD_CPUID_MASK) 1006 1007 #define IDN_MAKE_PDATA(mtype, atype, cookie) \ 1008 ((((uint64_t)(cookie) & UINT64_C(_IDNPD_COOKIE_MASK)) << \ 1009 _IDNPD_COOKIE_SHIFT) | \ 1010 (((uint64_t)idn.version & UINT64_C(_IDNPD_VER_MASK)) << \ 1011 _IDNPD_VER_SHIFT) | \ 1012 (((uint64_t)(mtype) & UINT64_C(_IDNPD_MTYPE_MASK)) << \ 1013 _IDNPD_MTYPE_SHIFT) | \ 1014 (((uint64_t)(atype) & UINT64_C(_IDNPD_ATYPE_MASK)) << \ 1015 _IDNPD_ATYPE_SHIFT) | \ 1016 (((uint64_t)idn.localid & UINT64_C(_IDNPD_DOMID_MASK)) << \ 1017 _IDNPD_DOMID_SHIFT) | \ 1018 (((uint64_t)CPU->cpu_id & UINT64_C(_IDNPD_CPUID_MASK)) << \ 1019 _IDNPD_CPUID_SHIFT)) 1020 1021 #define IDN_TCOOKIE(ck) (((ck) >> 8) & 0xff) 1022 #define IDN_DCOOKIE(ck) ((ck) & 0xff) 1023 #define IDN_MAKE_COOKIE(d, t) ((((t) & 0xff) << 8) | ((d) & 0xff)) 1024 1025 /* 1026 * IDNP_NEGO 1027 * 1028 * 127........96,95........64,63........32,31.........0 1029 * | vote | domainset | 1030 * ---------------------------------------------------- 1031 * vote Local/Remote domain's vote ticket. 1032 * domainset Mask of cpuids of domains to which 1033 * sender is connected. Position in domainset 1034 * designates respective domainid. 1035 * E.g. domainset[6] = 20 -> domainid 6 is 1036 * accessible via cpuid 20. 1037 * The slot for the receiving domain 1038 * contains the masterid of the sending 1039 * domain. If the sending domain does 1040 * not have a master then the entry will 1041 * contain IDNNEG_NO_MASTER. 1042 * 1043 * These macros insert a domainid-cpuid pair into the 1044 * domainset to be subsequently passed in a NEGO message, 1045 * also retrieve the cpuid from the domainset for a 1046 * given domainid. 1047 * 1048 * Usage: 1049 * Sending: 1050 * mask = IDNNEG_DSET_MYMASK(); 1051 * IDNNEG_DSET_INIT(dset, mask) 1052 * for (all domains except self) 1053 * IDNNEG_DSET_SET(dset, domain, cpuid, mask); 1054 * 1055 * Receiving: 1056 * IDNNEG_DSET_GET_MASK(dset, recv_domid, recv_mask); 1057 * for (all domains except recv_domid) 1058 * IDNNEG_DSET_GET(dset, domid, cpuid, recv_mask); 1059 */ 1060 typedef uint_t idnneg_dset_t[3]; 1061 1062 #define IDNNEG_NO_MASTER 0x3f 1063 #define __IDNNEG_DSET_CLEAR(dset) (bzero((caddr_t)(dset), \ 1064 sizeof (idnneg_dset_t))) 1065 #define IDNNEG_DSET_MYMASK() (idn_domain[idn.localid].dcpu) 1066 1067 #define IDNNEG_DSET_INIT(dset, mask) \ 1068 { \ 1069 __IDNNEG_DSET_CLEAR(dset); \ 1070 IDNNEG_DSET_SET((dset), idn.localid, (mask), idn.localid); \ 1071 } 1072 1073 #define IDNNEG_DSET_SET(dset, domid, cpuid, mask) \ 1074 { \ 1075 uint_t _s = ((domid) & 0xf) * 6; \ 1076 int _i = _s >> 5; \ 1077 uint_t _s0 = _s & 0x1f; \ 1078 uint_t _t = ((cpuid) ^ (mask)) & 0x3f; \ 1079 /*LINTED*/ \ 1080 ASSERT(((domid) == idn.localid) ? \ 1081 ((mask) == idn.localid) : ((cpuid) != (mask))); \ 1082 (dset)[_i] |= _t << _s0; \ 1083 if ((_s0 + 6) > 32) \ 1084 (dset)[_i + 1] |= _t >> (32 - _s0); \ 1085 } 1086 1087 #define __IDNNEG_DSET_GET(dset, domid, cpuid, mask, uncond) \ 1088 { \ 1089 uint_t _s = ((domid) & 0xf) * 6; \ 1090 int _i = _s >> 5; \ 1091 uint_t _s0 = _s & 0x1f; \ 1092 uint_t _s1 = (_s + 6) & 0x1f; \ 1093 (cpuid) = ((dset)[_i] >> _s0) & 0x3f; \ 1094 if ((_s0 + 6) > 32) \ 1095 (cpuid) |= ((dset)[_i + 1] << (6 - _s1)) & 0x3f; \ 1096 if ((cpuid) || (uncond)) \ 1097 (cpuid) ^= (mask) & 0x3f; \ 1098 else \ 1099 (cpuid) = -1; \ 1100 } 1101 1102 #define IDNNEG_DSET_GET_MASK(dset, domid, mask) \ 1103 __IDNNEG_DSET_GET((dset), (domid), (mask), (domid), 1) 1104 1105 #define IDNNEG_DSET_GET_MASTER(dset, master) \ 1106 __IDNNEG_DSET_GET((dset), idn.localid, (master), \ 1107 idn.localid+MAX_DOMAINS, 0) 1108 1109 #define IDNNEG_DSET_SET_MASTER(dset, domid, master) \ 1110 IDNNEG_DSET_SET((dset), (domid), (master), \ 1111 (domid)+MAX_DOMAINS) 1112 1113 #define IDNNEG_DSET_GET(dset, domid, cpuid, mask) \ 1114 __IDNNEG_DSET_GET((dset), (domid), (cpuid), (mask), 0) 1115 1116 /* 1117 * IDNP_CFG sub-types. 1118 * 1119 * Format of first 32 bit word in XDC: 1120 * stX = sub-type. 1121 * staX = sub-type arg. 1122 * X = position in idn_cfgsubtype_t.param.p[] array. 1123 * num = number of parameters in this XDC (0-3) 1124 * 1125 * 31...28,27...24,23...20,19...16,15...12,11....8,7.....3,2....0 1126 * | st0 . sta0 | st1 . sta1 | st2 . sta2 | phase | num | 1127 * -------------------------------------------------------------- 1128 * 1129 * Note that since the first 32-bit word in a (IDNP_CFG) XDC is used 1130 * for a sub-type, subsequent three 32-bits words are used for data that 1131 * pertains to respective sub-type, i.e. first sub-type corresponds 1132 * to first of the 3x32-bit words (pos=0), second sub-type corresponds 1133 * to second of the 3x32-bit words (pos=1), etc. Obviously, a max of 1134 * only three sub-types can be sent per xdc. 1135 */ 1136 #define IDNCFG_BARLAR 0x1 /* SMR base/limit pfn */ 1137 #define IDNCFGARG_BARLAR_BAR 0 /* BAR */ 1138 #define IDNCFGARG_BARLAR_LAR 1 /* LAR */ 1139 #define IDNCFG_MCADR 0x2 /* MC ADR, arg = board number */ 1140 #define IDNCFG_NMCADR 0x3 /* Number of MC ADRs to expect */ 1141 #define IDNCFG_CPUSET 0x4 /* dcpuset of remote domain */ 1142 #define IDNCFGARG_CPUSET_UPPER 0 /* 1st word */ 1143 #define IDNCFGARG_CPUSET_LOWER 1 /* 2nd word */ 1144 #define IDNCFG_NETID 0x5 /* dnetid, arg = 0 */ 1145 #define IDNCFG_BOARDSET 0x6 /* board set, arg = 0 */ 1146 #define IDNCFG_SIZE 0x7 /* SMR size parameters */ 1147 #define IDNCFGARG_SIZE_MTU 0 /* IDN_MTU */ 1148 #define IDNCFGARG_SIZE_BUF 1 /* IDN_SMR_BUFSIZE */ 1149 #define IDNCFGARG_SIZE_SLAB 2 /* IDN_SLAB_BUFCOUNT */ 1150 #define IDNCFGARG_SIZE_NWR 3 /* IDN_NWR_SIZE */ 1151 #define IDNCFG_DATAMBOX 0x8 /* SMR data mailbox info */ 1152 #define IDNCFGARG_DATAMBOX_TABLE 0 /* recvmbox table */ 1153 #define IDNCFGARG_DATAMBOX_DOMAIN 1 /* domain's recvmbox */ 1154 #define IDNCFGARG_DATAMBOX_INDEX 2 /* domain's index into table */ 1155 #define IDNCFG_DATASVR 0x9 /* Data server info */ 1156 #define IDNCFGARG_DATASVR_MAXNETS 0 /* max # of nets/channels */ 1157 #define IDNCFGARG_DATASVR_MBXPERNET 1 /* # mbox per net/channel */ 1158 #define IDNCFG_OPTIONS 0xa /* various options */ 1159 #define IDNCFGARG_CHECKSUM 0 /* IDN_CHECKSUM */ 1160 1161 #define IDN_CFGPARAM(st, sta) ((uchar_t)((((st) & 0xf) << 4) | ((sta) & 0xf))) 1162 #define IDN_CFGPARAM_TYPE(p) (((p) >> 4) & 0xf) 1163 #define IDN_CFGPARAM_ARG(p) ((p) & 0xf) 1164 1165 typedef union { 1166 struct { 1167 uchar_t p[3]; 1168 uchar_t _num_phase; /* info.num, info.phase used instead */ 1169 } param; 1170 struct { 1171 uint_t _p : 24; /* param.p[] used instead */ 1172 uint_t num : 2; 1173 uint_t phase : 6; 1174 } info; 1175 uint_t val; 1176 } idn_cfgsubtype_t; 1177 1178 /* 1179 * IDN_MASTER_NCFGITEMS 1180 * Minimum number of config items expected from master. 1181 * 1182 * IDN_SLAVE_NCFGITEMS 1183 * Number of config items expected from slave. 1184 */ 1185 #define IDN_MASTER_NCFGITEMS 17 /* max = +14 (mcadrs) */ 1186 #define IDN_SLAVE_NCFGITEMS 12 1187 1188 /* 1189 * IDNP_CMD sub-types. 1190 */ 1191 typedef enum { 1192 /* 1 */ IDNCMD_SLABALLOC = 1, /* Request to allocate a slab */ 1193 /* 2 */ IDNCMD_SLABFREE, /* Request to free a slab */ 1194 /* 3 */ IDNCMD_SLABREAP, /* Reap any free slabs */ 1195 /* 4 */ IDNCMD_NODENAME /* Query nodename of domain */ 1196 } idn_cmd_t; 1197 1198 #define VALID_IDNCMD(c) (((int)(c) >= (int)IDNCMD_SLABALLOC) && \ 1199 ((int)(c) <= (int)IDNCMD_NODENAME)) 1200 /* 1201 * IDNP_NACK 1202 */ 1203 typedef enum { 1204 /* 1 */ IDNNACK_NOCONN = 1, 1205 /* 2 */ IDNNACK_BADCHAN, 1206 /* 3 */ IDNNACK_BADCFG, 1207 /* 4 */ IDNNACK_BADCMD, 1208 /* 5 */ IDNNACK_RETRY, 1209 /* 6 */ IDNNACK_DUP, 1210 /* 7 */ IDNNACK_EXIT, 1211 /* 8 */ IDNNACK_RESERVED1, 1212 /* 9 */ IDNNACK_RESERVED2, 1213 /* 10 */ IDNNACK_RESERVED3 1214 } idn_nack_t; 1215 1216 /* 1217 * IDNP_CON sub-types. 1218 */ 1219 typedef enum { 1220 /* 0 */ IDNCON_OFF = 0, 1221 /* 1 */ IDNCON_NORMAL, /* regular connect sequence */ 1222 /* 2 */ IDNCON_QUERY /* query for connect info */ 1223 } idn_con_t; 1224 1225 /* 1226 * IDNP_FIN sub-types. 1227 */ 1228 typedef enum { 1229 /* 0 */ IDNFIN_OFF = 0, /* active, no fin */ 1230 /* 1 */ IDNFIN_NORMAL, /* normal disconnect req */ 1231 /* 2 */ IDNFIN_FORCE_SOFT, /* normal dis, force if goes AWOL */ 1232 /* 3 */ IDNFIN_FORCE_HARD, /* force disconnect of AWOL domain */ 1233 /* 4 */ IDNFIN_QUERY /* query for fin info */ 1234 } idn_fin_t; 1235 1236 #define VALID_FIN(f) (((int)(f) > 0) && \ 1237 ((int)(f) < (int)IDNFIN_QUERY)) 1238 #define FIN_IS_FORCE(f) (((f) == IDNFIN_FORCE_SOFT) || \ 1239 ((f) == IDNFIN_FORCE_HARD)) 1240 1241 /* 1242 * FIN ARG types - reasons a FIN was sent. 1243 */ 1244 typedef enum { 1245 /* 0 */ IDNFIN_ARG_NONE = 0, /* no argument */ 1246 /* 1 */ IDNFIN_ARG_SMRBAD, /* SMR is corrupted */ 1247 /* 2 */ IDNFIN_ARG_CPUCFG, /* missing cpu per board */ 1248 /* 3 */ IDNFIN_ARG_HWERR, /* error programming hardware */ 1249 /* 4 */ IDNFIN_ARG_CFGERR_FATAL, /* Fatal error during CONFIG */ 1250 /* 5 */ IDNFIN_ARG_CFGERR_MTU, /* MTU sizes conflict */ 1251 /* 6 */ IDNFIN_ARG_CFGERR_BUF, /* SMR_BUF_SIZE conflicts */ 1252 /* 7 */ IDNFIN_ARG_CFGERR_SLAB, /* SLAB sizes conflict */ 1253 /* 8 */ IDNFIN_ARG_CFGERR_NWR, /* NWR sizes conflict */ 1254 /* 9 */ IDNFIN_ARG_CFGERR_NETS, /* MAX_NETS conflict */ 1255 /* 10 */ IDNFIN_ARG_CFGERR_MBOX, /* MBOX_PER_NET conflict */ 1256 /* 11 */ IDNFIN_ARG_CFGERR_NMCADR, /* NMCADR mismatches actual */ 1257 /* 12 */ IDNFIN_ARG_CFGERR_MCADR, /* missing some MCADRs */ 1258 /* 13 */ IDNFIN_ARG_CFGERR_CKSUM, /* checksum settings conflict */ 1259 /* 14 */ IDNFIN_ARG_CFGERR_SMR /* SMR sizes conflict */ 1260 } idn_finarg_t; 1261 1262 #define IDNFIN_ARG_IS_FATAL(fa) ((fa) > IDNFIN_ARG_NONE) 1263 1264 #define SET_FIN_TYPE(x, t) \ 1265 ((x) &= 0xffff, (x) |= (((uint_t)(t) & 0xffff) << 16)) 1266 #define SET_FIN_ARG(x, a) \ 1267 ((x) &= ~0xffff, (x) |= ((uint_t)(a) & 0xffff)) 1268 #define GET_FIN_TYPE(x) ((idn_fin_t)(((x) >> 16) & 0xffff)) 1269 #define GET_FIN_ARG(x) ((idn_finarg_t)((x) & 0xffff)) 1270 1271 #define FINARG2IDNKERR(fa) \ 1272 (((fa) == IDNFIN_ARG_SMRBAD) ? IDNKERR_SMR_CORRUPTED : \ 1273 ((fa) == IDNFIN_ARG_CPUCFG) ? IDNKERR_CPU_CONFIG : \ 1274 ((fa) == IDNFIN_ARG_HWERR) ? IDNKERR_HW_ERROR : \ 1275 ((fa) == IDNFIN_ARG_CFGERR_FATAL) ? IDNKERR_HW_ERROR : \ 1276 ((fa) == IDNFIN_ARG_CFGERR_MTU) ? IDNKERR_CONFIG_MTU : \ 1277 ((fa) == IDNFIN_ARG_CFGERR_BUF) ? IDNKERR_CONFIG_BUF : \ 1278 ((fa) == IDNFIN_ARG_CFGERR_SLAB) ? IDNKERR_CONFIG_SLAB : \ 1279 ((fa) == IDNFIN_ARG_CFGERR_NWR) ? IDNKERR_CONFIG_NWR : \ 1280 ((fa) == IDNFIN_ARG_CFGERR_NETS) ? IDNKERR_CONFIG_NETS : \ 1281 ((fa) == IDNFIN_ARG_CFGERR_MBOX) ? IDNKERR_CONFIG_MBOX : \ 1282 ((fa) == IDNFIN_ARG_CFGERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \ 1283 ((fa) == IDNFIN_ARG_CFGERR_MCADR) ? IDNKERR_CONFIG_MCADR : \ 1284 ((fa) == IDNFIN_ARG_CFGERR_CKSUM) ? IDNKERR_CONFIG_CKSUM : \ 1285 ((fa) == IDNFIN_ARG_CFGERR_SMR) ? IDNKERR_CONFIG_SMR : 0) 1286 1287 /* 1288 * FIN SYNC types. 1289 */ 1290 #define IDNFIN_SYNC_OFF 0 /* not set */ 1291 #define IDNFIN_SYNC_NO 1 /* no-sync necessary */ 1292 #define IDNFIN_SYNC_YES 2 /* do fin synchronously */ 1293 1294 typedef short idn_finsync_t; 1295 1296 /* 1297 * IDNP_FIN options. 1298 */ 1299 typedef enum { 1300 /* 0 */ IDNFIN_OPT_NONE = 0, /* none (used w/query) */ 1301 /* 1 */ IDNFIN_OPT_UNLINK, /* normal unlink request */ 1302 /* 2 */ IDNFIN_OPT_RELINK /* disconnect and retry link */ 1303 } idn_finopt_t; 1304 1305 #define VALID_FINOPT(f) (((f) == IDNFIN_OPT_UNLINK) || \ 1306 ((f) == IDNFIN_OPT_RELINK)) 1307 1308 #define FIN_MASTER_DOMID(x) (((((x) >> 16) & 0xffff) == 0xffff) ? \ 1309 IDN_NIL_DOMID : (((x) >> 16) & 0xffff)) 1310 #define FIN_MASTER_CPUID(x) ((((x) & 0xffff) == 0xffff) ? \ 1311 IDN_NIL_DCPU : ((x) & 0xfff)) 1312 #define MAKE_FIN_MASTER(d, c) ((((uint_t)(d) & 0xffff) << 16) | \ 1313 ((uint_t)(c) & 0xffff)) 1314 #define NIL_FIN_MASTER MAKE_FIN_MASTER(IDN_NIL_DOMID, IDN_NIL_DCPU) 1315 1316 #ifdef DEBUG 1317 #define IDN_FSTATE_TRANSITION(dp, ns) \ 1318 { \ 1319 int _id; \ 1320 _id = (dp)->domid; \ 1321 if ((dp)->dfin != (ns)) { \ 1322 hrtime_t tstamp; \ 1323 tstamp = TIMESTAMP(); \ 1324 IDN_HISTORY_LOG(IDNH_FIN, _id, (ns), 0); \ 1325 PR_STATE("FSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \ 1326 "%s(%d) -> %s(%d)\n", \ 1327 (uint64_t)tstamp, _id, \ 1328 __LINE__, \ 1329 ((dp)->dcpu == IDN_NIL_DCPU) ? -1 : \ 1330 CPUID_TO_BOARDID((dp)->dcpu), \ 1331 (dp)->dcpu, \ 1332 idnfin_str[(dp)->dfin], (dp)->dfin, \ 1333 idnfin_str[ns], (ns)); \ 1334 (dp)->dfin = (ns); \ 1335 } \ 1336 } 1337 #else 1338 #define IDN_FSTATE_TRANSITION(dp, ns) \ 1339 { \ 1340 IDN_HISTORY_LOG(IDNH_FIN, (dp)->domid, (ns), 0); \ 1341 (dp)->dfin = (ns); \ 1342 } 1343 #endif /* DEBUG */ 1344 1345 #endif /* !_ASM */ 1346 #endif /* _KERNEL */ 1347 1348 #ifndef _ASM 1349 /* 1350 * IDN Per-Domain States. 1351 */ 1352 typedef enum { 1353 /* 0 */ IDNDS_CLOSED, /* idle */ 1354 /* 1 */ IDNDS_NEGO_PEND, /* link initiating */ 1355 /* 2 */ IDNDS_NEGO_SENT, /* link initiated, nego sent */ 1356 /* 3 */ IDNDS_NEGO_RCVD, /* link wanted, nego+ack sent */ 1357 /* 4 */ IDNDS_CONFIG, /* passing config info, prgm hw */ 1358 /* 5 */ IDNDS_CON_PEND, /* connection pending */ 1359 /* 6 */ IDNDS_CON_SENT, /* con sent */ 1360 /* 7 */ IDNDS_CON_RCVD, /* con sent & received */ 1361 /* 8 */ IDNDS_CON_READY, /* ready to establish link */ 1362 /* 9 */ IDNDS_CONNECTED, /* established - linked */ 1363 /* 10 */ IDNDS_FIN_PEND, /* unlink initiating */ 1364 /* 11 */ IDNDS_FIN_SENT, /* unlink initiated, fin sent */ 1365 /* 12 */ IDNDS_FIN_RCVD, /* unlink wanted by remote */ 1366 /* 13 */ IDNDS_DMAP /* deprogramming hw */ 1367 } idn_dstate_t; 1368 1369 #define IDNDS_IS_CLOSED(dp) (((dp)->dstate == IDNDS_CLOSED) || \ 1370 ((dp)->dstate == IDNDS_DMAP)) 1371 #define IDNDS_IS_CONNECTING(dp) (((dp)->dstate > IDNDS_CLOSED) && \ 1372 ((dp)->dstate < IDNDS_CONNECTED)) 1373 #define IDNDS_IS_DISCONNECTING(dp) ((dp)->dstate > IDNDS_CONNECTED) 1374 #define IDNDS_CONFIG_DONE(dp) (((dp)->dstate == IDNDS_CLOSED) || \ 1375 ((dp)->dstate > IDNDS_CONFIG)) 1376 #define IDNDS_SYNC_TYPE(dp) (((dp)->dfin_sync != IDNFIN_SYNC_OFF) ? \ 1377 (dp)->dfin_sync : \ 1378 ((dp)->dstate < IDNDS_CON_READY) ? \ 1379 IDNFIN_SYNC_NO : IDNFIN_SYNC_YES) 1380 1381 #endif /* !_ASM */ 1382 1383 #ifdef _KERNEL 1384 #ifndef _ASM 1385 /* 1386 * --------------------------------------------------------------------- 1387 */ 1388 typedef struct idn_timer { 1389 struct idn_timer *t_forw, 1390 *t_back; 1391 struct idn_timerq *t_q; 1392 1393 timeout_id_t t_id; 1394 short t_domid; 1395 short t_onq; 1396 ushort_t t_type; 1397 ushort_t t_subtype; 1398 uint_t t_cookie; 1399 #ifdef DEBUG 1400 hrtime_t t_posttime; 1401 hrtime_t t_exectime; 1402 #endif /* DEBUG */ 1403 } idn_timer_t; 1404 1405 #define IDN_TIMER_PUBLIC_COOKIE 0xf 1406 1407 #define IDN_TIMERQ_IS_LOCKED(tq) (MUTEX_HELD(&(tq)->tq_mutex)) 1408 #define IDN_TIMERQ_LOCK(tq) (mutex_enter(&(tq)->tq_mutex)) 1409 #define IDN_TIMERQ_UNLOCK(tq) (mutex_exit(&(tq)->tq_mutex)) 1410 1411 #define IDN_TIMERQ_INIT(tq) (idn_timerq_init(tq)) 1412 #define IDN_TIMERQ_DEINIT(tq) (idn_timerq_deinit(tq)) 1413 #define IDN_TIMER_ALLOC() (idn_timer_alloc()) 1414 #define IDN_TIMER_FREE(tp) (idn_timer_free(tp)) 1415 1416 #define IDN_TIMER_START(tq, tp, tim) \ 1417 (idn_timer_start((tq), (tp), (tim))) 1418 #define IDN_TIMER_STOP(tq, typ, ck) \ 1419 ((void) idn_timer_stop((tq), (typ), (ck))) 1420 #define IDN_TIMER_STOPALL(tp) \ 1421 ((void) idn_timer_stopall(tp)) 1422 #define IDN_TIMER_GET(tq, typ, tp, ck) \ 1423 { \ 1424 mutex_enter(&((tq)->tq_mutex)); \ 1425 (tp) = idn_timer_get((tq), (typ), (ck)); \ 1426 mutex_exit(&((tq)->tq_mutex)); \ 1427 } 1428 #define IDN_TIMER_DEQUEUE(tq, tp) \ 1429 (idn_timer_dequeue((tq), (tp))) 1430 #ifdef DEBUG 1431 #define IDN_TIMER_POST(tp) \ 1432 ((tp)->t_posttime = gethrtime(), (tp)->t_exectime = 0) 1433 #define IDN_TIMER_EXEC(tp) ((tp)->t_exectime = gethrtime()) 1434 #else /* DEBUG */ 1435 #define IDN_TIMER_POST(tp) 1436 #define IDN_TIMER_EXEC(tp) 1437 #endif /* DEBUG */ 1438 1439 #define IDN_MSGTIMER_START(domid, typ, subtyp, tim, ckp) \ 1440 { \ 1441 idn_timer_t *_tp; \ 1442 char _str[15]; \ 1443 ushort_t *_ckp = (ckp); \ 1444 inum2str((typ), _str); \ 1445 PR_TIMER("msgtimer:%d: START: type = %s (0x%x)\n", \ 1446 (domid), _str, (typ)); \ 1447 _tp = IDN_TIMER_ALLOC(); \ 1448 _tp->t_type = (ushort_t)(typ); \ 1449 _tp->t_subtype = (ushort_t)(subtyp); \ 1450 _tp->t_domid = (short)(domid); \ 1451 _tp->t_cookie = (_ckp) ? *(_ckp) : 0; \ 1452 IDN_TIMER_POST(_tp); \ 1453 if (_ckp) { \ 1454 *(_ckp) = IDN_TIMER_START(&idn_domain[domid].dtimerq, \ 1455 _tp, (tim)); \ 1456 } else { \ 1457 (void) IDN_TIMER_START(&idn_domain[domid].dtimerq, \ 1458 _tp, (tim)); \ 1459 } \ 1460 } 1461 #define IDN_MSGTIMER_STOP(domid, typ, ck) \ 1462 { \ 1463 char _str[15]; \ 1464 inum2str((typ), _str); \ 1465 PR_TIMER("msgtimer:%d: STOP: type = %s (0x%x), " \ 1466 "cookie = 0x%x\n", \ 1467 (domid), _str, (typ), (ck)); \ 1468 IDN_TIMER_STOP(&idn_domain[domid].dtimerq, (typ), (ck)); \ 1469 } 1470 #define IDN_MSGTIMER_GET(dp, typ, tp, ck) \ 1471 IDN_TIMER_GET(&(dp)->dtimerq, (typ), (tp), (ck)) 1472 1473 /* 1474 * IDN_SLABALLOC_WAITTIME 1475 * Max wait time in ticks that local domains waits for 1476 * master to respond to a slab allocation request. Has 1477 * to be at least as long as wait time for a response to 1478 * the command. 1479 */ 1480 #define IDN_SLABALLOC_WAITTIME ((3 * idn_msg_waittime[IDNP_CMD]) / 2) 1481 1482 /* 1483 * Domain state transition macros. 1484 */ 1485 #ifdef DEBUG 1486 #define IDN_DSTATE_TRANSITION(dp, ns) \ 1487 { \ 1488 int id; \ 1489 hrtime_t tstamp; \ 1490 tstamp = TIMESTAMP(); \ 1491 ASSERT(RW_WRITE_HELD(&(dp)->drwlock)); \ 1492 id = (dp)->domid; \ 1493 IDN_HISTORY_LOG(IDNH_DSTATE, id, (ns), \ 1494 (uint_t)(dp)->dcpu); \ 1495 PR_STATE("DSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \ 1496 "%s(%d) -> %s(%d)\n", \ 1497 (uint64_t)tstamp, id, \ 1498 __LINE__, \ 1499 ((dp)->dcpu == IDN_NIL_DCPU) ? \ 1500 -1 : CPUID_TO_BOARDID((dp)->dcpu), \ 1501 (dp)->dcpu, \ 1502 idnds_str[(dp)->dstate], (dp)->dstate, \ 1503 idnds_str[ns], (ns)); \ 1504 (dp)->dstate = (ns); \ 1505 IDNSB_DOMAIN_UPDATE(dp); \ 1506 } 1507 #else 1508 #define IDN_DSTATE_TRANSITION(dp, ns) \ 1509 { \ 1510 IDN_HISTORY_LOG(IDNH_DSTATE, (dp)->domid, \ 1511 (ns), (uint_t)(dp)->dcpu); \ 1512 (dp)->dstate = (ns); \ 1513 IDNSB_DOMAIN_UPDATE(dp); \ 1514 } 1515 #endif /* DEBUG */ 1516 1517 #define IDN_XSTATE_TRANSITION(dp, xs) \ 1518 { \ 1519 int _xs = (xs); \ 1520 (dp)->dxstate = _xs; \ 1521 if (_xs != IDNXS_NIL) { \ 1522 ASSERT((dp)->dxp); \ 1523 IDN_DSTATE_TRANSITION((dp), \ 1524 (dp)->dxp->xt_trans[_xs].t_state); \ 1525 } \ 1526 } 1527 1528 /* 1529 * --------------------------------------------------------------------- 1530 * IDN Per-Domain Data 1531 * 1532 * The comment to the right of the respective field represents 1533 * what lock protects that field. If there is no comment then 1534 * no lock is required to access the field. 1535 * --------------------------------------------------------------------- 1536 */ 1537 1538 #define MAXDNAME 32 1539 1540 typedef struct idn_domain { 1541 krwlock_t drwlock; 1542 /* 1543 * Assigned domid for domain. Never 1544 * changes once idn_domain[] is 1545 * initialized. We are guaranteed that 1546 * all domains in IDN will have a 1547 * uniqueue domid in the range (0-15). 1548 */ 1549 int domid; 1550 idn_dstate_t dstate; /* drwlock */ 1551 idn_xstate_t dxstate; /* drwlock */ 1552 /* 1553 * Gotten from uname -n for local 1554 * domain. Remote domains pass 1555 * theirs during Config phase. 1556 */ 1557 char dname[MAXDNAME]; /* drwlock */ 1558 /* 1559 * IDN-wide unique identifier for the 1560 * given domain. This value will be 1561 * the same as the domid. 1562 */ 1563 ushort_t dnetid; /* drwlock */ 1564 idn_vote_t dvote; /* drwlock */ 1565 /* 1566 * Used during FIN sequenece to 1567 * determine what type of shutdown 1568 * (unlink) we're executing with 1569 * respect to the given domain. 1570 */ 1571 idn_fin_t dfin; /* drwlock */ 1572 /* 1573 * A non-zero value for dfin_sync 1574 * indicates that unlink of respective 1575 * domain does not need to be performed 1576 * synchronously among all the IDN 1577 * member domains. 1578 */ 1579 short dfin_sync; /* grwlock */ 1580 /* 1581 * Cookie used to determine the 1582 * proper context in which we're 1583 * receiving messages from the given 1584 * domain. Assigned cookies are exchanged 1585 * during initial NEGO messages. 1586 */ 1587 ushort_t dcookie_send; /* drwlock */ 1588 ushort_t dcookie_recv; /* drwlock */ 1589 short dcookie_err; /* drwlock */ 1590 int dcookie_errcnt; /* drwlock */ 1591 /* 1592 * Primary target cpu for sending 1593 * messages. Can change to help 1594 * distribute interrupts on receiving 1595 * side. 1596 */ 1597 int dcpu; /* drwlock */ 1598 /* 1599 * Used to store dcpu from a previous 1600 * life. Only used when requesting 1601 * a RELINK with a domain we were just 1602 * previously linked with. Thus, it 1603 * does represent a valid cpu in the 1604 * remote domain. 1605 */ 1606 int dcpu_save; /* drwlock */ 1607 /* 1608 * Used to store from which cpu the 1609 * last message was received. 1610 */ 1611 int dcpu_last; 1612 /* 1613 * Transition phase area. This field 1614 * points to the proper phase structure 1615 * depending on what stage the given 1616 * domain is in. 1617 */ 1618 idn_xphase_t *dxp; /* drwlock */ 1619 /* 1620 * Actual synchronization object for 1621 * the given domain. 1622 */ 1623 idn_syncop_t dsync; /* drwlock & idn.sync.sz_mutex */ 1624 /* 1625 * Slab information for given domain. 1626 * If the local domain is a master, 1627 * then this field in each domain is used 1628 * to store which slabs have been assigned 1629 * to given domain. If the local domain 1630 * is a slave, then this information is 1631 * NULL for all remote idn_domain[] 1632 * entries, but for local domain holds 1633 * those slabs assigned to local domain. 1634 */ 1635 smr_slab_t *dslab; /* dslab_rwlock */ 1636 short dnslabs; /* dslab_rwlock */ 1637 short dslab_state; /* dslab_rwlock */ 1638 krwlock_t dslab_rwlock; 1639 /* 1640 * Set of cpus belonging to domain. 1641 */ 1642 cpuset_t dcpuset; /* drwlock */ 1643 1644 int dncpus; /* drwlock */ 1645 /* 1646 * Index into dcpumap to determine 1647 * which cpu to target next for 1648 * interrupt. Intended to allow fair 1649 * distribution of interrupts on 1650 * remote domain. 1651 */ 1652 uint_t dcpuindex; /* drwlock */ 1653 /* 1654 * Quick look-up map of cpus belonging 1655 * to domain. Used to select next target. 1656 */ 1657 uchar_t *dcpumap; /* drwlock */ 1658 /* 1659 * Non-zero indicates outstanding 1660 * I/O's to given domain. 1661 */ 1662 int dio; /* drwlock */ 1663 int dioerr; /* drwlock */ 1664 /* 1665 * Set when we fail to allocate a buffer 1666 * for a domain. Dictates whether to 1667 * reclaim max buffers or not. 1668 */ 1669 lock_t diowanted; 1670 /* 1671 * Set when remote domain does not 1672 * seem to be picking up messages sent 1673 * to it. Non-zero indicates we have 1674 * an outstanding "ping" to domain. 1675 */ 1676 lock_t diocheck; /* drwlock */ 1677 short dslabsize; /* drwlock */ 1678 uint_t dmtu; /* drwlock */ 1679 1680 uint_t dbufsize; /* drwlock */ 1681 short dnwrsize; /* drwlock */ 1682 lock_t dreclaim_inprogress; /* drwlock */ 1683 uchar_t dreclaim_index; /* drwlock */ 1684 /* 1685 * The following field is primarily 1686 * used during CFG exchange to keep 1687 * track of certain per-domain information. 1688 */ 1689 union { /* all - drwlock */ 1690 struct { 1691 uint_t _dcfgphase : 6; 1692 uint_t _dcfgsnddone : 1; 1693 uint_t _dcfgrcvdone : 1; 1694 uint_t _dcksum : 2; 1695 uint_t _dmaxnets : 6; 1696 uint_t _dmboxpernet : 9; 1697 uint_t _dncfgitems : 6; 1698 uint_t _drecfg : 1; 1699 } _s; 1700 int _dtmp; 1701 } _u; 1702 /* 1703 * Each domain entry maintains a 1704 * timer queue holding timers for 1705 * messages outstanding to that domain. 1706 */ 1707 struct idn_timerq { 1708 int tq_cookie; /* tq_mutex */ 1709 kmutex_t tq_mutex; 1710 int tq_count; /* tq_mutex */ 1711 idn_timer_t *tq_queue; /* tq_mutex */ 1712 } dtimerq; 1713 /* 1714 * dawol is used to keep 1715 * track of AWOL details for 1716 * given domain when it is 1717 * non-responsive. 1718 */ 1719 struct { 1720 int a_count; /* drwlock */ 1721 clock_t a_time; /* drwlock */ 1722 clock_t a_last; /* drwlock */ 1723 clock_t a_msg; /* drwlock */ 1724 } dawol; 1725 1726 struct hwconfig { 1727 short dh_nboards; /* drwlock */ 1728 short dh_nmcadr; /* drwlock */ 1729 boardset_t dh_boardset; /* drwlock */ 1730 uint_t dh_mcadr[MAX_BOARDS]; /* drwlock */ 1731 } dhw; 1732 /* 1733 * Mailbox information used to 1734 * send/recv messages to given domain. 1735 */ 1736 struct { 1737 kmutex_t m_mutex; 1738 struct idn_mboxtbl *m_tbl; /* m_mutex */ 1739 struct idn_mainmbox *m_send; /* m_mutex */ 1740 struct idn_mainmbox *m_recv; /* m_mutex */ 1741 } dmbox; 1742 } idn_domain_t; 1743 1744 typedef struct idn_timerq idn_timerq_t; 1745 1746 #define dcfgphase _u._s._dcfgphase 1747 #define dcfgsnddone _u._s._dcfgsnddone 1748 #define dcfgrcvdone _u._s._dcfgrcvdone 1749 #define dcksum _u._s._dcksum 1750 #define dmaxnets _u._s._dmaxnets 1751 #define dmboxpernet _u._s._dmboxpernet 1752 #define dncfgitems _u._s._dncfgitems 1753 #define drecfg _u._s._drecfg 1754 #define dbindport _u._dbindport 1755 #define dconnected _u._dconnected 1756 #define dtmp _u._dtmp 1757 1758 #define IDN_DLOCK_EXCL(dd) (rw_enter(&idn_domain[dd].drwlock, RW_WRITER)) 1759 #define IDN_DLOCK_SHARED(dd) (rw_enter(&idn_domain[dd].drwlock, RW_READER)) 1760 #define IDN_DLOCK_TRY_SHARED(dd) \ 1761 (rw_tryenter(&idn_domain[dd].drwlock, \ 1762 RW_READER)) 1763 #define IDN_DLOCK_DOWNGRADE(dd) (rw_downgrade(&idn_domain[dd].drwlock)) 1764 #define IDN_DUNLOCK(dd) (rw_exit(&idn_domain[dd].drwlock)) 1765 #define IDN_DLOCK_IS_EXCL(dd) (RW_WRITE_HELD(&idn_domain[dd].drwlock)) 1766 #define IDN_DLOCK_IS_SHARED(dd) (RW_READ_HELD(&idn_domain[dd].drwlock)) 1767 #define IDN_DLOCK_IS_HELD(dd) (RW_LOCK_HELD(&idn_domain[dd].drwlock)) 1768 1769 #define IDN_MBOX_LOCK(dd) (mutex_enter(&idn_domain[dd].dmbox.m_mutex)) 1770 #define IDN_MBOX_UNLOCK(dd) (mutex_exit(&idn_domain[dd].dmbox.m_mutex)) 1771 1772 #define IDN_RESET_COOKIES(dd) \ 1773 (idn_domain[dd].dcookie_send = idn_domain[dd].dcookie_recv = 0) 1774 1775 #define DSLAB_STATE_UNKNOWN 0 1776 #define DSLAB_STATE_LOCAL 1 1777 #define DSLAB_STATE_REMOTE 2 1778 1779 #define DSLAB_READ_HELD(d) RW_READ_HELD(&idn_domain[d].dslab_rwlock) 1780 #define DSLAB_WRITE_HELD(d) RW_WRITE_HELD(&idn_domain[d].dslab_rwlock) 1781 1782 #define DSLAB_LOCK_EXCL(d) \ 1783 rw_enter(&idn_domain[d].dslab_rwlock, RW_WRITER) 1784 #define DSLAB_LOCK_SHARED(d) \ 1785 rw_enter(&idn_domain[d].dslab_rwlock, RW_READER) 1786 #define DSLAB_LOCK_TRYUPGRADE(d) \ 1787 rw_tryupgrade(&idn_domain[d].dslab_rwlock) 1788 #define DSLAB_UNLOCK(d) rw_exit(&idn_domain[d].dslab_rwlock) 1789 1790 /* 1791 * --------------------------------------------------------------------- 1792 * Macro to pick another target for the given domain. This hopefully 1793 * improves performance by better distributing the SSI responsibilities 1794 * at the target domain. 1795 * --------------------------------------------------------------------- 1796 */ 1797 #define BUMP_INDEX(set, index) \ 1798 { \ 1799 register int p; \ 1800 for (p = (index)+1; p < NCPU; p++) \ 1801 if (CPU_IN_SET((set), p)) \ 1802 break; \ 1803 if (p >= NCPU) \ 1804 for (p = 0; p <= (index); p++) \ 1805 if (CPU_IN_SET((set), p)) \ 1806 break; \ 1807 if (!CPU_IN_SET((set), p)) { \ 1808 uint_t _u32, _l32; \ 1809 _u32 = UPPER32_CPUMASK(set); \ 1810 _l32 = LOWER32_CPUMASK(set); \ 1811 cmn_err(CE_PANIC, \ 1812 "IDN: cpu %d not in cpuset 0x%x.%0x\n", \ 1813 p, _u32, _l32); \ 1814 } \ 1815 (index) = p; \ 1816 } 1817 1818 #define IDN_ASSIGN_DCPU(dp, cookie) \ 1819 ((dp)->dcpu = (int)((dp)->dcpumap[(cookie) & (NCPU-1)])) 1820 1821 /* 1822 * --------------------------------------------------------------------- 1823 * Atomic increment/decrement, swap, compare-swap functions. 1824 * --------------------------------------------------------------------- 1825 */ 1826 #define ATOMIC_INC(v) atomic_inc_32((uint_t *)&(v)) 1827 #define ATOMIC_DEC(v) atomic_dec_32((uint_t *)&(v)) 1828 #define ATOMIC_SUB(v, n) atomic_add_32((uint_t *)&(v), -(n)) 1829 #define ATOMIC_CAS(a, c, n) atomic_cas_32((uint32_t *)(a), (uint32_t)(c), \ 1830 (uint32_t)(n)) 1831 #define ATOMIC_SWAPL(a, v) atomic_swap_32((uint32_t *)(a), (uint32_t)(v)) 1832 1833 /* 1834 * DMV vector interrupt support. 1835 * 1836 * A fixed-size circular buffer is maintained as a queue of 1837 * incoming interrupts. The low-level idn_dmv_handler() waits 1838 * for an entry to become FREE and will atomically mark it INUSE. 1839 * Once he has filled in the appropriate fields it will be marked 1840 * as READY. The high-level idn_handler() will be invoked and will 1841 * process all messages in the queue that are READY. Each message 1842 * is marked PROCESS, a protojob job created and filled in, and 1843 * then the interrupt message is marked FREE for use in the next 1844 * interrupt. The iv_state field is used to hold the relevant 1845 * state and is updated atomically. 1846 */ 1847 #define IDN_PIL PIL_8 1848 #define IDN_DMV_PENDING_MAX 128 /* per cpu */ 1849 1850 #endif /* !_ASM */ 1851 1852 #ifndef _ASM 1853 1854 /* 1855 * The size of this structure must be a power of 2 1856 * so that we can do a simple shift to calculate 1857 * our offset into based on cpuid. 1858 */ 1859 typedef struct idn_dmv_cpu { 1860 uint32_t idn_dmv_current; 1861 int32_t idn_dmv_lostintr; 1862 lock_t idn_dmv_active; 1863 char _padding[(2 * sizeof (uint64_t)) - \ 1864 sizeof (uint32_t) - \ 1865 sizeof (lock_t) - \ 1866 sizeof (int32_t)]; 1867 } idn_dmv_cpu_t; 1868 1869 typedef struct idn_dmv_data { 1870 uint_t idn_soft_inum; 1871 uint64_t idn_dmv_qbase; 1872 idn_dmv_cpu_t idn_dmv_cpu[NCPU]; 1873 } idn_dmv_data_t; 1874 1875 /* 1876 * Requirements of the following data structure: 1877 * - MUST be double-word (8 bytes) aligned. 1878 * - _iv_head field MUST start on double-word boundary. 1879 * - iv_xargs0 MUST start on double-word boundary 1880 * with iv_xargs1 immediately following. 1881 * - iv_xargs2 MUST start on double-word boundary 1882 * with iv_xargs3 immediately following. 1883 */ 1884 typedef struct idn_dmv_msg { 1885 uint32_t iv_next; /* offset */ 1886 uchar_t iv_inuse; 1887 uchar_t iv_ready; 1888 ushort_t _padding; 1889 uint32_t iv_head : 16; 1890 uint32_t iv_cookie : 16; 1891 uint32_t iv_ver : 8; 1892 uint32_t iv_mtype : 6; 1893 uint32_t iv_atype : 6; 1894 uint32_t iv_domid : 4; 1895 uint32_t iv_cpuid : 8; 1896 uint32_t iv_xargs0; 1897 uint32_t iv_xargs1; 1898 uint32_t iv_xargs2; 1899 uint32_t iv_xargs3; 1900 } idn_dmv_msg_t; 1901 1902 extern uint_t idn_dmv_inum; 1903 extern uint_t idn_soft_inum; 1904 1905 /* 1906 * An IDN-network address has the following format: 1907 * 1908 * 31......16,15........0 1909 * | channel | dnetid | 1910 * ---------------------- 1911 * channel - network interface. 1912 * netid - idn_domain[].dnetid 1913 */ 1914 #define IDN_MAXMAX_NETS 32 1915 #define IDN_BROADCAST_ALLCHAN ((ushort_t)-1) 1916 #define IDN_BROADCAST_ALLNETID ((ushort_t)-1) 1917 1918 typedef union { 1919 struct { 1920 ushort_t chan; 1921 ushort_t netid; 1922 } net; 1923 uint_t netaddr; 1924 } idn_netaddr_t; 1925 1926 #define CHANSET_ALL (~((idn_chanset_t)0)) 1927 #define CHANSET(c) \ 1928 ((idn_chanset_t)1 << ((c) & 31)) 1929 #define CHAN_IN_SET(m, c) \ 1930 (((m) & ((idn_chanset_t)1 << ((c) & 31))) != 0) 1931 #define CHANSET_ADD(m, c) \ 1932 ((m) |= ((idn_chanset_t)1 << ((c) & 31))) 1933 #define CHANSET_DEL(m, c) \ 1934 ((m) &= ~((idn_chanset_t)1 << ((c) & 31))) 1935 #define CHANSET_ZERO(m) ((m) = 0) 1936 1937 typedef enum { 1938 /* 0 */ IDNCHAN_OPEN, 1939 /* 1 */ IDNCHAN_SOFT_CLOSE, 1940 /* 2 */ IDNCHAN_HARD_CLOSE, 1941 /* 3 */ IDNCHAN_OFFLINE, 1942 /* 4 */ IDNCHAN_ONLINE 1943 } idn_chanop_t; 1944 1945 /* 1946 * Retry support. 1947 */ 1948 #define IDN_RETRY_TOKEN(d, x) ((((d) & 0xf) << 16) | \ 1949 (0xffff & (uint_t)(x))) 1950 #define IDN_RETRY_TOKEN2DOMID(t) ((int)(((t) >> 16) & 0xf)) 1951 #define IDN_RETRY_TOKEN2TYPE(t) ((idn_retry_t)((t) & 0xffff)) 1952 #define IDN_RETRY_TYPEALL ((idn_retry_t)0xffff) 1953 #define IDN_RETRY_INTERVAL hz /* 1 sec */ 1954 #define IDN_RETRY_RECFG_MULTIPLE 10 1955 1956 #define IDN_RETRYINTERVAL_NEGO (2 * hz) 1957 #define IDN_RETRYINTERVAL_CON (2 * hz) 1958 #define IDN_RETRYINTERVAL_FIN (2 * hz) 1959 1960 typedef struct idn_retry_job { 1961 struct idn_retry_job *rj_prev; 1962 struct idn_retry_job *rj_next; 1963 void (*rj_func)(uint_t token, void *arg); 1964 void *rj_arg; 1965 uint_t rj_token; 1966 short rj_onq; 1967 timeout_id_t rj_id; 1968 } idn_retry_job_t; 1969 1970 #define IDNRETRY_ALLOCJOB() \ 1971 ((idn_retry_job_t *)kmem_cache_alloc(idn.retryqueue.rq_cache, KM_SLEEP)) 1972 #define IDNRETRY_FREEJOB(j) \ 1973 (kmem_cache_free(idn.retryqueue.rq_cache, (void *)(j))) 1974 1975 typedef enum { 1976 /* 0 */ IDNRETRY_NIL = 0, 1977 /* 1 */ IDNRETRY_NEGO, 1978 /* 2 */ IDNRETRY_CON, 1979 /* 3 */ IDNRETRY_CONQ, /* for CON queries */ 1980 /* 4 */ IDNRETRY_FIN, 1981 /* 5 */ IDNRETRY_FINQ, /* for FIN queries */ 1982 /* 6 */ IDN_NUM_RETRYTYPES 1983 } idn_retry_t; 1984 1985 /* 1986 * --------------------------------------------------------------------- 1987 */ 1988 typedef struct { 1989 int m_domid; 1990 int m_cpuid; 1991 ushort_t m_msgtype; 1992 ushort_t m_acktype; 1993 ushort_t m_cookie; 1994 idn_xdcargs_t m_xargs; 1995 } idn_protomsg_t; 1996 1997 typedef struct idn_protojob { 1998 struct idn_protojob *j_next; 1999 int j_cache; 2000 idn_protomsg_t j_msg; 2001 } idn_protojob_t; 2002 2003 typedef struct idn_protoqueue { 2004 struct idn_protoqueue *q_next; 2005 idn_protojob_t *q_joblist; 2006 idn_protojob_t *q_joblist_tail; 2007 int q_die; 2008 int q_id; 2009 ksema_t *q_morgue; 2010 kthread_id_t q_threadp; 2011 kcondvar_t q_cv; 2012 kmutex_t q_mutex; 2013 } idn_protoqueue_t; 2014 2015 #define IDN_PROTOCOL_NSERVERS 4 2016 #define IDN_PROTOCOL_SERVER_HASH(d) ((d) % idn.nservers) 2017 #define IDN_PROTOJOB_CHUNKS (idn.nservers) 2018 2019 /* 2020 * --------------------------------------------------------------------- 2021 * Data Server definitions. 2022 * 2023 * idn_datasvr_t - Describes data server thread. 2024 * . ds_id - Per-domain identifier for data server. 2025 * . ds_domid - Domain which data server is handling. 2026 * . ds_state - Flag to enable/disable/terminate 2027 * data server. 2028 * . ds_mboxp - Pointer to data server's (local) 2029 * mailbox to be serviced. 2030 * . ds_waittime - cv_timedwait sleep time before 2031 * checking respective mailbox. 2032 * . ds_threadp - Pointer to data server thread. 2033 * . ds_cv - Condvar for sleeping. 2034 * . ds_morguep - Semaphore for terminating thread. 2035 * 2036 * idn_mboxhdr_t - Resides in SMR space (MUST be cache_linesize). 2037 * . mh_svr_active - Non-zero indicates data server is 2038 * actively reading mailbox for messages. 2039 * . mh_svr_ready - Non-zero indicates data server has 2040 * allocated and is ready to accept data. 2041 * . mh_cookie - Identifier primarily for debug purposes. 2042 * 2043 * idn_mboxmsg_t - Entry in the SMR space circular queue use to 2044 * represent a data packet. 2045 * . mm_owner - Non-zero indicates entry is available 2046 * to be processed by receiver's data server. 2047 * . mm_flag - Indicates whether entry needs to be 2048 * reclaimed by the sender. Also holds error 2049 * indications (e.g. bad offset). 2050 * . mm_offset - SMR offset of respective data packet. 2051 * 2052 * idn_mboxtbl_t - Encapsulation of a per-domain mailbox (SMR space). 2053 * . mt_header - Header information for synchronization. 2054 * . mt_queue - Circular queue of idn_mboxmsg_t entries. 2055 * 2056 * idn_mainmbox_t - Encapsulation of main SMR recv/send mailboxes. 2057 * . mm_mutex - Protects mm_* entries, enqueuing, and 2058 * dequeuing of messages. Also protects 2059 * updates to the route table pointed to 2060 * by mm_routetbl. 2061 * . mm_count - send: Current number of messages 2062 * enqueued. 2063 * - recv: Cumulative number of messages 2064 * processed. 2065 * . mm_max_count - send: Maximum number of messages 2066 * enqueued per iteration. 2067 * recv: Maximum number of messages 2068 * dequeued per iteration. 2069 * . mm_smr_mboxp - Pointer to SMR (vaddr) space where 2070 * respective mailbox resides. 2071 * --------------------------------------------------------------------- 2072 */ 2073 #define IDN_MBOXHDR_COOKIE_TOP ((uint_t)0xc0c0) 2074 #define IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch) \ 2075 ((IDN_MBOXHDR_COOKIE_TOP << 16) \ 2076 | (((uint_t)(pd) & 0xf) << 12) \ 2077 | (((uint_t)(sd) & 0xf) << 8) \ 2078 | ((uint_t)(ch) & 0xf)) 2079 #define IDN_GET_MBOXHDR_COOKIE(mhp) \ 2080 ((mhp)->mh_cookie & ~0xff00) 2081 #define VALID_MBOXHDR(mhp, ch, cksum) \ 2082 ((IDN_GET_MBOXHDR_COOKIE(mhp) == \ 2083 IDN_MAKE_MBOXHDR_COOKIE(0, 0, (ch))) && \ 2084 ((cksum) == (*(mhp)).mh_cksum)) 2085 /* 2086 * The number of entries in a mailbox queue must be chosen so 2087 * that (IDN_MMBOX_NUMENTRIES * sizeof (idn_mboxmsg_t)) is a multiple 2088 * of a cacheline size (64). 2089 */ 2090 #define IDN_MMBOX_NUMENTRIES IDN_MBOX_PER_NET 2091 /* 2092 * We step through the mailboxes in effectively cacheline size 2093 * incremenents so that the source and receiving cpus are not competing 2094 * for the same cacheline when transmitting/receiving messages into/from 2095 * the mailboxes. The hard requirement is that the step value be even 2096 * since the mailbox size will be chosen odd. This allows us to wraparound 2097 * the mailbox uniquely touching each entry until we've exhausted them 2098 * all at which point we'll end up where we initially started and repeat 2099 * again. 2100 */ 2101 #define IDN_MMBOXINDEX_STEP (((64 / sizeof (idn_mboxmsg_t)) + 1) & 0xfffe) 2102 #define IDN_MMBOXINDEX_INC(i) \ 2103 { \ 2104 if (((i) += IDN_MMBOXINDEX_STEP) >= IDN_MMBOX_NUMENTRIES) \ 2105 (i) -= IDN_MMBOX_NUMENTRIES; \ 2106 } 2107 2108 #define IDN_MMBOXINDEX_DIFF(i, j) \ 2109 (((i) >= (j)) ? (((i) - (j)) / IDN_MMBOXINDEX_STEP) \ 2110 : ((((i) + IDN_MMBOX_NUMENTRIES) - (j)) / IDN_MMBOXINDEX_STEP)) 2111 2112 /* 2113 * Require IDN_MBOXAREA_SIZE <= IDN_SLAB_SIZE so we don't waste 2114 * slab space. 2115 * 2116 * Each domain maintains a MAX_DOMAIN(16) entry mbox_table. Each 2117 * entry represents a receive mailbox for a possible domain to which 2118 * the given domain may have a connection. The send mailbox for each 2119 * respective domain is given to the local domain at the time of 2120 * connection establishment. 2121 */ 2122 2123 /* 2124 * --------------------------------------------------------------------- 2125 */ 2126 #define IDN_MBOXTBL_SIZE \ 2127 (IDNROUNDUP(((IDN_MBOX_PER_NET * sizeof (idn_mboxmsg_t)) \ 2128 + sizeof (idn_mboxhdr_t)), IDN_ALIGNSIZE)) 2129 2130 /* 2131 * --------------------------------------------------------------------- 2132 * Each domain has idn_max_nets worth of possible mailbox tables 2133 * for each domain to which it might possibly be connected. 2134 * --------------------------------------------------------------------- 2135 */ 2136 #define IDN_MBOXAREA_SIZE \ 2137 (IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS * MAX_DOMAINS) 2138 #define IDN_MBOXAREA_OFFSET(d) \ 2139 ((d) * IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS) 2140 2141 /* 2142 * --------------------------------------------------------------------- 2143 * Return the base of the mailbox area (set of tables) assigned 2144 * to the given domain id. 2145 * --------------------------------------------------------------------- 2146 */ 2147 #define IDN_MBOXAREA_BASE(m, d) \ 2148 ((idn_mboxtbl_t *)(((ulong_t)(m)) + IDN_MBOXAREA_OFFSET(d))) 2149 2150 /* 2151 * --------------------------------------------------------------------- 2152 * Return the pointer to the respective receive mailbox (table set) 2153 * for the given domain id relative to the given base mailbox table. 2154 * --------------------------------------------------------------------- 2155 */ 2156 #define IDN_MBOXTBL_PTR(t, d) \ 2157 ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((d) * IDN_MBOXTBL_SIZE \ 2158 * IDN_MAX_NETS))) 2159 /* 2160 * --------------------------------------------------------------------- 2161 * Return the pointer to the actual target mailbox based on the 2162 * given channel in the given mailbox table. 2163 * --------------------------------------------------------------------- 2164 */ 2165 #define IDN_MBOXTBL_PTR_CHAN(t, c) \ 2166 ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((c) * IDN_MBOXTBL_SIZE))) 2167 2168 #define IDN_MBOXTBL_PTR_INC(t) \ 2169 ((t) = (idn_mboxtbl_t *)(((ulong_t)(t)) + IDN_MBOXTBL_SIZE)) 2170 2171 #define IDN_MBOXCHAN_INC(i) \ 2172 { \ 2173 if (++(i) == IDN_MAX_NETS) \ 2174 (i) = 0; \ 2175 } 2176 2177 /* 2178 * --------------------------------------------------------------------- 2179 * Return the absolute location within the entire mailbox area 2180 * of the mboxtbl for the given primary and secondary domain and 2181 * channel. Only relevant when done by the master. 2182 * --------------------------------------------------------------------- 2183 */ 2184 #define IDN_MBOXTBL_ABS_PTR(mt, pd, sd, ch) \ 2185 (IDN_MBOXTBL_PTR_CHAN( \ 2186 IDN_MBOXTBL_PTR( \ 2187 IDN_MBOXAREA_BASE((mt), (pd)), \ 2188 (sd)), \ 2189 (ch))) 2190 2191 #define IDN_BFRAME_SHIFT idn.bframe_shift 2192 #define IDN_BFRAME2OFFSET(bf) ((bf) << IDN_BFRAME_SHIFT) 2193 #define IDN_BFRAME2ADDR(bf) IDN_OFFSET2ADDR(IDN_BFRAME2OFFSET(bf)) 2194 #define IDN_OFFSET2BFRAME(off) (((off) >> IDN_BFRAME_SHIFT) & 0xffffff) 2195 #define IDN_ADDR2BFRAME(addr) IDN_OFFSET2BFRAME(IDN_ADDR2OFFSET(addr)) 2196 2197 typedef struct idn_mboxmsg { 2198 uint_t ms_owner : 1, 2199 ms_flag : 7, 2200 ms_bframe : 24; 2201 } idn_mboxmsg_t; 2202 2203 typedef idn_mboxmsg_t idn_mboxq_t[1]; 2204 2205 #define IDN_CKSUM_MBOX_COUNT \ 2206 (((int)&((idn_mboxhdr_t *)(0))->mh_svr_ready) / 2) 2207 #define IDN_CKSUM_MBOX(h) \ 2208 (IDN_CHECKSUM ? \ 2209 idn_cksum((ushort_t *)(h), IDN_CKSUM_MBOX_COUNT) : 0) 2210 2211 typedef struct idn_mboxhdr { 2212 uint_t mh_cookie; 2213 uint_t mh_svr_ready_ptr; 2214 uint_t mh_svr_active_ptr; 2215 ushort_t mh_svr_ready; 2216 ushort_t mh_svr_active; 2217 2218 uint_t _padding[(64 - 2219 (4*sizeof (uint_t)) - 2220 (2*sizeof (ushort_t))) / sizeof (uint_t)]; 2221 2222 uint_t mh_cksum; 2223 } idn_mboxhdr_t; 2224 2225 typedef struct idn_mboxtbl { 2226 idn_mboxhdr_t mt_header; 2227 idn_mboxq_t mt_queue; 2228 } idn_mboxtbl_t; 2229 2230 #define IDN_CHAN_DOMAIN_REGISTER(csp, dom) \ 2231 (DOMAINSET_ADD((csp)->ch_reg_domset, (dom))) 2232 2233 #define IDN_CHAN_DOMAIN_UNREGISTER(csp, dom) \ 2234 (DOMAINSET_DEL((csp)->ch_reg_domset, (dom))) 2235 2236 #define IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dom) \ 2237 (DOMAIN_IN_SET((csp)->ch_reg_domset, (dom))) 2238 2239 #define IDN_CHANSVR_SCANSET_ADD_PENDING(csp, dom) \ 2240 { \ 2241 register int _d; \ 2242 register uint64_t _domset; \ 2243 (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \ 2244 _domset = 0ull; \ 2245 for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \ 2246 if ((int)(((csp)->ch_recv_scanset_pending >> \ 2247 (_d * 4)) & 0xf) == (dom)) \ 2248 break; \ 2249 else \ 2250 _domset = (_domset << 4) | 0xfull; \ 2251 } \ 2252 if (_d == (csp)->ch_recv_domcount) { \ 2253 _domset &= (csp)->ch_recv_scanset_pending; \ 2254 _domset |= (uint64_t)(dom) << \ 2255 ((csp)->ch_recv_domcount * 4); \ 2256 (csp)->ch_recv_domcount++; \ 2257 (csp)->ch_recv_scanset_pending = 0ull; \ 2258 for (_d = 0; _d < 16; \ 2259 _d += (csp)->ch_recv_domcount) { \ 2260 (csp)->ch_recv_scanset_pending |= _domset; \ 2261 _domset <<= (csp)->ch_recv_domcount * 4; \ 2262 } \ 2263 } \ 2264 } 2265 #define IDN_CHANSVR_SCANSET_DEL_PENDING(csp, dom) \ 2266 { \ 2267 register int _d; \ 2268 register uint64_t _domset; \ 2269 (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \ 2270 _domset = 0ull; \ 2271 for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \ 2272 if ((int)(((csp)->ch_recv_scanset_pending >> \ 2273 (_d * 4)) & 0xf) == (dom)) \ 2274 break; \ 2275 else \ 2276 _domset = (_domset << 4) | 0xfull; \ 2277 } \ 2278 if (_d < (csp)->ch_recv_domcount) { \ 2279 _domset &= (csp)->ch_recv_scanset_pending; \ 2280 (csp)->ch_recv_scanset_pending >>= 4; \ 2281 (csp)->ch_recv_domcount--; \ 2282 for (; _d < (csp)->ch_recv_domcount; _d++) \ 2283 _domset |= (csp)->ch_recv_scanset_pending &\ 2284 (0xfull << (_d * 4)); \ 2285 (csp)->ch_recv_scanset_pending = 0ull; \ 2286 if ((csp)->ch_recv_domcount) { \ 2287 for (_d = 0; _d < 16; \ 2288 _d += (csp)->ch_recv_domcount) { \ 2289 (csp)->ch_recv_scanset_pending |= \ 2290 _domset; \ 2291 _domset <<= \ 2292 (csp)->ch_recv_domcount * 4; \ 2293 } \ 2294 } \ 2295 } \ 2296 } 2297 2298 #define IDN_CHAN_TRYLOCK_GLOBAL(csp) \ 2299 mutex_tryenter(&(csp)->ch_mutex) 2300 #define IDN_CHAN_LOCK_GLOBAL(csp) \ 2301 mutex_enter(&(csp)->ch_mutex) 2302 #define IDN_CHAN_UNLOCK_GLOBAL(csp) \ 2303 mutex_exit(&(csp)->ch_mutex) 2304 #define IDN_CHAN_GLOBAL_IS_LOCKED(csp) \ 2305 (MUTEX_HELD(&(csp)->ch_mutex)) 2306 2307 #define IDN_CHAN_LOCAL_IS_LOCKED(csp) \ 2308 (MUTEX_HELD(&(csp)->ch_send.c_mutex) && \ 2309 MUTEX_HELD(&(csp)->ch_recv.c_mutex)) 2310 #define IDN_CHAN_LOCK_LOCAL(csp) \ 2311 (mutex_enter(&(csp)->ch_recv.c_mutex, \ 2312 mutex_enter(&(csp)->ch_send.c_mutex)) 2313 #define IDN_CHAN_UNLOCK_LOCAL(csp) \ 2314 (mutex_exit(&(csp)->ch_send.c_mutex), \ 2315 mutex_exit(&(csp)->ch_recv.c_mutex)) 2316 2317 #define IDN_CHAN_RECV_IS_LOCKED(csp) \ 2318 (MUTEX_HELD(&(csp)->ch_recv.c_mutex)) 2319 #define IDN_CHAN_TRYLOCK_RECV(csp) \ 2320 (mutex_tryenter(&(csp)->ch_recv.c_mutex)) 2321 #define IDN_CHAN_LOCK_RECV(csp) \ 2322 (mutex_enter(&(csp)->ch_recv.c_mutex)) 2323 #define IDN_CHAN_UNLOCK_RECV(csp) \ 2324 (mutex_exit(&(csp)->ch_recv.c_mutex)) 2325 2326 #define IDN_CHAN_SEND_IS_LOCKED(csp) \ 2327 (MUTEX_HELD(&(csp)->ch_send.c_mutex)) 2328 #define IDN_CHAN_TRYLOCK_SEND(csp) \ 2329 (mutex_tryenter(&(csp)->ch_send.c_mutex)) 2330 #define IDN_CHAN_LOCK_SEND(csp) \ 2331 (mutex_enter(&(csp)->ch_send.c_mutex)) 2332 #define IDN_CHAN_UNLOCK_SEND(csp) \ 2333 (mutex_exit(&(csp)->ch_send.c_mutex)) 2334 2335 /* 2336 * A channel table is an array of pointers to mailboxes 2337 * for the respective domains for the given channel. 2338 * Used a cache for the frequently used items. Respective 2339 * fields in mainmbox are updated just prior to sleeping. 2340 */ 2341 2342 /* 2343 * Reading c_state requires either c_mutex or ch_mutex. 2344 * Writing c_state requires both c_mutex and ch_mutex in the order: 2345 * ch_mutex 2346 * c_mutex 2347 */ 2348 typedef struct idn_chaninfo { 2349 kmutex_t c_mutex; 2350 uchar_t c_state; /* protected by c_mutex */ 2351 uchar_t c_checkin; /* asynchronous flag */ 2352 kcondvar_t c_cv; 2353 ushort_t c_waiters; /* protected by c_mutex */ 2354 ushort_t c_inprogress; /* protected by c_mutex */ 2355 } idn_chaninfo_t; 2356 2357 /* 2358 * Reading/Writing ch_state requires ch_mutex. 2359 * When updating both recv and send c_state's for the locks 2360 * must be grabbed in the following order: 2361 * ch_mutex 2362 * ch_recv.c_mutex 2363 * ch_send.c_mutex 2364 * This order is necessary to prevent deadlocks. 2365 * In general ch_state is intended to represent c_state of 2366 * individual send/recv sides. During state transitions the 2367 * ch_state and c_state values may be slightly different, 2368 * but eventually should end up identical. 2369 */ 2370 typedef struct idn_chansvr { 2371 uchar_t ch_id; 2372 uchar_t ch_state; /* protected by ch_mutex */ 2373 lock_t ch_initlck; 2374 lock_t ch_actvlck; 2375 domainset_t ch_reg_domset; 2376 kmutex_t ch_mutex; 2377 2378 idn_chaninfo_t ch_send; 2379 int _padding2[(64 - 2380 (2*sizeof (uchar_t)) - (2*sizeof (lock_t)) - 2381 sizeof (uint_t) - sizeof (kmutex_t) - 2382 sizeof (idn_chaninfo_t)) / sizeof (int)]; 2383 2384 idn_chaninfo_t ch_recv; 2385 2386 uint64_t ch_recv_scanset; 2387 uint64_t ch_recv_scanset_pending; 2388 2389 domainset_t ch_recv_domset; 2390 domainset_t ch_recv_domset_pending; 2391 short ch_recv_domcount; 2392 kcondvar_t ch_recv_cv; 2393 int ch_recv_waittime; 2394 int ch_recv_changed; 2395 2396 kthread_id_t ch_recv_threadp; 2397 ksema_t *ch_recv_morguep; 2398 int ch_bound_cpuid; 2399 int ch_bound_cpuid_pending; 2400 } idn_chansvr_t; 2401 2402 typedef struct idn_mainmbox { 2403 kmutex_t mm_mutex; 2404 short mm_channel; 2405 short mm_domid; 2406 ushort_t mm_flags; 2407 short mm_type; 2408 2409 idn_chansvr_t *mm_csp; /* non-NULL indicates reg'd */ 2410 int mm_count; 2411 int mm_dropped; 2412 idn_mboxtbl_t *mm_smr_mboxp; /* SMR vaddr */ 2413 2414 ushort_t *mm_smr_activep; /* SMR pointer */ 2415 ushort_t *mm_smr_readyp; /* SMR pointer */ 2416 int mm_qiget; /* next msg to get */ 2417 int mm_qiput; /* next slot to put msg */ 2418 } idn_mainmbox_t; 2419 2420 /* 2421 * mm_flags 2422 */ 2423 #define IDNMMBOX_FLAG_CORRUPTED 0x01 2424 /* 2425 * mm_type 2426 */ 2427 #define IDNMMBOX_TYPE_RECV 0x1 2428 #define IDNMMBOX_TYPE_SEND 0x2 2429 2430 #define IDNMBOX_IS_RECV(m) ((m) == IDNMMBOX_TYPE_RECV) 2431 #define IDNMBOX_IS_SEND(m) ((m) == IDNMMBOX_TYPE_SEND) 2432 2433 /* 2434 * Period between sending wakeup xdc's to remote domain. 2435 */ 2436 #define IDN_CHANNEL_WAKEUP_PERIOD (hz >> 1) 2437 /* 2438 * ms_flag bit values. 2439 */ 2440 #define IDN_MBOXMSG_FLAG_RECLAIM 0x1 /* needs to be reclaimed */ 2441 #define IDN_MBOXMSG_FLAG_INPROCESS 0x2 2442 #define IDN_MBOXMSG_FLAG_ERR_BADOFFSET 0x4 2443 #define IDN_MBOXMSG_FLAG_ERR_NOMBOX 0x8 2444 #define IDN_MBOXMSG_FLAG_ERRMASK 0xc 2445 /* 2446 * ch_state/c_state bit values. 2447 */ 2448 #define IDN_CHANSVC_STATE_ATTACHED 0x01 2449 #define IDN_CHANSVC_STATE_ENABLED 0x02 2450 #define IDN_CHANSVC_STATE_ACTIVE 0x04 2451 #define IDN_CHANSVC_STATE_FLUSH 0x10 2452 #define IDN_CHANSVC_STATE_CORRUPTED 0x20 2453 #define IDN_CHANSVC_STATE_MASK 0x07 /* ATTACHED/ENABLED/ACTIVE */ 2454 2455 #define IDN_CHANSVC_PENDING_BITS (IDN_CHANSVC_STATE_ATTACHED | \ 2456 IDN_CHANSVC_STATE_ENABLED) 2457 2458 /* 2459 * GLOBAL 2460 */ 2461 #define IDN_CHANNEL_IS_ATTACHED(csp) \ 2462 ((csp)->ch_state & IDN_CHANSVC_STATE_ATTACHED) 2463 #define IDN_CHANNEL_IS_DETACHED(csp) \ 2464 (!IDN_CHANNEL_IS_ATTACHED(csp)) 2465 #define IDN_CHANNEL_IS_PENDING(csp) \ 2466 (((csp)->ch_state & IDN_CHANSVC_STATE_MASK) == \ 2467 IDN_CHANSVC_PENDING_BITS) 2468 #define IDN_CHANNEL_IS_ACTIVE(csp) \ 2469 ((csp)->ch_state & IDN_CHANSVC_STATE_ACTIVE) 2470 #define IDN_CHANNEL_IS_ENABLED(csp) \ 2471 ((csp)->ch_state & IDN_CHANSVC_STATE_ENABLED) 2472 /* 2473 * SEND 2474 */ 2475 #define IDN_CHANNEL_IS_SEND_ACTIVE(csp) \ 2476 ((csp)->ch_send.c_state & IDN_CHANSVC_STATE_ACTIVE) 2477 /* 2478 * RECV 2479 */ 2480 #define IDN_CHANNEL_IS_RECV_ACTIVE(csp) \ 2481 ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_ACTIVE) 2482 #define IDN_CHANNEL_IS_RECV_CORRUPTED(csp) \ 2483 ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_CORRUPTED) 2484 2485 2486 #define IDN_CHAN_SEND_INPROGRESS(csp) ((csp)->ch_send.c_inprogress++) 2487 #define IDN_CHAN_SEND_DONE(csp) \ 2488 { \ 2489 ASSERT((csp)->ch_send.c_inprogress > 0); \ 2490 if ((--((csp)->ch_send.c_inprogress) == 0) && \ 2491 ((csp)->ch_send.c_waiters != 0)) \ 2492 cv_broadcast(&(csp)->ch_send.c_cv); \ 2493 } 2494 #define IDN_CHAN_RECV_INPROGRESS(csp) ((csp)->ch_recv.c_inprogress++) 2495 #define IDN_CHAN_RECV_DONE(csp) \ 2496 { \ 2497 ASSERT((csp)->ch_recv.c_inprogress > 0); \ 2498 if ((--((csp)->ch_recv.c_inprogress) == 0) && \ 2499 ((csp)->ch_recv.c_waiters != 0)) \ 2500 cv_broadcast(&(csp)->ch_recv.c_cv); \ 2501 } 2502 2503 #define IDN_CHANSVC_MARK_ATTACHED(csp) \ 2504 ((csp)->ch_state = IDN_CHANSVC_STATE_ATTACHED) 2505 #define IDN_CHANSVC_MARK_DETACHED(csp) \ 2506 ((csp)->ch_state = 0) 2507 #define IDN_CHANSVC_MARK_PENDING(csp) \ 2508 ((csp)->ch_state |= IDN_CHANSVC_STATE_ENABLED) 2509 #define IDN_CHANSVC_MARK_DISABLED(csp) \ 2510 ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ENABLED) 2511 #define IDN_CHANSVC_MARK_ACTIVE(csp) \ 2512 ((csp)->ch_state |= IDN_CHANSVC_STATE_ACTIVE) 2513 #define IDN_CHANSVC_MARK_IDLE(csp) \ 2514 ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ACTIVE) 2515 2516 #define IDN_CHANSVC_MARK_RECV_ACTIVE(csp) \ 2517 ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_ACTIVE) 2518 #define IDN_CHANSVC_MARK_RECV_CORRUPTED(csp) \ 2519 ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_CORRUPTED) 2520 #define IDN_CHANSVC_MARK_SEND_ACTIVE(csp) \ 2521 ((csp)->ch_send.c_state |= IDN_CHANSVC_STATE_ACTIVE) 2522 2523 typedef enum { 2524 IDNCHAN_ACTION_DETACH, /* DETACH (ATTACHED = 0) */ 2525 IDNCHAN_ACTION_STOP, /* DISABLE (ENABLED = 0) */ 2526 IDNCHAN_ACTION_SUSPEND, /* IDLE (ACTIVE = 0) */ 2527 IDNCHAN_ACTION_RESUME, 2528 IDNCHAN_ACTION_RESTART, 2529 IDNCHAN_ACTION_ATTACH 2530 } idn_chanaction_t; 2531 2532 #define IDN_CHANNEL_SUSPEND(c, w) \ 2533 (idn_chan_action((c), IDNCHAN_ACTION_SUSPEND, (w))) 2534 #define IDN_CHANNEL_RESUME(c) \ 2535 (idn_chan_action((c), IDNCHAN_ACTION_RESUME, 0)) 2536 #define IDN_CHANNEL_STOP(c, w) \ 2537 (idn_chan_action((c), IDNCHAN_ACTION_STOP, (w))) 2538 #define IDN_CHANNEL_RESTART(c) \ 2539 (idn_chan_action((c), IDNCHAN_ACTION_RESTART, 0)) 2540 #define IDN_CHANNEL_DETACH(c, w) \ 2541 (idn_chan_action((c), IDNCHAN_ACTION_DETACH, (w))) 2542 #define IDN_CHANNEL_ATTACH(c) \ 2543 (idn_chan_action((c), IDNCHAN_ACTION_ATTACH, 0)) 2544 2545 /* 2546 * ds_waittime range values. 2547 * When a packet arrives the waittime starts at MIN and gradually 2548 * shifts up to MAX until another packet arrives. If still no 2549 * packet arrives then we go to a hard sleep 2550 */ 2551 #define IDN_NETSVR_SPIN_COUNT idn_netsvr_spin_count 2552 #define IDN_NETSVR_WAIT_MIN idn_netsvr_wait_min 2553 #define IDN_NETSVR_WAIT_MAX idn_netsvr_wait_max 2554 #define IDN_NETSVR_WAIT_SHIFT idn_netsvr_wait_shift 2555 2556 /* 2557 * --------------------------------------------------------------------- 2558 * IDN Global Data 2559 * 2560 * The comment to the right of the respective field represents 2561 * what lock protects that field. If there is no comment then 2562 * no lock is required to access the field. 2563 * --------------------------------------------------------------------- 2564 */ 2565 typedef struct idn_global { /* protected by... */ 2566 krwlock_t grwlock; 2567 /* 2568 * Global state of IDN w.r.t. 2569 * the local domain. 2570 */ 2571 idn_gstate_t state; /* grwlock */ 2572 /* 2573 * Version of the IDN driver. 2574 * Is passed in DMV header so that 2575 * other domains can validate they 2576 * support protocol used by local 2577 * domain. 2578 */ 2579 int version; 2580 /* 2581 * Set to 1 if SMR region properly 2582 * allocated and available. 2583 */ 2584 int enabled; 2585 /* 2586 * Local domains "domain id". 2587 */ 2588 int localid; 2589 /* 2590 * Domain id of the Master domain. 2591 * Set to IDN_NIL_DOMID if none 2592 * currently exists. 2593 */ 2594 int masterid; /* grwlock */ 2595 /* 2596 * Primarily used during Reconfiguration 2597 * to track the expected new Master. 2598 * Once the current IDN is dismantled 2599 * the local domain will attempt to 2600 * connect to this new domain. 2601 */ 2602 int new_masterid; /* grwlock */ 2603 /* 2604 * Number of protocol servers configured. 2605 */ 2606 int nservers; 2607 2608 dev_info_t *dip; 2609 2610 struct { 2611 /* 2612 * dmv_inum 2613 * Interrupt number assigned by 2614 * DMV subsystem to IDN's DMV 2615 * handler. 2616 * soft_inum 2617 * Soft interrupt number assigned 2618 * by OS (add_softintr) for Soft 2619 * interrupt dispatched by DMV 2620 * handler. 2621 */ 2622 uint_t dmv_inum; 2623 uint_t soft_inum; 2624 caddr_t dmv_data; 2625 size_t dmv_data_len; 2626 } intr; 2627 /* 2628 * first_swlink 2629 * Used as synchronization to 2630 * know whether channels need 2631 * to be activated or not. 2632 * first_hwlink 2633 * Used as mechanism to determine 2634 * whether local domain needs 2635 * to publicize its SMR, assuming 2636 * it is the Master. 2637 * first_hwmaster 2638 * Domainid of the domain that 2639 * was the master at the time 2640 * the hardware was programmed. 2641 * We need to keep this so that 2642 * we deprogram with respect to 2643 * the correct domain that the 2644 * hardware was originally 2645 * programmed to. 2646 */ 2647 lock_t first_swlink; 2648 lock_t first_hwlink; 2649 short first_hwmasterid; 2650 /* 2651 * The xmit* fields are used to set-up a background 2652 * thread to monitor when a channel is ready to be 2653 * enabled again. This is necessary since IDN 2654 * can't rely on hardware to interrupt it when 2655 * things are ready to go. We need this ability 2656 * to wakeup our STREAMS queues. 2657 * Criteria for reenabling queues. 2658 * gstate == IDNGS_ONLINE 2659 * channel = !check-in 2660 * buffers are available 2661 * 2662 * xmit_chanset_wanted 2663 * Indicates which channels wish to have 2664 * their queues reenabled when ready. 2665 * xmit_tid 2666 * Timeout-id of monitor. 2667 */ 2668 kmutex_t xmit_lock; 2669 idn_chanset_t xmit_chanset_wanted; /* xmit_lock */ 2670 timeout_id_t xmit_tid; /* xmit_lock */ 2671 2672 struct { 2673 /* 2674 * ready 2675 * Indicates SMR region allocated 2676 * and available from OBP. 2677 * vaddr 2678 * Virtual address assigned to SMR. 2679 * locpfn 2680 * Page Frame Number associated 2681 * with local domain's SMR. 2682 * rempfn 2683 * Page Frame Number associated 2684 * with remote (Master) domain's SMR. 2685 * rempfnlim 2686 * PFN past end of remote domain's 2687 * SMR. 2688 * prom_paddr/prom_size 2689 * Physical address and size of 2690 * SMR that were assigned by OBP. 2691 */ 2692 int ready; 2693 caddr_t vaddr; 2694 pfn_t locpfn; 2695 pfn_t rempfn; /* grwlock */ 2696 2697 pfn_t rempfnlim; /* grwlock */ 2698 uint64_t prom_paddr; 2699 2700 uint64_t prom_size; 2701 } smr; 2702 2703 /* 2704 * idnsb_mutex 2705 * Protects access to IDN's 2706 * sigblock area. 2707 * idnsb_eventp 2708 * IDN's private area in sigblock 2709 * used for signaling events 2710 * regarding IDN state to SSP. 2711 * idnsb 2712 * Area within IDN's private 2713 * sigblock area used for tracking 2714 * certain IDN state which might 2715 * be useful during arbstop 2716 * conditions (if caused by IDN!). 2717 */ 2718 kmutex_t idnsb_mutex; 2719 idnsb_event_t *idnsb_eventp; 2720 idnsb_t *idnsb; 2721 2722 struct sigbintr { 2723 /* 2724 * sb_mutex 2725 * Protects sigbintr elements 2726 * to synchronize execution of 2727 * sigblock (IDN) mailbox handling. 2728 * sb_cpuid 2729 * Cpu whose sigblock mailbox 2730 * originally received IDN request 2731 * from SSP. Necessary to know 2732 * where to put response. 2733 * sb_busy 2734 * Flag indicating state of 2735 * sigblock handler thread. 2736 * Synchronize activity between 2737 * SSP and current IDN requests that 2738 * are in progress. 2739 * sb_cv 2740 * Condition variable for sigblock 2741 * handler thread to wait on. 2742 * sb_inum 2743 * Soft interrupt number assigned 2744 * by OS to handle soft interrupt 2745 * request make by low-level (IDN) 2746 * sigblock handler to dispatch actual 2747 * processing of sigblock (mailbox) 2748 * request. 2749 */ 2750 kmutex_t sb_mutex; 2751 uchar_t sb_cpuid; /* sigbintr.sb_mutex */ 2752 uchar_t sb_busy; /* sigbintr.sb_mutex */ 2753 kcondvar_t sb_cv; /* sigbintr.sb_mutex */ 2754 uint_t sb_inum; /* sigbintr.sb_mutex */ 2755 } sigbintr; 2756 2757 /* 2758 * struprwlock, strup, sip, siplock 2759 * Standard network streams 2760 * handling structures to manage 2761 * instances of IDN driver. 2762 */ 2763 krwlock_t struprwlock; 2764 struct idnstr *strup; /* struprwlock */ 2765 2766 struct idn *sip; /* siplock */ 2767 kmutex_t sipwenlock; 2768 kmutex_t siplock; 2769 2770 /* 2771 * Area where IDN maintains its kstats. 2772 */ 2773 kstat_t *ksp; 2774 /* 2775 * Number of domains that local domain 2776 * has "open". 2777 */ 2778 int ndomains; /* grwlock */ 2779 /* 2780 * Number of domains that local domain 2781 * has registered as non-responsive. 2782 */ 2783 int nawols; /* grwlock */ 2784 /* 2785 * Number of network channels (interfaces) 2786 * which are currently active. 2787 */ 2788 int nchannels; /* grwlock */ 2789 /* 2790 * Bitmask representing channels 2791 * that are currently active. 2792 */ 2793 idn_chanset_t chanset; /* grwlock */ 2794 /* 2795 * Array of channel (network/data) servers 2796 * that have been created. Not necessarily 2797 * all active. 2798 */ 2799 idn_chansvr_t *chan_servers; /* elmts = ch_mutex */ 2800 /* 2801 * Pointer to sigblock handler thread 2802 * which ultimately processes SSP 2803 * IDN requests. 2804 */ 2805 kthread_id_t sigb_threadp; 2806 /* 2807 * Pointer to area used by Master 2808 * to hold mailbox structures. 2809 * Actual memory is in SMR. 2810 */ 2811 idn_mboxtbl_t *mboxarea; /* grwlock */ 2812 2813 struct { 2814 /* 2815 * IDN_SYNC_LOCK - Provides serialization 2816 * mechanism when performing synchronous 2817 * operations across domains. 2818 */ 2819 kmutex_t sz_mutex; 2820 /* 2821 * Actual synchronization zones for 2822 * CONNECT/DISCONNECT phases. 2823 */ 2824 idn_synczone_t sz_zone[IDN_SYNC_NUMZONE]; 2825 } sync; /* sz_mutex */ 2826 2827 struct { 2828 /* 2829 * ds_trans_on 2830 * Set of domains which are trying 2831 * to establish a link w/local. 2832 * ds_ready_on 2833 * Set of domains which local knows 2834 * are ready for linking, but has 2835 * not yet confirmed w/peers. 2836 * ds_connected 2837 * Set of domains that local has 2838 * confirmed as being ready. 2839 * ds_trans_off 2840 * Set of domains which are trying 2841 * to unlink from local. 2842 * ds_ready_off 2843 * Set of domains which local knows 2844 * are ready for unlink, but has 2845 * not yet confirmed w/peers. 2846 * ds_relink 2847 * Set of domains we're expecting 2848 * to relink with subsequent to 2849 * a RECONFIG (new master selection). 2850 * ds_hwlinked 2851 * Set of domains for which local 2852 * has programmed its hardware. 2853 * ds_flush 2854 * Set of domains requiring that 2855 * local flush its ecache prior 2856 * to unlinking. 2857 * ds_awol 2858 * Set of domains believed to be 2859 * AWOL - haven't responded to 2860 * any queries. 2861 * ds_hitlist 2862 * Set of domains which local domain 2863 * is unlinking from and wishes to ignore 2864 * any extraneous indirect link requests 2865 * from other domains, e.g. during a 2866 * Reconfig. 2867 */ 2868 domainset_t ds_trans_on; /* sz_mutex */ 2869 domainset_t ds_ready_on; /* sz_mutex */ 2870 2871 domainset_t ds_connected; /* sz_mutex */ 2872 domainset_t ds_trans_off; /* sz_mutex */ 2873 2874 domainset_t ds_ready_off; /* sz_mutex */ 2875 domainset_t ds_relink; /* sz_mutex */ 2876 2877 domainset_t ds_hwlinked; /* sz_mutex */ 2878 domainset_t ds_flush; /* sz_mutex */ 2879 2880 domainset_t ds_awol; /* sz_mutex */ 2881 domainset_t ds_hitlist; /* sz_mutex */ 2882 } domset; 2883 /* 2884 * Bitmask identifying all cpus in 2885 * the local IDN. 2886 */ 2887 cpuset_t dc_cpuset; 2888 /* 2889 * Bitmask identifying all boards in 2890 * the local IDN. 2891 */ 2892 boardset_t dc_boardset; 2893 2894 struct dopers { 2895 /* 2896 * Waiting area for IDN requests, 2897 * i.e. link & unlinks. IDN requests 2898 * are performed asynchronously so 2899 * we need a place to wait until the 2900 * operation has completed. 2901 * 2902 * dop_domset 2903 * Identifies which domains the 2904 * current waiter is interested in. 2905 * dop_waitcount 2906 * Number of waiters in the room. 2907 * dop_waitlist 2908 * Actual waiting area. 2909 * dop_freelist 2910 * Freelist (small cache) of 2911 * structs for waiting area. 2912 */ 2913 kmutex_t dop_mutex; 2914 kcondvar_t dop_cv; /* dop_mutex */ 2915 domainset_t dop_domset; /* dop_mutex */ 2916 int dop_waitcount; /* dop_mutex */ 2917 dop_waitlist_t *dop_waitlist; /* dop_mutex */ 2918 dop_waitlist_t *dop_freelist; /* dop_mutex */ 2919 /* dop_mutex */ 2920 dop_waitlist_t _dop_wcache[IDNOP_CACHE_SIZE]; 2921 } *dopers; 2922 2923 struct { 2924 /* 2925 * Protocol Server: 2926 * 2927 * p_server 2928 * Linked list of queues 2929 * describing protocol 2930 * servers in use. 2931 * p_jobpool 2932 * Kmem cache of structs 2933 * used to enqueue protocol 2934 * jobs for protocol servers. 2935 * p_morgue 2936 * Synchronization (check-in) 2937 * area used when terminating 2938 * protocol servers (threads). 2939 */ 2940 struct idn_protoqueue *p_serverq; 2941 kmem_cache_t *p_jobpool; 2942 ksema_t p_morgue; 2943 } protocol; 2944 2945 struct idn_retry_queue { 2946 /* 2947 * rq_jobs 2948 * Queue of Retry jobs 2949 * that are outstanding. 2950 * rq_count 2951 * Number of jobs on retry 2952 * queue. 2953 * rq_cache 2954 * Kmem cache for structs 2955 * used to describe retry 2956 * jobs. 2957 */ 2958 idn_retry_job_t *rq_jobs; /* rq_mutex */ 2959 int rq_count; /* rq_mutex */ 2960 kmutex_t rq_mutex; /* rq_mutex */ 2961 2962 kcondvar_t rq_cv; /* rq_mutex */ 2963 kmem_cache_t *rq_cache; 2964 } retryqueue; 2965 2966 struct slabpool { 2967 /* 2968 * Slabpool: 2969 * 2970 * ntotslabs 2971 * Total number of slabs 2972 * in SMR (free & in-use). 2973 * npools 2974 * Number of pools available 2975 * in list. One smr_slabtbl 2976 * exists for each pool. 2977 */ 2978 int ntotslabs; 2979 int npools; 2980 struct smr_slabtbl { 2981 /* 2982 * sarray 2983 * Array of slab structs 2984 * representing slabs in SMR. 2985 * nfree 2986 * Number of slabs actually 2987 * available in sarray. 2988 * nslabs 2989 * Number of slabs represented 2990 * in sarray (free & in-use). 2991 */ 2992 smr_slab_t *sarray; 2993 int nfree; 2994 int nslabs; 2995 } *pool; 2996 /* 2997 * Holds array of smr_slab_t structs kmem_alloc'd 2998 * for slabpool. 2999 */ 3000 smr_slab_t *savep; 3001 } *slabpool; 3002 3003 struct slabwaiter { 3004 /* 3005 * Waiting area for threads 3006 * requesting slab allocations. 3007 * Used by Slaves for all requests, 3008 * but used by Master only for 3009 * redundant requests, i.e. multiple 3010 * requests on behalf of the same 3011 * domain. One slabwaiter area 3012 * exist for each possible domain. 3013 * 3014 * w_nwaiters 3015 * Number of threads waiting 3016 * in waiting area. 3017 * w_done 3018 * Flag to indicate that 3019 * allocation request has 3020 * completed. 3021 * w_serrno 3022 * Non-zero indicates an 3023 * errno value to represent 3024 * error that occurred during 3025 * attempt to allocate slab. 3026 * w_closed 3027 * Indicates that waiting area is 3028 * closed and won't allow any new 3029 * waiters. This occurs during 3030 * the small window where we're 3031 * trying to suspend a channel. 3032 * w_cv 3033 * Condvar for waiting on. 3034 * w_sp 3035 * Holds slab structure of 3036 * successfully allocated slab. 3037 */ 3038 kmutex_t w_mutex; 3039 short w_nwaiters; /* w_mutex */ 3040 short w_done; /* w_mutex */ 3041 short w_serrno; /* w_mutex */ 3042 short w_closed; /* w_mutex */ 3043 kcondvar_t w_cv; /* w_mutex */ 3044 smr_slab_t *w_sp; /* w_mutex */ 3045 } *slabwaiter; 3046 /* 3047 * Kmem cache used for allocating 3048 * timer structures for outstanding 3049 * IDN requests. 3050 */ 3051 kmem_cache_t *timer_cache; 3052 /* 3053 * Effectively constant used in 3054 * translating buffer frames in 3055 * mailbox message frames to 3056 * offsets within SMR. 3057 */ 3058 int bframe_shift; 3059 } idn_global_t; 3060 3061 typedef struct idn_retry_queue idn_retry_queue_t; 3062 3063 #define IDN_GET_MASTERID() (idn.masterid) 3064 #define IDN_SET_MASTERID(mid) \ 3065 { \ 3066 int _mid = (mid); \ 3067 mutex_enter(&idn.idnsb_mutex); \ 3068 if (idn.idnsb) { \ 3069 idn.idnsb->id_pmaster_board = \ 3070 idn.idnsb->id_master_board; \ 3071 if (_mid == IDN_NIL_DOMID) \ 3072 idn.idnsb->id_master_board = (uchar_t)0xff; \ 3073 else \ 3074 idn.idnsb->id_master_board = \ 3075 (uchar_t)idn_domain[_mid].dvote.v.board; \ 3076 } \ 3077 mutex_exit(&idn.idnsb_mutex); \ 3078 IDN_HISTORY_LOG(IDNH_MASTERID, _mid, idn.masterid, 0); \ 3079 PR_STATE("%d: MASTERID %d -> %d\n", __LINE__, \ 3080 idn.masterid, _mid); \ 3081 idn.masterid = _mid; \ 3082 } 3083 #define IDN_GET_NEW_MASTERID() (idn.new_masterid) 3084 #define IDN_SET_NEW_MASTERID(mid) \ 3085 { \ 3086 PR_STATE("%d: NEW MASTERID %d -> %d\n", __LINE__, \ 3087 idn.new_masterid, (mid)); \ 3088 idn.new_masterid = (mid); \ 3089 } 3090 3091 #define IDN_GLOCK_EXCL() (rw_enter(&idn.grwlock, RW_WRITER)) 3092 #define IDN_GLOCK_SHARED() (rw_enter(&idn.grwlock, RW_READER)) 3093 #define IDN_GLOCK_TRY_SHARED() (rw_tryenter(&idn.grwlock, RW_READER)) 3094 #define IDN_GLOCK_DOWNGRADE() (rw_downgrade(&idn.grwlock)) 3095 #define IDN_GUNLOCK() (rw_exit(&idn.grwlock)) 3096 #define IDN_GLOCK_IS_EXCL() (RW_WRITE_HELD(&idn.grwlock)) 3097 #define IDN_GLOCK_IS_SHARED() (RW_READ_HELD(&idn.grwlock)) 3098 #define IDN_GLOCK_IS_HELD() (RW_LOCK_HELD(&idn.grwlock)) 3099 3100 #define IDN_SYNC_LOCK() (mutex_enter(&idn.sync.sz_mutex)) 3101 #define IDN_SYNC_TRYLOCK() (mutex_tryenter(&idn.sync.sz_mutex)) 3102 #define IDN_SYNC_UNLOCK() (mutex_exit(&idn.sync.sz_mutex)) 3103 #define IDN_SYNC_IS_LOCKED() (MUTEX_HELD(&idn.sync.sz_mutex)) 3104 3105 /* 3106 * Macro to reset some globals necessary in preparing 3107 * for initialization of HW for IDN. 3108 */ 3109 #define IDN_PREP_HWINIT() \ 3110 { \ 3111 ASSERT(IDN_GLOCK_IS_EXCL()); \ 3112 lock_clear(&idn.first_swlink); \ 3113 lock_clear(&idn.first_hwlink); \ 3114 idn.first_hwmasterid = (short)IDN_NIL_DOMID; \ 3115 } 3116 3117 /* 3118 * Return values of idn_send_data. 3119 */ 3120 #define IDNXMIT_OKAY 0 /* xmit successful */ 3121 #define IDNXMIT_LOOP 1 /* loopback */ 3122 #define IDNXMIT_DROP 2 /* drop packet */ 3123 #define IDNXMIT_RETRY 3 /* retry packet (requeue and qenable) */ 3124 #define IDNXMIT_REQUEUE 4 /* requeue packet, but don't qenable */ 3125 3126 /* 3127 * --------------------------------------------------------------------- 3128 * ss_rwlock must be acquired _before_ any idn_domain locks are 3129 * acquired if both structs need to be accessed. 3130 * idn.struprwlock is acquired when traversing IDN's strup list 3131 * and when adding or deleting entries. 3132 * 3133 * ss_nextp Linked list of streams. 3134 * ss_rq Respective read queue. 3135 * ss_sip Attached device. 3136 * ss_state Current DL state. 3137 * ss_sap Bound SAP. 3138 * ss_flags Misc. flags. 3139 * ss_mccount # enabled multicast addrs. 3140 * ss_mctab Table of multicast addrs. 3141 * ss_minor Minor device number. 3142 * ss_rwlock Protects ss_linkup fields and DLPI state machine. 3143 * ss_linkup Boolean flag indicating whether particular (domain) link 3144 * is up. 3145 * --------------------------------------------------------------------- 3146 */ 3147 struct idnstr { /* gets shoved into q_ptr */ 3148 struct idnstr *ss_nextp; 3149 queue_t *ss_rq; 3150 struct idn *ss_sip; 3151 t_uscalar_t ss_state; 3152 t_uscalar_t ss_sap; 3153 uint_t ss_flags; 3154 uint_t ss_mccount; 3155 struct ether_addr *ss_mctab; 3156 minor_t ss_minor; 3157 krwlock_t ss_rwlock; 3158 }; 3159 3160 /* 3161 * idnstr.ss_flags - Per-stream flags 3162 */ 3163 #define IDNSFAST 0x01 /* "M_DATA fastpath" mode */ 3164 #define IDNSRAW 0x02 /* M_DATA plain raw mode */ 3165 #define IDNSALLPHYS 0x04 /* "promiscuous mode" */ 3166 #define IDNSALLMULTI 0x08 /* enable all multicast addresses */ 3167 #define IDNSALLSAP 0x10 /* enable all ether type values */ 3168 3169 /* 3170 * Maximum number of multicast address per stream. 3171 */ 3172 #define IDNMAXMC 64 3173 #define IDNMCALLOC (IDNMAXMC * sizeof (struct ether_addr)) 3174 3175 /* 3176 * Full DLSAP address length (in struct dladdr format). 3177 */ 3178 #define IDNADDRL (ETHERADDRL + sizeof (ushort_t)) 3179 3180 struct idndladdr { 3181 struct ether_addr dl_phys; 3182 ushort_t dl_sap; 3183 }; 3184 3185 #define IDNHEADROOM 64 3186 #define IDNROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) 3187 3188 /* 3189 * Respective interpretation of bytes in 6 byte ethernet address. 3190 */ 3191 #define IDNETHER_ZERO 0 3192 #define IDNETHER_COOKIE1 1 3193 #define IDNETHER_COOKIE1_VAL 0xe5 3194 #define IDNETHER_COOKIE2 2 3195 #define IDNETHER_COOKIE2_VAL 0x82 3196 #define IDNETHER_NETID 3 3197 #define IDNETHER_CHANNEL 4 3198 #define IDNETHER_RESERVED 5 3199 #define IDNETHER_RESERVED_VAL 0x64 3200 3201 /* 3202 * IDN driver supports multliple instances, however they 3203 * still all refer to the same "physical" device. Multiple 3204 * instances are supported primarily to allow increased 3205 * STREAMs bandwidth since each instance has it's own IP queue. 3206 * This structure is primarily defined to be consistent with 3207 * other network drivers and also to hold the kernel stats. 3208 */ 3209 struct idn_kstat { 3210 ulong_t si_ipackets; /* # packets received */ 3211 ulong_t si_ierrors; /* # total input errors */ 3212 ulong_t si_opackets; /* # packets sent */ 3213 ulong_t si_oerrors; /* # total output errors */ 3214 3215 ulong_t si_txcoll; /* # xmit collisions */ 3216 ulong_t si_rxcoll; /* # recv collisions */ 3217 ulong_t si_crc; /* # recv crc errors */ 3218 ulong_t si_buff; /* # recv pkt sz > buf sz */ 3219 3220 ulong_t si_nolink; /* # loss of connection */ 3221 ulong_t si_linkdown; /* # link is down */ 3222 ulong_t si_inits; /* # driver inits */ 3223 ulong_t si_nocanput; /* # canput() failures */ 3224 3225 ulong_t si_allocbfail; /* # allocb() failures */ 3226 ulong_t si_notbufs; /* # out of xmit buffers */ 3227 ulong_t si_reclaim; /* # reclaim failures */ 3228 ulong_t si_smraddr; /* # bad SMR addrs */ 3229 3230 ulong_t si_txmax; /* # xmit over limit */ 3231 ulong_t si_txfull; /* # xmit mbox full */ 3232 ulong_t si_xdcall; /* # xdcalls sent */ 3233 ulong_t si_sigsvr; /* # data server wakeups */ 3234 3235 ulong_t si_mboxcrc; /* # send mbox crc errors */ 3236 /* 3237 * MIB II kstat variables 3238 */ 3239 ulong_t si_rcvbytes; /* # bytes received */ 3240 ulong_t si_xmtbytes; /* # bytes transmitted */ 3241 ulong_t si_multircv; /* # multicast packets received */ 3242 3243 ulong_t si_multixmt; /* # multicast packets for xmit */ 3244 ulong_t si_brdcstrcv; /* # broadcast packets received */ 3245 ulong_t si_brdcstxmt; /* # broadcast packets for xmit */ 3246 ulong_t si_norcvbuf; /* # rcv packets discarded */ 3247 3248 ulong_t si_noxmtbuf; /* # xmit packets discarded */ 3249 /* 3250 * PSARC 1997/198 : 64 bit kstats 3251 */ 3252 uint64_t si_ipackets64; /* # packets received */ 3253 uint64_t si_opackets64; /* # packets transmitted */ 3254 uint64_t si_rbytes64; /* # bytes received */ 3255 uint64_t si_obytes64; /* # bytes transmitted */ 3256 /* 3257 * PSARC 1997/247 : RFC 1643 dot3Stats... 3258 */ 3259 ulong_t si_fcs_errors; /* FCSErrors */ 3260 ulong_t si_macxmt_errors; /* InternalMacTransmitErrors */ 3261 ulong_t si_toolong_errors; /* FrameTooLongs */ 3262 ulong_t si_macrcv_errors; /* InternalMacReceiveErrors */ 3263 }; 3264 3265 /* 3266 * Per logical interface private data structure. 3267 */ 3268 struct idn { 3269 struct idn *si_nextp; /* linked instances */ 3270 dev_info_t *si_dip; /* assoc. dev_info */ 3271 struct ether_addr si_ouraddr; /* enet address */ 3272 3273 uint_t si_flags; /* misc. flags */ 3274 uint_t si_wantw; /* xmit: out of res. */ 3275 queue_t *si_ip4q; /* ip (v4) read queue */ 3276 queue_t *si_ip6q; /* ip (v6) read queue */ 3277 3278 kstat_t *si_ksp; /* kstat pointer */ 3279 struct idn_kstat si_kstat; /* per-inst kstat */ 3280 }; 3281 3282 struct idn_gkstat { 3283 ulong_t gk_reconfigs; /* # reconfigs */ 3284 ulong_t gk_reconfig_last; /* timestamep */ 3285 ulong_t gk_reaps; /* # of reap request */ 3286 ulong_t gk_reap_last; /* timestamep */ 3287 3288 ulong_t gk_links; /* # of IDN links */ 3289 ulong_t gk_link_last; /* timestamep */ 3290 ulong_t gk_unlinks; /* # of IDN unlinks */ 3291 ulong_t gk_unlink_last; /* timestamep */ 3292 3293 ulong_t gk_buffail; /* # bad bufalloc */ 3294 ulong_t gk_buffail_last; /* timestamp */ 3295 ulong_t gk_slabfail; /* # bad slaballoc */ 3296 ulong_t gk_slabfail_last; /* timestamp */ 3297 3298 ulong_t gk_reap_count; /* # of slabs reaped */ 3299 ulong_t gk_dropped_intrs; /* dropped intrs */ 3300 }; 3301 3302 extern struct idn_gkstat sg_kstat; 3303 3304 #ifdef IDN_NO_KSTAT 3305 3306 #define IDN_KSTAT_INC(s, i) 3307 #define IDN_KSTAT_ADD(s, i, n) 3308 #define IDN_GKSTAT_INC(i) 3309 #define IDN_GKSTAT_ADD(vvv, iii) 3310 #define IDN_GKSTAT_GLOBAL_EVENT(vvv, nnn) 3311 3312 #else /* IDN_NO_KSTAT */ 3313 3314 #define IDN_KSTAT_INC(sss, vvv) \ 3315 ((((struct idn *)(sss))->si_kstat.vvv)++) 3316 #define IDN_KSTAT_ADD(sss, vvv, nnn) \ 3317 ((((struct idn *)(sss))->si_kstat.vvv) += (nnn)) 3318 #define IDN_GKSTAT_INC(vvv) ((sg_kstat.vvv)++) 3319 #define IDN_GKSTAT_ADD(vvv, iii) ((sg_kstat.vvv) += (iii)) 3320 #define IDN_GKSTAT_GLOBAL_EVENT(vvv, ttt) \ 3321 ((sg_kstat.vvv)++, ((sg_kstat.ttt) = lbolt)) 3322 3323 #endif /* IDN_NO_KSTAT */ 3324 3325 /* 3326 * idn.si_flags 3327 */ 3328 #define IDNRUNNING 0x01 /* IDNnet is UP */ 3329 #define IDNPROMISC 0x02 /* promiscuous mode enabled */ 3330 #define IDNSUSPENDED 0x04 /* suspended (DR) */ 3331 3332 typedef struct kstat_named kstate_named_t; 3333 3334 struct idn_kstat_named { 3335 kstat_named_t sk_ipackets; /* # packets received */ 3336 kstat_named_t sk_ierrors; /* # total input errors */ 3337 kstat_named_t sk_opackets; /* # packets sent */ 3338 kstat_named_t sk_oerrors; /* # total output errors */ 3339 3340 kstat_named_t sk_txcoll; /* # xmit collisions */ 3341 kstat_named_t sk_rxcoll; /* # recv collisions */ 3342 kstat_named_t sk_crc; /* # recv crc errors */ 3343 kstat_named_t sk_buff; /* # recv pkt sz > buf sz */ 3344 3345 kstat_named_t sk_nolink; /* # loss of connection */ 3346 kstat_named_t sk_linkdown; /* # link is down */ 3347 kstat_named_t sk_inits; /* # driver inits */ 3348 kstat_named_t sk_nocanput; /* # canput() failures */ 3349 3350 kstat_named_t sk_allocbfail; /* # allocb() failures */ 3351 kstat_named_t sk_notbufs; /* # out of xmit buffers */ 3352 kstat_named_t sk_reclaim; /* # reclaim failures */ 3353 kstat_named_t sk_smraddr; /* # bad SMR addrs */ 3354 3355 kstat_named_t sk_txmax; /* # xmit over limit */ 3356 kstat_named_t sk_txfull; /* # xmit mbox full */ 3357 kstat_named_t sk_xdcall; /* # xdcalls sent */ 3358 kstat_named_t sk_sigsvr; /* # data server wakeups */ 3359 3360 kstat_named_t sk_mboxcrc; /* # send mbox crc errors */ 3361 /* 3362 * MIB II kstat variables 3363 */ 3364 kstat_named_t sk_rcvbytes; /* # bytes received */ 3365 kstat_named_t sk_xmtbytes; /* # bytes transmitted */ 3366 kstat_named_t sk_multircv; /* # multicast packets received */ 3367 3368 kstat_named_t sk_multixmt; /* # multicast packets for xmit */ 3369 kstat_named_t sk_brdcstrcv; /* # broadcast packets received */ 3370 kstat_named_t sk_brdcstxmt; /* # broadcast packets for xmit */ 3371 kstat_named_t sk_norcvbuf; /* # rcv packets discarded */ 3372 3373 kstat_named_t sk_noxmtbuf; /* # xmit packets discarded */ 3374 /* 3375 * PSARC 1997/198 : 64bit kstats 3376 */ 3377 kstat_named_t sk_ipackets64; /* # packets received */ 3378 kstat_named_t sk_opackets64; /* # packets transmitted */ 3379 kstat_named_t sk_rbytes64; /* # bytes received */ 3380 kstat_named_t sk_obytes64; /* # bytes transmitted */ 3381 /* 3382 * PSARC 1997/247 : RFC 1643 dot3Stats... 3383 */ 3384 kstat_named_t sk_fcs_errors; /* FCSErr */ 3385 kstat_named_t sk_macxmt_errors; /* InternalMacXmtErr */ 3386 kstat_named_t sk_toolong_errors; /* FrameTooLongs */ 3387 kstat_named_t sk_macrcv_errors; /* InternalMacRcvErr */ 3388 }; 3389 3390 /* 3391 * Stats for global events of interest (non-counters). 3392 */ 3393 struct idn_gkstat_named { 3394 kstat_named_t sk_curtime; /* current time */ 3395 kstat_named_t sk_reconfigs; /* # master recfgs */ 3396 kstat_named_t sk_reconfig_last; /* timestamp */ 3397 kstat_named_t sk_reaps; /* # of reap req */ 3398 kstat_named_t sk_reap_last; /* timestamp */ 3399 kstat_named_t sk_links; /* # of links */ 3400 kstat_named_t sk_link_last; /* timestamp */ 3401 kstat_named_t sk_unlinks; /* # of unlinks */ 3402 kstat_named_t sk_unlink_last; /* timestamp */ 3403 kstat_named_t sk_buffail; /* # bad buf alloc */ 3404 kstat_named_t sk_buffail_last; /* timestamp */ 3405 kstat_named_t sk_slabfail; /* # bad buf alloc */ 3406 kstat_named_t sk_slabfail_last; /* timestamp */ 3407 kstat_named_t sk_reap_count; /* # slabs reaped */ 3408 kstat_named_t sk_dropped_intrs; /* intrs dropped */ 3409 }; 3410 3411 /* 3412 * --------------------------------------------------------------------- 3413 */ 3414 #ifdef DEBUG 3415 #define IDNXDC(d, mt, a1, a2, a3, a4) \ 3416 (debug_idnxdc("idnxdc", (int)(d), (mt), \ 3417 (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) 3418 #else /* DEBUG */ 3419 #define IDNXDC(d, mt, a1, a2, a3, a4) \ 3420 (idnxdc((int)(d), (mt), \ 3421 (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) 3422 #endif /* DEBUG */ 3423 #define IDNXDC_BROADCAST(ds, mt, a1, a2, a3, a4) \ 3424 (idnxdc_broadcast((domainset_t)(ds), (mt), \ 3425 (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) 3426 3427 /* 3428 * --------------------------------------------------------------------- 3429 */ 3430 #define SET_XARGS(x, a0, a1, a2, a3) \ 3431 ((x)[0] = (uint_t)(a0), (x)[1] = (uint_t)(a1), \ 3432 (x)[2] = (uint_t)(a2), (x)[3] = (uint_t)(a3)) 3433 3434 #define GET_XARGS(x, a0, a1, a2, a3) \ 3435 (((a0) ? *(uint_t *)(a0) = (x)[0] : 1), \ 3436 ((a1) ? *(uint_t *)(a1) = (x)[1] : 1), \ 3437 ((a2) ? *(uint_t *)(a2) = (x)[2] : 1), \ 3438 ((a3) ? *(uint_t *)(a3) = (x)[3] : 1)) 3439 3440 #define CLR_XARGS(x) \ 3441 ((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0) 3442 3443 #define GET_XARGS_NEGO_TICKET(x) ((uint_t)(x)[0]) 3444 #define GET_XARGS_NEGO_DSET(x, d) \ 3445 ((d)[0] = (x)[1], (d)[1] = (x)[2], (d)[2] = (x)[3]) 3446 #define SET_XARGS_NEGO_TICKET(x, t) ((x)[0] = (uint_t)(t)) 3447 #define SET_XARGS_NEGO_DSET(x, d) \ 3448 ((x)[1] = (uint_t)(d)[0], \ 3449 (x)[2] = (uint_t)(d)[1], \ 3450 (x)[3] = (uint_t)(d)[2]) 3451 3452 #define GET_XARGS_CON_TYPE(x) ((idn_con_t)(x)[0]) 3453 #define GET_XARGS_CON_DOMSET(x) ((domainset_t)(x)[1]) 3454 #define SET_XARGS_CON_TYPE(x, t) ((x)[0] = (uint_t)(t)) 3455 #define SET_XARGS_CON_DOMSET(x, s) ((x)[1] = (uint_t)(s)) 3456 3457 #define GET_XARGS_FIN_TYPE(x) GET_FIN_TYPE((x)[0]) 3458 #define GET_XARGS_FIN_ARG(x) GET_FIN_ARG((x)[0]) 3459 #define GET_XARGS_FIN_DOMSET(x) ((domainset_t)(x)[1]) 3460 #define GET_XARGS_FIN_OPT(x) ((idn_finopt_t)(x)[2]) 3461 #define GET_XARGS_FIN_MASTER(x) ((uint_t)(x)[3]) 3462 #define SET_XARGS_FIN_TYPE(x, t) SET_FIN_TYPE((x)[0], (t)) 3463 #define SET_XARGS_FIN_ARG(x, a) SET_FIN_ARG((x)[0], (a)) 3464 #define SET_XARGS_FIN_DOMSET(x, s) ((x)[1] = (uint_t)(s)) 3465 #define SET_XARGS_FIN_OPT(x, o) ((x)[2] = (uint_t)(o)) 3466 #define SET_XARGS_FIN_MASTER(x, m) ((x)[3] = (uint_t)(m)) 3467 3468 #define GET_XARGS_NACK_TYPE(x) ((idn_nack_t)(x)[0]) 3469 #define GET_XARGS_NACK_ARG1(x) ((x)[1]) 3470 #define GET_XARGS_NACK_ARG2(x) ((x)[2]) 3471 #define SET_XARGS_NACK_TYPE(x, t) ((x)[0] = (uint_t)(t)) 3472 #define SET_XARGS_NACK_ARG1(x, a1) ((x)[1] = (uint_t)(a1)) 3473 #define SET_XARGS_NACK_ARG2(x, a2) ((x)[2] = (uint_t)(a2)) 3474 3475 #define GET_XARGS_CFG_PHASE(x) ((int)(x)[0]) 3476 #define SET_XARGS_CFG_PHASE(x, p) ((x)[0] = (uint_t)(p)) 3477 3478 /* 3479 * --------------------------------------------------------------------- 3480 */ 3481 /* 3482 * Device instance to SIP (IDN instance pointer). 3483 */ 3484 #ifdef DEBUG 3485 #define IDN_INST2SIP(i) \ 3486 (ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))), \ 3487 idn_i2s_table[i]) 3488 #else /* DEBUG */ 3489 #define IDN_INST2SIP(i) (idn_i2s_table[i]) 3490 #endif /* DEBUG */ 3491 3492 #define IDN_SET_INST2SIP(i, s) \ 3493 { \ 3494 ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))); \ 3495 idn_i2s_table[i] = (s); \ 3496 } 3497 3498 #define IDN_NETID2DOMID(n) (VALID_UDOMAINID(n) ? \ 3499 ((int)(n)) : IDN_NIL_DOMID) 3500 #define IDN_DOMID2NETID(d) ((ushort_t)(d)) 3501 3502 #ifdef DEBUG 3503 #define IDNDL_ETHER2DOMAIN(eap) \ 3504 (_idndl_ether2domain(eap)) 3505 #define IDNDL_ETHER2SIP(eap) \ 3506 (_idndl_ether2sip(eap)) 3507 #else 3508 /* 3509 * The following values can be returned from IDNDL_ETHER2DOMAIN: 3510 * IDN_NIL_DOMID 3511 * Ether address is broadcast (0xff) or domain doesn't exist. 3512 * domid Domain id with drwlock(reader) held. 3513 */ 3514 #define IDNDL_ETHER2DOMAIN(eap) \ 3515 (IDN_NETID2DOMID((eap)->ether_addr_octet[IDNETHER_NETID])) 3516 #define IDNDL_ETHER2SIP(eap) \ 3517 (((eap)->ether_addr_octet[IDNETHER_CHANNEL] == 0xff) ? NULL : \ 3518 IDN_INST2SIP((int)(eap)->ether_addr_octet[IDNETHER_CHANNEL])) 3519 #endif /* DEBUG */ 3520 3521 #define UPPER32_CPUMASK(s) _upper32cpumask(s) 3522 #define LOWER32_CPUMASK(s) _lower32cpumask(s) 3523 #define MAKE64_CPUMASK(s, u, l) _make64cpumask(&(s), (u), (l)) 3524 3525 #ifdef DEBUG 3526 extern caddr_t _idn_getstruct(char *structname, int size); 3527 extern void _idn_freestruct(caddr_t ptr, char *structname, int size); 3528 3529 #define GETSTRUCT(structure, num) \ 3530 ((structure *)_idn_getstruct("structure", sizeof (structure)*(num))) 3531 #define FREESTRUCT(ptr, structure, num) \ 3532 (_idn_freestruct((caddr_t)ptr, "structure", sizeof (structure)*(num))) 3533 #else /* DEBUG */ 3534 #define GETSTRUCT(structure, num) \ 3535 ((structure *)kmem_zalloc((uint_t)(sizeof (structure) * (num)), \ 3536 KM_SLEEP)) 3537 #define FREESTRUCT(ptr, structure, num) \ 3538 (kmem_free((caddr_t)(ptr), sizeof (structure) * (num))) 3539 #endif /* DEBUG */ 3540 3541 extern int idn_debug; 3542 extern idn_global_t idn; 3543 extern idn_domain_t idn_domain[]; 3544 extern struct idn *idn_i2s_table[]; 3545 extern int idn_history; 3546 extern struct idn_history idnhlog; 3547 3548 extern int idn_smr_size; 3549 extern int idn_nwr_size; 3550 extern int idn_protocol_nservers; 3551 extern int idn_awolmsg_interval; 3552 extern int idn_smr_bufsize; 3553 extern int idn_slab_bufcount; 3554 extern int idn_slab_prealloc; 3555 extern int idn_slab_mintotal; 3556 extern int idn_window_max; 3557 extern int idn_window_incr; 3558 extern int idn_reclaim_min; 3559 extern int idn_reclaim_max; 3560 extern int idn_mbox_per_net; 3561 extern int idn_max_nets; 3562 3563 extern int idn_netsvr_spin_count; 3564 extern int idn_netsvr_wait_min; 3565 extern int idn_netsvr_wait_max; 3566 extern int idn_netsvr_wait_shift; 3567 3568 extern int idn_checksum; 3569 3570 extern int idn_msgwait_nego; 3571 extern int idn_msgwait_cfg; 3572 extern int idn_msgwait_con; 3573 extern int idn_msgwait_fin; 3574 extern int idn_msgwait_cmd; 3575 extern int idn_msgwait_data; 3576 3577 extern int idn_retryfreq_nego; 3578 extern int idn_retryfreq_con; 3579 extern int idn_retryfreq_fin; 3580 3581 extern int idn_window_emax; /* calculated */ 3582 extern int idn_slab_maxperdomain; /* calculated */ 3583 3584 /* 3585 * --------------------------------------------------------------------- 3586 * io/idn.c 3587 * --------------------------------------------------------------------- 3588 */ 3589 extern int board_to_ready_cpu(int board, cpuset_t cpuset); 3590 extern int idn_open_domain(int domid, int cpuid, uint_t ticket); 3591 extern void idn_close_domain(int domid); 3592 extern void inum2str(uint_t inum, char str[]); 3593 extern idn_timer_t *idn_timer_alloc(); 3594 extern void idn_timer_free(idn_timer_t *tp); 3595 extern void idn_timerq_init(idn_timerq_t *tq); 3596 extern void idn_timerq_deinit(idn_timerq_t *tq); 3597 extern void idn_timerq_free(idn_timerq_t *tq); 3598 extern ushort_t idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp, 3599 clock_t tval); 3600 extern int idn_timer_stopall(idn_timer_t *tp); 3601 extern void idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp); 3602 extern void idn_timer_stop(idn_timerq_t *tq, int subtype, ushort_t tcookie); 3603 extern idn_timer_t *idn_timer_get(idn_timerq_t *tq, int subtype, 3604 ushort_t tcookie); 3605 extern void idn_domain_resetentry(idn_domain_t *dp); 3606 extern void idn_strlinks_enable(uint_t netaddr, int domid); 3607 extern void idn_strlinks_disable(uint_t domset, uint_t netaddr, 3608 int disconnect); 3609 extern void idn_dopcache_init(); 3610 extern void idn_dopcache_deinit(); 3611 extern void *idn_init_op(idn_opflag_t opflag, boardset_t boardset, 3612 idnsb_error_t *sep); 3613 extern void idn_add_op(idn_opflag_t opflag, domainset_t domset); 3614 extern void idn_update_op(idn_opflag_t opflag, domainset_t domset, 3615 idnsb_error_t *sep); 3616 extern void idn_deinit_op(void *cookie); 3617 extern int idn_wait_op(void *cookie, boardset_t *domsetp, 3618 int wait_timeout); 3619 extern int idn_wakeup_op(boardset_t boardset, uint_t domset, 3620 idn_opflag_t opflag, int error); 3621 extern void idn_error_op(uint_t domset, boardset_t boardset, int error); 3622 extern void cpuset2str(cpuset_t cset, char buffer[]); 3623 extern void domainset2str(domainset_t dset, char buffer[]); 3624 extern void boardset2str(boardset_t bset, char buffer[]); 3625 extern void mask2str(uint_t mask, char buffer[], int maxnum); 3626 extern int idnxdc(int domid, idn_msgtype_t *mtp, 3627 uint_t arg1, uint_t arg2, 3628 uint_t arg3, uint_t arg4); 3629 extern void idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp, 3630 uint_t arg1, uint_t arg2, 3631 uint_t arg3, uint_t arg4); 3632 extern void idn_awol_event_set(boardset_t boardset); 3633 extern void idn_awol_event_clear(boardset_t boardset); 3634 #ifdef DEBUG 3635 extern int debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp, 3636 uint_t arg1, uint_t arg2, 3637 uint_t arg3, uint_t arg4); 3638 #endif /* DEBUG */ 3639 extern boardset_t cpuset2boardset(cpuset_t portset); 3640 extern uint_t _upper32cpumask(cpuset_t cset); 3641 extern uint_t _lower32cpumask(cpuset_t cset); 3642 extern void _make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower); 3643 3644 /* 3645 * --------------------------------------------------------------------- 3646 * io/idn_proto.c 3647 * --------------------------------------------------------------------- 3648 */ 3649 extern void idn_assign_cookie(int domid); 3650 extern int idn_rput_data(queue_t *q, mblk_t *mp, int isput); 3651 extern int idn_wput_data(queue_t *q, mblk_t *mp, int isput); 3652 extern int idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr, 3653 queue_t *wq, mblk_t *mp); 3654 extern void idn_recv_signal(mblk_t *mp); 3655 extern int idn_link(int domid, int cpuid, int pri, int waittime, 3656 idnsb_error_t *sep); 3657 extern int idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype, 3658 idn_finopt_t finopt, int waittime, 3659 idnsb_error_t *sep); 3660 extern int idnh_recv_dataack(int domid, int src_proc, 3661 uint_t acknack, idn_xdcargs_t xargs); 3662 extern int idnh_recv_other(int sourceid, int src_proc, int dst_proc, 3663 uint_t inum, uint_t acknack, 3664 idn_xdcargs_t xargs); 3665 extern void idn_send_cmd(int domid, idn_cmd_t cmdtype, 3666 uint_t arg1, uint_t arg2, uint_t arg3); 3667 extern void idn_send_cmdresp(int domid, idn_msgtype_t *mtp, 3668 idn_cmd_t cmdtype, uint_t arg1, 3669 uint_t arg2, uint_t cerrno); 3670 extern void idn_broadcast_cmd(idn_cmd_t cmdtype, 3671 uint_t arg1, uint_t arg2, uint_t arg3); 3672 extern int idn_reclaim_mboxdata(int domid, int channel, int nbufs); 3673 extern void idn_clear_awol(int domid); 3674 extern int idn_protocol_init(int nservers); 3675 extern void idn_protocol_deinit(); 3676 extern void idn_timer_expired(void *arg); 3677 extern int idn_open_channel(int channel); 3678 extern void idn_close_channel(int channel, idn_chanop_t chanop); 3679 extern idn_mainmbox_t *idn_mainmbox_init(int domid, int mbx); 3680 extern void idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp); 3681 extern void idn_signal_data_server(int domid, ushort_t channel); 3682 extern int idn_chanservers_init(); 3683 extern void idn_chanservers_deinit(); 3684 extern void idn_chanserver_bind(int net, int cpuid); 3685 extern int idn_retry_terminate(uint_t token); 3686 extern idn_protojob_t *idn_protojob_alloc(int kmflag); 3687 extern void idn_protojob_submit(int cookie, idn_protojob_t *jp); 3688 extern int idn_domain_is_registered(int domid, int channel, 3689 idn_chanset_t *chansetp); 3690 extern void idn_xmit_monitor_kickoff(int chan_wanted); 3691 extern void idn_sync_exit(int domid, idn_synccmd_t cmd); 3692 /* 3693 * --------------------------------------------------------------------- 3694 * io/idn_xf.c 3695 * --------------------------------------------------------------------- 3696 */ 3697 extern void idnxf_flushall_ecache(); 3698 extern int idnxf_shmem_add(int is_master, boardset_t boardset, 3699 pfn_t pfnbase, pfn_t pfnlimit, 3700 uint_t *mcadr); 3701 extern int idnxf_shmem_sub(int is_master, boardset_t boardset); 3702 extern int idn_cpu_per_board(void *p2o, cpuset_t cset, 3703 struct hwconfig *hwp); 3704 /* 3705 * --------------------------------------------------------------------- 3706 * io/idn_dlpi.c 3707 * --------------------------------------------------------------------- 3708 */ 3709 extern int idndl_init(struct idn *sip); 3710 extern void idndl_uninit(struct idn *sip); 3711 extern void idndl_statinit(struct idn *sip); 3712 extern void idndl_dodetach(struct idnstr *); 3713 extern int idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsize); 3714 extern void idndl_localetheraddr(struct idn *sip, struct ether_addr *eap); 3715 extern int idndl_domain_etheraddr(int domid, int instance, 3716 struct ether_addr *eap); 3717 extern void idndl_dlpi_init(); 3718 extern int idndl_start(queue_t *wq, mblk_t *mp, struct idn *sip); 3719 extern void idndl_read(struct idn *sip, mblk_t *mp); 3720 extern void idndl_proto(queue_t *wq, mblk_t *mp); 3721 extern void idndl_sendup(struct idn *, mblk_t *, struct idnstr *(*)()); 3722 extern struct idnstr *idndl_accept(struct idnstr *, struct idn *, int, 3723 struct ether_addr *); 3724 extern struct idnstr *idndl_paccept(struct idnstr *, struct idn *, int, 3725 struct ether_addr *); 3726 extern void idndl_wenable(struct idn *); 3727 /* 3728 * --------------------------------------------------------------------- 3729 * io/idn_smr.c 3730 * --------------------------------------------------------------------- 3731 */ 3732 extern void smr_slabwaiter_open(domainset_t domset); 3733 extern void smr_slabwaiter_close(domainset_t domset); 3734 /* 3735 * --------------------------------------------------------------------- 3736 */ 3737 extern void idn_smrsize_init(); 3738 extern void idn_init_autolink(); 3739 extern void idn_deinit_autolink(); 3740 3741 extern void idn_dmv_handler(void *arg); 3742 extern void idnxf_init_mondo(uint64_t dmv_word0, 3743 uint64_t dmv_word1, uint64_t dmv_word2); 3744 extern int idnxf_send_mondo(int upaid); 3745 3746 extern clock_t idn_msg_waittime[]; 3747 extern clock_t idn_msg_retrytime[]; 3748 3749 #endif /* !_ASM */ 3750 #endif /* _KERNEL */ 3751 3752 #ifndef _ASM 3753 /* 3754 * --------------------------------------------------------------------- 3755 */ 3756 #define IDN_NIL_DOMID -1 3757 #define IDN_NIL_DCPU -1 3758 3759 /* 3760 * --------------------------------------------------------------------- 3761 */ 3762 3763 /* 3764 * IOCTL Interface 3765 * 3766 * Commands must stay in the range (1 - 4096) since only 12 bits 3767 * are allotted. 3768 */ 3769 #define _IDN(n) (('I' << 20) | ('D' << 12) | (n)) 3770 #define IDNIOC_LINK _IDN(1) /* domain_link */ 3771 #define IDNIOC_UNLINK _IDN(2) /* domain_unlink */ 3772 #define IDNIOC_unused0 _IDN(3) 3773 #define IDNIOC_unused1 _IDN(4) 3774 #define IDNIOC_unused2 _IDN(5) 3775 #define IDNIOC_unused3 _IDN(6) 3776 #define IDNIOC_unused4 _IDN(7) 3777 #define IDNIOC_DLPI_ON _IDN(8) /* Turn ON DLPI on str */ 3778 #define IDNIOC_DLPI_OFF _IDN(9) /* Turn OFF DLPI on str */ 3779 #define IDNIOC_PING _IDN(10) /* For latency testing */ 3780 #define IDNIOC_PING_INIT _IDN(11) 3781 #define IDNIOC_PING_DEINIT _IDN(12) 3782 #define IDNIOC_MEM_RW _IDN(13) /* Random R/W of SMR */ 3783 3784 3785 #define VALID_NDOP(op) (((op) == ND_SET) || ((op) == ND_GET)) 3786 3787 #define VALID_DLPIOP(op) (((op) == DLIOCRAW) || \ 3788 ((op) == DL_IOC_HDR_INFO)) 3789 3790 #define VALID_IDNOP(op) (((op) >= _IDN(1)) && ((op) <= _IDN(13))) 3791 3792 #define VALID_IDNIOCTL(op) (VALID_IDNOP(op) || \ 3793 VALID_NDOP(op) || \ 3794 VALID_DLPIOP(op)) 3795 3796 typedef union idnop { 3797 struct { 3798 int domid; /* input */ 3799 int cpuid; /* input */ 3800 int master; /* input */ 3801 int wait; /* input */ 3802 } link; 3803 struct { 3804 int domid; /* input */ 3805 int cpuid; /* input */ 3806 int force; /* input */ 3807 int wait; /* input */ 3808 } unlink; 3809 struct { 3810 int domid; /* input */ 3811 int cpuid; /* input */ 3812 } ping; 3813 struct { 3814 uint_t lo_off; /* input */ 3815 uint_t hi_off; /* input */ 3816 int blksize; /* input */ 3817 int num; /* input */ 3818 int rw; /* input */ 3819 int goawol; /* input */ 3820 } rwmem; 3821 } idnop_t; 3822 3823 #ifdef _KERNEL 3824 /* 3825 * ndd support for IDN tunables. 3826 */ 3827 typedef struct idnparam { 3828 ulong_t sp_min; 3829 ulong_t sp_max; 3830 ulong_t sp_val; 3831 char *sp_name; 3832 } idnparam_t; 3833 3834 extern idnparam_t idn_param_arr[]; 3835 3836 #define idn_modunloadable idn_param_arr[0].sp_val 3837 #ifdef IDN_PERF 3838 #define _LP 0 3839 #define _xxx_tbd idn_param_arr[_LP+1].sp_val 3840 #endif /* IDN_PERF */ 3841 3842 /* 3843 * ===================================================================== 3844 */ 3845 3846 /* 3847 * Some junk to pretty print board lists and cpu lists in 3848 * log/console messages. Length is big enough to display 64 double 3849 * digit cpus separated by a command and single space. (Board list 3850 * is similar, but only 16 entries possible. 3851 */ 3852 #define _DSTRLEN 400 3853 #define ALLOC_DISPSTRING() ((char *)kmem_alloc(_DSTRLEN, KM_NOSLEEP)) 3854 #define FREE_DISPSTRING(b) (kmem_free((void *)(b), _DSTRLEN)) 3855 3856 /* 3857 * These are declared in idn.c. 3858 */ 3859 extern const char *idnds_str[]; 3860 extern const char *idnxs_str[]; 3861 extern const char *idngs_str[]; 3862 extern const char *idncmd_str[]; 3863 extern const char *idncon_str[]; 3864 extern const char *idnfin_str[]; 3865 extern const char *idnfinarg_str[]; 3866 extern const char *idnfinopt_str[]; 3867 extern const char *idnreg_str[]; 3868 extern const char *idnnack_str[]; 3869 extern const char *idnop_str[]; 3870 extern const char *idnsync_str[]; 3871 extern const char *chanop_str[]; 3872 extern const char *chanaction_str[]; 3873 extern const char *inum_str[]; 3874 extern const int inum_bump; 3875 extern const int inum_max; 3876 extern const int acknack_shift; 3877 3878 extern const char *timer_str[]; 3879 extern const char *res_str[]; 3880 3881 #endif /* _KERNEL */ 3882 #endif /* !_ASM */ 3883 3884 #ifdef __cplusplus 3885 } 3886 #endif 3887 3888 #endif /* _SYS_IDN_H */ 3889