idn.h revision bf30efa4af94cd71664f6c1be0e6e950b1d7a0f4
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Inter-Domain Network
*/
#ifndef _SYS_IDN_H
#define _SYS_IDN_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef _ASM
#ifdef _KERNEL
#include <sys/dditypes.h>
#include <sys/machsystm.h>
#include <sys/ethernet.h>
#include <sys/idn_sigb.h>
#endif /* _KERNEL */
#ifdef __cplusplus
extern "C" {
#endif
typedef const char * const procname_t;
#ifdef _KERNEL
/*
* IDN_PROP_SMRSIZE - User specified size in MBytes.
* IDN_PROP_SMRADDR - OBP's internal physical address of the region.
*
* OBP properties of "memory" node that define the SMR space.
*/
#define IDN_PROP_SMRSIZE "idn-smr-size"
#define IDN_PROP_SMRADDR "idn-smr-addr"
/*
* IDN_AWOLMSG_INTERVAL (driver.conf)
*
* Number of seconds between AWOL messages on a per-domain basis.
* The purpose is to throttle the frequency at which these
* messages appear.
*
* IDN_MSGWAIT_NEGO (driver.conf)
* IDN_MSGWAIT_CFG
* IDN_MSGWAIT_CON
* IDN_MSGWAIT_FIN
* IDN_MSGWAIT_CMD
* IDN_MSGWAIT_DATA
*
* Number of seconds to wait for response to respective
* message type.
*
* IDN_RETRYFREQ_NEGO (driver.conf)
* IDN_RETRYFREQ_CON
* IDN_RETRYFREQ_FIN
*
* Number of seconds to wait between retries of the respective
* message type.
*
* IDN_SMR_ALIGN (not tunable)
*
* The hardware registers that describe the SMR are based on a 64K
* aligned physical address.
*
* IDN_SMR_SIZE (OBP [only])
*
* Total size of the SMR (Shared Memory Region) in bytes.
*
* IDN_NWR_SIZE (driver.conf)
*
* Total size of the NWR (NetWork Region) portion of the SMR which
* is actually used to support network activity. The NWR is managed
* as simply a pool of I/O buffers which are distributed by the
* Master domain to the Slaves for the purpose of communicating
* between each other. If not set then the entire SMR is used
* as the NWR.
* Req: IDN_NWR_SIZE <= IDN_SMR_SIZE
*
* IDN_SMR_BUFSIZE (driver.conf)
*
* Size of individual SMR buffers. The SMR is divided into chunks
* of IDN_SMR_BUFSIZE bytes. The IDN_MTU is based on this size
* and thus the IDN_SMR_BUFSIZE should be chosen based on performance.
*
* IDN_DATA_SIZE (NOT tunable)
*
* Portion of IDN_SMR_BUFSIZE that can contain raw non-IDN dependent
* data. We subtract IDN_ALIGNSIZE bytes to allow for fast bcopy
* alignment.
* Req: IDN_DATA_SIZE <=
* (IDN_SMR_BUFSIZE - sizeof (smr_pkthdr_t) - IDN_ALIGNSIZE)
*
* IDN_MTU (indirectly tunable via IDN_SMR_BUFSIZE)
*
* This size represents the portion of an SMR I/O buffers that can
* contain (ethernet headerless) data.
* Req: IDN_MTU <= IDN_DATA_SIZE - sizeof (ether_header)
*
* IDN_WINDOW_MAX (driver.conf)
*
* Maximum number of outstanding packets that are allowed per
* domain. If this value is exceeded for a particular domain
* has acknowledged enough of the previous transmission to bring
* down its outstanding I/O count (idn_domain.dio) below this
* value. In addition, if this value is exceeded then a Timer
* is scheduled to check for any response from the remote domain.
*
* IDN_WINDOW_INCR (driver.conf)
*
* the greater the number of possible outstanding data packets
* that can be outstanding to a given domain. Since this natural
* occurence can result in the outstanding-I/O count to a given
* domain to increase we run the risk of dropping into the
* IDN_WINDOW_MAX region even though the receiving domain
* may be fine with handling the load. In order to compensate
* for this increased activity and to not incur unjustified
* slips into the IDN_WINDOW_MAX region, the IDN_WINDOW_MAX
* that is activated for a given domain.
*
* IDN_WINDOW_EMAX (not tunable)
*
* The effective value of IDN_WINDOW_MAX once it has
* been adjusted by IDN_WINDOW_INCR.
*
* IDN_RECLAIM_MIN (driver.conf)
*
* Minimum number of outstanding packets that our allowed
* before subsequent sends will attempt to reclaim some number
* of outstanding data packets.
*
* IDN_RECLAIM_MAX (driver.conf)
* This value represents the maximum number of outstanding
* packets we will try to reclaim during a send once we've
* passed the IDN_RECLAIM_MIN boundary.
*
* IDN_MODUNLOADABLE (ndd)
*
* By default the IDN driver is unloadable. Setting this
* variable will allow the IDN driver to be unloaded provided
* it's not in use.
*
*
*
* IDN_MBOX_PER_NET (driver.conf)
*
* This value effectively represents the amount of outstanding
* activity that can reside at a domain. Increasing this value
* allows more packets to be in transit to a domain, however
* at some point there are diminishing returns since the receiver
* can only consume packets so fast.
*
* IDN_MAX_NETS (driver.conf)
*
* Maximum number of network interfaces (channels) that IDN
* is currently configured to allow. The absolute max is
* IDN_MAXMAX_NETS. We don't automatically default IDN_MAX_NETS
* to IDN_MAXMAX_NETS because it would mean wasted space in
* the mailbox region having to reserve mailboxes that will
* very likely go unused. The smaller this value the fewer
* the number of mailboxes in the SMR and thus the greater the
* number of possible I/O buffers available.
* Req: IDN_MAX_NETS <= IDN_MAXMAX_NETS
*
* IDN_CHECKSUM (driver.conf)
*
* If enabled, IDN validates the smr_pkthdr_t of incoming packets
* via a checksum, and calculates the checksum for outgoing packets.
* Only the first 3 fields of smr_pkthdr_t are checksummed and
* must be set to their expected values prior to calculating the
* checksum. Turned OFF by default when compiled DEBUG.
*
* IDN_SMR_MAXSIZE (not tunable)
*
* The absolute maximum size of the SMR region that we'll allow.
* Note that the virtual address space comes out kernelmap.
*/
#define IDN_MSGWAIT_CFG 40
#define IDN_MSGWAIT_CON 20
#define IDN_MSGWAIT_FIN 40
#define IDN_MSGWAIT_CMD 40
#define IDN_MSGWAIT_DATA 30
#define IDN_RETRYFREQ_NEGO 2
#define IDN_RETRYFREQ_CON 2
#define IDN_RETRYFREQ_FIN 3
#define IDN_SMR_BUFSIZE_MIN 512
#define IDN_SMR_SHIFT (16)
#define IDN_SMR_SIZE idn_smr_size
#define IDN_NWR_SIZE idn_nwr_size
#define IDN_SMR_BUFSIZE idn_smr_bufsize
#define IDN_DATA_SIZE (IDN_SMR_BUFSIZE \
- sizeof (smr_pkthdr_t) \
#define IDN_WINDOW_MAX idn_window_max
#define IDN_WINDOW_INCR idn_window_incr
#define IDN_WINDOW_EMAX idn_window_emax
#define IDN_RECLAIM_MIN idn_reclaim_min
#define IDN_RECLAIM_MAX idn_reclaim_max
#define IDN_MODUNLOADABLE idn_modunloadable
#define IDN_MBOX_PER_NET idn_mbox_per_net
#define IDN_MAX_NETS idn_max_nets
#define IDN_CHECKSUM idn_checksum
#define IDN_SMR_MAXSIZE 96
#define IDN_TUNEVAR_VALUE(v) (v)
/*
* History structure to support problem analysis.
*/
#define IDN_HISTORY_NUM 1024
if (idn_history) { \
}
struct idn_h_entry {
};
struct idn_history {
int h_index;
};
#endif /* _KERNEL */
/*
* IDN_SIGBPIL - Interrupt level at which IDN driver
* wakes up idn_sigbhandler_thread
*/
#define IDN_SIGBPIL PIL_3
/*
* Definition of sigbintr.sb_busy values which
* represents state of idn_sigbhandler.
*/
#define IDNSIGB_NOTREADY ((uchar_t)0)
/*
* Some Xfire based macros that assume 4 cpus per board.
*/
#define CPUID_TO_BOARDID(c) ((c) >> 2)
#define MAX_CPU_PER_BRD 4
{ \
register int c, b; \
(bset) = 0; \
for (b = 0; b < MAX_BOARDS; b++) \
for (c = 0; c < MAX_CPU_PER_BRD; c++) \
if (CPU_IN_SET((cset), \
(b * MAX_CPU_PER_BRD) + c)) \
(bset) |= 1 << b; \
}
/*
* Macros to manipulate boardset and domainset masks.
*/
#define BOARDSET_ALL ((boardset_t)~0)
#define DOMAINSET_ALL ((domainset_t)~0)
#define DOMAIN_IN_SET(s, d) ((s) & DOMAINSET(d))
#define DOMAINSET_ADD(s, d) ((s) |= DOMAINSET(d))
#define DOMAINSET_DEL(s, d) ((s) &= ~DOMAINSET(d))
/*
* PFN_TO_SMADDR macro converts a PFN to a IDN_SMR_ALIGN'ed
*/
#if (IDN_SMR_SHIFT <= MMU_PAGESHIFT)
#else
#endif
/*
* Translate a physical address to a unique domain identifier.
* IMPORTANT - Assumes each board's memory is configured on a 8GB
* boundary. PA(8G) = PFN(1M).
*/
#define VALID_DOMAINID(d) (((d) >= 0) && ((d) < MAX_DOMAINS))
#define VALID_UDOMAINID(d) ((d) < MAX_DOMAINS)
#define VALID_CPUID(c) (((c) >= 0) && ((c) < NCPU))
#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < IDN_MAX_NETS))
#define VALID_UCHANNEL(c) ((c) < IDN_MAX_NETS)
/*
* The following are bit values of idn_debug, currently
* only useful if compiled with DEBUG.
*/
#ifdef DEBUG
#define IDNDBG_XDC 0x00000001
#define IDNDBG_XF 0x00000002
#define IDNDBG_REGS 0x00000004
#define IDNDBG_SMR 0x00000008
#define IDNDBG_PROTO 0x00000010
#define IDNDBG_STR 0x00000020
#define IDNDBG_DRV 0x00000040
#define IDNDBG_DATA 0x00000080
#define IDNDBG_STATE 0x00000100
#define IDNDBG_DLPI 0x00000200
#define IDNDBG_KERN 0x00000400
#define IDNDBG_ALLOC 0x00000800
#define IDNDBG_REMAP 0x00001000
#define IDNDBG_TIMER 0x00002000
#define IDNDBG_CHAN 0x00004000
#define IDNDBG_AWOL 0x00008000
#define IDNDBG_SYNC 0x00010000
#define _IDNDBG_UNUSED0 0x00020000
#define IDNDBG_HITLIST 0x00040000
#define IDNDBG_XMON 0x00080000
#define IDNDBG_TEST 0x80000000
#else
#define PR_HITLIST PR_ALL
#endif /* DEBUG */
#ifdef _KERNEL
/*
* IDN drivers fields.
*
* IDNMINPSZ Minimum packet size the IDN supports.
*
* IDNMAXPSZ Maximum packet size that IDN supports from upper
* layers. Is equal to IDN_MTU + ether_header. Note
* that the IDN driver could support larger packets
* however the infrastructure to support fragmentation
* does not (and should not) exist with respect to
* ethernet packet types.
*/
#ifdef DEBUG
#define IDNDESC "Inter-Domain Network (DEBUG)"
#else
#define IDNDESC "Inter-Domain Network"
#endif /* DEBUG */
#define IDNIDNUM 8264
#define IDNNAME "idn"
#define IDNMINPSZ 0 /* set at idnopen() */
#define IDNMAXPSZ 0 /* set at idnopen() */
#endif /* _KERNEL */
/*
* IDN Global States.
*/
typedef enum {
/* 5 */ _IDNGS_UNUNSED5,
/* 6 */ _IDNGS_UNUNSED6,
/* 7 */ _IDNGS_UNUNSED7,
/* 8 */ _IDNGS_UNUNSED8,
/* 9 */ _IDNGS_UNUNSED9,
} idn_gstate_t;
#ifdef _KERNEL
/*
* Spaced defined in:
* sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
*/
#define IDNSB_GSTATE_NEW 0
#define IDNSB_GSTATE_OLD 1
#define IDNSB_MASTERCPU 2
#define IDNSB_RESERVED 3
#define IDNSB_HWCHKPT_MAX 4
#define IDNSB_SIZE 72
/*
* This structure gets overlay onto:
* sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
*
* This structure must be exactly IDNSB_SIZE bytes.
*/
typedef struct idnsb {
struct {
} id_status[MAX_DOMAINS];
} idnsb_t; /* sizeof = 72 (0x48) 18X bytes */
#define IDNSB_DOMAIN_UPDATE(dp) \
{ \
(uchar_t)0xff; \
else \
} \
}
/*
* The following definitions and macros pertain to the
* id_hwstate and id_hwchkpt[] fields.
*
* id_hwstate (m = mark: 1=open, 2=close)
* 0 1 2 3 4 5 6 7
* ---------------------------------
* | m | m | m | m | XX unused XXX |
* ---------------------------------
* | | | |
* | | | +- CACHE
* | | +- CHAN
* | +- LINK
* +- SMR
*
* Note that nibble 4 is used in DEBUG for noting cache
* flush progress through idnxf_flushall_ecache(). This
* will override id_hwchkpt[] since it only has room for
* 4 items, however the BBSRAM space is there and
* unofficially available :-o
*
* id_hwchkpt[0] = SMR boardset
* id_hwchkpt[1] = LINK boardset
* id_hwchkpt[2] = CHAN boardset
* id_hwchkpt[3] = CACHE boardset.
*/
#define IDNSB_CHKPT_SMR 0
#define IDNSB_CHKPT_LINK 1
#define IDNSB_CHKPT_CHAN 2
#define IDNSB_CHKPT_CACHE 3
{ \
}
{ \
} \
}
{ \
} \
}
{ \
} \
}
#ifdef DEBUG
#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) \
#else
#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark)
#endif /* DEBUG */
#ifdef DEBUG
#define IDN_GSTATE_TRANSITION(ns) \
{ \
/*LINTED*/ \
ASSERT(IDN_GLOCK_IS_EXCL()); \
PR_STATE("GSTATE:%ld: (l=%d) %s(%d) -> %s(%d)\n", \
} \
}
#else
#define IDN_GSTATE_TRANSITION(ns) \
{ \
} \
}
#endif /* DEBUG */
/*
* caller. The following definitions are to support the return of
* just provide a very small cache of waiting list entries. If the
* cache becomes exhausted then additional ones are kmem_alloc'd.
*/
#define IDNOP_CACHE_SIZE 3
#define IDNOP_IN_CACHE(dwl) \
typedef struct dop_waitlist {
struct dop_waitlist *dw_next;
short dw_op;
short dw_errors[MAX_DOMAINS];
typedef uint_t idn_chanset_t;
/*
* Types of synchronization zones which a connection
* could be in.
*/
typedef enum {
/*
* Type of sync-registration that is being requested.
*/
typedef enum {
#define IDN_SYNC_NUMZONE 3
#define IDN_SYNC_GETZONE(s) ((((s) != IDNSYNC_CONNECT) && \
((s) != IDNSYNC_DISCONNECT)) ? \
-1 : (int)(s) - 1)
#define IDN_SYNC_GETTRANS(s) (((s) == IDNSYNC_CONNECT) ? \
((s) == IDNSYNC_DISCONNECT) ? \
/*
* Generic states when in a state transition region.
* These ultimately map to domain states via
* a idn_xphase_t definition. General model:
*
* PEND
* /\
* / \
* | |
* V V
* SENT--->RCVD
* \ /
* \ /
* VV
* FINAL
*
* Start these types with PEND = 0 so that they're
* compatible with idnxs_state_table[] and idn_xphase_t
* phases that use the value as an index.
*/
typedef enum {
/* 0 */ IDNXS_PEND = 0,
/* 1 */ IDNXS_SENT,
/* 2 */ IDNXS_RCVD,
/* 3 */ IDNXS_FINAL,
/* 4 */ IDNXS_NIL
} idn_xstate_t;
/*
* Locking protocol:
*
* Each routine is called with SYNC_LOCK and
* the respective domain's DLOCK(EXCL) held.
* The routines must return with these locks
* still held.
*/
struct idn_msgtype;
typedef struct {
int t_state;
} idn_trans_t;
/*
* The callback routines (xt_final & xt_exit) are called with
* DLOCK and SYNC_LOCK held and they are required to return
* with these locks still held.
*/
typedef struct {
} idn_xphase_t;
/*
* Synchronization entry representing the synchronization
* state with respect to a given domain for a given zone.
*/
typedef struct idn_syncop {
struct idn_syncop *s_next;
int s_domid;
int s_msg;
void *s_transarg;
#ifdef DEBUG
int s_query[MAX_DOMAINS];
#endif /* DEBUG */
} idn_syncop_t;
#ifdef DEBUG
#define IDN_SYNC_QUERY_INIT(d) \
#else /* DEBUG */
#define IDN_SYNC_QUERY_INIT(d)
#endif /* DEBUG */
typedef struct {
int sc_cnt;
#endif /* _KERNEL */
/*
* Vote Ticket used during negotiations and elections.
*
* 31 0
* -----------------------------------------
* |m...|....|pppp|....|Cbbb|bccc|cccB|BBB1|
* -----------------------------------------
* . [30:24] = unused
* p [23:20] = priority
* . [19:16] = unused
* C [15] = connected (has master)
* b [14:11] = nmembrds-1
* c [10:5] = ncpus-1
* B [4:1] = board_id
* 1 [0] = one
*/
typedef union {
struct {
} v;
} idn_vote_t;
#define IDNVOTE_PRI_MASK 0xf
#define IDNVOTE_MAXPRI 0xf
#define IDNVOTE_MINPRI 0
/*
* Initially:
* vote.v.priority = IDNVOTE_DEFPRI
* vote.v.one = 1
*/
#define IDNVOTE_PRIVALUE(vvv) \
/*
* During elections we only use the "elect" attributes of the
* election ticket, i.e. those physical attributes pertaining
* to the individual domain (priority, nboards, ncpus, board).
*/
#define IDNVOTE_ELECT_MASK 0x00f07fff
#define IDNVOTE_BASICS_MASK 0x00f0ffff
/*
* Values used in idn_select_master().
*/
#define MASTER_IS_NONE 0 /* index into master_select_table */
#define MASTER_IS_OTHER 1
#define MASTER_IS_LOCAL 2
#define MASTER_IS_REMOTE 3
typedef enum {
/*
* the original requester (user). Necessary since link establishment
* occurs asynchronously.
*/
typedef enum {
} idn_opflag_t;
/*
* IDN Protocol Messages.
* These are IDN version (IDN_VERSION) dependent.
*
* ----- 7, --- 6,5.................0
* | ack | nack | IDN message type |
* ----------------------------------
*/
#define IDN_VERSION 1
/*
* Must be no more than 6-bits. See DMV private data.
*/
#define IDNP_ACK 0x20
#define IDNP_NACK 0x10
#define IDNP_NULL 0x00
#define IDNP_NEGO 0x01
#define IDNP_CON 0x02
#define IDNP_CFG 0x03
#define IDNP_FIN 0x04
#define IDNP_CMD 0x05
#define IDNP_DATA 0x06
#define IDN_NUM_MSGTYPES 7
#define IDNP_MSGTYPE_MASK 0x0f
typedef struct idn_msgtype {
/*
* IDN private data section of DMV layout (48 bits).
*
* 47......40,39.....34,33.....28,27..24,23......16,15..............0
* | version | msgtype | acktype | did | cpuid | cookie |
* ------------------------------------------------------------------
*
* version Local domain's version of IDN software.
* msgtype Type of IDN message, e.g. nego, syn, etc.
* acktype If msgtype is a ACK or NACK, then acktype is the
* did Local domain's ID (netid) - system-wide unique.
* cpuid Local domain's CPU->cpu_id that sending message.
* cookie Cookie assigned by remote domain for authentication.
* For NEGO & NEGO+ACK messages, it's the cookie that
* the sender expects the receiver to use in subsequent
* messages. The upper-eight bits represent a timer
* cookie to associate timers with expected messages.
*/
#endif /* !_ASM */
#ifdef _KERNEL
#define _IDNPD_COOKIE_MASK 0xffff
#define _IDNPD_COOKIE_SHIFT 32
#define _IDNPD_VER_MASK 0xff
#define _IDNPD_VER_SHIFT 24
#define _IDNPD_MTYPE_MASK 0x3f
#define _IDNPD_MTYPE_SHIFT 18
#define _IDNPD_ATYPE_MASK 0x3f
#define _IDNPD_ATYPE_SHIFT 12
#define _IDNPD_DOMID_MASK 0xf
#define _IDNPD_DOMID_SHIFT 8
#define _IDNPD_CPUID_MASK 0xff
#define _IDNPD_CPUID_SHIFT 0
#define _IDNPD_COOKIE_LEN 16
#ifndef _ASM
#define IDN_PD2COOKIE(pdata) \
#define IDN_PD2VER(pdata) \
#define IDN_PD2MTYPE(pdata) \
#define IDN_PD2ATYPE(pdata) \
#define IDN_PD2DOMID(pdata) \
#define IDN_PD2CPUID(pdata) \
_IDNPD_COOKIE_SHIFT) | \
_IDNPD_VER_SHIFT) | \
_IDNPD_MTYPE_SHIFT) | \
_IDNPD_ATYPE_SHIFT) | \
_IDNPD_DOMID_SHIFT) | \
/*
* IDNP_NEGO
*
* 127........96,95........64,63........32,31.........0
* | vote | domainset |
* ----------------------------------------------------
* domainset Mask of cpuids of domains to which
* sender is connected. Position in domainset
* designates respective domainid.
* E.g. domainset[6] = 20 -> domainid 6 is
* accessible via cpuid 20.
* The slot for the receiving domain
* contains the masterid of the sending
* domain. If the sending domain does
* not have a master then the entry will
* contain IDNNEG_NO_MASTER.
*
* These macros insert a domainid-cpuid pair into the
* domainset to be subsequently passed in a NEGO message,
* also retrieve the cpuid from the domainset for a
* given domainid.
*
* Usage:
* Sending:
* mask = IDNNEG_DSET_MYMASK();
* IDNNEG_DSET_INIT(dset, mask)
* for (all domains except self)
* IDNNEG_DSET_SET(dset, domain, cpuid, mask);
*
* Receiving:
* IDNNEG_DSET_GET_MASK(dset, recv_domid, recv_mask);
* for (all domains except recv_domid)
* IDNNEG_DSET_GET(dset, domid, cpuid, recv_mask);
*/
#define IDNNEG_NO_MASTER 0x3f
sizeof (idnneg_dset_t)))
{ \
}
{ \
/*LINTED*/ \
}
{ \
else \
(cpuid) = -1; \
}
(domid)+MAX_DOMAINS)
/*
* IDNP_CFG sub-types.
*
* Format of first 32 bit word in XDC:
* stX = sub-type.
* staX = sub-type arg.
* X = position in idn_cfgsubtype_t.param.p[] array.
* num = number of parameters in this XDC (0-3)
*
* 31...28,27...24,23...20,19...16,15...12,11....8,7.....3,2....0
* | st0 . sta0 | st1 . sta1 | st2 . sta2 | phase | num |
* --------------------------------------------------------------
*
* Note that since the first 32-bit word in a (IDNP_CFG) XDC is used
* for a sub-type, subsequent three 32-bits words are used for data that
* pertains to respective sub-type, i.e. first sub-type corresponds
* to first of the 3x32-bit words (pos=0), second sub-type corresponds
* to second of the 3x32-bit words (pos=1), etc. Obviously, a max of
* only three sub-types can be sent per xdc.
*/
#define IDNCFGARG_BARLAR_BAR 0 /* BAR */
#define IDNCFGARG_CPUSET_UPPER 0 /* 1st word */
#define IDNCFGARG_SIZE_MTU 0 /* IDN_MTU */
#define IDNCFGARG_DATAMBOX_TABLE 0 /* recvmbox table */
#define IDNCFGARG_DATASVR_MAXNETS 0 /* max # of nets/channels */
#define IDNCFGARG_CHECKSUM 0 /* IDN_CHECKSUM */
#define IDN_CFGPARAM_ARG(p) ((p) & 0xf)
typedef union {
struct {
uchar_t p[3];
} param;
struct {
} info;
/*
* IDN_MASTER_NCFGITEMS
* Minimum number of config items expected from master.
*
* IDN_SLAVE_NCFGITEMS
* Number of config items expected from slave.
*/
#define IDN_SLAVE_NCFGITEMS 12
/*
* IDNP_CMD sub-types.
*/
typedef enum {
} idn_cmd_t;
#define VALID_IDNCMD(c) (((int)(c) >= (int)IDNCMD_SLABALLOC) && \
((int)(c) <= (int)IDNCMD_NODENAME))
/*
* IDNP_NACK
*/
typedef enum {
/* 2 */ IDNNACK_BADCHAN,
/* 3 */ IDNNACK_BADCFG,
/* 4 */ IDNNACK_BADCMD,
/* 5 */ IDNNACK_RETRY,
/* 6 */ IDNNACK_DUP,
/* 7 */ IDNNACK_EXIT,
/* 8 */ IDNNACK_RESERVED1,
/* 9 */ IDNNACK_RESERVED2,
/* 10 */ IDNNACK_RESERVED3
} idn_nack_t;
/*
* IDNP_CON sub-types.
*/
typedef enum {
/* 0 */ IDNCON_OFF = 0,
} idn_con_t;
/*
* IDNP_FIN sub-types.
*/
typedef enum {
} idn_fin_t;
#define VALID_FIN(f) (((int)(f) > 0) && \
((int)(f) < (int)IDNFIN_QUERY))
#define FIN_IS_FORCE(f) (((f) == IDNFIN_FORCE_SOFT) || \
((f) == IDNFIN_FORCE_HARD))
/*
* FIN ARG types - reasons a FIN was sent.
*/
typedef enum {
} idn_finarg_t;
#define SET_FIN_TYPE(x, t) \
#define SET_FIN_ARG(x, a) \
#define FINARG2IDNKERR(fa) \
/*
* FIN SYNC types.
*/
#define IDNFIN_SYNC_OFF 0 /* not set */
typedef short idn_finsync_t;
/*
* IDNP_FIN options.
*/
typedef enum {
} idn_finopt_t;
#define VALID_FINOPT(f) (((f) == IDNFIN_OPT_UNLINK) || \
((f) == IDNFIN_OPT_RELINK))
IDN_NIL_DCPU : ((x) & 0xfff))
((uint_t)(c) & 0xffff))
#ifdef DEBUG
{ \
int _id; \
PR_STATE("FSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
"%s(%d) -> %s(%d)\n", \
__LINE__, \
} \
}
#else
{ \
}
#endif /* DEBUG */
#endif /* !_ASM */
#endif /* _KERNEL */
#ifndef _ASM
/*
* IDN Per-Domain States.
*/
typedef enum {
} idn_dstate_t;
#endif /* !_ASM */
#ifdef _KERNEL
#ifndef _ASM
/*
* ---------------------------------------------------------------------
*/
typedef struct idn_timer {
*t_back;
struct idn_timerq *t_q;
short t_domid;
short t_onq;
#ifdef DEBUG
#endif /* DEBUG */
} idn_timer_t;
#define IDN_TIMER_PUBLIC_COOKIE 0xf
#define IDN_TIMER_ALLOC() (idn_timer_alloc())
#define IDN_TIMER_STOPALL(tp) \
((void) idn_timer_stopall(tp))
{ \
}
#ifdef DEBUG
#define IDN_TIMER_POST(tp) \
#else /* DEBUG */
#define IDN_TIMER_POST(tp)
#define IDN_TIMER_EXEC(tp)
#endif /* DEBUG */
{ \
idn_timer_t *_tp; \
char _str[15]; \
PR_TIMER("msgtimer:%d: START: type = %s (0x%x)\n", \
_tp = IDN_TIMER_ALLOC(); \
IDN_TIMER_POST(_tp); \
if (_ckp) { \
} else { \
} \
}
{ \
char _str[15]; \
PR_TIMER("msgtimer:%d: STOP: type = %s (0x%x), " \
"cookie = 0x%x\n", \
}
/*
* IDN_SLABALLOC_WAITTIME
* Max wait time in ticks that local domains waits for
* master to respond to a slab allocation request. Has
* to be at least as long as wait time for a response to
* the command.
*/
/*
* Domain state transition macros.
*/
#ifdef DEBUG
{ \
int id; \
PR_STATE("DSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
"%s(%d) -> %s(%d)\n", \
__LINE__, \
}
#else
{ \
}
#endif /* DEBUG */
{ \
IDN_DSTATE_TRANSITION((dp), \
} \
}
/*
* ---------------------------------------------------------------------
* IDN Per-Domain Data
*
* The comment to the right of the respective field represents
* what lock protects that field. If there is no comment then
* no lock is required to access the field.
* ---------------------------------------------------------------------
*/
#define MAXDNAME 32
typedef struct idn_domain {
/*
* Assigned domid for domain. Never
* changes once idn_domain[] is
* initialized. We are guaranteed that
* all domains in IDN will have a
* uniqueue domid in the range (0-15).
*/
int domid;
/*
* Gotten from uname -n for local
* domain. Remote domains pass
* theirs during Config phase.
*/
/*
* IDN-wide unique identifier for the
* given domain. This value will be
* the same as the domid.
*/
/*
* Used during FIN sequenece to
* determine what type of shutdown
* (unlink) we're executing with
* respect to the given domain.
*/
/*
* A non-zero value for dfin_sync
* indicates that unlink of respective
* domain does not need to be performed
* synchronously among all the IDN
* member domains.
*/
short dfin_sync; /* grwlock */
/*
* Cookie used to determine the
* proper context in which we're
* receiving messages from the given
* domain. Assigned cookies are exchanged
* during initial NEGO messages.
*/
short dcookie_err; /* drwlock */
int dcookie_errcnt; /* drwlock */
/*
* Primary target cpu for sending
* messages. Can change to help
* distribute interrupts on receiving
* side.
*/
int dcpu; /* drwlock */
/*
* Used to store dcpu from a previous
* life. Only used when requesting
* a RELINK with a domain we were just
* previously linked with. Thus, it
* does represent a valid cpu in the
* remote domain.
*/
int dcpu_save; /* drwlock */
/*
* Used to store from which cpu the
* last message was received.
*/
int dcpu_last;
/*
* Transition phase area. This field
* points to the proper phase structure
* depending on what stage the given
* domain is in.
*/
/*
* Actual synchronization object for
* the given domain.
*/
/*
* Slab information for given domain.
* If the local domain is a master,
* then this field in each domain is used
* to store which slabs have been assigned
* to given domain. If the local domain
* is a slave, then this information is
* NULL for all remote idn_domain[]
* entries, but for local domain holds
* those slabs assigned to local domain.
*/
short dnslabs; /* dslab_rwlock */
short dslab_state; /* dslab_rwlock */
/*
* Set of cpus belonging to domain.
*/
int dncpus; /* drwlock */
/*
* Index into dcpumap to determine
* which cpu to target next for
* interrupt. Intended to allow fair
* distribution of interrupts on
* remote domain.
*/
/*
* Quick look-up map of cpus belonging
* to domain. Used to select next target.
*/
/*
* Non-zero indicates outstanding
* I/O's to given domain.
*/
int dio; /* drwlock */
int dioerr; /* drwlock */
/*
* Set when we fail to allocate a buffer
* for a domain. Dictates whether to
* reclaim max buffers or not.
*/
/*
* Set when remote domain does not
* seem to be picking up messages sent
* to it. Non-zero indicates we have
* an outstanding "ping" to domain.
*/
short dslabsize; /* drwlock */
short dnwrsize; /* drwlock */
/*
* The following field is primarily
* used during CFG exchange to keep
* track of certain per-domain information.
*/
union { /* all - drwlock */
struct {
} _s;
int _dtmp;
} _u;
/*
* Each domain entry maintains a
* timer queue holding timers for
* messages outstanding to that domain.
*/
struct idn_timerq {
int tq_cookie; /* tq_mutex */
int tq_count; /* tq_mutex */
} dtimerq;
/*
* dawol is used to keep
* track of AWOL details for
* given domain when it is
* non-responsive.
*/
struct {
int a_count; /* drwlock */
} dawol;
struct hwconfig {
short dh_nboards; /* drwlock */
short dh_nmcadr; /* drwlock */
} dhw;
/*
* Mailbox information used to
*/
struct {
} dmbox;
} idn_domain_t;
typedef struct idn_timerq idn_timerq_t;
#define IDN_DLOCK_TRY_SHARED(dd) \
#define IDN_RESET_COOKIES(dd) \
#define DSLAB_STATE_UNKNOWN 0
#define DSLAB_STATE_LOCAL 1
#define DSLAB_STATE_REMOTE 2
#define DSLAB_LOCK_EXCL(d) \
#define DSLAB_LOCK_SHARED(d) \
#define DSLAB_LOCK_TRYUPGRADE(d) \
/*
* ---------------------------------------------------------------------
* Macro to pick another target for the given domain. This hopefully
* improves performance by better distributing the SSI responsibilities
* at the target domain.
* ---------------------------------------------------------------------
*/
{ \
register int p; \
if (CPU_IN_SET((set), p)) \
break; \
if (p >= NCPU) \
for (p = 0; p <= (index); p++) \
if (CPU_IN_SET((set), p)) \
break; \
if (!CPU_IN_SET((set), p)) { \
"IDN: cpu %d not in cpuset 0x%x.%0x\n", \
} \
(index) = p; \
}
/*
* ---------------------------------------------------------------------
* ---------------------------------------------------------------------
*/
(uint32_t)(n))
/*
* DMV vector interrupt support.
*
* A fixed-size circular buffer is maintained as a queue of
* incoming interrupts. The low-level idn_dmv_handler() waits
* for an entry to become FREE and will atomically mark it INUSE.
* Once he has filled in the appropriate fields it will be marked
* as READY. The high-level idn_handler() will be invoked and will
* process all messages in the queue that are READY. Each message
* is marked PROCESS, a protojob job created and filled in, and
* then the interrupt message is marked FREE for use in the next
* interrupt. The iv_state field is used to hold the relevant
* state and is updated atomically.
*/
#endif /* !_ASM */
#ifndef _ASM
/*
* The size of this structure must be a power of 2
* so that we can do a simple shift to calculate
* our offset into based on cpuid.
*/
typedef struct idn_dmv_cpu {
sizeof (uint32_t) - \
sizeof (lock_t) - \
sizeof (int32_t)];
typedef struct idn_dmv_data {
/*
* Requirements of the following data structure:
* - MUST be double-word (8 bytes) aligned.
* - _iv_head field MUST start on double-word boundary.
* - iv_xargs0 MUST start on double-word boundary
* with iv_xargs1 immediately following.
* - iv_xargs2 MUST start on double-word boundary
* with iv_xargs3 immediately following.
*/
typedef struct idn_dmv_msg {
extern uint_t idn_dmv_inum;
extern uint_t idn_soft_inum;
/*
* An IDN-network address has the following format:
*
* 31......16,15........0
* | channel | dnetid |
* ----------------------
* channel - network interface.
* netid - idn_domain[].dnetid
*/
#define IDN_MAXMAX_NETS 32
typedef union {
struct {
} net;
#define CHANSET_ALL (~((idn_chanset_t)0))
#define CHANSET(c) \
#define CHAN_IN_SET(m, c) \
#define CHANSET_ADD(m, c) \
#define CHANSET_DEL(m, c) \
#define CHANSET_ZERO(m) ((m) = 0)
typedef enum {
/* 0 */ IDNCHAN_OPEN,
/* 1 */ IDNCHAN_SOFT_CLOSE,
/* 2 */ IDNCHAN_HARD_CLOSE,
/* 3 */ IDNCHAN_OFFLINE,
/* 4 */ IDNCHAN_ONLINE
} idn_chanop_t;
/*
* Retry support.
*/
(0xffff & (uint_t)(x)))
#define IDN_RETRY_RECFG_MULTIPLE 10
typedef struct idn_retry_job {
struct idn_retry_job *rj_prev;
struct idn_retry_job *rj_next;
void *rj_arg;
short rj_onq;
#define IDNRETRY_ALLOCJOB() \
#define IDNRETRY_FREEJOB(j) \
typedef enum {
/* 0 */ IDNRETRY_NIL = 0,
/* 1 */ IDNRETRY_NEGO,
/* 2 */ IDNRETRY_CON,
/* 4 */ IDNRETRY_FIN,
/* 6 */ IDN_NUM_RETRYTYPES
} idn_retry_t;
/*
* ---------------------------------------------------------------------
*/
typedef struct {
int m_domid;
int m_cpuid;
typedef struct idn_protojob {
struct idn_protojob *j_next;
int j_cache;
typedef struct idn_protoqueue {
struct idn_protoqueue *q_next;
int q_die;
int q_id;
#define IDN_PROTOCOL_NSERVERS 4
/*
* ---------------------------------------------------------------------
* Data Server definitions.
*
* idn_datasvr_t - Describes data server thread.
* . ds_id - Per-domain identifier for data server.
* . ds_domid - Domain which data server is handling.
* data server.
* . ds_mboxp - Pointer to data server's (local)
* mailbox to be serviced.
* . ds_waittime - cv_timedwait sleep time before
* checking respective mailbox.
* . ds_threadp - Pointer to data server thread.
* . ds_cv - Condvar for sleeping.
* . ds_morguep - Semaphore for terminating thread.
*
* idn_mboxhdr_t - Resides in SMR space (MUST be cache_linesize).
* . mh_svr_active - Non-zero indicates data server is
* actively reading mailbox for messages.
* . mh_svr_ready - Non-zero indicates data server has
* allocated and is ready to accept data.
* . mh_cookie - Identifier primarily for debug purposes.
*
* idn_mboxmsg_t - Entry in the SMR space circular queue use to
* represent a data packet.
* . mm_owner - Non-zero indicates entry is available
* to be processed by receiver's data server.
* . mm_flag - Indicates whether entry needs to be
* reclaimed by the sender. Also holds error
* indications (e.g. bad offset).
* . mm_offset - SMR offset of respective data packet.
*
* idn_mboxtbl_t - Encapsulation of a per-domain mailbox (SMR space).
* . mt_header - Header information for synchronization.
* . mt_queue - Circular queue of idn_mboxmsg_t entries.
*
* . mm_mutex - Protects mm_* entries, enqueuing, and
* dequeuing of messages. Also protects
* updates to the route table pointed to
* by mm_routetbl.
* . mm_count - send: Current number of messages
* enqueued.
* - recv: Cumulative number of messages
* processed.
* . mm_max_count - send: Maximum number of messages
* enqueued per iteration.
* recv: Maximum number of messages
* dequeued per iteration.
* . mm_smr_mboxp - Pointer to SMR (vaddr) space where
* respective mailbox resides.
* ---------------------------------------------------------------------
*/
((IDN_MBOXHDR_COOKIE_TOP << 16) \
#define IDN_GET_MBOXHDR_COOKIE(mhp) \
((IDN_GET_MBOXHDR_COOKIE(mhp) == \
IDN_MAKE_MBOXHDR_COOKIE(0, 0, (ch))) && \
/*
* The number of entries in a mailbox queue must be chosen so
* that (IDN_MMBOX_NUMENTRIES * sizeof (idn_mboxmsg_t)) is a multiple
* of a cacheline size (64).
*/
#define IDN_MMBOX_NUMENTRIES IDN_MBOX_PER_NET
/*
* We step through the mailboxes in effectively cacheline size
* incremenents so that the source and receiving cpus are not competing
* for the same cacheline when transmitting/receiving messages into/from
* the mailboxes. The hard requirement is that the step value be even
* since the mailbox size will be chosen odd. This allows us to wraparound
* the mailbox uniquely touching each entry until we've exhausted them
* all at which point we'll end up where we initially started and repeat
* again.
*/
#define IDN_MMBOXINDEX_INC(i) \
{ \
if (((i) += IDN_MMBOXINDEX_STEP) >= IDN_MMBOX_NUMENTRIES) \
(i) -= IDN_MMBOX_NUMENTRIES; \
}
#define IDN_MMBOXINDEX_DIFF(i, j) \
(((i) >= (j)) ? (((i) - (j)) / IDN_MMBOXINDEX_STEP) \
: ((((i) + IDN_MMBOX_NUMENTRIES) - (j)) / IDN_MMBOXINDEX_STEP))
/*
* Require IDN_MBOXAREA_SIZE <= IDN_SLAB_SIZE so we don't waste
* slab space.
*
* Each domain maintains a MAX_DOMAIN(16) entry mbox_table. Each
* entry represents a receive mailbox for a possible domain to which
* the given domain may have a connection. The send mailbox for each
* respective domain is given to the local domain at the time of
* connection establishment.
*/
/*
* ---------------------------------------------------------------------
*/
#define IDN_MBOXTBL_SIZE \
+ sizeof (idn_mboxhdr_t)), IDN_ALIGNSIZE))
/*
* ---------------------------------------------------------------------
* Each domain has idn_max_nets worth of possible mailbox tables
* for each domain to which it might possibly be connected.
* ---------------------------------------------------------------------
*/
#define IDN_MBOXAREA_SIZE \
#define IDN_MBOXAREA_OFFSET(d) \
/*
* ---------------------------------------------------------------------
* Return the base of the mailbox area (set of tables) assigned
* to the given domain id.
* ---------------------------------------------------------------------
*/
#define IDN_MBOXAREA_BASE(m, d) \
/*
* ---------------------------------------------------------------------
* Return the pointer to the respective receive mailbox (table set)
* for the given domain id relative to the given base mailbox table.
* ---------------------------------------------------------------------
*/
#define IDN_MBOXTBL_PTR(t, d) \
* IDN_MAX_NETS)))
/*
* ---------------------------------------------------------------------
* Return the pointer to the actual target mailbox based on the
* given channel in the given mailbox table.
* ---------------------------------------------------------------------
*/
#define IDN_MBOXTBL_PTR_CHAN(t, c) \
#define IDN_MBOXTBL_PTR_INC(t) \
#define IDN_MBOXCHAN_INC(i) \
{ \
if (++(i) == IDN_MAX_NETS) \
(i) = 0; \
}
/*
* ---------------------------------------------------------------------
* Return the absolute location within the entire mailbox area
* of the mboxtbl for the given primary and secondary domain and
* channel. Only relevant when done by the master.
* ---------------------------------------------------------------------
*/
(sd)), \
(ch)))
typedef struct idn_mboxmsg {
ms_flag : 7,
ms_bframe : 24;
#define IDN_CKSUM_MBOX_COUNT \
#define IDN_CKSUM_MBOX(h) \
(IDN_CHECKSUM ? \
typedef struct idn_mboxhdr {
(4*sizeof (uint_t)) -
typedef struct idn_mboxtbl {
{ \
register int _d; \
if ((int)(((csp)->ch_recv_scanset_pending >> \
break; \
else \
} \
(csp)->ch_recv_domcount++; \
} \
} \
}
{ \
register int _d; \
if ((int)(((csp)->ch_recv_scanset_pending >> \
break; \
else \
} \
(csp)->ch_recv_domcount--; \
if ((csp)->ch_recv_domcount) { \
(csp)->ch_recv_scanset_pending |= \
_domset; \
_domset <<= \
} \
} \
} \
}
#define IDN_CHAN_TRYLOCK_GLOBAL(csp) \
#define IDN_CHAN_LOCK_GLOBAL(csp) \
#define IDN_CHAN_UNLOCK_GLOBAL(csp) \
#define IDN_CHAN_GLOBAL_IS_LOCKED(csp) \
#define IDN_CHAN_LOCAL_IS_LOCKED(csp) \
#define IDN_CHAN_LOCK_LOCAL(csp) \
#define IDN_CHAN_UNLOCK_LOCAL(csp) \
#define IDN_CHAN_RECV_IS_LOCKED(csp) \
#define IDN_CHAN_TRYLOCK_RECV(csp) \
#define IDN_CHAN_LOCK_RECV(csp) \
#define IDN_CHAN_UNLOCK_RECV(csp) \
#define IDN_CHAN_SEND_IS_LOCKED(csp) \
#define IDN_CHAN_TRYLOCK_SEND(csp) \
#define IDN_CHAN_LOCK_SEND(csp) \
#define IDN_CHAN_UNLOCK_SEND(csp) \
/*
* A channel table is an array of pointers to mailboxes
* for the respective domains for the given channel.
* Used a cache for the frequently used items. Respective
* fields in mainmbox are updated just prior to sleeping.
*/
/*
* Reading c_state requires either c_mutex or ch_mutex.
* Writing c_state requires both c_mutex and ch_mutex in the order:
* ch_mutex
* c_mutex
*/
typedef struct idn_chaninfo {
/*
* When updating both recv and send c_state's for the locks
* must be grabbed in the following order:
* ch_mutex
* ch_recv.c_mutex
* ch_send.c_mutex
* This order is necessary to prevent deadlocks.
* In general ch_state is intended to represent c_state of
* ch_state and c_state values may be slightly different,
* but eventually should end up identical.
*/
typedef struct idn_chansvr {
int _padding2[(64 -
sizeof (idn_chaninfo_t)) / sizeof (int)];
short ch_recv_domcount;
int ch_recv_waittime;
int ch_recv_changed;
int ch_bound_cpuid;
typedef struct idn_mainmbox {
short mm_channel;
short mm_domid;
short mm_type;
int mm_count;
int mm_dropped;
int mm_qiget; /* next msg to get */
int mm_qiput; /* next slot to put msg */
/*
* mm_flags
*/
#define IDNMMBOX_FLAG_CORRUPTED 0x01
/*
* mm_type
*/
#define IDNMMBOX_TYPE_RECV 0x1
#define IDNMMBOX_TYPE_SEND 0x2
#define IDNMBOX_IS_RECV(m) ((m) == IDNMMBOX_TYPE_RECV)
#define IDNMBOX_IS_SEND(m) ((m) == IDNMMBOX_TYPE_SEND)
/*
* Period between sending wakeup xdc's to remote domain.
*/
/*
* ms_flag bit values.
*/
#define IDN_MBOXMSG_FLAG_INPROCESS 0x2
#define IDN_MBOXMSG_FLAG_ERR_BADOFFSET 0x4
#define IDN_MBOXMSG_FLAG_ERR_NOMBOX 0x8
#define IDN_MBOXMSG_FLAG_ERRMASK 0xc
/*
*/
#define IDN_CHANSVC_STATE_ATTACHED 0x01
#define IDN_CHANSVC_STATE_ENABLED 0x02
#define IDN_CHANSVC_STATE_ACTIVE 0x04
#define IDN_CHANSVC_STATE_FLUSH 0x10
#define IDN_CHANSVC_STATE_CORRUPTED 0x20
#define IDN_CHANSVC_PENDING_BITS (IDN_CHANSVC_STATE_ATTACHED | \
/*
* GLOBAL
*/
#define IDN_CHANNEL_IS_ATTACHED(csp) \
#define IDN_CHANNEL_IS_DETACHED(csp) \
#define IDN_CHANNEL_IS_PENDING(csp) \
#define IDN_CHANNEL_IS_ACTIVE(csp) \
#define IDN_CHANNEL_IS_ENABLED(csp) \
/*
* SEND
*/
#define IDN_CHANNEL_IS_SEND_ACTIVE(csp) \
/*
* RECV
*/
#define IDN_CHANNEL_IS_RECV_ACTIVE(csp) \
#define IDN_CHANNEL_IS_RECV_CORRUPTED(csp) \
#define IDN_CHAN_SEND_DONE(csp) \
{ \
}
#define IDN_CHAN_RECV_DONE(csp) \
{ \
}
#define IDN_CHANSVC_MARK_ATTACHED(csp) \
#define IDN_CHANSVC_MARK_DETACHED(csp) \
#define IDN_CHANSVC_MARK_PENDING(csp) \
#define IDN_CHANSVC_MARK_DISABLED(csp) \
#define IDN_CHANSVC_MARK_ACTIVE(csp) \
#define IDN_CHANSVC_MARK_IDLE(csp) \
#define IDN_CHANSVC_MARK_RECV_ACTIVE(csp) \
#define IDN_CHANSVC_MARK_RECV_CORRUPTED(csp) \
#define IDN_CHANSVC_MARK_SEND_ACTIVE(csp) \
typedef enum {
IDNCHAN_ACTION_DETACH, /* DETACH (ATTACHED = 0) */
IDNCHAN_ACTION_STOP, /* DISABLE (ENABLED = 0) */
IDNCHAN_ACTION_SUSPEND, /* IDLE (ACTIVE = 0) */
#define IDN_CHANNEL_SUSPEND(c, w) \
(idn_chan_action((c), IDNCHAN_ACTION_SUSPEND, (w)))
#define IDN_CHANNEL_RESUME(c) \
(idn_chan_action((c), IDNCHAN_ACTION_RESUME, 0))
#define IDN_CHANNEL_STOP(c, w) \
(idn_chan_action((c), IDNCHAN_ACTION_STOP, (w)))
#define IDN_CHANNEL_RESTART(c) \
(idn_chan_action((c), IDNCHAN_ACTION_RESTART, 0))
#define IDN_CHANNEL_DETACH(c, w) \
(idn_chan_action((c), IDNCHAN_ACTION_DETACH, (w)))
#define IDN_CHANNEL_ATTACH(c) \
(idn_chan_action((c), IDNCHAN_ACTION_ATTACH, 0))
/*
* ds_waittime range values.
* When a packet arrives the waittime starts at MIN and gradually
* shifts up to MAX until another packet arrives. If still no
* packet arrives then we go to a hard sleep
*/
/*
* ---------------------------------------------------------------------
* IDN Global Data
*
* The comment to the right of the respective field represents
* what lock protects that field. If there is no comment then
* no lock is required to access the field.
* ---------------------------------------------------------------------
*/
typedef struct idn_global { /* protected by... */
/*
* Global state of IDN w.r.t.
* the local domain.
*/
/*
* Version of the IDN driver.
* Is passed in DMV header so that
* other domains can validate they
* support protocol used by local
* domain.
*/
int version;
/*
* Set to 1 if SMR region properly
* allocated and available.
*/
int enabled;
/*
* Local domains "domain id".
*/
int localid;
/*
* Domain id of the Master domain.
* Set to IDN_NIL_DOMID if none
* currently exists.
*/
int masterid; /* grwlock */
/*
* Primarily used during Reconfiguration
* to track the expected new Master.
* Once the current IDN is dismantled
* the local domain will attempt to
* connect to this new domain.
*/
int new_masterid; /* grwlock */
/*
* Number of protocol servers configured.
*/
int nservers;
struct {
/*
* dmv_inum
* Interrupt number assigned by
* DMV subsystem to IDN's DMV
* handler.
* soft_inum
* Soft interrupt number assigned
* by OS (add_softintr) for Soft
* interrupt dispatched by DMV
* handler.
*/
} intr;
/*
* first_swlink
* Used as synchronization to
* know whether channels need
* to be activated or not.
* first_hwlink
* Used as mechanism to determine
* whether local domain needs
* to publicize its SMR, assuming
* it is the Master.
* first_hwmaster
* Domainid of the domain that
* was the master at the time
* the hardware was programmed.
* We need to keep this so that
* we deprogram with respect to
* the correct domain that the
* hardware was originally
* programmed to.
*/
short first_hwmasterid;
/*
* The xmit* fields are used to set-up a background
* thread to monitor when a channel is ready to be
* enabled again. This is necessary since IDN
* can't rely on hardware to interrupt it when
* things are ready to go. We need this ability
* to wakeup our STREAMS queues.
* Criteria for reenabling queues.
* gstate == IDNGS_ONLINE
* channel = !check-in
* buffers are available
*
* xmit_chanset_wanted
* Indicates which channels wish to have
* their queues reenabled when ready.
* xmit_tid
* Timeout-id of monitor.
*/
struct {
/*
* ready
* Indicates SMR region allocated
* and available from OBP.
* vaddr
* Virtual address assigned to SMR.
* locpfn
* Page Frame Number associated
* with local domain's SMR.
* rempfn
* Page Frame Number associated
* with remote (Master) domain's SMR.
* rempfnlim
* PFN past end of remote domain's
* SMR.
* Physical address and size of
* SMR that were assigned by OBP.
*/
int ready;
} smr;
/*
* idnsb_mutex
* Protects access to IDN's
* sigblock area.
* idnsb_eventp
* IDN's private area in sigblock
* used for signaling events
* regarding IDN state to SSP.
* idnsb
* Area within IDN's private
* sigblock area used for tracking
* certain IDN state which might
* be useful during arbstop
* conditions (if caused by IDN!).
*/
struct sigbintr {
/*
* sb_mutex
* Protects sigbintr elements
* to synchronize execution of
* sigblock (IDN) mailbox handling.
* sb_cpuid
* Cpu whose sigblock mailbox
* originally received IDN request
* from SSP. Necessary to know
* where to put response.
* sb_busy
* Flag indicating state of
* sigblock handler thread.
* Synchronize activity between
* SSP and current IDN requests that
* are in progress.
* sb_cv
* Condition variable for sigblock
* handler thread to wait on.
* sb_inum
* Soft interrupt number assigned
* by OS to handle soft interrupt
* request make by low-level (IDN)
* sigblock handler to dispatch actual
* processing of sigblock (mailbox)
* request.
*/
} sigbintr;
/*
* struprwlock, strup, sip, siplock
* Standard network streams
* handling structures to manage
* instances of IDN driver.
*/
/*
* Area where IDN maintains its kstats.
*/
/*
* Number of domains that local domain
* has "open".
*/
int ndomains; /* grwlock */
/*
* Number of domains that local domain
* has registered as non-responsive.
*/
int nawols; /* grwlock */
/*
* Number of network channels (interfaces)
* which are currently active.
*/
int nchannels; /* grwlock */
/*
* Bitmask representing channels
* that are currently active.
*/
/*
* that have been created. Not necessarily
* all active.
*/
/*
* Pointer to sigblock handler thread
* which ultimately processes SSP
* IDN requests.
*/
/*
* Pointer to area used by Master
* to hold mailbox structures.
* Actual memory is in SMR.
*/
struct {
/*
* IDN_SYNC_LOCK - Provides serialization
* mechanism when performing synchronous
* operations across domains.
*/
/*
* Actual synchronization zones for
* CONNECT/DISCONNECT phases.
*/
} sync; /* sz_mutex */
struct {
/*
* ds_trans_on
* Set of domains which are trying
* ds_ready_on
* Set of domains which local knows
* are ready for linking, but has
* ds_connected
* Set of domains that local has
* confirmed as being ready.
* ds_trans_off
* Set of domains which are trying
* to unlink from local.
* ds_ready_off
* Set of domains which local knows
* are ready for unlink, but has
* ds_relink
* Set of domains we're expecting
* to relink with subsequent to
* a RECONFIG (new master selection).
* ds_hwlinked
* Set of domains for which local
* has programmed its hardware.
* ds_flush
* Set of domains requiring that
* local flush its ecache prior
* to unlinking.
* ds_awol
* Set of domains believed to be
* AWOL - haven't responded to
* any queries.
* ds_hitlist
* Set of domains which local domain
* is unlinking from and wishes to ignore
* any extraneous indirect link requests
* from other domains, e.g. during a
* Reconfig.
*/
} domset;
/*
* Bitmask identifying all cpus in
* the local IDN.
*/
/*
* Bitmask identifying all boards in
* the local IDN.
*/
struct dopers {
/*
* Waiting area for IDN requests,
* i.e. link & unlinks. IDN requests
* are performed asynchronously so
* we need a place to wait until the
* operation has completed.
*
* dop_domset
* Identifies which domains the
* current waiter is interested in.
* dop_waitcount
* Number of waiters in the room.
* dop_waitlist
* Actual waiting area.
* dop_freelist
* Freelist (small cache) of
* structs for waiting area.
*/
int dop_waitcount; /* dop_mutex */
/* dop_mutex */
} *dopers;
struct {
/*
* Protocol Server:
*
* p_server
* Linked list of queues
* describing protocol
* servers in use.
* p_jobpool
* Kmem cache of structs
* used to enqueue protocol
* jobs for protocol servers.
* p_morgue
* Synchronization (check-in)
* area used when terminating
* protocol servers (threads).
*/
struct idn_protoqueue *p_serverq;
} protocol;
struct idn_retry_queue {
/*
* rq_jobs
* Queue of Retry jobs
* that are outstanding.
* rq_count
* Number of jobs on retry
* queue.
* rq_cache
* Kmem cache for structs
* used to describe retry
* jobs.
*/
int rq_count; /* rq_mutex */
} retryqueue;
struct slabpool {
/*
* Slabpool:
*
* ntotslabs
* Total number of slabs
* in SMR (free & in-use).
* npools
* Number of pools available
* in list. One smr_slabtbl
* exists for each pool.
*/
int ntotslabs;
int npools;
struct smr_slabtbl {
/*
* sarray
* Array of slab structs
* representing slabs in SMR.
* nfree
* Number of slabs actually
* available in sarray.
* nslabs
* Number of slabs represented
* in sarray (free & in-use).
*/
int nfree;
int nslabs;
} *pool;
/*
* Holds array of smr_slab_t structs kmem_alloc'd
* for slabpool.
*/
} *slabpool;
struct slabwaiter {
/*
* Waiting area for threads
* requesting slab allocations.
* Used by Slaves for all requests,
* but used by Master only for
* redundant requests, i.e. multiple
* requests on behalf of the same
* domain. One slabwaiter area
* exist for each possible domain.
*
* w_nwaiters
* Number of threads waiting
* in waiting area.
* w_done
* Flag to indicate that
* allocation request has
* completed.
* w_serrno
* Non-zero indicates an
* errno value to represent
* error that occurred during
* attempt to allocate slab.
* w_closed
* Indicates that waiting area is
* closed and won't allow any new
* waiters. This occurs during
* the small window where we're
* trying to suspend a channel.
* w_cv
* Condvar for waiting on.
* w_sp
* Holds slab structure of
* successfully allocated slab.
*/
short w_nwaiters; /* w_mutex */
short w_done; /* w_mutex */
short w_serrno; /* w_mutex */
short w_closed; /* w_mutex */
} *slabwaiter;
/*
* Kmem cache used for allocating
* timer structures for outstanding
* IDN requests.
*/
/*
* Effectively constant used in
* translating buffer frames in
* mailbox message frames to
* offsets within SMR.
*/
int bframe_shift;
} idn_global_t;
typedef struct idn_retry_queue idn_retry_queue_t;
#define IDN_SET_MASTERID(mid) \
{ \
if (_mid == IDN_NIL_DOMID) \
else \
} \
}
#define IDN_SET_NEW_MASTERID(mid) \
{ \
}
/*
* Macro to reset some globals necessary in preparing
* for initialization of HW for IDN.
*/
#define IDN_PREP_HWINIT() \
{ \
ASSERT(IDN_GLOCK_IS_EXCL()); \
}
/*
* Return values of idn_send_data.
*/
#define IDNXMIT_OKAY 0 /* xmit successful */
/*
* ---------------------------------------------------------------------
* ss_rwlock must be acquired _before_ any idn_domain locks are
* acquired if both structs need to be accessed.
* idn.struprwlock is acquired when traversing IDN's strup list
* and when adding or deleting entries.
*
* ss_nextp Linked list of streams.
* ss_rq Respective read queue.
* ss_sip Attached device.
* ss_state Current DL state.
* ss_sap Bound SAP.
* ss_flags Misc. flags.
* ss_mccount # enabled multicast addrs.
* ss_mctab Table of multicast addrs.
* ss_minor Minor device number.
* ss_rwlock Protects ss_linkup fields and DLPI state machine.
* ss_linkup Boolean flag indicating whether particular (domain) link
* is up.
* ---------------------------------------------------------------------
*/
struct idnstr { /* gets shoved into q_ptr */
struct ether_addr *ss_mctab;
};
/*
* idnstr.ss_flags - Per-stream flags
*/
/*
* Maximum number of multicast address per stream.
*/
#define IDNMAXMC 64
/*
* Full DLSAP address length (in struct dladdr format).
*/
struct idndladdr {
struct ether_addr dl_phys;
};
#define IDNHEADROOM 64
/*
* Respective interpretation of bytes in 6 byte ethernet address.
*/
#define IDNETHER_ZERO 0
#define IDNETHER_COOKIE1 1
#define IDNETHER_COOKIE1_VAL 0xe5
#define IDNETHER_COOKIE2 2
#define IDNETHER_COOKIE2_VAL 0x82
#define IDNETHER_NETID 3
#define IDNETHER_CHANNEL 4
#define IDNETHER_RESERVED 5
#define IDNETHER_RESERVED_VAL 0x64
/*
* IDN driver supports multliple instances, however they
* still all refer to the same "physical" device. Multiple
* instances are supported primarily to allow increased
* STREAMs bandwidth since each instance has it's own IP queue.
* This structure is primarily defined to be consistent with
* other network drivers and also to hold the kernel stats.
*/
struct idn_kstat {
/*
* MIB II kstat variables
*/
/*
* PSARC 1997/198 : 64 bit kstats
*/
/*
* PSARC 1997/247 : RFC 1643 dot3Stats...
*/
};
/*
* Per logical interface private data structure.
*/
struct idn {
};
struct idn_gkstat {
};
extern struct idn_gkstat sg_kstat;
#ifdef IDN_NO_KSTAT
#define IDN_KSTAT_INC(s, i)
#define IDN_KSTAT_ADD(s, i, n)
#define IDN_GKSTAT_INC(i)
#else /* IDN_NO_KSTAT */
#endif /* IDN_NO_KSTAT */
/*
* idn.si_flags
*/
typedef struct kstat_named kstate_named_t;
struct idn_kstat_named {
/*
* MIB II kstat variables
*/
/*
* PSARC 1997/198 : 64bit kstats
*/
/*
* PSARC 1997/247 : RFC 1643 dot3Stats...
*/
};
/*
* Stats for global events of interest (non-counters).
*/
struct idn_gkstat_named {
};
/*
* ---------------------------------------------------------------------
*/
#ifdef DEBUG
#else /* DEBUG */
#endif /* DEBUG */
/*
* ---------------------------------------------------------------------
*/
#define CLR_XARGS(x) \
((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0)
#define GET_XARGS_NEGO_TICKET(x) ((uint_t)(x)[0])
#define GET_XARGS_NEGO_DSET(x, d) \
((d)[0] = (x)[1], (d)[1] = (x)[2], (d)[2] = (x)[3])
#define SET_XARGS_NEGO_TICKET(x, t) ((x)[0] = (uint_t)(t))
#define SET_XARGS_NEGO_DSET(x, d) \
((x)[1] = (uint_t)(d)[0], \
#define GET_XARGS_CON_TYPE(x) ((idn_con_t)(x)[0])
#define SET_XARGS_CON_TYPE(x, t) ((x)[0] = (uint_t)(t))
#define GET_XARGS_FIN_TYPE(x) GET_FIN_TYPE((x)[0])
#define GET_XARGS_FIN_ARG(x) GET_FIN_ARG((x)[0])
#define SET_XARGS_FIN_TYPE(x, t) SET_FIN_TYPE((x)[0], (t))
#define SET_XARGS_FIN_ARG(x, a) SET_FIN_ARG((x)[0], (a))
#define GET_XARGS_NACK_TYPE(x) ((idn_nack_t)(x)[0])
#define GET_XARGS_NACK_ARG1(x) ((x)[1])
#define GET_XARGS_NACK_ARG2(x) ((x)[2])
#define SET_XARGS_NACK_TYPE(x, t) ((x)[0] = (uint_t)(t))
#define GET_XARGS_CFG_PHASE(x) ((int)(x)[0])
#define SET_XARGS_CFG_PHASE(x, p) ((x)[0] = (uint_t)(p))
/*
* ---------------------------------------------------------------------
*/
/*
* Device instance to SIP (IDN instance pointer).
*/
#ifdef DEBUG
#define IDN_INST2SIP(i) \
idn_i2s_table[i])
#else /* DEBUG */
#define IDN_INST2SIP(i) (idn_i2s_table[i])
#endif /* DEBUG */
#define IDN_SET_INST2SIP(i, s) \
{ \
idn_i2s_table[i] = (s); \
}
#define IDN_NETID2DOMID(n) (VALID_UDOMAINID(n) ? \
((int)(n)) : IDN_NIL_DOMID)
#define IDN_DOMID2NETID(d) ((ushort_t)(d))
#ifdef DEBUG
#define IDNDL_ETHER2DOMAIN(eap) \
#define IDNDL_ETHER2SIP(eap) \
#else
/*
* The following values can be returned from IDNDL_ETHER2DOMAIN:
* IDN_NIL_DOMID
* Ether address is broadcast (0xff) or domain doesn't exist.
* domid Domain id with drwlock(reader) held.
*/
#define IDNDL_ETHER2DOMAIN(eap) \
#define IDNDL_ETHER2SIP(eap) \
#endif /* DEBUG */
#define UPPER32_CPUMASK(s) _upper32cpumask(s)
#define LOWER32_CPUMASK(s) _lower32cpumask(s)
#define MAKE64_CPUMASK(s, u, l) _make64cpumask(&(s), (u), (l))
#ifdef DEBUG
#else /* DEBUG */
KM_SLEEP))
#endif /* DEBUG */
extern int idn_debug;
extern idn_global_t idn;
extern idn_domain_t idn_domain[];
extern struct idn *idn_i2s_table[];
extern int idn_history;
extern struct idn_history idnhlog;
extern int idn_smr_size;
extern int idn_nwr_size;
extern int idn_protocol_nservers;
extern int idn_awolmsg_interval;
extern int idn_smr_bufsize;
extern int idn_slab_bufcount;
extern int idn_slab_prealloc;
extern int idn_slab_mintotal;
extern int idn_window_max;
extern int idn_window_incr;
extern int idn_reclaim_min;
extern int idn_reclaim_max;
extern int idn_mbox_per_net;
extern int idn_max_nets;
extern int idn_netsvr_spin_count;
extern int idn_netsvr_wait_min;
extern int idn_netsvr_wait_max;
extern int idn_netsvr_wait_shift;
extern int idn_checksum;
extern int idn_msgwait_nego;
extern int idn_msgwait_cfg;
extern int idn_msgwait_con;
extern int idn_msgwait_fin;
extern int idn_msgwait_cmd;
extern int idn_msgwait_data;
extern int idn_retryfreq_nego;
extern int idn_retryfreq_con;
extern int idn_retryfreq_fin;
extern int idn_window_emax; /* calculated */
extern int idn_slab_maxperdomain; /* calculated */
/*
* ---------------------------------------------------------------------
* ---------------------------------------------------------------------
*/
extern void idn_close_domain(int domid);
extern idn_timer_t *idn_timer_alloc();
int disconnect);
extern void idn_dopcache_init();
extern void idn_dopcache_deinit();
idnsb_error_t *sep);
idnsb_error_t *sep);
extern void idn_deinit_op(void *cookie);
int wait_timeout);
#ifdef DEBUG
#endif /* DEBUG */
/*
* ---------------------------------------------------------------------
* ---------------------------------------------------------------------
*/
extern void idn_assign_cookie(int domid);
idnsb_error_t *sep);
idnsb_error_t *sep);
extern void idn_clear_awol(int domid);
extern int idn_protocol_init(int nservers);
extern void idn_protocol_deinit();
extern void idn_timer_expired(void *arg);
extern int idn_open_channel(int channel);
extern int idn_chanservers_init();
extern void idn_chanservers_deinit();
extern void idn_xmit_monitor_kickoff(int chan_wanted);
/*
* ---------------------------------------------------------------------
* ---------------------------------------------------------------------
*/
extern void idnxf_flushall_ecache();
/*
* ---------------------------------------------------------------------
* io/idn_dlpi.c
* ---------------------------------------------------------------------
*/
extern void idndl_dodetach(struct idnstr *);
struct ether_addr *eap);
extern void idndl_dlpi_init();
struct ether_addr *);
struct ether_addr *);
extern void idndl_wenable(struct idn *);
/*
* ---------------------------------------------------------------------
* ---------------------------------------------------------------------
*/
/*
* ---------------------------------------------------------------------
*/
extern void idn_smrsize_init();
extern void idn_init_autolink();
extern void idn_deinit_autolink();
extern void idn_dmv_handler(void *arg);
extern int idnxf_send_mondo(int upaid);
extern clock_t idn_msg_waittime[];
extern clock_t idn_msg_retrytime[];
#endif /* !_ASM */
#endif /* _KERNEL */
#ifndef _ASM
/*
* ---------------------------------------------------------------------
*/
#define IDN_NIL_DOMID -1
#define IDN_NIL_DCPU -1
/*
* ---------------------------------------------------------------------
*/
/*
* IOCTL Interface
*
* Commands must stay in the range (1 - 4096) since only 12 bits
* are allotted.
*/
((op) == DL_IOC_HDR_INFO))
VALID_NDOP(op) || \
typedef union idnop {
struct {
int domid; /* input */
int cpuid; /* input */
int master; /* input */
int wait; /* input */
} link;
struct {
int domid; /* input */
int cpuid; /* input */
int force; /* input */
int wait; /* input */
} unlink;
struct {
int domid; /* input */
int cpuid; /* input */
} ping;
struct {
int blksize; /* input */
int num; /* input */
int rw; /* input */
int goawol; /* input */
} rwmem;
} idnop_t;
#ifdef _KERNEL
/*
* ndd support for IDN tunables.
*/
typedef struct idnparam {
char *sp_name;
} idnparam_t;
extern idnparam_t idn_param_arr[];
#ifdef IDN_PERF
#define _LP 0
#endif /* IDN_PERF */
/*
* =====================================================================
*/
/*
* Some junk to pretty print board lists and cpu lists in
* digit cpus separated by a command and single space. (Board list
* is similar, but only 16 entries possible.
*/
#define _DSTRLEN 400
/*
* These are declared in idn.c.
*/
extern const char *idnds_str[];
extern const char *idnxs_str[];
extern const char *idngs_str[];
extern const char *idncmd_str[];
extern const char *idncon_str[];
extern const char *idnfin_str[];
extern const char *idnfinarg_str[];
extern const char *idnfinopt_str[];
extern const char *idnreg_str[];
extern const char *idnnack_str[];
extern const char *idnop_str[];
extern const char *idnsync_str[];
extern const char *chanop_str[];
extern const char *chanaction_str[];
extern const char *inum_str[];
extern const int inum_bump;
extern const int inum_max;
extern const int acknack_shift;
extern const char *timer_str[];
extern const char *res_str[];
#endif /* _KERNEL */
#endif /* !_ASM */
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IDN_H */