Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
0007  */
0008 
0009 /*
0010  * Cross Partition Communication (XPC) structures and macros.
0011  */
0012 
0013 #ifndef _DRIVERS_MISC_SGIXP_XPC_H
0014 #define _DRIVERS_MISC_SGIXP_XPC_H
0015 
0016 #include <linux/wait.h>
0017 #include <linux/completion.h>
0018 #include <linux/timer.h>
0019 #include <linux/sched.h>
0020 #include "xp.h"
0021 
0022 /*
0023  * XPC Version numbers consist of a major and minor number. XPC can always
0024  * talk to versions with same major #, and never talk to versions with a
0025  * different major #.
0026  */
0027 #define _XPC_VERSION(_maj, _min)    (((_maj) << 4) | ((_min) & 0xf))
0028 #define XPC_VERSION_MAJOR(_v)       ((_v) >> 4)
0029 #define XPC_VERSION_MINOR(_v)       ((_v) & 0xf)
0030 
0031 /* define frequency of the heartbeat and frequency how often it's checked */
0032 #define XPC_HB_DEFAULT_INTERVAL     5   /* incr HB every x secs */
0033 #define XPC_HB_CHECK_DEFAULT_INTERVAL   20  /* check HB every x secs */
0034 
0035 /* define the process name of HB checker and the CPU it is pinned to */
0036 #define XPC_HB_CHECK_THREAD_NAME    "xpc_hb"
0037 #define XPC_HB_CHECK_CPU        0
0038 
0039 /* define the process name of the discovery thread */
0040 #define XPC_DISCOVERY_THREAD_NAME   "xpc_discovery"
0041 
0042 /*
0043  * the reserved page
0044  *
0045  *   SAL reserves one page of memory per partition for XPC. Though a full page
0046  *   in length (16384 bytes), its starting address is not page aligned, but it
0047  *   is cacheline aligned. The reserved page consists of the following:
0048  *
0049  *   reserved page header
0050  *
0051  *     The first two 64-byte cachelines of the reserved page contain the
0052  *     header (struct xpc_rsvd_page). Before SAL initialization has completed,
0053  *     SAL has set up the following fields of the reserved page header:
0054  *     SAL_signature, SAL_version, SAL_partid, and SAL_nasids_size. The
0055  *     other fields are set up by XPC. (xpc_rsvd_page points to the local
0056  *     partition's reserved page.)
0057  *
0058  *   part_nasids mask
0059  *   mach_nasids mask
0060  *
0061  *     SAL also sets up two bitmaps (or masks), one that reflects the actual
0062  *     nasids in this partition (part_nasids), and the other that reflects
0063  *     the actual nasids in the entire machine (mach_nasids). We're only
0064  *     interested in the even numbered nasids (which contain the processors
0065  *     and/or memory), so we only need half as many bits to represent the
0066  *     nasids. When mapping nasid to bit in a mask (or bit to nasid) be sure
0067  *     to either divide or multiply by 2. The part_nasids mask is located
0068  *     starting at the first cacheline following the reserved page header. The
0069  *     mach_nasids mask follows right after the part_nasids mask. The size in
0070  *     bytes of each mask is reflected by the reserved page header field
0071  *     'SAL_nasids_size'. (Local partition's mask pointers are xpc_part_nasids
0072  *     and xpc_mach_nasids.)
0073  *
0074  *     Immediately following the mach_nasids mask are the XPC variables
0075  *     required by other partitions. First are those that are generic to all
0076  *     partitions (vars), followed on the next available cacheline by those
0077  *     which are partition specific (vars part). These are setup by XPC.
0078  *
0079  * Note: Until 'ts_jiffies' is set non-zero, the partition XPC code has not been
0080  *       initialized.
0081  */
0082 struct xpc_rsvd_page {
0083     u64 SAL_signature;  /* SAL: unique signature */
0084     u64 SAL_version;    /* SAL: version */
0085     short SAL_partid;   /* SAL: partition ID */
0086     short max_npartitions;  /* value of XPC_MAX_PARTITIONS */
0087     u8 version;
0088     u8 pad1[3];     /* align to next u64 in 1st 64-byte cacheline */
0089     unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
0090     union {
0091         struct {
0092             unsigned long heartbeat_gpa; /* phys addr */
0093             unsigned long activate_gru_mq_desc_gpa; /* phys addr */
0094         } uv;
0095     } sn;
0096     u64 pad2[9];        /* align to last u64 in 2nd 64-byte cacheline */
0097     u64 SAL_nasids_size;    /* SAL: size of each nasid mask in bytes */
0098 };
0099 
0100 #define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */
0101 
0102 /* the reserved page sizes and offsets */
0103 
0104 #define XPC_RP_HEADER_SIZE  L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
0105 
0106 #define XPC_RP_PART_NASIDS(_rp) ((unsigned long *)((u8 *)(_rp) + \
0107                  XPC_RP_HEADER_SIZE))
0108 #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + \
0109                  xpc_nasid_mask_nlongs)
0110 
0111 
0112 /*
0113  * The following structure describes the partition's heartbeat info which
0114  * will be periodically read by other partitions to determine whether this
0115  * XPC is still 'alive'.
0116  */
0117 struct xpc_heartbeat_uv {
0118     unsigned long value;
0119     unsigned long offline;  /* if 0, heartbeat should be changing */
0120 };
0121 
0122 /*
0123  * Info pertinent to a GRU message queue using a watch list for irq generation.
0124  */
0125 struct xpc_gru_mq_uv {
0126     void *address;      /* address of GRU message queue */
0127     unsigned int order; /* size of GRU message queue as a power of 2 */
0128     int irq;        /* irq raised when message is received in mq */
0129     int mmr_blade;      /* blade where watchlist was allocated from */
0130     unsigned long mmr_offset; /* offset of irq mmr located on mmr_blade */
0131     unsigned long mmr_value; /* value of irq mmr located on mmr_blade */
0132     int watchlist_num;  /* number of watchlist allocatd by BIOS */
0133     void *gru_mq_desc;  /* opaque structure used by the GRU driver */
0134 };
0135 
0136 /*
0137  * The activate_mq is used to send/receive GRU messages that affect XPC's
0138  * partition active state and channel state. This is uv only.
0139  */
0140 struct xpc_activate_mq_msghdr_uv {
0141     unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */
0142     short partid;       /* sender's partid */
0143     u8 act_state;       /* sender's act_state at time msg sent */
0144     u8 type;        /* message's type */
0145     unsigned long rp_ts_jiffies; /* timestamp of sender's rp setup by XPC */
0146 };
0147 
0148 /* activate_mq defined message types */
0149 #define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV       0
0150 
0151 #define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV     1
0152 #define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV       2
0153 
0154 #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV   3
0155 #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV     4
0156 #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV    5
0157 #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV      6
0158 #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV   7
0159 
0160 #define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV     8
0161 #define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV      9
0162 
0163 struct xpc_activate_mq_msg_uv {
0164     struct xpc_activate_mq_msghdr_uv hdr;
0165 };
0166 
0167 struct xpc_activate_mq_msg_activate_req_uv {
0168     struct xpc_activate_mq_msghdr_uv hdr;
0169     unsigned long rp_gpa;
0170     unsigned long heartbeat_gpa;
0171     unsigned long activate_gru_mq_desc_gpa;
0172 };
0173 
0174 struct xpc_activate_mq_msg_deactivate_req_uv {
0175     struct xpc_activate_mq_msghdr_uv hdr;
0176     enum xp_retval reason;
0177 };
0178 
0179 struct xpc_activate_mq_msg_chctl_closerequest_uv {
0180     struct xpc_activate_mq_msghdr_uv hdr;
0181     short ch_number;
0182     enum xp_retval reason;
0183 };
0184 
0185 struct xpc_activate_mq_msg_chctl_closereply_uv {
0186     struct xpc_activate_mq_msghdr_uv hdr;
0187     short ch_number;
0188 };
0189 
0190 struct xpc_activate_mq_msg_chctl_openrequest_uv {
0191     struct xpc_activate_mq_msghdr_uv hdr;
0192     short ch_number;
0193     short entry_size;   /* size of notify_mq's GRU messages */
0194     short local_nentries;   /* ??? Is this needed? What is? */
0195 };
0196 
0197 struct xpc_activate_mq_msg_chctl_openreply_uv {
0198     struct xpc_activate_mq_msghdr_uv hdr;
0199     short ch_number;
0200     short remote_nentries;  /* ??? Is this needed? What is? */
0201     short local_nentries;   /* ??? Is this needed? What is? */
0202     unsigned long notify_gru_mq_desc_gpa;
0203 };
0204 
0205 struct xpc_activate_mq_msg_chctl_opencomplete_uv {
0206     struct xpc_activate_mq_msghdr_uv hdr;
0207     short ch_number;
0208 };
0209 
0210 /*
0211  * Functions registered by add_timer() or called by kernel_thread() only
0212  * allow for a single 64-bit argument. The following macros can be used to
0213  * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
0214  * the passed argument.
0215  */
0216 #define XPC_PACK_ARGS(_arg1, _arg2) \
0217             ((((u64)_arg1) & 0xffffffff) | \
0218             ((((u64)_arg2) & 0xffffffff) << 32))
0219 
0220 #define XPC_UNPACK_ARG1(_args)  (((u64)_args) & 0xffffffff)
0221 #define XPC_UNPACK_ARG2(_args)  ((((u64)_args) >> 32) & 0xffffffff)
0222 
0223 /*
0224  * Define a structure that contains arguments associated with opening and
0225  * closing a channel.
0226  */
0227 struct xpc_openclose_args {
0228     u16 reason;     /* reason why channel is closing */
0229     u16 entry_size;     /* sizeof each message entry */
0230     u16 remote_nentries;    /* #of message entries in remote msg queue */
0231     u16 local_nentries; /* #of message entries in local msg queue */
0232     unsigned long local_msgqueue_pa; /* phys addr of local message queue */
0233 };
0234 
0235 #define XPC_OPENCLOSE_ARGS_SIZE \
0236           L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \
0237           XPC_MAX_NCHANNELS)
0238 
0239 
0240 /*
0241  * Structures to define a fifo singly-linked list.
0242  */
0243 
0244 struct xpc_fifo_entry_uv {
0245     struct xpc_fifo_entry_uv *next;
0246 };
0247 
0248 struct xpc_fifo_head_uv {
0249     struct xpc_fifo_entry_uv *first;
0250     struct xpc_fifo_entry_uv *last;
0251     spinlock_t lock;
0252     int n_entries;
0253 };
0254 
0255 /*
0256  * The format of a uv XPC notify_mq GRU message is as follows:
0257  *
0258  * A user-defined message resides in the payload area. The max size of the
0259  * payload is defined by the user via xpc_connect().
0260  *
0261  * The size of a message (payload and header) sent via the GRU must be either 1
0262  * or 2 GRU_CACHE_LINE_BYTES in length.
0263  */
0264 
0265 struct xpc_notify_mq_msghdr_uv {
0266     union {
0267         unsigned int gru_msg_hdr;   /* FOR GRU INTERNAL USE ONLY */
0268         struct xpc_fifo_entry_uv next;  /* FOR XPC INTERNAL USE ONLY */
0269     } u;
0270     short partid;       /* FOR XPC INTERNAL USE ONLY */
0271     u8 ch_number;       /* FOR XPC INTERNAL USE ONLY */
0272     u8 size;        /* FOR XPC INTERNAL USE ONLY */
0273     unsigned int msg_slot_number;   /* FOR XPC INTERNAL USE ONLY */
0274 };
0275 
0276 struct xpc_notify_mq_msg_uv {
0277     struct xpc_notify_mq_msghdr_uv hdr;
0278     unsigned long payload;
0279 };
0280 
0281 /* struct xpc_notify_sn2 type of notification */
0282 
0283 #define XPC_N_CALL  0x01    /* notify function provided by user */
0284 
0285 /*
0286  * Define uv's version of the notify entry. It additionally is used to allocate
0287  * a msg slot on the remote partition into which is copied a sent message.
0288  */
0289 struct xpc_send_msg_slot_uv {
0290     struct xpc_fifo_entry_uv next;
0291     unsigned int msg_slot_number;
0292     xpc_notify_func func;   /* user's notify function */
0293     void *key;      /* pointer to user's key */
0294 };
0295 
0296 /*
0297  * Define the structure that manages all the stuff required by a channel. In
0298  * particular, they are used to manage the messages sent across the channel.
0299  *
0300  * This structure is private to a partition, and is NOT shared across the
0301  * partition boundary.
0302  *
0303  * There is an array of these structures for each remote partition. It is
0304  * allocated at the time a partition becomes active. The array contains one
0305  * of these structures for each potential channel connection to that partition.
0306  */
0307 
0308 struct xpc_channel_uv {
0309     void *cached_notify_gru_mq_desc; /* remote partition's notify mq's */
0310                      /* gru mq descriptor */
0311 
0312     struct xpc_send_msg_slot_uv *send_msg_slots;
0313     void *recv_msg_slots;   /* each slot will hold a xpc_notify_mq_msg_uv */
0314                 /* structure plus the user's payload */
0315 
0316     struct xpc_fifo_head_uv msg_slot_free_list;
0317     struct xpc_fifo_head_uv recv_msg_list;  /* deliverable payloads */
0318 };
0319 
0320 struct xpc_channel {
0321     short partid;       /* ID of remote partition connected */
0322     spinlock_t lock;    /* lock for updating this structure */
0323     unsigned int flags; /* general flags */
0324 
0325     enum xp_retval reason;  /* reason why channel is disconnect'g */
0326     int reason_line;    /* line# disconnect initiated from */
0327 
0328     u16 number;     /* channel # */
0329 
0330     u16 entry_size;     /* sizeof each msg entry */
0331     u16 local_nentries; /* #of msg entries in local msg queue */
0332     u16 remote_nentries;    /* #of msg entries in remote msg queue */
0333 
0334     atomic_t references;    /* #of external references to queues */
0335 
0336     atomic_t n_on_msg_allocate_wq;  /* #on msg allocation wait queue */
0337     wait_queue_head_t msg_allocate_wq;  /* msg allocation wait queue */
0338 
0339     u8 delayed_chctl_flags; /* chctl flags received, but delayed */
0340                 /* action until channel disconnected */
0341 
0342     atomic_t n_to_notify;   /* #of msg senders to notify */
0343 
0344     xpc_channel_func func;  /* user's channel function */
0345     void *key;      /* pointer to user's key */
0346 
0347     struct completion wdisconnect_wait;    /* wait for channel disconnect */
0348 
0349     /* kthread management related fields */
0350 
0351     atomic_t kthreads_assigned; /* #of kthreads assigned to channel */
0352     u32 kthreads_assigned_limit;    /* limit on #of kthreads assigned */
0353     atomic_t kthreads_idle; /* #of kthreads idle waiting for work */
0354     u32 kthreads_idle_limit;    /* limit on #of kthreads idle */
0355     atomic_t kthreads_active;   /* #of kthreads actively working */
0356 
0357     wait_queue_head_t idle_wq;  /* idle kthread wait queue */
0358 
0359     union {
0360         struct xpc_channel_uv uv;
0361     } sn;
0362 
0363 } ____cacheline_aligned;
0364 
0365 /* struct xpc_channel flags */
0366 
0367 #define XPC_C_WASCONNECTED  0x00000001  /* channel was connected */
0368 
0369 #define XPC_C_ROPENCOMPLETE 0x00000002    /* remote open channel complete */
0370 #define XPC_C_OPENCOMPLETE  0x00000004     /* local open channel complete */
0371 #define XPC_C_ROPENREPLY    0x00000008  /* remote open channel reply */
0372 #define XPC_C_OPENREPLY     0x00000010  /* local open channel reply */
0373 #define XPC_C_ROPENREQUEST  0x00000020     /* remote open channel request */
0374 #define XPC_C_OPENREQUEST   0x00000040  /* local open channel request */
0375 
0376 #define XPC_C_SETUP     0x00000080 /* channel's msgqueues are alloc'd */
0377 #define XPC_C_CONNECTEDCALLOUT  0x00000100     /* connected callout initiated */
0378 #define XPC_C_CONNECTEDCALLOUT_MADE \
0379                 0x00000200     /* connected callout completed */
0380 #define XPC_C_CONNECTED     0x00000400  /* local channel is connected */
0381 #define XPC_C_CONNECTING    0x00000800  /* channel is being connected */
0382 
0383 #define XPC_C_RCLOSEREPLY   0x00001000  /* remote close channel reply */
0384 #define XPC_C_CLOSEREPLY    0x00002000  /* local close channel reply */
0385 #define XPC_C_RCLOSEREQUEST 0x00004000    /* remote close channel request */
0386 #define XPC_C_CLOSEREQUEST  0x00008000     /* local close channel request */
0387 
0388 #define XPC_C_DISCONNECTED  0x00010000  /* channel is disconnected */
0389 #define XPC_C_DISCONNECTING 0x00020000   /* channel is being disconnected */
0390 #define XPC_C_DISCONNECTINGCALLOUT \
0391                 0x00040000 /* disconnecting callout initiated */
0392 #define XPC_C_DISCONNECTINGCALLOUT_MADE \
0393                 0x00080000 /* disconnecting callout completed */
0394 #define XPC_C_WDISCONNECT   0x00100000  /* waiting for channel disconnect */
0395 
0396 /*
0397  * The channel control flags (chctl) union consists of a 64-bit variable which
0398  * is divided up into eight bytes, ordered from right to left. Byte zero
0399  * pertains to channel 0, byte one to channel 1, and so on. Each channel's byte
0400  * can have one or more of the chctl flags set in it.
0401  */
0402 
0403 union xpc_channel_ctl_flags {
0404     u64 all_flags;
0405     u8 flags[XPC_MAX_NCHANNELS];
0406 };
0407 
0408 /* chctl flags */
0409 #define XPC_CHCTL_CLOSEREQUEST  0x01
0410 #define XPC_CHCTL_CLOSEREPLY    0x02
0411 #define XPC_CHCTL_OPENREQUEST   0x04
0412 #define XPC_CHCTL_OPENREPLY 0x08
0413 #define XPC_CHCTL_OPENCOMPLETE  0x10
0414 #define XPC_CHCTL_MSGREQUEST    0x20
0415 
0416 #define XPC_OPENCLOSE_CHCTL_FLAGS \
0417             (XPC_CHCTL_CLOSEREQUEST | XPC_CHCTL_CLOSEREPLY | \
0418              XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY | \
0419              XPC_CHCTL_OPENCOMPLETE)
0420 #define XPC_MSG_CHCTL_FLAGS XPC_CHCTL_MSGREQUEST
0421 
0422 static inline int
0423 xpc_any_openclose_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
0424 {
0425     int ch_number;
0426 
0427     for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
0428         if (chctl->flags[ch_number] & XPC_OPENCLOSE_CHCTL_FLAGS)
0429             return 1;
0430     }
0431     return 0;
0432 }
0433 
0434 static inline int
0435 xpc_any_msg_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
0436 {
0437     int ch_number;
0438 
0439     for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
0440         if (chctl->flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
0441             return 1;
0442     }
0443     return 0;
0444 }
0445 
0446 struct xpc_partition_uv {
0447     unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */
0448     struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */
0449                           /* partition's heartbeat */
0450     unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */
0451                         /* activate mq's gru mq */
0452                         /* descriptor */
0453     void *cached_activate_gru_mq_desc; /* cached copy of partition's */
0454                        /* activate mq's gru mq descriptor */
0455     struct mutex cached_activate_gru_mq_desc_mutex;
0456     spinlock_t flags_lock;  /* protect updating of flags */
0457     unsigned int flags; /* general flags */
0458     u8 remote_act_state;    /* remote partition's act_state */
0459     u8 act_state_req;   /* act_state request from remote partition */
0460     enum xp_retval reason;  /* reason for deactivate act_state request */
0461 };
0462 
0463 /* struct xpc_partition_uv flags */
0464 
0465 #define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV    0x00000001
0466 #define XPC_P_ENGAGED_UV            0x00000002
0467 
0468 /* struct xpc_partition_uv act_state change requests */
0469 
0470 #define XPC_P_ASR_ACTIVATE_UV       0x01
0471 #define XPC_P_ASR_REACTIVATE_UV     0x02
0472 #define XPC_P_ASR_DEACTIVATE_UV     0x03
0473 
0474 struct xpc_partition {
0475 
0476     /* XPC HB infrastructure */
0477 
0478     u8 remote_rp_version;   /* version# of partition's rsvd pg */
0479     unsigned long remote_rp_ts_jiffies; /* timestamp when rsvd pg setup */
0480     unsigned long remote_rp_pa; /* phys addr of partition's rsvd pg */
0481     u64 last_heartbeat; /* HB at last read */
0482     u32 activate_IRQ_rcvd;  /* IRQs since activation */
0483     spinlock_t act_lock;    /* protect updating of act_state */
0484     u8 act_state;       /* from XPC HB viewpoint */
0485     enum xp_retval reason;  /* reason partition is deactivating */
0486     int reason_line;    /* line# deactivation initiated from */
0487 
0488     unsigned long disengage_timeout;    /* timeout in jiffies */
0489     struct timer_list disengage_timer;
0490 
0491     /* XPC infrastructure referencing and teardown control */
0492 
0493     u8 setup_state;     /* infrastructure setup state */
0494     wait_queue_head_t teardown_wq;  /* kthread waiting to teardown infra */
0495     atomic_t references;    /* #of references to infrastructure */
0496 
0497     u8 nchannels;       /* #of defined channels supported */
0498     atomic_t nchannels_active;  /* #of channels that are not DISCONNECTED */
0499     atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
0500     struct xpc_channel *channels;   /* array of channel structures */
0501 
0502     /* fields used for managing channel avialability and activity */
0503 
0504     union xpc_channel_ctl_flags chctl; /* chctl flags yet to be processed */
0505     spinlock_t chctl_lock;  /* chctl flags lock */
0506 
0507     void *remote_openclose_args_base;  /* base address of kmalloc'd space */
0508     struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
0509                               /* args */
0510 
0511     /* channel manager related fields */
0512 
0513     atomic_t channel_mgr_requests;  /* #of requests to activate chan mgr */
0514     wait_queue_head_t channel_mgr_wq;   /* channel mgr's wait queue */
0515 
0516     union {
0517         struct xpc_partition_uv uv;
0518     } sn;
0519 
0520 } ____cacheline_aligned;
0521 
0522 struct xpc_arch_operations {
0523     int (*setup_partitions) (void);
0524     void (*teardown_partitions) (void);
0525     void (*process_activate_IRQ_rcvd) (void);
0526     enum xp_retval (*get_partition_rsvd_page_pa)
0527         (void *, u64 *, unsigned long *, size_t *);
0528     int (*setup_rsvd_page) (struct xpc_rsvd_page *);
0529 
0530     void (*allow_hb) (short);
0531     void (*disallow_hb) (short);
0532     void (*disallow_all_hbs) (void);
0533     void (*increment_heartbeat) (void);
0534     void (*offline_heartbeat) (void);
0535     void (*online_heartbeat) (void);
0536     void (*heartbeat_init) (void);
0537     void (*heartbeat_exit) (void);
0538     enum xp_retval (*get_remote_heartbeat) (struct xpc_partition *);
0539 
0540     void (*request_partition_activation) (struct xpc_rsvd_page *,
0541                          unsigned long, int);
0542     void (*request_partition_reactivation) (struct xpc_partition *);
0543     void (*request_partition_deactivation) (struct xpc_partition *);
0544     void (*cancel_partition_deactivation_request) (struct xpc_partition *);
0545     enum xp_retval (*setup_ch_structures) (struct xpc_partition *);
0546     void (*teardown_ch_structures) (struct xpc_partition *);
0547 
0548     enum xp_retval (*make_first_contact) (struct xpc_partition *);
0549 
0550     u64 (*get_chctl_all_flags) (struct xpc_partition *);
0551     void (*send_chctl_closerequest) (struct xpc_channel *, unsigned long *);
0552     void (*send_chctl_closereply) (struct xpc_channel *, unsigned long *);
0553     void (*send_chctl_openrequest) (struct xpc_channel *, unsigned long *);
0554     void (*send_chctl_openreply) (struct xpc_channel *, unsigned long *);
0555     void (*send_chctl_opencomplete) (struct xpc_channel *, unsigned long *);
0556     void (*process_msg_chctl_flags) (struct xpc_partition *, int);
0557 
0558     enum xp_retval (*save_remote_msgqueue_pa) (struct xpc_channel *,
0559                               unsigned long);
0560 
0561     enum xp_retval (*setup_msg_structures) (struct xpc_channel *);
0562     void (*teardown_msg_structures) (struct xpc_channel *);
0563 
0564     void (*indicate_partition_engaged) (struct xpc_partition *);
0565     void (*indicate_partition_disengaged) (struct xpc_partition *);
0566     void (*assume_partition_disengaged) (short);
0567     int (*partition_engaged) (short);
0568     int (*any_partition_engaged) (void);
0569 
0570     int (*n_of_deliverable_payloads) (struct xpc_channel *);
0571     enum xp_retval (*send_payload) (struct xpc_channel *, u32, void *,
0572                        u16, u8, xpc_notify_func, void *);
0573     void *(*get_deliverable_payload) (struct xpc_channel *);
0574     void (*received_payload) (struct xpc_channel *, void *);
0575     void (*notify_senders_of_disconnect) (struct xpc_channel *);
0576 };
0577 
0578 /* struct xpc_partition act_state values (for XPC HB) */
0579 
0580 #define XPC_P_AS_INACTIVE   0x00    /* partition is not active */
0581 #define XPC_P_AS_ACTIVATION_REQ 0x01    /* created thread to activate */
0582 #define XPC_P_AS_ACTIVATING 0x02    /* activation thread started */
0583 #define XPC_P_AS_ACTIVE     0x03    /* xpc_partition_up() was called */
0584 #define XPC_P_AS_DEACTIVATING   0x04    /* partition deactivation initiated */
0585 
0586 #define XPC_DEACTIVATE_PARTITION(_p, _reason) \
0587             xpc_deactivate_partition(__LINE__, (_p), (_reason))
0588 
0589 /* struct xpc_partition setup_state values */
0590 
0591 #define XPC_P_SS_UNSET      0x00    /* infrastructure was never setup */
0592 #define XPC_P_SS_SETUP      0x01    /* infrastructure is setup */
0593 #define XPC_P_SS_WTEARDOWN  0x02    /* waiting to teardown infrastructure */
0594 #define XPC_P_SS_TORNDOWN   0x03    /* infrastructure is torndown */
0595 
0596 /* number of seconds to wait for other partitions to disengage */
0597 #define XPC_DISENGAGE_DEFAULT_TIMELIMIT     90
0598 
0599 /* interval in seconds to print 'waiting deactivation' messages */
0600 #define XPC_DEACTIVATE_PRINTMSG_INTERVAL    10
0601 
0602 #define XPC_PARTID(_p)  ((short)((_p) - &xpc_partitions[0]))
0603 
0604 /* found in xp_main.c */
0605 extern struct xpc_registration xpc_registrations[];
0606 
0607 /* found in xpc_main.c */
0608 extern struct device *xpc_part;
0609 extern struct device *xpc_chan;
0610 extern struct xpc_arch_operations xpc_arch_ops;
0611 extern int xpc_disengage_timelimit;
0612 extern int xpc_disengage_timedout;
0613 extern int xpc_activate_IRQ_rcvd;
0614 extern spinlock_t xpc_activate_IRQ_rcvd_lock;
0615 extern wait_queue_head_t xpc_activate_IRQ_wq;
0616 extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
0617 extern void xpc_activate_partition(struct xpc_partition *);
0618 extern void xpc_activate_kthreads(struct xpc_channel *, int);
0619 extern void xpc_create_kthreads(struct xpc_channel *, int, int);
0620 extern void xpc_disconnect_wait(int);
0621 
0622 /* found in xpc_uv.c */
0623 extern int xpc_init_uv(void);
0624 extern void xpc_exit_uv(void);
0625 
0626 /* found in xpc_partition.c */
0627 extern int xpc_exiting;
0628 extern int xpc_nasid_mask_nlongs;
0629 extern struct xpc_rsvd_page *xpc_rsvd_page;
0630 extern unsigned long *xpc_mach_nasids;
0631 extern struct xpc_partition *xpc_partitions;
0632 extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
0633 extern int xpc_setup_rsvd_page(void);
0634 extern void xpc_teardown_rsvd_page(void);
0635 extern int xpc_identify_activate_IRQ_sender(void);
0636 extern int xpc_partition_disengaged(struct xpc_partition *);
0637 extern int xpc_partition_disengaged_from_timer(struct xpc_partition *part);
0638 extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *);
0639 extern void xpc_mark_partition_inactive(struct xpc_partition *);
0640 extern void xpc_discovery(void);
0641 extern enum xp_retval xpc_get_remote_rp(int, unsigned long *,
0642                     struct xpc_rsvd_page *,
0643                     unsigned long *);
0644 extern void xpc_deactivate_partition(const int, struct xpc_partition *,
0645                      enum xp_retval);
0646 extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *);
0647 
0648 /* found in xpc_channel.c */
0649 extern void xpc_initiate_connect(int);
0650 extern void xpc_initiate_disconnect(int);
0651 extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *);
0652 extern enum xp_retval xpc_initiate_send(short, int, u32, void *, u16);
0653 extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
0654                            xpc_notify_func, void *);
0655 extern void xpc_initiate_received(short, int, void *);
0656 extern void xpc_process_sent_chctl_flags(struct xpc_partition *);
0657 extern void xpc_connected_callout(struct xpc_channel *);
0658 extern void xpc_deliver_payload(struct xpc_channel *);
0659 extern void xpc_disconnect_channel(const int, struct xpc_channel *,
0660                    enum xp_retval, unsigned long *);
0661 extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
0662 extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
0663 
0664 static inline void
0665 xpc_wakeup_channel_mgr(struct xpc_partition *part)
0666 {
0667     if (atomic_inc_return(&part->channel_mgr_requests) == 1)
0668         wake_up(&part->channel_mgr_wq);
0669 }
0670 
0671 /*
0672  * These next two inlines are used to keep us from tearing down a channel's
0673  * msg queues while a thread may be referencing them.
0674  */
0675 static inline void
0676 xpc_msgqueue_ref(struct xpc_channel *ch)
0677 {
0678     atomic_inc(&ch->references);
0679 }
0680 
0681 static inline void
0682 xpc_msgqueue_deref(struct xpc_channel *ch)
0683 {
0684     s32 refs = atomic_dec_return(&ch->references);
0685 
0686     DBUG_ON(refs < 0);
0687     if (refs == 0)
0688         xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
0689 }
0690 
0691 #define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
0692         xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
0693 
0694 /*
0695  * These two inlines are used to keep us from tearing down a partition's
0696  * setup infrastructure while a thread may be referencing it.
0697  */
0698 static inline void
0699 xpc_part_deref(struct xpc_partition *part)
0700 {
0701     s32 refs = atomic_dec_return(&part->references);
0702 
0703     DBUG_ON(refs < 0);
0704     if (refs == 0 && part->setup_state == XPC_P_SS_WTEARDOWN)
0705         wake_up(&part->teardown_wq);
0706 }
0707 
0708 static inline int
0709 xpc_part_ref(struct xpc_partition *part)
0710 {
0711     int setup;
0712 
0713     atomic_inc(&part->references);
0714     setup = (part->setup_state == XPC_P_SS_SETUP);
0715     if (!setup)
0716         xpc_part_deref(part);
0717 
0718     return setup;
0719 }
0720 
0721 /*
0722  * The following macro is to be used for the setting of the reason and
0723  * reason_line fields in both the struct xpc_channel and struct xpc_partition
0724  * structures.
0725  */
0726 #define XPC_SET_REASON(_p, _reason, _line) \
0727     { \
0728         (_p)->reason = _reason; \
0729         (_p)->reason_line = _line; \
0730     }
0731 
0732 #endif /* _DRIVERS_MISC_SGIXP_XPC_H */