xref: /openbmc/linux/drivers/misc/sgi-xp/xpc.h (revision a47d5dac)
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 /*
12645d9ca49SDean Nelson  * Define the structures by which XPC variables can be exported to other
12745d9ca49SDean Nelson  * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
12845d9ca49SDean Nelson  */
12945d9ca49SDean Nelson 
13045d9ca49SDean Nelson /*
13145d9ca49SDean Nelson  * The following structure describes the partition generic variables
13245d9ca49SDean Nelson  * needed by other partitions in order to properly initialize.
13345d9ca49SDean Nelson  *
13445d9ca49SDean Nelson  * struct xpc_vars version number also applies to struct xpc_vars_part.
13545d9ca49SDean Nelson  * Changes to either structure and/or related functionality should be
13645d9ca49SDean Nelson  * reflected by incrementing either the major or minor version numbers
13745d9ca49SDean Nelson  * of struct xpc_vars.
13845d9ca49SDean Nelson  */
13933ba3c77SDean Nelson struct xpc_vars_sn2 {
14045d9ca49SDean Nelson 	u8 version;
14145d9ca49SDean Nelson 	u64 heartbeat;
14233ba3c77SDean Nelson 	DECLARE_BITMAP(heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
14345d9ca49SDean Nelson 	u64 heartbeat_offline;	/* if 0, heartbeat should be changing */
144a47d5dacSDean Nelson 	int activate_IRQ_nasid;
145a47d5dacSDean Nelson 	int activate_IRQ_phys_cpuid;
14645d9ca49SDean Nelson 	u64 vars_part_pa;
14745d9ca49SDean Nelson 	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
14845d9ca49SDean Nelson 	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
14945d9ca49SDean Nelson };
15045d9ca49SDean Nelson 
15145d9ca49SDean Nelson #define XPC_V_VERSION _XPC_VERSION(3, 1)    /* version 3.1 of the cross vars */
15245d9ca49SDean Nelson 
15345d9ca49SDean Nelson /*
15433ba3c77SDean Nelson  * The following pertains to ia64-sn2 only.
15533ba3c77SDean Nelson  *
15633ba3c77SDean Nelson  * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
15733ba3c77SDean Nelson  * pages are located in the lowest granule. The lowest granule uses 4k pages
15833ba3c77SDean Nelson  * for cached references and an alternate TLB handler to never provide a
15933ba3c77SDean Nelson  * cacheable mapping for the entire region. This will prevent speculative
16033ba3c77SDean Nelson  * reading of cached copies of our lines from being issued which will cause
16133ba3c77SDean Nelson  * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
16233ba3c77SDean Nelson  * AMO variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of
16333ba3c77SDean Nelson  * NOTIFY IRQs, 128 AMO variables (based on XP_NASID_MASK_WORDS) to identify
164a47d5dacSDean Nelson  * the senders of ACTIVATE IRQs, 1 AMO variable to identify which remote
16533ba3c77SDean Nelson  * partitions (i.e., XPCs) consider themselves currently engaged with the
166a47d5dacSDean Nelson  * local XPC and 1 AMO variable to request partition deactivation.
16745d9ca49SDean Nelson  */
16845d9ca49SDean Nelson #define XPC_NOTIFY_IRQ_AMOS	0
169bc63d387SDean Nelson #define XPC_ACTIVATE_IRQ_AMOS	(XPC_NOTIFY_IRQ_AMOS + XP_MAX_NPARTITIONS_SN2)
17045d9ca49SDean Nelson #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
171a47d5dacSDean Nelson #define XPC_DEACTIVATE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
17245d9ca49SDean Nelson 
17345d9ca49SDean Nelson /*
17445d9ca49SDean Nelson  * The following structure describes the per partition specific variables.
17545d9ca49SDean Nelson  *
17645d9ca49SDean Nelson  * An array of these structures, one per partition, will be defined. As a
17745d9ca49SDean Nelson  * partition becomes active XPC will copy the array entry corresponding to
17894bd2708SDean Nelson  * itself from that partition. It is desirable that the size of this structure
17994bd2708SDean Nelson  * evenly divides into a 128-byte cacheline, such that none of the entries in
18094bd2708SDean Nelson  * this array crosses a 128-byte cacheline boundary. As it is now, each entry
181e17d416bSDean Nelson  * occupies 64-bytes.
18245d9ca49SDean Nelson  */
183e17d416bSDean Nelson struct xpc_vars_part_sn2 {
1842c2b94f9SDean Nelson 	u64 magic;
18545d9ca49SDean Nelson 
18645d9ca49SDean Nelson 	u64 openclose_args_pa;	/* physical address of open and close args */
18745d9ca49SDean Nelson 	u64 GPs_pa;		/* physical address of Get/Put values */
18845d9ca49SDean Nelson 
18945d9ca49SDean Nelson 	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
19045d9ca49SDean Nelson 	int IPI_nasid;		/* nasid of where to send IPIs */
19145d9ca49SDean Nelson 	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
19245d9ca49SDean Nelson 
19345d9ca49SDean Nelson 	u8 nchannels;		/* #of defined channels supported */
19445d9ca49SDean Nelson 
19545d9ca49SDean Nelson 	u8 reserved[23];	/* pad to a full 64 bytes */
19645d9ca49SDean Nelson };
19745d9ca49SDean Nelson 
19845d9ca49SDean Nelson /*
19945d9ca49SDean Nelson  * The vars_part MAGIC numbers play a part in the first contact protocol.
20045d9ca49SDean Nelson  *
20145d9ca49SDean Nelson  * MAGIC1 indicates that the per partition specific variables for a remote
20245d9ca49SDean Nelson  * partition have been initialized by this partition.
20345d9ca49SDean Nelson  *
20445d9ca49SDean Nelson  * MAGIC2 indicates that this partition has pulled the remote partititions
20545d9ca49SDean Nelson  * per partition variables that pertain to this partition.
20645d9ca49SDean Nelson  */
20745d9ca49SDean Nelson #define XPC_VP_MAGIC1	0x0053524156435058L   /* 'XPCVARS\0'L (little endian) */
20845d9ca49SDean Nelson #define XPC_VP_MAGIC2	0x0073726176435058L   /* 'XPCvars\0'L (little endian) */
20945d9ca49SDean Nelson 
21045d9ca49SDean Nelson /* the reserved page sizes and offsets */
21145d9ca49SDean Nelson 
21245d9ca49SDean Nelson #define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
21333ba3c77SDean Nelson #define XPC_RP_VARS_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_vars_sn2))
21445d9ca49SDean Nelson 
2152c2b94f9SDean Nelson #define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE))
21645d9ca49SDean Nelson #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
21733ba3c77SDean Nelson #define XPC_RP_VARS(_rp)	((struct xpc_vars_sn2 *)(XPC_RP_MACH_NASIDS(_rp) + \
2182c2b94f9SDean Nelson 				    xp_nasid_mask_words))
21945d9ca49SDean Nelson 
22045d9ca49SDean Nelson /*
22145d9ca49SDean Nelson  * Functions registered by add_timer() or called by kernel_thread() only
22245d9ca49SDean Nelson  * allow for a single 64-bit argument. The following macros can be used to
22345d9ca49SDean Nelson  * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
22445d9ca49SDean Nelson  * the passed argument.
22545d9ca49SDean Nelson  */
22645d9ca49SDean Nelson #define XPC_PACK_ARGS(_arg1, _arg2) \
22745d9ca49SDean Nelson 			((((u64) _arg1) & 0xffffffff) | \
22845d9ca49SDean Nelson 			((((u64) _arg2) & 0xffffffff) << 32))
22945d9ca49SDean Nelson 
23045d9ca49SDean Nelson #define XPC_UNPACK_ARG1(_args)	(((u64) _args) & 0xffffffff)
23145d9ca49SDean Nelson #define XPC_UNPACK_ARG2(_args)	((((u64) _args) >> 32) & 0xffffffff)
23245d9ca49SDean Nelson 
23345d9ca49SDean Nelson /*
23445d9ca49SDean Nelson  * Define a Get/Put value pair (pointers) used with a message queue.
23545d9ca49SDean Nelson  */
23645d9ca49SDean Nelson struct xpc_gp {
2372c2b94f9SDean Nelson 	s64 get;		/* Get value */
2382c2b94f9SDean Nelson 	s64 put;		/* Put value */
23945d9ca49SDean Nelson };
24045d9ca49SDean Nelson 
24145d9ca49SDean Nelson #define XPC_GP_SIZE \
242bc63d387SDean Nelson 		L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_MAX_NCHANNELS)
24345d9ca49SDean Nelson 
24445d9ca49SDean Nelson /*
24545d9ca49SDean Nelson  * Define a structure that contains arguments associated with opening and
24645d9ca49SDean Nelson  * closing a channel.
24745d9ca49SDean Nelson  */
24845d9ca49SDean Nelson struct xpc_openclose_args {
24945d9ca49SDean Nelson 	u16 reason;		/* reason why channel is closing */
25045d9ca49SDean Nelson 	u16 msg_size;		/* sizeof each message entry */
25145d9ca49SDean Nelson 	u16 remote_nentries;	/* #of message entries in remote msg queue */
25245d9ca49SDean Nelson 	u16 local_nentries;	/* #of message entries in local msg queue */
25345d9ca49SDean Nelson 	u64 local_msgqueue_pa;	/* physical address of local message queue */
25445d9ca49SDean Nelson };
25545d9ca49SDean Nelson 
25645d9ca49SDean Nelson #define XPC_OPENCLOSE_ARGS_SIZE \
257bc63d387SDean Nelson 	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \
258bc63d387SDean Nelson 	      XPC_MAX_NCHANNELS)
25945d9ca49SDean Nelson 
26045d9ca49SDean Nelson /* struct xpc_msg flags */
26145d9ca49SDean Nelson 
26245d9ca49SDean Nelson #define	XPC_M_DONE		0x01	/* msg has been received/consumed */
26345d9ca49SDean Nelson #define	XPC_M_READY		0x02	/* msg is ready to be sent */
26445d9ca49SDean Nelson #define	XPC_M_INTERRUPT		0x04	/* send interrupt when msg consumed */
26545d9ca49SDean Nelson 
26645d9ca49SDean Nelson #define XPC_MSG_ADDRESS(_payload) \
26745d9ca49SDean Nelson 		((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
26845d9ca49SDean Nelson 
26945d9ca49SDean Nelson /*
27045d9ca49SDean Nelson  * Defines notify entry.
27145d9ca49SDean Nelson  *
27245d9ca49SDean Nelson  * This is used to notify a message's sender that their message was received
27345d9ca49SDean Nelson  * and consumed by the intended recipient.
27445d9ca49SDean Nelson  */
27545d9ca49SDean Nelson struct xpc_notify {
2762c2b94f9SDean Nelson 	u8 type;		/* type of notification */
27745d9ca49SDean Nelson 
27845d9ca49SDean Nelson 	/* the following two fields are only used if type == XPC_N_CALL */
27945d9ca49SDean Nelson 	xpc_notify_func func;	/* user's notify function */
28045d9ca49SDean Nelson 	void *key;		/* pointer to user's key */
28145d9ca49SDean Nelson };
28245d9ca49SDean Nelson 
28345d9ca49SDean Nelson /* struct xpc_notify type of notification */
28445d9ca49SDean Nelson 
28545d9ca49SDean Nelson #define	XPC_N_CALL		0x01	/* notify function provided by user */
28645d9ca49SDean Nelson 
28745d9ca49SDean Nelson /*
28845d9ca49SDean Nelson  * Define the structure that manages all the stuff required by a channel. In
28945d9ca49SDean Nelson  * particular, they are used to manage the messages sent across the channel.
29045d9ca49SDean Nelson  *
29145d9ca49SDean Nelson  * This structure is private to a partition, and is NOT shared across the
29245d9ca49SDean Nelson  * partition boundary.
29345d9ca49SDean Nelson  *
29445d9ca49SDean Nelson  * There is an array of these structures for each remote partition. It is
29545d9ca49SDean Nelson  * allocated at the time a partition becomes active. The array contains one
29645d9ca49SDean Nelson  * of these structures for each potential channel connection to that partition.
29745d9ca49SDean Nelson  *
29833ba3c77SDean Nelson >>> sn2 only!!!
29945d9ca49SDean Nelson  * Each of these structures manages two message queues (circular buffers).
30045d9ca49SDean Nelson  * They are allocated at the time a channel connection is made. One of
30145d9ca49SDean Nelson  * these message queues (local_msgqueue) holds the locally created messages
30245d9ca49SDean Nelson  * that are destined for the remote partition. The other of these message
30345d9ca49SDean Nelson  * queues (remote_msgqueue) is a locally cached copy of the remote partition's
30445d9ca49SDean Nelson  * own local_msgqueue.
30545d9ca49SDean Nelson  *
30645d9ca49SDean Nelson  * The following is a description of the Get/Put pointers used to manage these
30745d9ca49SDean Nelson  * two message queues. Consider the local_msgqueue to be on one partition
30845d9ca49SDean Nelson  * and the remote_msgqueue to be its cached copy on another partition. A
30945d9ca49SDean Nelson  * description of what each of the lettered areas contains is included.
31045d9ca49SDean Nelson  *
31145d9ca49SDean Nelson  *
31245d9ca49SDean Nelson  *                     local_msgqueue      remote_msgqueue
31345d9ca49SDean Nelson  *
31445d9ca49SDean Nelson  *                        |/////////|      |/////////|
31545d9ca49SDean Nelson  *    w_remote_GP.get --> +---------+      |/////////|
31645d9ca49SDean Nelson  *                        |    F    |      |/////////|
31745d9ca49SDean Nelson  *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
31845d9ca49SDean Nelson  *                        |         |      |         |
31945d9ca49SDean Nelson  *                        |         |      |    E    |
32045d9ca49SDean Nelson  *                        |         |      |         |
32145d9ca49SDean Nelson  *                        |         |      +---------+ <-- w_local_GP.get
32245d9ca49SDean Nelson  *                        |    B    |      |/////////|
32345d9ca49SDean Nelson  *                        |         |      |////D////|
32445d9ca49SDean Nelson  *                        |         |      |/////////|
32545d9ca49SDean Nelson  *                        |         |      +---------+ <-- w_remote_GP.put
32645d9ca49SDean Nelson  *                        |         |      |////C////|
32745d9ca49SDean Nelson  *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
32845d9ca49SDean Nelson  *                        |         |      |/////////|
32945d9ca49SDean Nelson  *                        |    A    |      |/////////|
33045d9ca49SDean Nelson  *                        |         |      |/////////|
33145d9ca49SDean Nelson  *     w_local_GP.put --> +---------+      |/////////|
33245d9ca49SDean Nelson  *                        |/////////|      |/////////|
33345d9ca49SDean Nelson  *
33445d9ca49SDean Nelson  *
33545d9ca49SDean Nelson  *	    ( remote_GP.[get|put] are cached copies of the remote
33645d9ca49SDean Nelson  *	      partition's local_GP->[get|put], and thus their values can
33745d9ca49SDean Nelson  *	      lag behind their counterparts on the remote partition. )
33845d9ca49SDean Nelson  *
33945d9ca49SDean Nelson  *
34045d9ca49SDean Nelson  *  A - Messages that have been allocated, but have not yet been sent to the
34145d9ca49SDean Nelson  *	remote partition.
34245d9ca49SDean Nelson  *
34345d9ca49SDean Nelson  *  B - Messages that have been sent, but have not yet been acknowledged by the
34445d9ca49SDean Nelson  *      remote partition as having been received.
34545d9ca49SDean Nelson  *
34645d9ca49SDean Nelson  *  C - Area that needs to be prepared for the copying of sent messages, by
34745d9ca49SDean Nelson  *	the clearing of the message flags of any previously received messages.
34845d9ca49SDean Nelson  *
34945d9ca49SDean Nelson  *  D - Area into which sent messages are to be copied from the remote
35045d9ca49SDean Nelson  *	partition's local_msgqueue and then delivered to their intended
35145d9ca49SDean Nelson  *	recipients. [ To allow for a multi-message copy, another pointer
35245d9ca49SDean Nelson  *	(next_msg_to_pull) has been added to keep track of the next message
35345d9ca49SDean Nelson  *	number needing to be copied (pulled). It chases after w_remote_GP.put.
35445d9ca49SDean Nelson  *	Any messages lying between w_local_GP.get and next_msg_to_pull have
35545d9ca49SDean Nelson  *	been copied and are ready to be delivered. ]
35645d9ca49SDean Nelson  *
35745d9ca49SDean Nelson  *  E - Messages that have been copied and delivered, but have not yet been
35845d9ca49SDean Nelson  *	acknowledged by the recipient as having been received.
35945d9ca49SDean Nelson  *
36045d9ca49SDean Nelson  *  F - Messages that have been acknowledged, but XPC has not yet notified the
36145d9ca49SDean Nelson  *	sender that the message was received by its intended recipient.
36245d9ca49SDean Nelson  *	This is also an area that needs to be prepared for the allocating of
36345d9ca49SDean Nelson  *	new messages, by the clearing of the message flags of the acknowledged
36445d9ca49SDean Nelson  *	messages.
36545d9ca49SDean Nelson  */
366a47d5dacSDean Nelson struct xpc_channel_sn2 {
367a47d5dacSDean Nelson 
368a47d5dacSDean Nelson 	/* various flavors of local and remote Get/Put values */
369a47d5dacSDean Nelson 
370a47d5dacSDean Nelson 	struct xpc_gp *local_GP;	/* local Get/Put values */
371a47d5dacSDean Nelson 	struct xpc_gp remote_GP;	/* remote Get/Put values */
372a47d5dacSDean Nelson 	struct xpc_gp w_local_GP;	/* working local Get/Put values */
373a47d5dacSDean Nelson 	struct xpc_gp w_remote_GP;	/* working remote Get/Put values */
374a47d5dacSDean Nelson 	s64 next_msg_to_pull;	/* Put value of next msg to pull */
375a47d5dacSDean Nelson 
376a47d5dacSDean Nelson 	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
377a47d5dacSDean Nelson };
378a47d5dacSDean Nelson 
379a47d5dacSDean Nelson struct xpc_channel_uv {
380a47d5dacSDean Nelson 	/* >>> code is coming */
381a47d5dacSDean Nelson };
382a47d5dacSDean Nelson 
38345d9ca49SDean Nelson struct xpc_channel {
38464d032baSDean Nelson 	short partid;		/* ID of remote partition connected */
38545d9ca49SDean Nelson 	spinlock_t lock;	/* lock for updating this structure */
38645d9ca49SDean Nelson 	u32 flags;		/* general flags */
38745d9ca49SDean Nelson 
38865c17b80SDean Nelson 	enum xp_retval reason;	/* reason why channel is disconnect'g */
38945d9ca49SDean Nelson 	int reason_line;	/* line# disconnect initiated from */
39045d9ca49SDean Nelson 
39145d9ca49SDean Nelson 	u16 number;		/* channel # */
39245d9ca49SDean Nelson 
39345d9ca49SDean Nelson 	u16 msg_size;		/* sizeof each msg entry */
39445d9ca49SDean Nelson 	u16 local_nentries;	/* #of msg entries in local msg queue */
39545d9ca49SDean Nelson 	u16 remote_nentries;	/* #of msg entries in remote msg queue */
39645d9ca49SDean Nelson 
39745d9ca49SDean Nelson 	void *local_msgqueue_base;	/* base address of kmalloc'd space */
39845d9ca49SDean Nelson 	struct xpc_msg *local_msgqueue;	/* local message queue */
39945d9ca49SDean Nelson 	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
40045d9ca49SDean Nelson 	struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */
40145d9ca49SDean Nelson 					 /* local message queue */
40245d9ca49SDean Nelson 	u64 remote_msgqueue_pa;	/* phys addr of remote partition's */
40345d9ca49SDean Nelson 				/* local message queue */
40445d9ca49SDean Nelson 
40545d9ca49SDean Nelson 	atomic_t references;	/* #of external references to queues */
40645d9ca49SDean Nelson 
40745d9ca49SDean Nelson 	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
40845d9ca49SDean Nelson 	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */
40945d9ca49SDean Nelson 
41045d9ca49SDean Nelson 	u8 delayed_IPI_flags;	/* IPI flags received, but delayed */
41145d9ca49SDean Nelson 				/* action until channel disconnected */
41245d9ca49SDean Nelson 
41345d9ca49SDean Nelson 	/* queue of msg senders who want to be notified when msg received */
41445d9ca49SDean Nelson 
41545d9ca49SDean Nelson 	atomic_t n_to_notify;	/* #of msg senders to notify */
41645d9ca49SDean Nelson 	struct xpc_notify *notify_queue;    /* notify queue for messages sent */
41745d9ca49SDean Nelson 
41845d9ca49SDean Nelson 	xpc_channel_func func;	/* user's channel function */
41945d9ca49SDean Nelson 	void *key;		/* pointer to user's key */
42045d9ca49SDean Nelson 
42145d9ca49SDean Nelson 	struct completion wdisconnect_wait;    /* wait for channel disconnect */
42245d9ca49SDean Nelson 
42345d9ca49SDean Nelson 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
42445d9ca49SDean Nelson 					     /* opening or closing of channel */
42545d9ca49SDean Nelson 
42645d9ca49SDean Nelson 	/* kthread management related fields */
42745d9ca49SDean Nelson 
42845d9ca49SDean Nelson 	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
42945d9ca49SDean Nelson 	u32 kthreads_assigned_limit;	/* limit on #of kthreads assigned */
43045d9ca49SDean Nelson 	atomic_t kthreads_idle;	/* #of kthreads idle waiting for work */
43145d9ca49SDean Nelson 	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
43245d9ca49SDean Nelson 	atomic_t kthreads_active;	/* #of kthreads actively working */
43345d9ca49SDean Nelson 
43445d9ca49SDean Nelson 	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
43545d9ca49SDean Nelson 
436a47d5dacSDean Nelson 	union {
437a47d5dacSDean Nelson 		struct xpc_channel_sn2 sn2;
438a47d5dacSDean Nelson 		struct xpc_channel_uv uv;
439a47d5dacSDean Nelson 	} sn;
440a47d5dacSDean Nelson 
44145d9ca49SDean Nelson } ____cacheline_aligned;
44245d9ca49SDean Nelson 
44345d9ca49SDean Nelson /* struct xpc_channel flags */
44445d9ca49SDean Nelson 
44545d9ca49SDean Nelson #define	XPC_C_WASCONNECTED	0x00000001	/* channel was connected */
44645d9ca49SDean Nelson 
44745d9ca49SDean Nelson #define	XPC_C_ROPENREPLY	0x00000002	/* remote open channel reply */
44845d9ca49SDean Nelson #define	XPC_C_OPENREPLY		0x00000004	/* local open channel reply */
44945d9ca49SDean Nelson #define	XPC_C_ROPENREQUEST	0x00000008     /* remote open channel request */
45045d9ca49SDean Nelson #define	XPC_C_OPENREQUEST	0x00000010	/* local open channel request */
45145d9ca49SDean Nelson 
45245d9ca49SDean Nelson #define	XPC_C_SETUP		0x00000020 /* channel's msgqueues are alloc'd */
45345d9ca49SDean Nelson #define	XPC_C_CONNECTEDCALLOUT	0x00000040     /* connected callout initiated */
45445d9ca49SDean Nelson #define	XPC_C_CONNECTEDCALLOUT_MADE \
45545d9ca49SDean Nelson 				0x00000080     /* connected callout completed */
45645d9ca49SDean Nelson #define	XPC_C_CONNECTED		0x00000100	/* local channel is connected */
45745d9ca49SDean Nelson #define	XPC_C_CONNECTING	0x00000200	/* channel is being connected */
45845d9ca49SDean Nelson 
45945d9ca49SDean Nelson #define	XPC_C_RCLOSEREPLY	0x00000400	/* remote close channel reply */
46045d9ca49SDean Nelson #define	XPC_C_CLOSEREPLY	0x00000800	/* local close channel reply */
46145d9ca49SDean Nelson #define	XPC_C_RCLOSEREQUEST	0x00001000    /* remote close channel request */
46245d9ca49SDean Nelson #define	XPC_C_CLOSEREQUEST	0x00002000     /* local close channel request */
46345d9ca49SDean Nelson 
46445d9ca49SDean Nelson #define	XPC_C_DISCONNECTED	0x00004000	/* channel is disconnected */
46545d9ca49SDean Nelson #define	XPC_C_DISCONNECTING	0x00008000   /* channel is being disconnected */
46645d9ca49SDean Nelson #define	XPC_C_DISCONNECTINGCALLOUT \
46745d9ca49SDean Nelson 				0x00010000 /* disconnecting callout initiated */
46845d9ca49SDean Nelson #define	XPC_C_DISCONNECTINGCALLOUT_MADE \
46945d9ca49SDean Nelson 				0x00020000 /* disconnecting callout completed */
47045d9ca49SDean Nelson #define	XPC_C_WDISCONNECT	0x00040000  /* waiting for channel disconnect */
47145d9ca49SDean Nelson 
47245d9ca49SDean Nelson /*
47345d9ca49SDean Nelson  * Manages channels on a partition basis. There is one of these structures
47445d9ca49SDean Nelson  * for each partition (a partition will never utilize the structure that
47545d9ca49SDean Nelson  * represents itself).
47645d9ca49SDean Nelson  */
477a47d5dacSDean Nelson 
478a47d5dacSDean Nelson struct xpc_partition_sn2 {
479a47d5dacSDean Nelson 	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
480a47d5dacSDean Nelson 	int activate_IRQ_nasid;	/* active partition's act/deact nasid */
481a47d5dacSDean Nelson 	int activate_IRQ_phys_cpuid;	/* active part's act/deact phys cpuid */
482a47d5dacSDean Nelson 
483a47d5dacSDean Nelson 	u64 remote_vars_pa;	/* phys addr of partition's vars */
484a47d5dacSDean Nelson 	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
485a47d5dacSDean Nelson 	u8 remote_vars_version;	/* version# of partition's vars */
486a47d5dacSDean Nelson 
487a47d5dacSDean Nelson 	void *local_GPs_base;	/* base address of kmalloc'd space */
488a47d5dacSDean Nelson 	struct xpc_gp *local_GPs;	/* local Get/Put values */
489a47d5dacSDean Nelson 	void *remote_GPs_base;	/* base address of kmalloc'd space */
490a47d5dacSDean Nelson 	struct xpc_gp *remote_GPs;	/* copy of remote partition's local */
491a47d5dacSDean Nelson 					/* Get/Put values */
492a47d5dacSDean Nelson 	u64 remote_GPs_pa;	/* phys address of remote partition's local */
493a47d5dacSDean Nelson 				/* Get/Put values */
494a47d5dacSDean Nelson 
495a47d5dacSDean Nelson 	u64 remote_openclose_args_pa;	/* phys addr of remote's args */
496a47d5dacSDean Nelson 
497a47d5dacSDean Nelson 	int remote_IPI_nasid;	/* nasid of where to send IPIs */
498a47d5dacSDean Nelson 	int remote_IPI_phys_cpuid;	/* phys CPU ID of where to send IPIs */
499a47d5dacSDean Nelson 	char IPI_owner[8];	/* IPI owner's name */
500a47d5dacSDean Nelson 
501a47d5dacSDean Nelson 	AMO_t *remote_IPI_amo_va;    /* address of remote IPI AMO_t structure */
502a47d5dacSDean Nelson 	AMO_t *local_IPI_amo_va;	/* address of IPI AMO_t structure */
503a47d5dacSDean Nelson 
504a47d5dacSDean Nelson 	struct timer_list dropped_notify_IRQ_timer;	/* dropped IRQ timer */
505a47d5dacSDean Nelson };
506a47d5dacSDean Nelson 
507a47d5dacSDean Nelson struct xpc_partition_uv {
508a47d5dacSDean Nelson 	/* >>> code is coming */
509a47d5dacSDean Nelson };
510a47d5dacSDean Nelson 
51145d9ca49SDean Nelson struct xpc_partition {
51245d9ca49SDean Nelson 
51345d9ca49SDean Nelson 	/* XPC HB infrastructure */
51445d9ca49SDean Nelson 
51545d9ca49SDean Nelson 	u8 remote_rp_version;	/* version# of partition's rsvd pg */
516aaa3cd69SDean Nelson 	unsigned long remote_rp_stamp; /* time when rsvd pg was initialized */
51745d9ca49SDean Nelson 	u64 remote_rp_pa;	/* phys addr of partition's rsvd pg */
51845d9ca49SDean Nelson 	u64 last_heartbeat;	/* HB at last read */
5196e41017aSDean Nelson 	u32 activate_IRQ_rcvd;	/* IRQs since activation */
52045d9ca49SDean Nelson 	spinlock_t act_lock;	/* protect updating of act_state */
52145d9ca49SDean Nelson 	u8 act_state;		/* from XPC HB viewpoint */
52265c17b80SDean Nelson 	enum xp_retval reason;	/* reason partition is deactivating */
52345d9ca49SDean Nelson 	int reason_line;	/* line# deactivation initiated from */
52445d9ca49SDean Nelson 
525a47d5dacSDean Nelson 	unsigned long disengage_timeout;	/* timeout in jiffies */
526a47d5dacSDean Nelson 	struct timer_list disengage_timer;
52745d9ca49SDean Nelson 
52845d9ca49SDean Nelson 	/* XPC infrastructure referencing and teardown control */
52945d9ca49SDean Nelson 
5302c2b94f9SDean Nelson 	u8 setup_state;		/* infrastructure setup state */
53145d9ca49SDean Nelson 	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
53245d9ca49SDean Nelson 	atomic_t references;	/* #of references to infrastructure */
53345d9ca49SDean Nelson 
53445d9ca49SDean Nelson 	u8 nchannels;		/* #of defined channels supported */
53545d9ca49SDean Nelson 	atomic_t nchannels_active;  /* #of channels that are not DISCONNECTED */
53645d9ca49SDean Nelson 	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
53745d9ca49SDean Nelson 	struct xpc_channel *channels;	/* array of channel structures */
53845d9ca49SDean Nelson 
53945d9ca49SDean Nelson 	/* fields used to pass args when opening or closing a channel */
54045d9ca49SDean Nelson 
54145d9ca49SDean Nelson 	void *local_openclose_args_base;   /* base address of kmalloc'd space */
54245d9ca49SDean Nelson 	struct xpc_openclose_args *local_openclose_args;      /* local's args */
54345d9ca49SDean Nelson 	void *remote_openclose_args_base;  /* base address of kmalloc'd space */
54445d9ca49SDean Nelson 	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
54545d9ca49SDean Nelson 							  /* args */
54645d9ca49SDean Nelson 
54745d9ca49SDean Nelson 	/* IPI sending, receiving and handling related fields */
54845d9ca49SDean Nelson 
54945d9ca49SDean Nelson 	u64 local_IPI_amo;	/* IPI amo flags yet to be handled */
55045d9ca49SDean Nelson 	spinlock_t IPI_lock;	/* IPI handler lock */
55145d9ca49SDean Nelson 
55245d9ca49SDean Nelson 	/* channel manager related fields */
55345d9ca49SDean Nelson 
55445d9ca49SDean Nelson 	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
55545d9ca49SDean Nelson 	wait_queue_head_t channel_mgr_wq;	/* channel mgr's wait queue */
55645d9ca49SDean Nelson 
557a47d5dacSDean Nelson 	union {
558a47d5dacSDean Nelson 		struct xpc_partition_sn2 sn2;
559a47d5dacSDean Nelson 		struct xpc_partition_uv uv;
560a47d5dacSDean Nelson 	} sn;
561a47d5dacSDean Nelson 
56245d9ca49SDean Nelson } ____cacheline_aligned;
56345d9ca49SDean Nelson 
56445d9ca49SDean Nelson /* struct xpc_partition act_state values (for XPC HB) */
56545d9ca49SDean Nelson 
56645d9ca49SDean Nelson #define	XPC_P_INACTIVE		0x00	/* partition is not active */
56745d9ca49SDean Nelson #define XPC_P_ACTIVATION_REQ	0x01	/* created thread to activate */
56845d9ca49SDean Nelson #define XPC_P_ACTIVATING	0x02	/* activation thread started */
56945d9ca49SDean Nelson #define XPC_P_ACTIVE		0x03	/* xpc_partition_up() was called */
57045d9ca49SDean Nelson #define XPC_P_DEACTIVATING	0x04	/* partition deactivation initiated */
57145d9ca49SDean Nelson 
57245d9ca49SDean Nelson #define XPC_DEACTIVATE_PARTITION(_p, _reason) \
57345d9ca49SDean Nelson 			xpc_deactivate_partition(__LINE__, (_p), (_reason))
57445d9ca49SDean Nelson 
57545d9ca49SDean Nelson /* struct xpc_partition setup_state values */
57645d9ca49SDean Nelson 
57745d9ca49SDean Nelson #define XPC_P_UNSET		0x00	/* infrastructure was never setup */
57845d9ca49SDean Nelson #define XPC_P_SETUP		0x01	/* infrastructure is setup */
57945d9ca49SDean Nelson #define XPC_P_WTEARDOWN		0x02	/* waiting to teardown infrastructure */
58045d9ca49SDean Nelson #define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
58145d9ca49SDean Nelson 
58245d9ca49SDean Nelson /*
58345d9ca49SDean Nelson  * struct xpc_partition IPI_timer #of seconds to wait before checking for
58445d9ca49SDean Nelson  * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
58545d9ca49SDean Nelson  * after the IPI was received.
58645d9ca49SDean Nelson  */
587e17d416bSDean Nelson #define XPC_P_DROPPED_IPI_WAIT_INTERVAL	(0.25 * HZ)
58845d9ca49SDean Nelson 
58945d9ca49SDean Nelson /* number of seconds to wait for other partitions to disengage */
590a47d5dacSDean Nelson #define XPC_DISENGAGE_DEFAULT_TIMELIMIT		90
59145d9ca49SDean Nelson 
592a47d5dacSDean Nelson /* interval in seconds to print 'waiting deactivation' messages */
593a47d5dacSDean Nelson #define XPC_DEACTIVATE_PRINTMSG_INTERVAL	10
59445d9ca49SDean Nelson 
59564d032baSDean Nelson #define XPC_PARTID(_p)	((short)((_p) - &xpc_partitions[0]))
59645d9ca49SDean Nelson 
59745d9ca49SDean Nelson /* found in xp_main.c */
59845d9ca49SDean Nelson extern struct xpc_registration xpc_registrations[];
59945d9ca49SDean Nelson 
60045d9ca49SDean Nelson /* found in xpc_main.c */
60145d9ca49SDean Nelson extern struct device *xpc_part;
60245d9ca49SDean Nelson extern struct device *xpc_chan;
603a47d5dacSDean Nelson extern int xpc_disengage_timelimit;
604a47d5dacSDean Nelson extern int xpc_disengage_timedout;
6056e41017aSDean Nelson extern atomic_t xpc_activate_IRQ_rcvd;
6066e41017aSDean Nelson extern wait_queue_head_t xpc_activate_IRQ_wq;
60733ba3c77SDean Nelson extern void *xpc_heartbeating_to_mask;
60845d9ca49SDean Nelson extern void xpc_activate_partition(struct xpc_partition *);
60945d9ca49SDean Nelson extern void xpc_activate_kthreads(struct xpc_channel *, int);
61045d9ca49SDean Nelson extern void xpc_create_kthreads(struct xpc_channel *, int, int);
61145d9ca49SDean Nelson extern void xpc_disconnect_wait(int);
61294bd2708SDean Nelson extern enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *);
61333ba3c77SDean Nelson extern void (*xpc_heartbeat_init) (void);
61433ba3c77SDean Nelson extern void (*xpc_heartbeat_exit) (void);
61533ba3c77SDean Nelson extern void (*xpc_increment_heartbeat) (void);
61633ba3c77SDean Nelson extern void (*xpc_offline_heartbeat) (void);
61733ba3c77SDean Nelson extern void (*xpc_online_heartbeat) (void);
61833ba3c77SDean Nelson extern void (*xpc_check_remote_hb) (void);
619e17d416bSDean Nelson extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
620e17d416bSDean Nelson extern u64 (*xpc_get_IPI_flags) (struct xpc_partition *);
621a47d5dacSDean Nelson extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
622a47d5dacSDean Nelson extern void (*xpc_process_msg_IPI) (struct xpc_partition *, int);
623a47d5dacSDean Nelson extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *);
624e17d416bSDean Nelson extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *);
625a47d5dacSDean Nelson extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, u64,
62633ba3c77SDean Nelson 						 int);
627a47d5dacSDean Nelson extern void (*xpc_request_partition_reactivation) (struct xpc_partition *);
628a47d5dacSDean Nelson extern void (*xpc_request_partition_deactivation) (struct xpc_partition *);
629a47d5dacSDean Nelson extern void (*xpc_cancel_partition_deactivation_request) (
630a47d5dacSDean Nelson 							struct xpc_partition *);
6316e41017aSDean Nelson extern void (*xpc_process_activate_IRQ_rcvd) (int);
632e17d416bSDean Nelson extern enum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *);
633e17d416bSDean Nelson extern void (*xpc_teardown_infrastructure) (struct xpc_partition *);
63433ba3c77SDean Nelson 
635a47d5dacSDean Nelson extern void (*xpc_indicate_partition_engaged) (struct xpc_partition *);
636a47d5dacSDean Nelson extern int (*xpc_partition_engaged) (short);
637a47d5dacSDean Nelson extern int (*xpc_any_partition_engaged) (void);
638a47d5dacSDean Nelson extern void (*xpc_indicate_partition_disengaged) (struct xpc_partition *);
639a47d5dacSDean Nelson extern void (*xpc_assume_partition_disengaged) (short);
64033ba3c77SDean Nelson 
641a47d5dacSDean Nelson extern void (*xpc_send_channel_closerequest) (struct xpc_channel *,
64233ba3c77SDean Nelson 					      unsigned long *);
643a47d5dacSDean Nelson extern void (*xpc_send_channel_closereply) (struct xpc_channel *,
644a47d5dacSDean Nelson 					    unsigned long *);
645a47d5dacSDean Nelson extern void (*xpc_send_channel_openrequest) (struct xpc_channel *,
646a47d5dacSDean Nelson 					     unsigned long *);
647a47d5dacSDean Nelson extern void (*xpc_send_channel_openreply) (struct xpc_channel *,
648a47d5dacSDean Nelson 					   unsigned long *);
64933ba3c77SDean Nelson 
65097bf1aa1SDean Nelson extern enum xp_retval (*xpc_send_msg) (struct xpc_channel *, u32, void *, u16,
65133ba3c77SDean Nelson 				       u8, xpc_notify_func, void *);
65233ba3c77SDean Nelson extern void (*xpc_received_msg) (struct xpc_channel *, struct xpc_msg *);
65394bd2708SDean Nelson 
65494bd2708SDean Nelson /* found in xpc_sn2.c */
6556e41017aSDean Nelson extern int xpc_init_sn2(void);
6566e41017aSDean Nelson extern void xpc_exit_sn2(void);
65794bd2708SDean Nelson 
65894bd2708SDean Nelson /* found in xpc_uv.c */
65994bd2708SDean Nelson extern void xpc_init_uv(void);
6606e41017aSDean Nelson extern void xpc_exit_uv(void);
66194bd2708SDean Nelson 
66245d9ca49SDean Nelson /* found in xpc_partition.c */
66345d9ca49SDean Nelson extern int xpc_exiting;
66494bd2708SDean Nelson extern int xp_nasid_mask_words;
66545d9ca49SDean Nelson extern struct xpc_rsvd_page *xpc_rsvd_page;
66633ba3c77SDean Nelson extern u64 *xpc_mach_nasids;
667bc63d387SDean Nelson extern struct xpc_partition *xpc_partitions;
66845d9ca49SDean Nelson extern char *xpc_remote_copy_buffer;
66945d9ca49SDean Nelson extern void *xpc_remote_copy_buffer_base;
67045d9ca49SDean Nelson extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
67194bd2708SDean Nelson extern struct xpc_rsvd_page *xpc_setup_rsvd_page(void);
6726e41017aSDean Nelson extern int xpc_identify_activate_IRQ_sender(void);
67345d9ca49SDean Nelson extern int xpc_partition_disengaged(struct xpc_partition *);
67465c17b80SDean Nelson extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *);
67545d9ca49SDean Nelson extern void xpc_mark_partition_inactive(struct xpc_partition *);
67645d9ca49SDean Nelson extern void xpc_discovery(void);
67733ba3c77SDean Nelson extern enum xp_retval xpc_get_remote_rp(int, u64 *, struct xpc_rsvd_page *,
67833ba3c77SDean Nelson 					u64 *);
67945d9ca49SDean Nelson extern void xpc_deactivate_partition(const int, struct xpc_partition *,
68065c17b80SDean Nelson 				     enum xp_retval);
68164d032baSDean Nelson extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *);
68245d9ca49SDean Nelson 
68345d9ca49SDean Nelson /* found in xpc_channel.c */
684e17d416bSDean Nelson extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
68545d9ca49SDean Nelson extern void xpc_initiate_connect(int);
68645d9ca49SDean Nelson extern void xpc_initiate_disconnect(int);
68733ba3c77SDean Nelson extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *);
68897bf1aa1SDean Nelson extern enum xp_retval xpc_initiate_send(short, int, u32, void *, u16);
68997bf1aa1SDean Nelson extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
69045d9ca49SDean Nelson 					       xpc_notify_func, void *);
69164d032baSDean Nelson extern void xpc_initiate_received(short, int, void *);
69245d9ca49SDean Nelson extern void xpc_process_channel_activity(struct xpc_partition *);
69345d9ca49SDean Nelson extern void xpc_connected_callout(struct xpc_channel *);
69445d9ca49SDean Nelson extern void xpc_deliver_msg(struct xpc_channel *);
69545d9ca49SDean Nelson extern void xpc_disconnect_channel(const int, struct xpc_channel *,
69665c17b80SDean Nelson 				   enum xp_retval, unsigned long *);
69765c17b80SDean Nelson extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
69865c17b80SDean Nelson extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
69945d9ca49SDean Nelson 
70033ba3c77SDean Nelson static inline int
70133ba3c77SDean Nelson xpc_hb_allowed(short partid, void *heartbeating_to_mask)
70233ba3c77SDean Nelson {
70333ba3c77SDean Nelson 	return test_bit(partid, heartbeating_to_mask);
70433ba3c77SDean Nelson }
70533ba3c77SDean Nelson 
70633ba3c77SDean Nelson static inline int
70733ba3c77SDean Nelson xpc_any_hbs_allowed(void)
70833ba3c77SDean Nelson {
70933ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
71033ba3c77SDean Nelson 	return !bitmap_empty(xpc_heartbeating_to_mask, xp_max_npartitions);
71133ba3c77SDean Nelson }
71233ba3c77SDean Nelson 
71333ba3c77SDean Nelson static inline void
71433ba3c77SDean Nelson xpc_allow_hb(short partid)
71533ba3c77SDean Nelson {
71633ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
71733ba3c77SDean Nelson 	set_bit(partid, xpc_heartbeating_to_mask);
71833ba3c77SDean Nelson }
71933ba3c77SDean Nelson 
72033ba3c77SDean Nelson static inline void
72133ba3c77SDean Nelson xpc_disallow_hb(short partid)
72233ba3c77SDean Nelson {
72333ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
72433ba3c77SDean Nelson 	clear_bit(partid, xpc_heartbeating_to_mask);
72533ba3c77SDean Nelson }
72633ba3c77SDean Nelson 
72733ba3c77SDean Nelson static inline void
72833ba3c77SDean Nelson xpc_disallow_all_hbs(void)
72933ba3c77SDean Nelson {
73033ba3c77SDean Nelson 	DBUG_ON(xpc_heartbeating_to_mask == NULL);
73133ba3c77SDean Nelson 	bitmap_zero(xpc_heartbeating_to_mask, xp_max_npartitions);
73233ba3c77SDean Nelson }
73333ba3c77SDean Nelson 
73445d9ca49SDean Nelson static inline void
73545d9ca49SDean Nelson xpc_wakeup_channel_mgr(struct xpc_partition *part)
73645d9ca49SDean Nelson {
7372c2b94f9SDean Nelson 	if (atomic_inc_return(&part->channel_mgr_requests) == 1)
73845d9ca49SDean Nelson 		wake_up(&part->channel_mgr_wq);
73945d9ca49SDean Nelson }
74045d9ca49SDean Nelson 
74145d9ca49SDean Nelson /*
74245d9ca49SDean Nelson  * These next two inlines are used to keep us from tearing down a channel's
74345d9ca49SDean Nelson  * msg queues while a thread may be referencing them.
74445d9ca49SDean Nelson  */
74545d9ca49SDean Nelson static inline void
74645d9ca49SDean Nelson xpc_msgqueue_ref(struct xpc_channel *ch)
74745d9ca49SDean Nelson {
74845d9ca49SDean Nelson 	atomic_inc(&ch->references);
74945d9ca49SDean Nelson }
75045d9ca49SDean Nelson 
75145d9ca49SDean Nelson static inline void
75245d9ca49SDean Nelson xpc_msgqueue_deref(struct xpc_channel *ch)
75345d9ca49SDean Nelson {
75445d9ca49SDean Nelson 	s32 refs = atomic_dec_return(&ch->references);
75545d9ca49SDean Nelson 
75645d9ca49SDean Nelson 	DBUG_ON(refs < 0);
7572c2b94f9SDean Nelson 	if (refs == 0)
75845d9ca49SDean Nelson 		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
75945d9ca49SDean Nelson }
76045d9ca49SDean Nelson 
76145d9ca49SDean Nelson #define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
76245d9ca49SDean Nelson 		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
76345d9ca49SDean Nelson 
76445d9ca49SDean Nelson /*
76545d9ca49SDean Nelson  * These two inlines are used to keep us from tearing down a partition's
76645d9ca49SDean Nelson  * setup infrastructure while a thread may be referencing it.
76745d9ca49SDean Nelson  */
76845d9ca49SDean Nelson static inline void
76945d9ca49SDean Nelson xpc_part_deref(struct xpc_partition *part)
77045d9ca49SDean Nelson {
77145d9ca49SDean Nelson 	s32 refs = atomic_dec_return(&part->references);
77245d9ca49SDean Nelson 
77345d9ca49SDean Nelson 	DBUG_ON(refs < 0);
7742c2b94f9SDean Nelson 	if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN)
77545d9ca49SDean Nelson 		wake_up(&part->teardown_wq);
77645d9ca49SDean Nelson }
77745d9ca49SDean Nelson 
77845d9ca49SDean Nelson static inline int
77945d9ca49SDean Nelson xpc_part_ref(struct xpc_partition *part)
78045d9ca49SDean Nelson {
78145d9ca49SDean Nelson 	int setup;
78245d9ca49SDean Nelson 
78345d9ca49SDean Nelson 	atomic_inc(&part->references);
78445d9ca49SDean Nelson 	setup = (part->setup_state == XPC_P_SETUP);
7852c2b94f9SDean Nelson 	if (!setup)
78645d9ca49SDean Nelson 		xpc_part_deref(part);
7872c2b94f9SDean Nelson 
78845d9ca49SDean Nelson 	return setup;
78945d9ca49SDean Nelson }
79045d9ca49SDean Nelson 
79145d9ca49SDean Nelson /*
79245d9ca49SDean Nelson  * The following macro is to be used for the setting of the reason and
79345d9ca49SDean Nelson  * reason_line fields in both the struct xpc_channel and struct xpc_partition
79445d9ca49SDean Nelson  * structures.
79545d9ca49SDean Nelson  */
79645d9ca49SDean Nelson #define XPC_SET_REASON(_p, _reason, _line) \
79745d9ca49SDean Nelson 	{ \
79845d9ca49SDean Nelson 		(_p)->reason = _reason; \
79945d9ca49SDean Nelson 		(_p)->reason_line = _line; \
80045d9ca49SDean Nelson 	}
80145d9ca49SDean Nelson 
80245d9ca49SDean Nelson /*
80333ba3c77SDean Nelson  * The sending and receiving of IPIs includes the setting of an >>>AMO variable
80445d9ca49SDean Nelson  * to indicate the reason the IPI was sent. The 64-bit variable is divided
80545d9ca49SDean Nelson  * up into eight bytes, ordered from right to left. Byte zero pertains to
80645d9ca49SDean Nelson  * channel 0, byte one to channel 1, and so on. Each byte is described by
80745d9ca49SDean Nelson  * the following IPI flags.
80845d9ca49SDean Nelson  */
80945d9ca49SDean Nelson 
81045d9ca49SDean Nelson #define	XPC_IPI_CLOSEREQUEST	0x01
81145d9ca49SDean Nelson #define	XPC_IPI_CLOSEREPLY	0x02
81245d9ca49SDean Nelson #define	XPC_IPI_OPENREQUEST	0x04
81345d9ca49SDean Nelson #define	XPC_IPI_OPENREPLY	0x08
81445d9ca49SDean Nelson #define	XPC_IPI_MSGREQUEST	0x10
81545d9ca49SDean Nelson 
81633ba3c77SDean Nelson /* given an >>>AMO variable and a channel#, get its associated IPI flags */
81745d9ca49SDean Nelson #define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
81845d9ca49SDean Nelson #define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
81945d9ca49SDean Nelson 
8202c2b94f9SDean Nelson #define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0fUL)
8212c2b94f9SDean Nelson #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010UL)
82245d9ca49SDean Nelson 
82345d9ca49SDean Nelson #endif /* _DRIVERS_MISC_SGIXP_XPC_H */
824