xref: /openbmc/linux/drivers/misc/sgi-xp/xpc.h (revision aaa3cd69)
145d9ca49SDean Nelson /*
245d9ca49SDean Nelson  * This file is subject to the terms and conditions of the GNU General Public
345d9ca49SDean Nelson  * License.  See the file "COPYING" in the main directory of this archive
445d9ca49SDean Nelson  * for more details.
545d9ca49SDean Nelson  *
645d9ca49SDean Nelson  * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
745d9ca49SDean Nelson  */
845d9ca49SDean Nelson 
945d9ca49SDean Nelson /*
1045d9ca49SDean Nelson  * Cross Partition Communication (XPC) structures and macros.
1145d9ca49SDean Nelson  */
1245d9ca49SDean Nelson 
1345d9ca49SDean Nelson #ifndef _DRIVERS_MISC_SGIXP_XPC_H
1445d9ca49SDean Nelson #define _DRIVERS_MISC_SGIXP_XPC_H
1545d9ca49SDean Nelson 
1645d9ca49SDean Nelson #include <linux/interrupt.h>
1745d9ca49SDean Nelson #include <linux/sysctl.h>
1845d9ca49SDean Nelson #include <linux/device.h>
1945d9ca49SDean Nelson #include <linux/mutex.h>
2045d9ca49SDean Nelson #include <linux/completion.h>
2145d9ca49SDean Nelson #include <asm/pgtable.h>
2245d9ca49SDean Nelson #include <asm/processor.h>
2345d9ca49SDean Nelson #include <asm/sn/clksupport.h>
2445d9ca49SDean Nelson #include <asm/sn/addrs.h>
2545d9ca49SDean Nelson #include <asm/sn/mspec.h>
2645d9ca49SDean Nelson #include <asm/sn/shub_mmr.h>
2745d9ca49SDean Nelson #include "xp.h"
2845d9ca49SDean Nelson 
2945d9ca49SDean Nelson /*
3045d9ca49SDean Nelson  * XPC Version numbers consist of a major and minor number. XPC can always
3145d9ca49SDean Nelson  * talk to versions with same major #, and never talk to versions with a
3245d9ca49SDean Nelson  * different major #.
3345d9ca49SDean Nelson  */
3445d9ca49SDean Nelson #define _XPC_VERSION(_maj, _min)	(((_maj) << 4) | ((_min) & 0xf))
3545d9ca49SDean Nelson #define XPC_VERSION_MAJOR(_v)		((_v) >> 4)
3645d9ca49SDean Nelson #define XPC_VERSION_MINOR(_v)		((_v) & 0xf)
3745d9ca49SDean Nelson 
3845d9ca49SDean Nelson /*
3945d9ca49SDean Nelson  * The next macros define word or bit representations for given
4045d9ca49SDean Nelson  * C-brick nasid in either the SAL provided bit array representing
4145d9ca49SDean Nelson  * nasids in the partition/machine or the AMO_t array used for
4245d9ca49SDean Nelson  * inter-partition initiation communications.
4345d9ca49SDean Nelson  *
4445d9ca49SDean Nelson  * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
4545d9ca49SDean Nelson  * such, some space will be saved by insisting that nasid information
4645d9ca49SDean Nelson  * passed from SAL always be packed for C-Bricks and the
4745d9ca49SDean Nelson  * cross-partition interrupts use the same packing scheme.
4845d9ca49SDean Nelson  */
4945d9ca49SDean Nelson #define XPC_NASID_W_INDEX(_n)	(((_n) / 64) / 2)
5045d9ca49SDean Nelson #define XPC_NASID_B_INDEX(_n)	(((_n) / 2) & (64 - 1))
5145d9ca49SDean Nelson #define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
5245d9ca49SDean Nelson 				    (1UL << XPC_NASID_B_INDEX(_n)))
5345d9ca49SDean Nelson #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
5445d9ca49SDean Nelson 
5545d9ca49SDean Nelson #define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
5645d9ca49SDean Nelson #define XPC_HB_CHECK_DEFAULT_INTERVAL	20	/* check HB every x secs */
5745d9ca49SDean Nelson 
5845d9ca49SDean Nelson /* define the process name of HB checker and the CPU it is pinned to */
5945d9ca49SDean Nelson #define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
6045d9ca49SDean Nelson #define XPC_HB_CHECK_CPU		0
6145d9ca49SDean Nelson 
6245d9ca49SDean Nelson /* define the process name of the discovery thread */
6345d9ca49SDean Nelson #define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
6445d9ca49SDean Nelson 
6545d9ca49SDean Nelson /*
6645d9ca49SDean Nelson  * the reserved page
6745d9ca49SDean Nelson  *
6845d9ca49SDean Nelson  *   SAL reserves one page of memory per partition for XPC. Though a full page
6945d9ca49SDean Nelson  *   in length (16384 bytes), its starting address is not page aligned, but it
7045d9ca49SDean Nelson  *   is cacheline aligned. The reserved page consists of the following:
7145d9ca49SDean Nelson  *
7245d9ca49SDean Nelson  *   reserved page header
7345d9ca49SDean Nelson  *
7494bd2708SDean Nelson  *     The first two 64-byte cachelines of the reserved page contain the
7594bd2708SDean Nelson  *     header (struct xpc_rsvd_page). Before SAL initialization has completed,
7645d9ca49SDean Nelson  *     SAL has set up the following fields of the reserved page header:
7794bd2708SDean Nelson  *     SAL_signature, SAL_version, SAL_partid, and SAL_nasids_size. The
7894bd2708SDean Nelson  *     other fields are set up by XPC. (xpc_rsvd_page points to the local
7945d9ca49SDean Nelson  *     partition's reserved page.)
8045d9ca49SDean Nelson  *
8145d9ca49SDean Nelson  *   part_nasids mask
8245d9ca49SDean Nelson  *   mach_nasids mask
8345d9ca49SDean Nelson  *
8445d9ca49SDean Nelson  *     SAL also sets up two bitmaps (or masks), one that reflects the actual
8545d9ca49SDean Nelson  *     nasids in this partition (part_nasids), and the other that reflects
8645d9ca49SDean Nelson  *     the actual nasids in the entire machine (mach_nasids). We're only
8745d9ca49SDean Nelson  *     interested in the even numbered nasids (which contain the processors
8845d9ca49SDean Nelson  *     and/or memory), so we only need half as many bits to represent the
8945d9ca49SDean Nelson  *     nasids. The part_nasids mask is located starting at the first cacheline
9045d9ca49SDean Nelson  *     following the reserved page header. The mach_nasids mask follows right
9145d9ca49SDean Nelson  *     after the part_nasids mask. The size in bytes of each mask is reflected
9294bd2708SDean Nelson  *     by the reserved page header field 'SAL_nasids_size'. (Local partition's
9345d9ca49SDean Nelson  *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
9445d9ca49SDean Nelson  *
9594bd2708SDean Nelson  *   vars	(ia64-sn2 only)
9694bd2708SDean Nelson  *   vars part	(ia64-sn2 only)
9745d9ca49SDean Nelson  *
9845d9ca49SDean Nelson  *     Immediately following the mach_nasids mask are the XPC variables
9945d9ca49SDean Nelson  *     required by other partitions. First are those that are generic to all
10045d9ca49SDean Nelson  *     partitions (vars), followed on the next available cacheline by those
10145d9ca49SDean Nelson  *     which are partition specific (vars part). These are setup by XPC.
10245d9ca49SDean Nelson  *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
10345d9ca49SDean Nelson  *
10494bd2708SDean Nelson  * Note: Until 'stamp' is set non-zero, the partition XPC code has not been
10594bd2708SDean Nelson  *       initialized.
10645d9ca49SDean Nelson  */
10745d9ca49SDean Nelson struct xpc_rsvd_page {
10845d9ca49SDean Nelson 	u64 SAL_signature;	/* SAL: unique signature */
10945d9ca49SDean Nelson 	u64 SAL_version;	/* SAL: version */
11094bd2708SDean Nelson 	short SAL_partid;	/* SAL: partition ID */
11194bd2708SDean Nelson 	short max_npartitions;	/* value of XPC_MAX_PARTITIONS */
11245d9ca49SDean Nelson 	u8 version;
11394bd2708SDean Nelson 	u8 pad1[3];		/* align to next u64 in 1st 64-byte cacheline */
11494bd2708SDean Nelson 	union {
1152c2b94f9SDean Nelson 		u64 vars_pa;	/* physical address of struct xpc_vars */
11694bd2708SDean Nelson 		u64 activate_mq_gpa;	/* global phys address of activate_mq */
11794bd2708SDean Nelson 	} sn;
118aaa3cd69SDean Nelson 	unsigned long stamp;	/* time when reserved page was setup by XPC */
119aaa3cd69SDean Nelson 	u64 pad2[10];		/* align to last u64 in 2nd 64-byte cacheline */
12094bd2708SDean Nelson 	u64 SAL_nasids_size;	/* SAL: size of each nasid mask in bytes */
12145d9ca49SDean Nelson };
12245d9ca49SDean Nelson 
12394bd2708SDean Nelson #define XPC_RP_VERSION _XPC_VERSION(2, 0) /* version 2.0 of the reserved page */
12445d9ca49SDean Nelson 
12545d9ca49SDean Nelson #define XPC_SUPPORTS_RP_STAMP(_version) \
12645d9ca49SDean Nelson 			(_version >= _XPC_VERSION(1, 1))
12745d9ca49SDean Nelson 
12845d9ca49SDean Nelson /*
12945d9ca49SDean Nelson  * Define the structures by which XPC variables can be exported to other
13045d9ca49SDean Nelson  * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
13145d9ca49SDean Nelson  */
13245d9ca49SDean Nelson 
13345d9ca49SDean Nelson /*
13445d9ca49SDean Nelson  * The following structure describes the partition generic variables
13545d9ca49SDean Nelson  * needed by other partitions in order to properly initialize.
13645d9ca49SDean Nelson  *
13745d9ca49SDean Nelson  * struct xpc_vars version number also applies to struct xpc_vars_part.
13845d9ca49SDean Nelson  * Changes to either structure and/or related functionality should be
13945d9ca49SDean Nelson  * reflected by incrementing either the major or minor version numbers
14045d9ca49SDean Nelson  * of struct xpc_vars.
14145d9ca49SDean Nelson  */
14233ba3c77SDean Nelson struct xpc_vars_sn2 {
14345d9ca49SDean Nelson 	u8 version;
14445d9ca49SDean Nelson 	u64 heartbeat;
14533ba3c77SDean Nelson 	DECLARE_BITMAP(heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
14645d9ca49SDean Nelson 	u64 heartbeat_offline;	/* if 0, heartbeat should be changing */
14745d9ca49SDean Nelson 	int act_nasid;
14845d9ca49SDean Nelson 	int act_phys_cpuid;
14945d9ca49SDean Nelson 	u64 vars_part_pa;
15045d9ca49SDean Nelson 	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
15145d9ca49SDean Nelson 	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
15245d9ca49SDean Nelson };
15345d9ca49SDean Nelson 
15445d9ca49SDean Nelson #define XPC_V_VERSION _XPC_VERSION(3, 1)    /* version 3.1 of the cross vars */
15545d9ca49SDean Nelson 
15645d9ca49SDean Nelson #define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
15745d9ca49SDean Nelson 			(_version >= _XPC_VERSION(3, 1))
15845d9ca49SDean Nelson 
15945d9ca49SDean Nelson /*
16033ba3c77SDean Nelson  * The following pertains to ia64-sn2 only.
16133ba3c77SDean Nelson  *
16233ba3c77SDean Nelson  * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
16333ba3c77SDean Nelson  * pages are located in the lowest granule. The lowest granule uses 4k pages
16433ba3c77SDean Nelson  * for cached references and an alternate TLB handler to never provide a
16533ba3c77SDean Nelson  * cacheable mapping for the entire region. This will prevent speculative
16633ba3c77SDean Nelson  * reading of cached copies of our lines from being issued which will cause
16733ba3c77SDean Nelson  * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
16833ba3c77SDean Nelson  * AMO variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of
16933ba3c77SDean Nelson  * NOTIFY IRQs, 128 AMO variables (based on XP_NASID_MASK_WORDS) to identify
17033ba3c77SDean Nelson  * the senders of ACTIVATE IRQs, and 2 AMO variables to identify which remote
17133ba3c77SDean Nelson  * partitions (i.e., XPCs) consider themselves currently engaged with the
17233ba3c77SDean Nelson  * local XPC.
17345d9ca49SDean Nelson  */
17445d9ca49SDean Nelson #define XPC_NOTIFY_IRQ_AMOS	0
175bc63d387SDean Nelson #define XPC_ACTIVATE_IRQ_AMOS	(XPC_NOTIFY_IRQ_AMOS + XP_MAX_NPARTITIONS_SN2)
17645d9ca49SDean Nelson #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
17745d9ca49SDean Nelson #define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
17845d9ca49SDean Nelson 
17945d9ca49SDean Nelson /*
18045d9ca49SDean Nelson  * The following structure describes the per partition specific variables.
18145d9ca49SDean Nelson  *
18245d9ca49SDean Nelson  * An array of these structures, one per partition, will be defined. As a
18345d9ca49SDean Nelson  * partition becomes active XPC will copy the array entry corresponding to
18494bd2708SDean Nelson  * itself from that partition. It is desirable that the size of this structure
18594bd2708SDean Nelson  * evenly divides into a 128-byte cacheline, such that none of the entries in
18694bd2708SDean Nelson  * this array crosses a 128-byte cacheline boundary. As it is now, each entry
187e17d416bSDean Nelson  * occupies 64-bytes.
18845d9ca49SDean Nelson  */
189e17d416bSDean Nelson struct xpc_vars_part_sn2 {
1902c2b94f9SDean Nelson 	u64 magic;
19145d9ca49SDean Nelson 
19245d9ca49SDean Nelson 	u64 openclose_args_pa;	/* physical address of open and close args */
19345d9ca49SDean Nelson 	u64 GPs_pa;		/* physical address of Get/Put values */
19445d9ca49SDean Nelson 
19545d9ca49SDean Nelson 	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
19645d9ca49SDean Nelson 	int IPI_nasid;		/* nasid of where to send IPIs */
19745d9ca49SDean Nelson 	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
19845d9ca49SDean Nelson 
19945d9ca49SDean Nelson 	u8 nchannels;		/* #of defined channels supported */
20045d9ca49SDean Nelson 
20145d9ca49SDean Nelson 	u8 reserved[23];	/* pad to a full 64 bytes */
20245d9ca49SDean Nelson };
20345d9ca49SDean Nelson 
20445d9ca49SDean Nelson /*
20545d9ca49SDean Nelson  * The vars_part MAGIC numbers play a part in the first contact protocol.
20645d9ca49SDean Nelson  *
20745d9ca49SDean Nelson  * MAGIC1 indicates that the per partition specific variables for a remote
20845d9ca49SDean Nelson  * partition have been initialized by this partition.
20945d9ca49SDean Nelson  *
21045d9ca49SDean Nelson  * MAGIC2 indicates that this partition has pulled the remote partititions
21145d9ca49SDean Nelson  * per partition variables that pertain to this partition.
21245d9ca49SDean Nelson  */
21345d9ca49SDean Nelson #define XPC_VP_MAGIC1	0x0053524156435058L   /* 'XPCVARS\0'L (little endian) */
21445d9ca49SDean Nelson #define XPC_VP_MAGIC2	0x0073726176435058L   /* 'XPCvars\0'L (little endian) */
21545d9ca49SDean Nelson 
21645d9ca49SDean Nelson /* the reserved page sizes and offsets */
21745d9ca49SDean Nelson 
21845d9ca49SDean Nelson #define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
21933ba3c77SDean Nelson #define XPC_RP_VARS_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_vars_sn2))
22045d9ca49SDean Nelson 
2212c2b94f9SDean Nelson #define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE))
22245d9ca49SDean Nelson #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
22333ba3c77SDean Nelson #define XPC_RP_VARS(_rp)	((struct xpc_vars_sn2 *)(XPC_RP_MACH_NASIDS(_rp) + \
2242c2b94f9SDean Nelson 				    xp_nasid_mask_words))
22545d9ca49SDean Nelson 
22645d9ca49SDean Nelson /*
22745d9ca49SDean Nelson  * Functions registered by add_timer() or called by kernel_thread() only
22845d9ca49SDean Nelson  * allow for a single 64-bit argument. The following macros can be used to
22945d9ca49SDean Nelson  * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
23045d9ca49SDean Nelson  * the passed argument.
23145d9ca49SDean Nelson  */
23245d9ca49SDean Nelson #define XPC_PACK_ARGS(_arg1, _arg2) \
23345d9ca49SDean Nelson 			((((u64) _arg1) & 0xffffffff) | \
23445d9ca49SDean Nelson 			((((u64) _arg2) & 0xffffffff) << 32))
23545d9ca49SDean Nelson 
23645d9ca49SDean Nelson #define XPC_UNPACK_ARG1(_args)	(((u64) _args) & 0xffffffff)
23745d9ca49SDean Nelson #define XPC_UNPACK_ARG2(_args)	((((u64) _args) >> 32) & 0xffffffff)
23845d9ca49SDean Nelson 
23945d9ca49SDean Nelson /*
24045d9ca49SDean Nelson  * Define a Get/Put value pair (pointers) used with a message queue.
24145d9ca49SDean Nelson  */
24245d9ca49SDean Nelson struct xpc_gp {
2432c2b94f9SDean Nelson 	s64 get;		/* Get value */
2442c2b94f9SDean Nelson 	s64 put;		/* Put value */
24545d9ca49SDean Nelson };
24645d9ca49SDean Nelson 
24745d9ca49SDean Nelson #define XPC_GP_SIZE \
248bc63d387SDean Nelson 		L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_MAX_NCHANNELS)
24945d9ca49SDean Nelson 
25045d9ca49SDean Nelson /*
25145d9ca49SDean Nelson  * Define a structure that contains arguments associated with opening and
25245d9ca49SDean Nelson  * closing a channel.
25345d9ca49SDean Nelson  */
25445d9ca49SDean Nelson struct xpc_openclose_args {
25545d9ca49SDean Nelson 	u16 reason;		/* reason why channel is closing */
25645d9ca49SDean Nelson 	u16 msg_size;		/* sizeof each message entry */
25745d9ca49SDean Nelson 	u16 remote_nentries;	/* #of message entries in remote msg queue */
25845d9ca49SDean Nelson 	u16 local_nentries;	/* #of message entries in local msg queue */
25945d9ca49SDean Nelson 	u64 local_msgqueue_pa;	/* physical address of local message queue */
26045d9ca49SDean Nelson };
26145d9ca49SDean Nelson 
26245d9ca49SDean Nelson #define XPC_OPENCLOSE_ARGS_SIZE \
263bc63d387SDean Nelson 	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \
264bc63d387SDean Nelson 	      XPC_MAX_NCHANNELS)
26545d9ca49SDean Nelson 
26645d9ca49SDean Nelson /* struct xpc_msg flags */
26745d9ca49SDean Nelson 
26845d9ca49SDean Nelson #define	XPC_M_DONE		0x01	/* msg has been received/consumed */
26945d9ca49SDean Nelson #define	XPC_M_READY		0x02	/* msg is ready to be sent */
27045d9ca49SDean Nelson #define	XPC_M_INTERRUPT		0x04	/* send interrupt when msg consumed */
27145d9ca49SDean Nelson 
27245d9ca49SDean Nelson #define XPC_MSG_ADDRESS(_payload) \
27345d9ca49SDean Nelson 		((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
27445d9ca49SDean Nelson 
27545d9ca49SDean Nelson /*
27645d9ca49SDean Nelson  * Defines notify entry.
27745d9ca49SDean Nelson  *
27845d9ca49SDean Nelson  * This is used to notify a message's sender that their message was received
27945d9ca49SDean Nelson  * and consumed by the intended recipient.
28045d9ca49SDean Nelson  */
28145d9ca49SDean Nelson struct xpc_notify {
2822c2b94f9SDean Nelson 	u8 type;		/* type of notification */
28345d9ca49SDean Nelson 
28445d9ca49SDean Nelson 	/* the following two fields are only used if type == XPC_N_CALL */
28545d9ca49SDean Nelson 	xpc_notify_func func;	/* user's notify function */
28645d9ca49SDean Nelson 	void *key;		/* pointer to user's key */
28745d9ca49SDean Nelson };
28845d9ca49SDean Nelson 
28945d9ca49SDean Nelson /* struct xpc_notify type of notification */
29045d9ca49SDean Nelson 
29145d9ca49SDean Nelson #define	XPC_N_CALL		0x01	/* notify function provided by user */
29245d9ca49SDean Nelson 
29345d9ca49SDean Nelson /*
29445d9ca49SDean Nelson  * Define the structure that manages all the stuff required by a channel. In
29545d9ca49SDean Nelson  * particular, they are used to manage the messages sent across the channel.
29645d9ca49SDean Nelson  *
29745d9ca49SDean Nelson  * This structure is private to a partition, and is NOT shared across the
29845d9ca49SDean Nelson  * partition boundary.
29945d9ca49SDean Nelson  *
30045d9ca49SDean Nelson  * There is an array of these structures for each remote partition. It is
30145d9ca49SDean Nelson  * allocated at the time a partition becomes active. The array contains one
30245d9ca49SDean Nelson  * of these structures for each potential channel connection to that partition.
30345d9ca49SDean Nelson  *
30433ba3c77SDean Nelson >>> sn2 only!!!
30545d9ca49SDean Nelson  * Each of these structures manages two message queues (circular buffers).
30645d9ca49SDean Nelson  * They are allocated at the time a channel connection is made. One of
30745d9ca49SDean Nelson  * these message queues (local_msgqueue) holds the locally created messages
30845d9ca49SDean Nelson  * that are destined for the remote partition. The other of these message
30945d9ca49SDean Nelson  * queues (remote_msgqueue) is a locally cached copy of the remote partition's
31045d9ca49SDean Nelson  * own local_msgqueue.
31145d9ca49SDean Nelson  *
31245d9ca49SDean Nelson  * The following is a description of the Get/Put pointers used to manage these
31345d9ca49SDean Nelson  * two message queues. Consider the local_msgqueue to be on one partition
31445d9ca49SDean Nelson  * and the remote_msgqueue to be its cached copy on another partition. A
31545d9ca49SDean Nelson  * description of what each of the lettered areas contains is included.
31645d9ca49SDean Nelson  *
31745d9ca49SDean Nelson  *
31845d9ca49SDean Nelson  *                     local_msgqueue      remote_msgqueue
31945d9ca49SDean Nelson  *
32045d9ca49SDean Nelson  *                        |/////////|      |/////////|
32145d9ca49SDean Nelson  *    w_remote_GP.get --> +---------+      |/////////|
32245d9ca49SDean Nelson  *                        |    F    |      |/////////|
32345d9ca49SDean Nelson  *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
32445d9ca49SDean Nelson  *                        |         |      |         |
32545d9ca49SDean Nelson  *                        |         |      |    E    |
32645d9ca49SDean Nelson  *                        |         |      |         |
32745d9ca49SDean Nelson  *                        |         |      +---------+ <-- w_local_GP.get
32845d9ca49SDean Nelson  *                        |    B    |      |/////////|
32945d9ca49SDean Nelson  *                        |         |      |////D////|
33045d9ca49SDean Nelson  *                        |         |      |/////////|
33145d9ca49SDean Nelson  *                        |         |      +---------+ <-- w_remote_GP.put
33245d9ca49SDean Nelson  *                        |         |      |////C////|
33345d9ca49SDean Nelson  *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
33445d9ca49SDean Nelson  *                        |         |      |/////////|
33545d9ca49SDean Nelson  *                        |    A    |      |/////////|
33645d9ca49SDean Nelson  *                        |         |      |/////////|
33745d9ca49SDean Nelson  *     w_local_GP.put --> +---------+      |/////////|
33845d9ca49SDean Nelson  *                        |/////////|      |/////////|
33945d9ca49SDean Nelson  *
34045d9ca49SDean Nelson  *
34145d9ca49SDean Nelson  *	    ( remote_GP.[get|put] are cached copies of the remote
34245d9ca49SDean Nelson  *	      partition's local_GP->[get|put], and thus their values can
34345d9ca49SDean Nelson  *	      lag behind their counterparts on the remote partition. )
34445d9ca49SDean Nelson  *
34545d9ca49SDean Nelson  *
34645d9ca49SDean Nelson  *  A - Messages that have been allocated, but have not yet been sent to the
34745d9ca49SDean Nelson  *	remote partition.
34845d9ca49SDean Nelson  *
34945d9ca49SDean Nelson  *  B - Messages that have been sent, but have not yet been acknowledged by the
35045d9ca49SDean Nelson  *      remote partition as having been received.
35145d9ca49SDean Nelson  *
35245d9ca49SDean Nelson  *  C - Area that needs to be prepared for the copying of sent messages, by
35345d9ca49SDean Nelson  *	the clearing of the message flags of any previously received messages.
35445d9ca49SDean Nelson  *
35545d9ca49SDean Nelson  *  D - Area into which sent messages are to be copied from the remote
35645d9ca49SDean Nelson  *	partition's local_msgqueue and then delivered to their intended
35745d9ca49SDean Nelson  *	recipients. [ To allow for a multi-message copy, another pointer
35845d9ca49SDean Nelson  *	(next_msg_to_pull) has been added to keep track of the next message
35945d9ca49SDean Nelson  *	number needing to be copied (pulled). It chases after w_remote_GP.put.
36045d9ca49SDean Nelson  *	Any messages lying between w_local_GP.get and next_msg_to_pull have
36145d9ca49SDean Nelson  *	been copied and are ready to be delivered. ]
36245d9ca49SDean Nelson  *
36345d9ca49SDean Nelson  *  E - Messages that have been copied and delivered, but have not yet been
36445d9ca49SDean Nelson  *	acknowledged by the recipient as having been received.
36545d9ca49SDean Nelson  *
36645d9ca49SDean Nelson  *  F - Messages that have been acknowledged, but XPC has not yet notified the
36745d9ca49SDean Nelson  *	sender that the message was received by its intended recipient.
36845d9ca49SDean Nelson  *	This is also an area that needs to be prepared for the allocating of
36945d9ca49SDean Nelson  *	new messages, by the clearing of the message flags of the acknowledged
37045d9ca49SDean Nelson  *	messages.
37145d9ca49SDean Nelson  */
37245d9ca49SDean Nelson struct xpc_channel {
37364d032baSDean Nelson 	short partid;		/* ID of remote partition connected */
37445d9ca49SDean Nelson 	spinlock_t lock;	/* lock for updating this structure */
37545d9ca49SDean Nelson 	u32 flags;		/* general flags */
37645d9ca49SDean Nelson 
37765c17b80SDean Nelson 	enum xp_retval reason;	/* reason why channel is disconnect'g */
37845d9ca49SDean Nelson 	int reason_line;	/* line# disconnect initiated from */
37945d9ca49SDean Nelson 
38045d9ca49SDean Nelson 	u16 number;		/* channel # */
38145d9ca49SDean Nelson 
38245d9ca49SDean Nelson 	u16 msg_size;		/* sizeof each msg entry */
38345d9ca49SDean Nelson 	u16 local_nentries;	/* #of msg entries in local msg queue */
38445d9ca49SDean Nelson 	u16 remote_nentries;	/* #of msg entries in remote msg queue */
38545d9ca49SDean Nelson 
38645d9ca49SDean Nelson 	void *local_msgqueue_base;	/* base address of kmalloc'd space */
38745d9ca49SDean Nelson 	struct xpc_msg *local_msgqueue;	/* local message queue */
38845d9ca49SDean Nelson 	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
38945d9ca49SDean Nelson 	struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */
39045d9ca49SDean Nelson 					 /* local message queue */
39145d9ca49SDean Nelson 	u64 remote_msgqueue_pa;	/* phys addr of remote partition's */
39245d9ca49SDean Nelson 				/* local message queue */
39345d9ca49SDean Nelson 
39445d9ca49SDean Nelson 	atomic_t references;	/* #of external references to queues */
39545d9ca49SDean Nelson 
39645d9ca49SDean Nelson 	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
39745d9ca49SDean Nelson 	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */
39845d9ca49SDean Nelson 
39945d9ca49SDean Nelson 	u8 delayed_IPI_flags;	/* IPI flags received, but delayed */
40045d9ca49SDean Nelson 				/* action until channel disconnected */
40145d9ca49SDean Nelson 
40245d9ca49SDean Nelson 	/* queue of msg senders who want to be notified when msg received */
40345d9ca49SDean Nelson 
40445d9ca49SDean Nelson 	atomic_t n_to_notify;	/* #of msg senders to notify */
40545d9ca49SDean Nelson 	struct xpc_notify *notify_queue;    /* notify queue for messages sent */
40645d9ca49SDean Nelson 
40745d9ca49SDean Nelson 	xpc_channel_func func;	/* user's channel function */
40845d9ca49SDean Nelson 	void *key;		/* pointer to user's key */
40945d9ca49SDean Nelson 
41045d9ca49SDean Nelson 	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
41145d9ca49SDean Nelson 	struct completion wdisconnect_wait;    /* wait for channel disconnect */
41245d9ca49SDean Nelson 
41345d9ca49SDean Nelson 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
41445d9ca49SDean Nelson 					     /* opening or closing of channel */
41545d9ca49SDean Nelson 
41645d9ca49SDean Nelson 	/* various flavors of local and remote Get/Put values */
41745d9ca49SDean Nelson 
41845d9ca49SDean Nelson 	struct xpc_gp *local_GP;	/* local Get/Put values */
41945d9ca49SDean Nelson 	struct xpc_gp remote_GP;	/* remote Get/Put values */
42045d9ca49SDean Nelson 	struct xpc_gp w_local_GP;	/* working local Get/Put values */
42145d9ca49SDean Nelson 	struct xpc_gp w_remote_GP;	/* working remote Get/Put values */
42245d9ca49SDean Nelson 	s64 next_msg_to_pull;	/* Put value of next msg to pull */
42345d9ca49SDean Nelson 
42445d9ca49SDean Nelson 	/* kthread management related fields */
42545d9ca49SDean Nelson 
42645d9ca49SDean Nelson 	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
42745d9ca49SDean Nelson 	u32 kthreads_assigned_limit;	/* limit on #of kthreads assigned */
42845d9ca49SDean Nelson 	atomic_t kthreads_idle;	/* #of kthreads idle waiting for work */
42945d9ca49SDean Nelson 	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
43045d9ca49SDean Nelson 	atomic_t kthreads_active;	/* #of kthreads actively working */
43145d9ca49SDean Nelson 
43245d9ca49SDean Nelson 	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
43345d9ca49SDean Nelson 
43445d9ca49SDean Nelson } ____cacheline_aligned;
43545d9ca49SDean Nelson 
43645d9ca49SDean Nelson /* struct xpc_channel flags */
43745d9ca49SDean Nelson 
43845d9ca49SDean Nelson #define	XPC_C_WASCONNECTED	0x00000001	/* channel was connected */
43945d9ca49SDean Nelson 
44045d9ca49SDean Nelson #define	XPC_C_ROPENREPLY	0x00000002	/* remote open channel reply */
44145d9ca49SDean Nelson #define	XPC_C_OPENREPLY		0x00000004	/* local open channel reply */
44245d9ca49SDean Nelson #define	XPC_C_ROPENREQUEST	0x00000008     /* remote open channel request */
44345d9ca49SDean Nelson #define	XPC_C_OPENREQUEST	0x00000010	/* local open channel request */
44445d9ca49SDean Nelson 
44545d9ca49SDean Nelson #define	XPC_C_SETUP		0x00000020 /* channel's msgqueues are alloc'd */
44645d9ca49SDean Nelson #define	XPC_C_CONNECTEDCALLOUT	0x00000040     /* connected callout initiated */
44745d9ca49SDean Nelson #define	XPC_C_CONNECTEDCALLOUT_MADE \
44845d9ca49SDean Nelson 				0x00000080     /* connected callout completed */
44945d9ca49SDean Nelson #define	XPC_C_CONNECTED		0x00000100	/* local channel is connected */
45045d9ca49SDean Nelson #define	XPC_C_CONNECTING	0x00000200	/* channel is being connected */
45145d9ca49SDean Nelson 
45245d9ca49SDean Nelson #define	XPC_C_RCLOSEREPLY	0x00000400	/* remote close channel reply */
45345d9ca49SDean Nelson #define	XPC_C_CLOSEREPLY	0x00000800	/* local close channel reply */
45445d9ca49SDean Nelson #define	XPC_C_RCLOSEREQUEST	0x00001000    /* remote close channel request */
45545d9ca49SDean Nelson #define	XPC_C_CLOSEREQUEST	0x00002000     /* local close channel request */
45645d9ca49SDean Nelson 
45745d9ca49SDean Nelson #define	XPC_C_DISCONNECTED	0x00004000	/* channel is disconnected */
45845d9ca49SDean Nelson #define	XPC_C_DISCONNECTING	0x00008000   /* channel is being disconnected */
45945d9ca49SDean Nelson #define	XPC_C_DISCONNECTINGCALLOUT \
46045d9ca49SDean Nelson 				0x00010000 /* disconnecting callout initiated */
46145d9ca49SDean Nelson #define	XPC_C_DISCONNECTINGCALLOUT_MADE \
46245d9ca49SDean Nelson 				0x00020000 /* disconnecting callout completed */
46345d9ca49SDean Nelson #define	XPC_C_WDISCONNECT	0x00040000  /* waiting for channel disconnect */
46445d9ca49SDean Nelson 
46545d9ca49SDean Nelson /*
46645d9ca49SDean Nelson  * Manages channels on a partition basis. There is one of these structures
46745d9ca49SDean Nelson  * for each partition (a partition will never utilize the structure that
46845d9ca49SDean Nelson  * represents itself).
46945d9ca49SDean Nelson  */
47045d9ca49SDean Nelson struct xpc_partition {
47145d9ca49SDean Nelson 
47245d9ca49SDean Nelson 	/* XPC HB infrastructure */
47345d9ca49SDean Nelson 
47445d9ca49SDean Nelson 	u8 remote_rp_version;	/* version# of partition's rsvd pg */
475aaa3cd69SDean Nelson 	unsigned long remote_rp_stamp; /* time when rsvd pg was initialized */
47645d9ca49SDean Nelson 	u64 remote_rp_pa;	/* phys addr of partition's rsvd pg */
47745d9ca49SDean Nelson 	u64 remote_vars_pa;	/* phys addr of partition's vars */
47845d9ca49SDean Nelson 	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
47945d9ca49SDean Nelson 	u64 last_heartbeat;	/* HB at last read */
48045d9ca49SDean Nelson 	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
48145d9ca49SDean Nelson 	int remote_act_nasid;	/* active part's act/deact nasid */
48245d9ca49SDean Nelson 	int remote_act_phys_cpuid;	/* active part's act/deact phys cpuid */
48345d9ca49SDean Nelson 	u32 act_IRQ_rcvd;	/* IRQs since activation */
48445d9ca49SDean Nelson 	spinlock_t act_lock;	/* protect updating of act_state */
48545d9ca49SDean Nelson 	u8 act_state;		/* from XPC HB viewpoint */
48645d9ca49SDean Nelson 	u8 remote_vars_version;	/* version# of partition's vars */
48765c17b80SDean Nelson 	enum xp_retval reason;	/* reason partition is deactivating */
48845d9ca49SDean Nelson 	int reason_line;	/* line# deactivation initiated from */
48945d9ca49SDean Nelson 	int reactivate_nasid;	/* nasid in partition to reactivate */
49045d9ca49SDean Nelson 
49145d9ca49SDean Nelson 	unsigned long disengage_request_timeout;	/* timeout in jiffies */
49245d9ca49SDean Nelson 	struct timer_list disengage_request_timer;
49345d9ca49SDean Nelson 
49445d9ca49SDean Nelson 	/* XPC infrastructure referencing and teardown control */
49545d9ca49SDean Nelson 
4962c2b94f9SDean Nelson 	u8 setup_state;		/* infrastructure setup state */
49745d9ca49SDean Nelson 	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
49845d9ca49SDean Nelson 	atomic_t references;	/* #of references to infrastructure */
49945d9ca49SDean Nelson 
50045d9ca49SDean Nelson 	u8 nchannels;		/* #of defined channels supported */
50145d9ca49SDean Nelson 	atomic_t nchannels_active;  /* #of channels that are not DISCONNECTED */
50245d9ca49SDean Nelson 	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
50345d9ca49SDean Nelson 	struct xpc_channel *channels;	/* array of channel structures */
50445d9ca49SDean Nelson 
50545d9ca49SDean Nelson 	void *local_GPs_base;	/* base address of kmalloc'd space */
50645d9ca49SDean Nelson 	struct xpc_gp *local_GPs;	/* local Get/Put values */
50745d9ca49SDean Nelson 	void *remote_GPs_base;	/* base address of kmalloc'd space */
5082c2b94f9SDean Nelson 	struct xpc_gp *remote_GPs;	/* copy of remote partition's local */
5092c2b94f9SDean Nelson 					/* Get/Put values */
51045d9ca49SDean Nelson 	u64 remote_GPs_pa;	/* phys address of remote partition's local */
51145d9ca49SDean Nelson 				/* Get/Put values */
51245d9ca49SDean Nelson 
51345d9ca49SDean Nelson 	/* fields used to pass args when opening or closing a channel */
51445d9ca49SDean Nelson 
51545d9ca49SDean Nelson 	void *local_openclose_args_base;   /* base address of kmalloc'd space */
51645d9ca49SDean Nelson 	struct xpc_openclose_args *local_openclose_args;      /* local's args */
51745d9ca49SDean Nelson 	void *remote_openclose_args_base;  /* base address of kmalloc'd space */
51845d9ca49SDean Nelson 	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
51945d9ca49SDean Nelson 							  /* args */
52045d9ca49SDean Nelson 	u64 remote_openclose_args_pa;	/* phys addr of remote's args */
52145d9ca49SDean Nelson 
52245d9ca49SDean Nelson 	/* IPI sending, receiving and handling related fields */
52345d9ca49SDean Nelson 
52445d9ca49SDean Nelson 	int remote_IPI_nasid;	/* nasid of where to send IPIs */
52545d9ca49SDean Nelson 	int remote_IPI_phys_cpuid;	/* phys CPU ID of where to send IPIs */
52645d9ca49SDean Nelson 	AMO_t *remote_IPI_amo_va;    /* address of remote IPI AMO_t structure */
52745d9ca49SDean Nelson 
52845d9ca49SDean Nelson 	AMO_t *local_IPI_amo_va;	/* address of IPI AMO_t structure */
52945d9ca49SDean Nelson 	u64 local_IPI_amo;	/* IPI amo flags yet to be handled */
53045d9ca49SDean Nelson 	char IPI_owner[8];	/* IPI owner's name */
53145d9ca49SDean Nelson 	struct timer_list dropped_IPI_timer;	/* dropped IPI timer */
53245d9ca49SDean Nelson 
53345d9ca49SDean Nelson 	spinlock_t IPI_lock;	/* IPI handler lock */
53445d9ca49SDean Nelson 
53545d9ca49SDean Nelson 	/* channel manager related fields */
53645d9ca49SDean Nelson 
53745d9ca49SDean Nelson 	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
53845d9ca49SDean Nelson 	wait_queue_head_t channel_mgr_wq;	/* channel mgr's wait queue */
53945d9ca49SDean Nelson 
54045d9ca49SDean Nelson } ____cacheline_aligned;
54145d9ca49SDean Nelson 
54245d9ca49SDean Nelson /* struct xpc_partition act_state values (for XPC HB) */
54345d9ca49SDean Nelson 
54445d9ca49SDean Nelson #define	XPC_P_INACTIVE		0x00	/* partition is not active */
54545d9ca49SDean Nelson #define XPC_P_ACTIVATION_REQ	0x01	/* created thread to activate */
54645d9ca49SDean Nelson #define XPC_P_ACTIVATING	0x02	/* activation thread started */
54745d9ca49SDean Nelson #define XPC_P_ACTIVE		0x03	/* xpc_partition_up() was called */
54845d9ca49SDean Nelson #define XPC_P_DEACTIVATING	0x04	/* partition deactivation initiated */
54945d9ca49SDean Nelson 
55045d9ca49SDean Nelson #define XPC_DEACTIVATE_PARTITION(_p, _reason) \
55145d9ca49SDean Nelson 			xpc_deactivate_partition(__LINE__, (_p), (_reason))
55245d9ca49SDean Nelson 
55345d9ca49SDean Nelson /* struct xpc_partition setup_state values */
55445d9ca49SDean Nelson 
55545d9ca49SDean Nelson #define XPC_P_UNSET		0x00	/* infrastructure was never setup */
55645d9ca49SDean Nelson #define XPC_P_SETUP		0x01	/* infrastructure is setup */
55745d9ca49SDean Nelson #define XPC_P_WTEARDOWN		0x02	/* waiting to teardown infrastructure */
55845d9ca49SDean Nelson #define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
55945d9ca49SDean Nelson 
56045d9ca49SDean Nelson /*
56145d9ca49SDean Nelson  * struct xpc_partition IPI_timer #of seconds to wait before checking for
56245d9ca49SDean Nelson  * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
56345d9ca49SDean Nelson  * after the IPI was received.
56445d9ca49SDean Nelson  */
565e17d416bSDean Nelson #define XPC_P_DROPPED_IPI_WAIT_INTERVAL	(0.25 * HZ)
56645d9ca49SDean Nelson 
56745d9ca49SDean Nelson /* number of seconds to wait for other partitions to disengage */
56845d9ca49SDean Nelson #define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT	90
56945d9ca49SDean Nelson 
57045d9ca49SDean Nelson /* interval in seconds to print 'waiting disengagement' messages */
57145d9ca49SDean Nelson #define XPC_DISENGAGE_PRINTMSG_INTERVAL		10
57245d9ca49SDean Nelson 
57364d032baSDean Nelson #define XPC_PARTID(_p)	((short)((_p) - &xpc_partitions[0]))
57445d9ca49SDean Nelson 
57545d9ca49SDean Nelson /* found in xp_main.c */
57645d9ca49SDean Nelson extern struct xpc_registration xpc_registrations[];
57745d9ca49SDean Nelson 
57845d9ca49SDean Nelson /* found in xpc_main.c */
57945d9ca49SDean Nelson extern struct device *xpc_part;
58045d9ca49SDean Nelson extern struct device *xpc_chan;
58145d9ca49SDean Nelson extern int xpc_disengage_request_timelimit;
58245d9ca49SDean Nelson extern int xpc_disengage_request_timedout;
58333ba3c77SDean Nelson extern atomic_t xpc_act_IRQ_rcvd;
58433ba3c77SDean Nelson extern wait_queue_head_t xpc_act_IRQ_wq;
58533ba3c77SDean Nelson extern void *xpc_heartbeating_to_mask;
58645d9ca49SDean Nelson extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
58745d9ca49SDean Nelson extern void xpc_dropped_IPI_check(struct xpc_partition *);
58845d9ca49SDean Nelson extern void xpc_activate_partition(struct xpc_partition *);
58945d9ca49SDean Nelson extern void xpc_activate_kthreads(struct xpc_channel *, int);
59045d9ca49SDean Nelson extern void xpc_create_kthreads(struct xpc_channel *, int, int);
59145d9ca49SDean Nelson extern void xpc_disconnect_wait(int);
59294bd2708SDean Nelson extern enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *);
59333ba3c77SDean Nelson extern void (*xpc_heartbeat_init) (void);
59433ba3c77SDean Nelson extern void (*xpc_heartbeat_exit) (void);
59533ba3c77SDean Nelson extern void (*xpc_increment_heartbeat) (void);
59633ba3c77SDean Nelson extern void (*xpc_offline_heartbeat) (void);
59733ba3c77SDean Nelson extern void (*xpc_online_heartbeat) (void);
59833ba3c77SDean Nelson extern void (*xpc_check_remote_hb) (void);
599e17d416bSDean Nelson extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
600e17d416bSDean Nelson extern u64 (*xpc_get_IPI_flags) (struct xpc_partition *);
601e17d416bSDean Nelson extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *);
60233ba3c77SDean Nelson extern void (*xpc_initiate_partition_activation) (struct xpc_rsvd_page *, u64,
60333ba3c77SDean Nelson 						  int);
60433ba3c77SDean Nelson extern void (*xpc_process_act_IRQ_rcvd) (int);
605e17d416bSDean Nelson extern enum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *);
606e17d416bSDean Nelson extern void (*xpc_teardown_infrastructure) (struct xpc_partition *);
60733ba3c77SDean Nelson extern void (*xpc_mark_partition_engaged) (struct xpc_partition *);
60833ba3c77SDean Nelson extern void (*xpc_mark_partition_disengaged) (struct xpc_partition *);
60933ba3c77SDean Nelson extern void (*xpc_request_partition_disengage) (struct xpc_partition *);
61033ba3c77SDean Nelson extern void (*xpc_cancel_partition_disengage_request) (struct xpc_partition *);
61133ba3c77SDean Nelson extern u64 (*xpc_partition_engaged) (u64);
61233ba3c77SDean Nelson extern u64 (*xpc_partition_disengage_requested) (u64);;
61333ba3c77SDean Nelson extern void (*xpc_clear_partition_engaged) (u64);
61433ba3c77SDean Nelson extern void (*xpc_clear_partition_disengage_request) (u64);
61533ba3c77SDean Nelson 
61633ba3c77SDean Nelson extern void (*xpc_IPI_send_local_activate) (int);
61733ba3c77SDean Nelson extern void (*xpc_IPI_send_activated) (struct xpc_partition *);
61833ba3c77SDean Nelson extern void (*xpc_IPI_send_local_reactivate) (int);
61933ba3c77SDean Nelson extern void (*xpc_IPI_send_disengage) (struct xpc_partition *);
62033ba3c77SDean Nelson 
62133ba3c77SDean Nelson extern void (*xpc_IPI_send_closerequest) (struct xpc_channel *,
62233ba3c77SDean Nelson 					  unsigned long *);
62333ba3c77SDean Nelson extern void (*xpc_IPI_send_closereply) (struct xpc_channel *, unsigned long *);
62433ba3c77SDean Nelson extern void (*xpc_IPI_send_openrequest) (struct xpc_channel *, unsigned long *);
62533ba3c77SDean Nelson extern void (*xpc_IPI_send_openreply) (struct xpc_channel *, unsigned long *);
62633ba3c77SDean Nelson 
62733ba3c77SDean Nelson extern enum xp_retval (*xpc_allocate_msg) (struct xpc_channel *, u32,
62833ba3c77SDean Nelson 					   struct xpc_msg **);
62933ba3c77SDean Nelson extern enum xp_retval (*xpc_send_msg) (struct xpc_channel *, struct xpc_msg *,
63033ba3c77SDean Nelson 				       u8, xpc_notify_func, void *);
63133ba3c77SDean Nelson extern void (*xpc_received_msg) (struct xpc_channel *, struct xpc_msg *);
63294bd2708SDean Nelson 
63394bd2708SDean Nelson /* found in xpc_sn2.c */
63494bd2708SDean Nelson extern void xpc_init_sn2(void);
63594bd2708SDean Nelson 
63694bd2708SDean Nelson /* found in xpc_uv.c */
63794bd2708SDean Nelson extern void xpc_init_uv(void);
63894bd2708SDean Nelson 
63945d9ca49SDean Nelson /* found in xpc_partition.c */
64045d9ca49SDean Nelson extern int xpc_exiting;
64194bd2708SDean Nelson extern int xp_nasid_mask_words;
64245d9ca49SDean Nelson extern struct xpc_rsvd_page *xpc_rsvd_page;
64333ba3c77SDean Nelson extern u64 *xpc_mach_nasids;
644bc63d387SDean Nelson extern struct xpc_partition *xpc_partitions;
64545d9ca49SDean Nelson extern char *xpc_remote_copy_buffer;
64645d9ca49SDean Nelson extern void *xpc_remote_copy_buffer_base;
64745d9ca49SDean Nelson extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
64894bd2708SDean Nelson extern struct xpc_rsvd_page *xpc_setup_rsvd_page(void);
64945d9ca49SDean Nelson extern void xpc_allow_IPI_ops(void);
65045d9ca49SDean Nelson extern void xpc_restrict_IPI_ops(void);
65145d9ca49SDean Nelson extern int xpc_identify_act_IRQ_sender(void);
65245d9ca49SDean Nelson extern int xpc_partition_disengaged(struct xpc_partition *);
65365c17b80SDean Nelson extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *);
65445d9ca49SDean Nelson extern void xpc_mark_partition_inactive(struct xpc_partition *);
65545d9ca49SDean Nelson extern void xpc_discovery(void);
65633ba3c77SDean Nelson extern enum xp_retval xpc_get_remote_rp(int, u64 *, struct xpc_rsvd_page *,
65733ba3c77SDean Nelson 					u64 *);
65845d9ca49SDean Nelson extern void xpc_deactivate_partition(const int, struct xpc_partition *,
65965c17b80SDean Nelson 				     enum xp_retval);
66064d032baSDean Nelson extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *);
66145d9ca49SDean Nelson 
66245d9ca49SDean Nelson /* found in xpc_channel.c */
663e17d416bSDean Nelson extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
66445d9ca49SDean Nelson extern void xpc_initiate_connect(int);
66545d9ca49SDean Nelson extern void xpc_initiate_disconnect(int);
66633ba3c77SDean Nelson extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *);
66764d032baSDean Nelson extern enum xp_retval xpc_initiate_allocate(short, int, u32, void **);
66864d032baSDean Nelson extern enum xp_retval xpc_initiate_send(short, int, void *);
66964d032baSDean Nelson extern enum xp_retval xpc_initiate_send_notify(short, int, void *,
67045d9ca49SDean Nelson 					       xpc_notify_func, void *);
67164d032baSDean Nelson extern void xpc_initiate_received(short, int, void *);
67245d9ca49SDean Nelson extern void xpc_process_channel_activity(struct xpc_partition *);
67345d9ca49SDean Nelson extern void xpc_connected_callout(struct xpc_channel *);
67445d9ca49SDean Nelson extern void xpc_deliver_msg(struct xpc_channel *);
67545d9ca49SDean Nelson extern void xpc_disconnect_channel(const int, struct xpc_channel *,
67665c17b80SDean Nelson 				   enum xp_retval, unsigned long *);
67765c17b80SDean Nelson extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
67865c17b80SDean Nelson extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
67945d9ca49SDean Nelson 
68033ba3c77SDean Nelson static inline int
68133ba3c77SDean Nelson xpc_hb_allowed(short partid, void *heartbeating_to_mask)
68233ba3c77SDean Nelson {
68333ba3c77SDean Nelson 	return test_bit(partid, heartbeating_to_mask);
68433ba3c77SDean Nelson }
68533ba3c77SDean Nelson 
68633ba3c77SDean Nelson static inline int
68733ba3c77SDean Nelson xpc_any_hbs_allowed(void)
68833ba3c77SDean Nelson {
68933ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
69033ba3c77SDean Nelson 	return !bitmap_empty(xpc_heartbeating_to_mask, xp_max_npartitions);
69133ba3c77SDean Nelson }
69233ba3c77SDean Nelson 
69333ba3c77SDean Nelson static inline void
69433ba3c77SDean Nelson xpc_allow_hb(short partid)
69533ba3c77SDean Nelson {
69633ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
69733ba3c77SDean Nelson 	set_bit(partid, xpc_heartbeating_to_mask);
69833ba3c77SDean Nelson }
69933ba3c77SDean Nelson 
70033ba3c77SDean Nelson static inline void
70133ba3c77SDean Nelson xpc_disallow_hb(short partid)
70233ba3c77SDean Nelson {
70333ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
70433ba3c77SDean Nelson 	clear_bit(partid, xpc_heartbeating_to_mask);
70533ba3c77SDean Nelson }
70633ba3c77SDean Nelson 
70733ba3c77SDean Nelson static inline void
70833ba3c77SDean Nelson xpc_disallow_all_hbs(void)
70933ba3c77SDean Nelson {
71033ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
71133ba3c77SDean Nelson 	bitmap_zero(xpc_heartbeating_to_mask, xp_max_npartitions);
71233ba3c77SDean Nelson }
71333ba3c77SDean Nelson 
71445d9ca49SDean Nelson static inline void
71545d9ca49SDean Nelson xpc_wakeup_channel_mgr(struct xpc_partition *part)
71645d9ca49SDean Nelson {
7172c2b94f9SDean Nelson 	if (atomic_inc_return(&part->channel_mgr_requests) == 1)
71845d9ca49SDean Nelson 		wake_up(&part->channel_mgr_wq);
71945d9ca49SDean Nelson }
72045d9ca49SDean Nelson 
72145d9ca49SDean Nelson /*
72245d9ca49SDean Nelson  * These next two inlines are used to keep us from tearing down a channel's
72345d9ca49SDean Nelson  * msg queues while a thread may be referencing them.
72445d9ca49SDean Nelson  */
72545d9ca49SDean Nelson static inline void
72645d9ca49SDean Nelson xpc_msgqueue_ref(struct xpc_channel *ch)
72745d9ca49SDean Nelson {
72845d9ca49SDean Nelson 	atomic_inc(&ch->references);
72945d9ca49SDean Nelson }
73045d9ca49SDean Nelson 
73145d9ca49SDean Nelson static inline void
73245d9ca49SDean Nelson xpc_msgqueue_deref(struct xpc_channel *ch)
73345d9ca49SDean Nelson {
73445d9ca49SDean Nelson 	s32 refs = atomic_dec_return(&ch->references);
73545d9ca49SDean Nelson 
73645d9ca49SDean Nelson 	DBUG_ON(refs < 0);
7372c2b94f9SDean Nelson 	if (refs == 0)
73845d9ca49SDean Nelson 		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
73945d9ca49SDean Nelson }
74045d9ca49SDean Nelson 
74145d9ca49SDean Nelson #define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
74245d9ca49SDean Nelson 		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
74345d9ca49SDean Nelson 
74445d9ca49SDean Nelson /*
74545d9ca49SDean Nelson  * These two inlines are used to keep us from tearing down a partition's
74645d9ca49SDean Nelson  * setup infrastructure while a thread may be referencing it.
74745d9ca49SDean Nelson  */
74845d9ca49SDean Nelson static inline void
74945d9ca49SDean Nelson xpc_part_deref(struct xpc_partition *part)
75045d9ca49SDean Nelson {
75145d9ca49SDean Nelson 	s32 refs = atomic_dec_return(&part->references);
75245d9ca49SDean Nelson 
75345d9ca49SDean Nelson 	DBUG_ON(refs < 0);
7542c2b94f9SDean Nelson 	if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN)
75545d9ca49SDean Nelson 		wake_up(&part->teardown_wq);
75645d9ca49SDean Nelson }
75745d9ca49SDean Nelson 
75845d9ca49SDean Nelson static inline int
75945d9ca49SDean Nelson xpc_part_ref(struct xpc_partition *part)
76045d9ca49SDean Nelson {
76145d9ca49SDean Nelson 	int setup;
76245d9ca49SDean Nelson 
76345d9ca49SDean Nelson 	atomic_inc(&part->references);
76445d9ca49SDean Nelson 	setup = (part->setup_state == XPC_P_SETUP);
7652c2b94f9SDean Nelson 	if (!setup)
76645d9ca49SDean Nelson 		xpc_part_deref(part);
7672c2b94f9SDean Nelson 
76845d9ca49SDean Nelson 	return setup;
76945d9ca49SDean Nelson }
77045d9ca49SDean Nelson 
77145d9ca49SDean Nelson /*
77245d9ca49SDean Nelson  * The following macro is to be used for the setting of the reason and
77345d9ca49SDean Nelson  * reason_line fields in both the struct xpc_channel and struct xpc_partition
77445d9ca49SDean Nelson  * structures.
77545d9ca49SDean Nelson  */
77645d9ca49SDean Nelson #define XPC_SET_REASON(_p, _reason, _line) \
77745d9ca49SDean Nelson 	{ \
77845d9ca49SDean Nelson 		(_p)->reason = _reason; \
77945d9ca49SDean Nelson 		(_p)->reason_line = _line; \
78045d9ca49SDean Nelson 	}
78145d9ca49SDean Nelson 
78245d9ca49SDean Nelson /*
78333ba3c77SDean Nelson  * The sending and receiving of IPIs includes the setting of an >>>AMO variable
78445d9ca49SDean Nelson  * to indicate the reason the IPI was sent. The 64-bit variable is divided
78545d9ca49SDean Nelson  * up into eight bytes, ordered from right to left. Byte zero pertains to
78645d9ca49SDean Nelson  * channel 0, byte one to channel 1, and so on. Each byte is described by
78745d9ca49SDean Nelson  * the following IPI flags.
78845d9ca49SDean Nelson  */
78945d9ca49SDean Nelson 
79045d9ca49SDean Nelson #define	XPC_IPI_CLOSEREQUEST	0x01
79145d9ca49SDean Nelson #define	XPC_IPI_CLOSEREPLY	0x02
79245d9ca49SDean Nelson #define	XPC_IPI_OPENREQUEST	0x04
79345d9ca49SDean Nelson #define	XPC_IPI_OPENREPLY	0x08
79445d9ca49SDean Nelson #define	XPC_IPI_MSGREQUEST	0x10
79545d9ca49SDean Nelson 
79633ba3c77SDean Nelson /* given an >>>AMO variable and a channel#, get its associated IPI flags */
79745d9ca49SDean Nelson #define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
79845d9ca49SDean Nelson #define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
79945d9ca49SDean Nelson 
8002c2b94f9SDean Nelson #define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0fUL)
8012c2b94f9SDean Nelson #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010UL)
80245d9ca49SDean Nelson 
80345d9ca49SDean Nelson #endif /* _DRIVERS_MISC_SGIXP_XPC_H */
804