home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-ia64 / sn / xpc.h < prev   
Encoding:
C/C++ Source or Header  |  2006-08-11  |  41.2 KB  |  1,258 lines

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (c) 2004-2006 Silicon Graphics, Inc.  All Rights Reserved.
  7.  */
  8.  
  9.  
  10. /*
  11.  * Cross Partition Communication (XPC) structures and macros.
  12.  */
  13.  
  14. #ifndef _ASM_IA64_SN_XPC_H
  15. #define _ASM_IA64_SN_XPC_H
  16.  
  17.  
  18. #include <linux/interrupt.h>
  19. #include <linux/sysctl.h>
  20. #include <linux/device.h>
  21. #include <linux/mutex.h>
  22. #include <linux/completion.h>
  23. #include <asm/pgtable.h>
  24. #include <asm/processor.h>
  25. #include <asm/sn/bte.h>
  26. #include <asm/sn/clksupport.h>
  27. #include <asm/sn/addrs.h>
  28. #include <asm/sn/mspec.h>
  29. #include <asm/sn/shub_mmr.h>
  30. #include <asm/sn/xp.h>
  31.  
  32.  
  33. /*
  34.  * XPC Version numbers consist of a major and minor number. XPC can always
  35.  * talk to versions with same major #, and never talk to versions with a
  36.  * different major #.
  37.  */
  38. #define _XPC_VERSION(_maj, _min)    (((_maj) << 4) | ((_min) & 0xf))
  39. #define XPC_VERSION_MAJOR(_v)        ((_v) >> 4)
  40. #define XPC_VERSION_MINOR(_v)        ((_v) & 0xf)
  41.  
  42.  
  43. /*
  44.  * The next macros define word or bit representations for given
  45.  * C-brick nasid in either the SAL provided bit array representing
  46.  * nasids in the partition/machine or the AMO_t array used for
  47.  * inter-partition initiation communications.
  48.  *
  49.  * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
  50.  * such, some space will be saved by insisting that nasid information
  51.  * passed from SAL always be packed for C-Bricks and the
  52.  * cross-partition interrupts use the same packing scheme.
  53.  */
  54. #define XPC_NASID_W_INDEX(_n)    (((_n) / 64) / 2)
  55. #define XPC_NASID_B_INDEX(_n)    (((_n) / 2) & (64 - 1))
  56. #define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
  57.                     (1UL << XPC_NASID_B_INDEX(_n)))
  58. #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
  59.  
  60. #define XPC_HB_DEFAULT_INTERVAL        5    /* incr HB every x secs */
  61. #define XPC_HB_CHECK_DEFAULT_INTERVAL    20    /* check HB every x secs */
  62.  
  63. /* define the process name of HB checker and the CPU it is pinned to */
  64. #define XPC_HB_CHECK_THREAD_NAME    "xpc_hb"
  65. #define XPC_HB_CHECK_CPU        0
  66.  
  67. /* define the process name of the discovery thread */
  68. #define XPC_DISCOVERY_THREAD_NAME    "xpc_discovery"
  69.  
  70.  
  71. /*
  72.  * the reserved page
  73.  *
  74.  *   SAL reserves one page of memory per partition for XPC. Though a full page
  75.  *   in length (16384 bytes), its starting address is not page aligned, but it
  76.  *   is cacheline aligned. The reserved page consists of the following:
  77.  *
  78.  *   reserved page header
  79.  *
  80.  *     The first cacheline of the reserved page contains the header
  81.  *     (struct xpc_rsvd_page). Before SAL initialization has completed,
  82.  *     SAL has set up the following fields of the reserved page header:
  83.  *     SAL_signature, SAL_version, partid, and nasids_size. The other
  84.  *     fields are set up by XPC. (xpc_rsvd_page points to the local
  85.  *     partition's reserved page.)
  86.  *
  87.  *   part_nasids mask
  88.  *   mach_nasids mask
  89.  *
  90.  *     SAL also sets up two bitmaps (or masks), one that reflects the actual
  91.  *     nasids in this partition (part_nasids), and the other that reflects
  92.  *     the actual nasids in the entire machine (mach_nasids). We're only
  93.  *     interested in the even numbered nasids (which contain the processors
  94.  *     and/or memory), so we only need half as many bits to represent the
  95.  *     nasids. The part_nasids mask is located starting at the first cacheline
  96.  *     following the reserved page header. The mach_nasids mask follows right
  97.  *     after the part_nasids mask. The size in bytes of each mask is reflected
  98.  *     by the reserved page header field 'nasids_size'. (Local partition's
  99.  *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
  100.  *
  101.  *   vars
  102.  *   vars part
  103.  *
  104.  *     Immediately following the mach_nasids mask are the XPC variables
  105.  *     required by other partitions. First are those that are generic to all
  106.  *     partitions (vars), followed on the next available cacheline by those
  107.  *     which are partition specific (vars part). These are setup by XPC.
  108.  *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
  109.  *
  110.  * Note: Until vars_pa is set, the partition XPC code has not been initialized.
  111.  */
  112. struct xpc_rsvd_page {
  113.     u64 SAL_signature;    /* SAL: unique signature */
  114.     u64 SAL_version;    /* SAL: version */
  115.     u8 partid;        /* SAL: partition ID */
  116.     u8 version;
  117.     u8 pad1[6];        /* align to next u64 in cacheline */
  118.     volatile u64 vars_pa;
  119.     struct timespec stamp;    /* time when reserved page was setup by XPC */
  120.     u64 pad2[9];        /* align to last u64 in cacheline */
  121.     u64 nasids_size;    /* SAL: size of each nasid mask in bytes */
  122. };
  123.  
  124. #define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */
  125.  
  126. #define XPC_SUPPORTS_RP_STAMP(_version) \
  127.             (_version >= _XPC_VERSION(1,1))
  128.  
  129. /*
  130.  * compare stamps - the return value is:
  131.  *
  132.  *    < 0,    if stamp1 < stamp2
  133.  *    = 0,    if stamp1 == stamp2
  134.  *    > 0,    if stamp1 > stamp2
  135.  */
  136. static inline int
  137. xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
  138. {
  139.     int ret;
  140.  
  141.  
  142.     if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) {
  143.         ret = stamp1->tv_nsec - stamp2->tv_nsec;
  144.     }
  145.     return ret;
  146. }
  147.  
  148.  
  149. /*
  150.  * Define the structures by which XPC variables can be exported to other
  151.  * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
  152.  */
  153.  
  154. /*
  155.  * The following structure describes the partition generic variables
  156.  * needed by other partitions in order to properly initialize.
  157.  *
  158.  * struct xpc_vars version number also applies to struct xpc_vars_part.
  159.  * Changes to either structure and/or related functionality should be
  160.  * reflected by incrementing either the major or minor version numbers
  161.  * of struct xpc_vars.
  162.  */
  163. struct xpc_vars {
  164.     u8 version;
  165.     u64 heartbeat;
  166.     u64 heartbeating_to_mask;
  167.     u64 heartbeat_offline;    /* if 0, heartbeat should be changing */
  168.     int act_nasid;
  169.     int act_phys_cpuid;
  170.     u64 vars_part_pa;
  171.     u64 amos_page_pa;    /* paddr of page of AMOs from MSPEC driver */
  172.     AMO_t *amos_page;    /* vaddr of page of AMOs from MSPEC driver */
  173. };
  174.  
  175. #define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */
  176.  
  177. #define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
  178.             (_version >= _XPC_VERSION(3,1))
  179.  
  180.  
  181. static inline int
  182. xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
  183. {
  184.     return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
  185. }
  186.  
  187. static inline void
  188. xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
  189. {
  190.     u64 old_mask, new_mask;
  191.  
  192.     do {
  193.         old_mask = vars->heartbeating_to_mask;
  194.         new_mask = (old_mask | (1UL << partid));
  195.     } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
  196.                             old_mask);
  197. }
  198.  
  199. static inline void
  200. xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
  201. {
  202.     u64 old_mask, new_mask;
  203.  
  204.     do {
  205.         old_mask = vars->heartbeating_to_mask;
  206.         new_mask = (old_mask & ~(1UL << partid));
  207.     } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
  208.                             old_mask);
  209. }
  210.  
  211.  
  212. /*
  213.  * The AMOs page consists of a number of AMO variables which are divided into
  214.  * four groups, The first two groups are used to identify an IRQ's sender.
  215.  * These two groups consist of 64 and 128 AMO variables respectively. The last
  216.  * two groups, consisting of just one AMO variable each, are used to identify
  217.  * the remote partitions that are currently engaged (from the viewpoint of
  218.  * the XPC running on the remote partition).
  219.  */
  220. #define XPC_NOTIFY_IRQ_AMOS       0
  221. #define XPC_ACTIVATE_IRQ_AMOS       (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
  222. #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
  223. #define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
  224.  
  225.  
  226. /*
  227.  * The following structure describes the per partition specific variables.
  228.  *
  229.  * An array of these structures, one per partition, will be defined. As a
  230.  * partition becomes active XPC will copy the array entry corresponding to
  231.  * itself from that partition. It is desirable that the size of this
  232.  * structure evenly divide into a cacheline, such that none of the entries
  233.  * in this array crosses a cacheline boundary. As it is now, each entry
  234.  * occupies half a cacheline.
  235.  */
  236. struct xpc_vars_part {
  237.     volatile u64 magic;
  238.  
  239.     u64 openclose_args_pa;    /* physical address of open and close args */
  240.     u64 GPs_pa;        /* physical address of Get/Put values */
  241.  
  242.     u64 IPI_amo_pa;        /* physical address of IPI AMO_t structure */
  243.     int IPI_nasid;        /* nasid of where to send IPIs */
  244.     int IPI_phys_cpuid;    /* physical CPU ID of where to send IPIs */
  245.  
  246.     u8 nchannels;        /* #of defined channels supported */
  247.  
  248.     u8 reserved[23];    /* pad to a full 64 bytes */
  249. };
  250.  
  251. /*
  252.  * The vars_part MAGIC numbers play a part in the first contact protocol.
  253.  *
  254.  * MAGIC1 indicates that the per partition specific variables for a remote
  255.  * partition have been initialized by this partition.
  256.  *
  257.  * MAGIC2 indicates that this partition has pulled the remote partititions
  258.  * per partition variables that pertain to this partition.
  259.  */
  260. #define XPC_VP_MAGIC1    0x0053524156435058L  /* 'XPCVARS\0'L (little endian) */
  261. #define XPC_VP_MAGIC2    0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
  262.  
  263.  
  264. /* the reserved page sizes and offsets */
  265.  
  266. #define XPC_RP_HEADER_SIZE    L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
  267. #define XPC_RP_VARS_SIZE     L1_CACHE_ALIGN(sizeof(struct xpc_vars))
  268.  
  269. #define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE)
  270. #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
  271. #define XPC_RP_VARS(_rp)    ((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words)
  272. #define XPC_RP_VARS_PART(_rp)    (struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE)
  273.  
  274.  
  275. /*
  276.  * Functions registered by add_timer() or called by kernel_thread() only
  277.  * allow for a single 64-bit argument. The following macros can be used to
  278.  * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
  279.  * the passed argument.
  280.  */
  281. #define XPC_PACK_ARGS(_arg1, _arg2) \
  282.             ((((u64) _arg1) & 0xffffffff) | \
  283.             ((((u64) _arg2) & 0xffffffff) << 32))
  284.  
  285. #define XPC_UNPACK_ARG1(_args)    (((u64) _args) & 0xffffffff)
  286. #define XPC_UNPACK_ARG2(_args)    ((((u64) _args) >> 32) & 0xffffffff)
  287.  
  288.  
  289.  
  290. /*
  291.  * Define a Get/Put value pair (pointers) used with a message queue.
  292.  */
  293. struct xpc_gp {
  294.     volatile s64 get;    /* Get value */
  295.     volatile s64 put;    /* Put value */
  296. };
  297.  
  298. #define XPC_GP_SIZE \
  299.         L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
  300.  
  301.  
  302.  
  303. /*
  304.  * Define a structure that contains arguments associated with opening and
  305.  * closing a channel.
  306.  */
  307. struct xpc_openclose_args {
  308.     u16 reason;        /* reason why channel is closing */
  309.     u16 msg_size;        /* sizeof each message entry */
  310.     u16 remote_nentries;    /* #of message entries in remote msg queue */
  311.     u16 local_nentries;    /* #of message entries in local msg queue */
  312.     u64 local_msgqueue_pa;    /* physical address of local message queue */
  313. };
  314.  
  315. #define XPC_OPENCLOSE_ARGS_SIZE \
  316.           L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
  317.  
  318.  
  319.  
  320. /* struct xpc_msg flags */
  321.  
  322. #define    XPC_M_DONE        0x01    /* msg has been received/consumed */
  323. #define    XPC_M_READY        0x02    /* msg is ready to be sent */
  324. #define    XPC_M_INTERRUPT        0x04    /* send interrupt when msg consumed */
  325.  
  326.  
  327. #define XPC_MSG_ADDRESS(_payload) \
  328.         ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
  329.  
  330.  
  331.  
  332. /*
  333.  * Defines notify entry.
  334.  *
  335.  * This is used to notify a message's sender that their message was received
  336.  * and consumed by the intended recipient.
  337.  */
  338. struct xpc_notify {
  339.     volatile u8 type;        /* type of notification */
  340.  
  341.     /* the following two fields are only used if type == XPC_N_CALL */
  342.     xpc_notify_func func;        /* user's notify function */
  343.     void *key;            /* pointer to user's key */
  344. };
  345.  
  346. /* struct xpc_notify type of notification */
  347.  
  348. #define    XPC_N_CALL        0x01    /* notify function provided by user */
  349.  
  350.  
  351.  
  352. /*
  353.  * Define the structure that manages all the stuff required by a channel. In
  354.  * particular, they are used to manage the messages sent across the channel.
  355.  *
  356.  * This structure is private to a partition, and is NOT shared across the
  357.  * partition boundary.
  358.  *
  359.  * There is an array of these structures for each remote partition. It is
  360.  * allocated at the time a partition becomes active. The array contains one
  361.  * of these structures for each potential channel connection to that partition.
  362.  *
  363.  * Each of these structures manages two message queues (circular buffers).
  364.  * They are allocated at the time a channel connection is made. One of
  365.  * these message queues (local_msgqueue) holds the locally created messages
  366.  * that are destined for the remote partition. The other of these message
  367.  * queues (remote_msgqueue) is a locally cached copy of the remote partition's
  368.  * own local_msgqueue.
  369.  *
  370.  * The following is a description of the Get/Put pointers used to manage these
  371.  * two message queues. Consider the local_msgqueue to be on one partition
  372.  * and the remote_msgqueue to be its cached copy on another partition. A
  373.  * description of what each of the lettered areas contains is included.
  374.  *
  375.  *
  376.  *                     local_msgqueue      remote_msgqueue
  377.  *
  378.  *                        |/////////|      |/////////|
  379.  *    w_remote_GP.get --> +---------+      |/////////|
  380.  *                        |    F    |      |/////////|
  381.  *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
  382.  *                        |         |      |         |
  383.  *                        |         |      |    E    |
  384.  *                        |         |      |         |
  385.  *                        |         |      +---------+ <-- w_local_GP.get
  386.  *                        |    B    |      |/////////|
  387.  *                        |         |      |////D////|
  388.  *                        |         |      |/////////|
  389.  *                        |         |      +---------+ <-- w_remote_GP.put
  390.  *                        |         |      |////C////|
  391.  *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
  392.  *                        |         |      |/////////|
  393.  *                        |    A    |      |/////////|
  394.  *                        |         |      |/////////|
  395.  *     w_local_GP.put --> +---------+      |/////////|
  396.  *                        |/////////|      |/////////|
  397.  *
  398.  *
  399.  *        ( remote_GP.[get|put] are cached copies of the remote
  400.  *          partition's local_GP->[get|put], and thus their values can
  401.  *          lag behind their counterparts on the remote partition. )
  402.  *
  403.  *
  404.  *  A - Messages that have been allocated, but have not yet been sent to the
  405.  *    remote partition.
  406.  *
  407.  *  B - Messages that have been sent, but have not yet been acknowledged by the
  408.  *      remote partition as having been received.
  409.  *
  410.  *  C - Area that needs to be prepared for the copying of sent messages, by
  411.  *    the clearing of the message flags of any previously received messages.
  412.  *
  413.  *  D - Area into which sent messages are to be copied from the remote
  414.  *    partition's local_msgqueue and then delivered to their intended
  415.  *    recipients. [ To allow for a multi-message copy, another pointer
  416.  *    (next_msg_to_pull) has been added to keep track of the next message
  417.  *    number needing to be copied (pulled). It chases after w_remote_GP.put.
  418.  *    Any messages lying between w_local_GP.get and next_msg_to_pull have
  419.  *    been copied and are ready to be delivered. ]
  420.  *
  421.  *  E - Messages that have been copied and delivered, but have not yet been
  422.  *    acknowledged by the recipient as having been received.
  423.  *
  424.  *  F - Messages that have been acknowledged, but XPC has not yet notified the
  425.  *    sender that the message was received by its intended recipient.
  426.  *    This is also an area that needs to be prepared for the allocating of
  427.  *    new messages, by the clearing of the message flags of the acknowledged
  428.  *    messages.
  429.  */
  430. struct xpc_channel {
  431.     partid_t partid;        /* ID of remote partition connected */
  432.     spinlock_t lock;        /* lock for updating this structure */
  433.     u32 flags;            /* general flags */
  434.  
  435.     enum xpc_retval reason;        /* reason why channel is disconnect'g */
  436.     int reason_line;        /* line# disconnect initiated from */
  437.  
  438.     u16 number;            /* channel # */
  439.  
  440.     u16 msg_size;            /* sizeof each msg entry */
  441.     u16 local_nentries;        /* #of msg entries in local msg queue */
  442.     u16 remote_nentries;        /* #of msg entries in remote msg queue*/
  443.  
  444.     void *local_msgqueue_base;    /* base address of kmalloc'd space */
  445.     struct xpc_msg *local_msgqueue;    /* local message queue */
  446.     void *remote_msgqueue_base;    /* base address of kmalloc'd space */
  447.     struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */
  448.                     /* local message queue */
  449.     u64 remote_msgqueue_pa;        /* phys addr of remote partition's */
  450.                     /* local message queue */
  451.  
  452.     atomic_t references;        /* #of external references to queues */
  453.  
  454.     atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
  455.     wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
  456.  
  457.     u8 delayed_IPI_flags;        /* IPI flags received, but delayed */
  458.                     /* action until channel disconnected */
  459.  
  460.     /* queue of msg senders who want to be notified when msg received */
  461.  
  462.     atomic_t n_to_notify;        /* #of msg senders to notify */
  463.     struct xpc_notify *notify_queue;/* notify queue for messages sent */
  464.  
  465.     xpc_channel_func func;        /* user's channel function */
  466.     void *key;            /* pointer to user's key */
  467.  
  468.     struct mutex msg_to_pull_mutex;    /* next msg to pull serialization */
  469.     struct completion wdisconnect_wait; /* wait for channel disconnect */
  470.  
  471.     struct xpc_openclose_args *local_openclose_args; /* args passed on */
  472.                     /* opening or closing of channel */
  473.  
  474.     /* various flavors of local and remote Get/Put values */
  475.  
  476.     struct xpc_gp *local_GP;    /* local Get/Put values */
  477.     struct xpc_gp remote_GP;    /* remote Get/Put values */
  478.     struct xpc_gp w_local_GP;    /* working local Get/Put values */
  479.     struct xpc_gp w_remote_GP;    /* working remote Get/Put values */
  480.     s64 next_msg_to_pull;        /* Put value of next msg to pull */
  481.  
  482.     /* kthread management related fields */
  483.  
  484. // >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps
  485. // >>> allow the assigned limit be unbounded and let the idle limit be dynamic
  486. // >>> dependent on activity over the last interval of time
  487.     atomic_t kthreads_assigned;    /* #of kthreads assigned to channel */
  488.     u32 kthreads_assigned_limit;     /* limit on #of kthreads assigned */
  489.     atomic_t kthreads_idle;        /* #of kthreads idle waiting for work */
  490.     u32 kthreads_idle_limit;    /* limit on #of kthreads idle */
  491.     atomic_t kthreads_active;    /* #of kthreads actively working */
  492.     // >>> following field is temporary
  493.     u32 kthreads_created;        /* total #of kthreads created */
  494.  
  495.     wait_queue_head_t idle_wq;    /* idle kthread wait queue */
  496.  
  497. } ____cacheline_aligned;
  498.  
  499.  
  500. /* struct xpc_channel flags */
  501.  
  502. #define    XPC_C_WASCONNECTED    0x00000001 /* channel was connected */
  503.  
  504. #define    XPC_C_ROPENREPLY    0x00000002 /* remote open channel reply */
  505. #define    XPC_C_OPENREPLY        0x00000004 /* local open channel reply */
  506. #define    XPC_C_ROPENREQUEST    0x00000008 /* remote open channel request */
  507. #define    XPC_C_OPENREQUEST    0x00000010 /* local open channel request */
  508.  
  509. #define    XPC_C_SETUP        0x00000020 /* channel's msgqueues are alloc'd */
  510. #define    XPC_C_CONNECTEDCALLOUT    0x00000040 /* connected callout initiated */
  511. #define    XPC_C_CONNECTEDCALLOUT_MADE \
  512.                 0x00000080 /* connected callout completed */
  513. #define    XPC_C_CONNECTED        0x00000100 /* local channel is connected */
  514. #define    XPC_C_CONNECTING    0x00000200 /* channel is being connected */
  515.  
  516. #define    XPC_C_RCLOSEREPLY    0x00000400 /* remote close channel reply */
  517. #define    XPC_C_CLOSEREPLY    0x00000800 /* local close channel reply */
  518. #define    XPC_C_RCLOSEREQUEST    0x00001000 /* remote close channel request */
  519. #define    XPC_C_CLOSEREQUEST    0x00002000 /* local close channel request */
  520.  
  521. #define    XPC_C_DISCONNECTED    0x00004000 /* channel is disconnected */
  522. #define    XPC_C_DISCONNECTING    0x00008000 /* channel is being disconnected */
  523. #define    XPC_C_DISCONNECTINGCALLOUT \
  524.                 0x00010000 /* disconnecting callout initiated */
  525. #define    XPC_C_DISCONNECTINGCALLOUT_MADE \
  526.                 0x00020000 /* disconnecting callout completed */
  527. #define    XPC_C_WDISCONNECT    0x00040000 /* waiting for channel disconnect */
  528.  
  529.  
  530.  
  531. /*
  532.  * Manages channels on a partition basis. There is one of these structures
  533.  * for each partition (a partition will never utilize the structure that
  534.  * represents itself).
  535.  */
  536. struct xpc_partition {
  537.  
  538.     /* XPC HB infrastructure */
  539.  
  540.     u8 remote_rp_version;        /* version# of partition's rsvd pg */
  541.     struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */
  542.     u64 remote_rp_pa;        /* phys addr of partition's rsvd pg */
  543.     u64 remote_vars_pa;        /* phys addr of partition's vars */
  544.     u64 remote_vars_part_pa;    /* phys addr of partition's vars part */
  545.     u64 last_heartbeat;        /* HB at last read */
  546.     u64 remote_amos_page_pa;    /* phys addr of partition's amos page */
  547.     int remote_act_nasid;        /* active part's act/deact nasid */
  548.     int remote_act_phys_cpuid;    /* active part's act/deact phys cpuid */
  549.     u32 act_IRQ_rcvd;        /* IRQs since activation */
  550.     spinlock_t act_lock;        /* protect updating of act_state */
  551.     u8 act_state;            /* from XPC HB viewpoint */
  552.     u8 remote_vars_version;        /* version# of partition's vars */
  553.     enum xpc_retval reason;        /* reason partition is deactivating */
  554.     int reason_line;        /* line# deactivation initiated from */
  555.     int reactivate_nasid;        /* nasid in partition to reactivate */
  556.  
  557.     unsigned long disengage_request_timeout; /* timeout in jiffies */
  558.     struct timer_list disengage_request_timer;
  559.  
  560.  
  561.     /* XPC infrastructure referencing and teardown control */
  562.  
  563.     volatile u8 setup_state;    /* infrastructure setup state */
  564.     wait_queue_head_t teardown_wq;    /* kthread waiting to teardown infra */
  565.     atomic_t references;        /* #of references to infrastructure */
  566.  
  567.  
  568.     /*
  569.      * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
  570.      * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
  571.      * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
  572.      * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
  573.      */
  574.  
  575.  
  576.     u8 nchannels;           /* #of defined channels supported */
  577.     atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
  578.     atomic_t nchannels_engaged;/* #of channels engaged with remote part */
  579.     struct xpc_channel *channels;/* array of channel structures */
  580.  
  581.     void *local_GPs_base;      /* base address of kmalloc'd space */
  582.     struct xpc_gp *local_GPs; /* local Get/Put values */
  583.     void *remote_GPs_base;    /* base address of kmalloc'd space */
  584.     struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */
  585.                   /* values */
  586.     u64 remote_GPs_pa;      /* phys address of remote partition's local */
  587.                   /* Get/Put values */
  588.  
  589.  
  590.     /* fields used to pass args when opening or closing a channel */
  591.  
  592.     void *local_openclose_args_base;  /* base address of kmalloc'd space */
  593.     struct xpc_openclose_args *local_openclose_args;  /* local's args */
  594.     void *remote_openclose_args_base; /* base address of kmalloc'd space */
  595.     struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
  596.                       /* args */
  597.     u64 remote_openclose_args_pa;      /* phys addr of remote's args */
  598.  
  599.  
  600.     /* IPI sending, receiving and handling related fields */
  601.  
  602.     int remote_IPI_nasid;        /* nasid of where to send IPIs */
  603.     int remote_IPI_phys_cpuid;  /* phys CPU ID of where to send IPIs */
  604.     AMO_t *remote_IPI_amo_va;   /* address of remote IPI AMO_t structure */
  605.  
  606.     AMO_t *local_IPI_amo_va;    /* address of IPI AMO_t structure */
  607.     u64 local_IPI_amo;        /* IPI amo flags yet to be handled */
  608.     char IPI_owner[8];        /* IPI owner's name */
  609.     struct timer_list dropped_IPI_timer; /* dropped IPI timer */
  610.  
  611.     spinlock_t IPI_lock;        /* IPI handler lock */
  612.  
  613.  
  614.     /* channel manager related fields */
  615.  
  616.     atomic_t channel_mgr_requests;    /* #of requests to activate chan mgr */
  617.     wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
  618.  
  619. } ____cacheline_aligned;
  620.  
  621.  
  622. /* struct xpc_partition act_state values (for XPC HB) */
  623.  
  624. #define    XPC_P_INACTIVE        0x00    /* partition is not active */
  625. #define XPC_P_ACTIVATION_REQ    0x01    /* created thread to activate */
  626. #define XPC_P_ACTIVATING    0x02    /* activation thread started */
  627. #define XPC_P_ACTIVE        0x03    /* xpc_partition_up() was called */
  628. #define XPC_P_DEACTIVATING    0x04    /* partition deactivation initiated */
  629.  
  630.  
  631. #define XPC_DEACTIVATE_PARTITION(_p, _reason) \
  632.             xpc_deactivate_partition(__LINE__, (_p), (_reason))
  633.  
  634.  
  635. /* struct xpc_partition setup_state values */
  636.  
  637. #define XPC_P_UNSET        0x00    /* infrastructure was never setup */
  638. #define XPC_P_SETUP        0x01    /* infrastructure is setup */
  639. #define XPC_P_WTEARDOWN        0x02    /* waiting to teardown infrastructure */
  640. #define XPC_P_TORNDOWN        0x03    /* infrastructure is torndown */
  641.  
  642.  
  643.  
  644. /*
  645.  * struct xpc_partition IPI_timer #of seconds to wait before checking for
  646.  * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
  647.  * after the IPI was received.
  648.  */
  649. #define XPC_P_DROPPED_IPI_WAIT    (0.25 * HZ)
  650.  
  651.  
  652. /* number of seconds to wait for other partitions to disengage */
  653. #define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT    90
  654.  
  655. /* interval in seconds to print 'waiting disengagement' messages */
  656. #define XPC_DISENGAGE_PRINTMSG_INTERVAL        10
  657.  
  658.  
  659. #define XPC_PARTID(_p)    ((partid_t) ((_p) - &xpc_partitions[0]))
  660.  
  661.  
  662.  
  663. /* found in xp_main.c */
  664. extern struct xpc_registration xpc_registrations[];
  665.  
  666.  
  667. /* found in xpc_main.c */
  668. extern struct device *xpc_part;
  669. extern struct device *xpc_chan;
  670. extern int xpc_disengage_request_timelimit;
  671. extern int xpc_disengage_request_timedout;
  672. extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
  673. extern void xpc_dropped_IPI_check(struct xpc_partition *);
  674. extern void xpc_activate_partition(struct xpc_partition *);
  675. extern void xpc_activate_kthreads(struct xpc_channel *, int);
  676. extern void xpc_create_kthreads(struct xpc_channel *, int);
  677. extern void xpc_disconnect_wait(int);
  678.  
  679.  
  680. /* found in xpc_partition.c */
  681. extern int xpc_exiting;
  682. extern struct xpc_vars *xpc_vars;
  683. extern struct xpc_rsvd_page *xpc_rsvd_page;
  684. extern struct xpc_vars_part *xpc_vars_part;
  685. extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
  686. extern char xpc_remote_copy_buffer[];
  687. extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
  688. extern void xpc_allow_IPI_ops(void);
  689. extern void xpc_restrict_IPI_ops(void);
  690. extern int xpc_identify_act_IRQ_sender(void);
  691. extern int xpc_partition_disengaged(struct xpc_partition *);
  692. extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
  693. extern void xpc_mark_partition_inactive(struct xpc_partition *);
  694. extern void xpc_discovery(void);
  695. extern void xpc_check_remote_hb(void);
  696. extern void xpc_deactivate_partition(const int, struct xpc_partition *,
  697.                         enum xpc_retval);
  698. extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
  699.  
  700.  
  701. /* found in xpc_channel.c */
  702. extern void xpc_initiate_connect(int);
  703. extern void xpc_initiate_disconnect(int);
  704. extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
  705. extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
  706. extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
  707.                         xpc_notify_func, void *);
  708. extern void xpc_initiate_received(partid_t, int, void *);
  709. extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
  710. extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
  711. extern void xpc_process_channel_activity(struct xpc_partition *);
  712. extern void xpc_connected_callout(struct xpc_channel *);
  713. extern void xpc_deliver_msg(struct xpc_channel *);
  714. extern void xpc_disconnect_channel(const int, struct xpc_channel *,
  715.                     enum xpc_retval, unsigned long *);
  716. extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
  717. extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
  718. extern void xpc_teardown_infrastructure(struct xpc_partition *);
  719.  
  720.  
  721.  
  722. static inline void
  723. xpc_wakeup_channel_mgr(struct xpc_partition *part)
  724. {
  725.     if (atomic_inc_return(&part->channel_mgr_requests) == 1) {
  726.         wake_up(&part->channel_mgr_wq);
  727.     }
  728. }
  729.  
  730.  
  731.  
  732. /*
  733.  * These next two inlines are used to keep us from tearing down a channel's
  734.  * msg queues while a thread may be referencing them.
  735.  */
  736. static inline void
  737. xpc_msgqueue_ref(struct xpc_channel *ch)
  738. {
  739.     atomic_inc(&ch->references);
  740. }
  741.  
  742. static inline void
  743. xpc_msgqueue_deref(struct xpc_channel *ch)
  744. {
  745.     s32 refs = atomic_dec_return(&ch->references);
  746.  
  747.     DBUG_ON(refs < 0);
  748.     if (refs == 0) {
  749.         xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
  750.     }
  751. }
  752.  
  753.  
  754.  
  755. #define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
  756.         xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
  757.  
  758.  
  759. /*
  760.  * These two inlines are used to keep us from tearing down a partition's
  761.  * setup infrastructure while a thread may be referencing it.
  762.  */
  763. static inline void
  764. xpc_part_deref(struct xpc_partition *part)
  765. {
  766.     s32 refs = atomic_dec_return(&part->references);
  767.  
  768.  
  769.     DBUG_ON(refs < 0);
  770.     if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {
  771.         wake_up(&part->teardown_wq);
  772.     }
  773. }
  774.  
  775. static inline int
  776. xpc_part_ref(struct xpc_partition *part)
  777. {
  778.     int setup;
  779.  
  780.  
  781.     atomic_inc(&part->references);
  782.     setup = (part->setup_state == XPC_P_SETUP);
  783.     if (!setup) {
  784.         xpc_part_deref(part);
  785.     }
  786.     return setup;
  787. }
  788.  
  789.  
  790.  
  791. /*
  792.  * The following macro is to be used for the setting of the reason and
  793.  * reason_line fields in both the struct xpc_channel and struct xpc_partition
  794.  * structures.
  795.  */
  796. #define XPC_SET_REASON(_p, _reason, _line) \
  797.     { \
  798.         (_p)->reason = _reason; \
  799.         (_p)->reason_line = _line; \
  800.     }
  801.  
  802.  
  803.  
  804. /*
  805.  * This next set of inlines are used to keep track of when a partition is
  806.  * potentially engaged in accessing memory belonging to another partition.
  807.  */
  808.  
  809. static inline void
  810. xpc_mark_partition_engaged(struct xpc_partition *part)
  811. {
  812.     unsigned long irq_flags;
  813.     AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
  814.                 (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
  815.  
  816.  
  817.     local_irq_save(irq_flags);
  818.  
  819.     /* set bit corresponding to our partid in remote partition's AMO */
  820.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
  821.                         (1UL << sn_partition_id));
  822.     /*
  823.      * We must always use the nofault function regardless of whether we
  824.      * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
  825.      * didn't, we'd never know that the other partition is down and would
  826.      * keep sending IPIs and AMOs to it until the heartbeat times out.
  827.      */
  828.     (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
  829.                 variable), xp_nofault_PIOR_target));
  830.  
  831.     local_irq_restore(irq_flags);
  832. }
  833.  
  834. static inline void
  835. xpc_mark_partition_disengaged(struct xpc_partition *part)
  836. {
  837.     unsigned long irq_flags;
  838.     AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
  839.                 (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
  840.  
  841.  
  842.     local_irq_save(irq_flags);
  843.  
  844.     /* clear bit corresponding to our partid in remote partition's AMO */
  845.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
  846.                         ~(1UL << sn_partition_id));
  847.     /*
  848.      * We must always use the nofault function regardless of whether we
  849.      * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
  850.      * didn't, we'd never know that the other partition is down and would
  851.      * keep sending IPIs and AMOs to it until the heartbeat times out.
  852.      */
  853.     (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
  854.                 variable), xp_nofault_PIOR_target));
  855.  
  856.     local_irq_restore(irq_flags);
  857. }
  858.  
  859. static inline void
  860. xpc_request_partition_disengage(struct xpc_partition *part)
  861. {
  862.     unsigned long irq_flags;
  863.     AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
  864.                 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
  865.  
  866.  
  867.     local_irq_save(irq_flags);
  868.  
  869.     /* set bit corresponding to our partid in remote partition's AMO */
  870.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
  871.                         (1UL << sn_partition_id));
  872.     /*
  873.      * We must always use the nofault function regardless of whether we
  874.      * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
  875.      * didn't, we'd never know that the other partition is down and would
  876.      * keep sending IPIs and AMOs to it until the heartbeat times out.
  877.      */
  878.     (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
  879.                 variable), xp_nofault_PIOR_target));
  880.  
  881.     local_irq_restore(irq_flags);
  882. }
  883.  
  884. static inline void
  885. xpc_cancel_partition_disengage_request(struct xpc_partition *part)
  886. {
  887.     unsigned long irq_flags;
  888.     AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
  889.                 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
  890.  
  891.  
  892.     local_irq_save(irq_flags);
  893.  
  894.     /* clear bit corresponding to our partid in remote partition's AMO */
  895.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
  896.                         ~(1UL << sn_partition_id));
  897.     /*
  898.      * We must always use the nofault function regardless of whether we
  899.      * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
  900.      * didn't, we'd never know that the other partition is down and would
  901.      * keep sending IPIs and AMOs to it until the heartbeat times out.
  902.      */
  903.     (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
  904.                 variable), xp_nofault_PIOR_target));
  905.  
  906.     local_irq_restore(irq_flags);
  907. }
  908.  
  909. static inline u64
  910. xpc_partition_engaged(u64 partid_mask)
  911. {
  912.     AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
  913.  
  914.  
  915.     /* return our partition's AMO variable ANDed with partid_mask */
  916.     return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
  917.                                 partid_mask);
  918. }
  919.  
  920. static inline u64
  921. xpc_partition_disengage_requested(u64 partid_mask)
  922. {
  923.     AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
  924.  
  925.  
  926.     /* return our partition's AMO variable ANDed with partid_mask */
  927.     return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
  928.                                 partid_mask);
  929. }
  930.  
  931. static inline void
  932. xpc_clear_partition_engaged(u64 partid_mask)
  933. {
  934.     AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
  935.  
  936.  
  937.     /* clear bit(s) based on partid_mask in our partition's AMO */
  938.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
  939.                                 ~partid_mask);
  940. }
  941.  
  942. static inline void
  943. xpc_clear_partition_disengage_request(u64 partid_mask)
  944. {
  945.     AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
  946.  
  947.  
  948.     /* clear bit(s) based on partid_mask in our partition's AMO */
  949.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
  950.                                 ~partid_mask);
  951. }
  952.  
  953.  
  954.  
  955. /*
  956.  * The following set of macros and inlines are used for the sending and
  957.  * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
  958.  * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
  959.  * the other that is associated with channel activity (SGI_XPC_NOTIFY).
  960.  */
  961.  
  962. static inline u64
  963. xpc_IPI_receive(AMO_t *amo)
  964. {
  965.     return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);
  966. }
  967.  
  968.  
  969. static inline enum xpc_retval
  970. xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
  971. {
  972.     int ret = 0;
  973.     unsigned long irq_flags;
  974.  
  975.  
  976.     local_irq_save(irq_flags);
  977.  
  978.     FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);
  979.     sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
  980.  
  981.     /*
  982.      * We must always use the nofault function regardless of whether we
  983.      * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
  984.      * didn't, we'd never know that the other partition is down and would
  985.      * keep sending IPIs and AMOs to it until the heartbeat times out.
  986.      */
  987.     ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
  988.                 xp_nofault_PIOR_target));
  989.  
  990.     local_irq_restore(irq_flags);
  991.  
  992.     return ((ret == 0) ? xpcSuccess : xpcPioReadError);
  993. }
  994.  
  995.  
  996. /*
  997.  * IPIs associated with SGI_XPC_ACTIVATE IRQ.
  998.  */
  999.  
  1000. /*
  1001.  * Flag the appropriate AMO variable and send an IPI to the specified node.
  1002.  */
  1003. static inline void
  1004. xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
  1005.             int to_phys_cpuid)
  1006. {
  1007.     int w_index = XPC_NASID_W_INDEX(from_nasid);
  1008.     int b_index = XPC_NASID_B_INDEX(from_nasid);
  1009.     AMO_t *amos = (AMO_t *) __va(amos_page_pa +
  1010.                 (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
  1011.  
  1012.  
  1013.     (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
  1014.                 to_phys_cpuid, SGI_XPC_ACTIVATE);
  1015. }
  1016.  
  1017. static inline void
  1018. xpc_IPI_send_activate(struct xpc_vars *vars)
  1019. {
  1020.     xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
  1021.                 vars->act_nasid, vars->act_phys_cpuid);
  1022. }
  1023.  
  1024. static inline void
  1025. xpc_IPI_send_activated(struct xpc_partition *part)
  1026. {
  1027.     xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
  1028.             part->remote_act_nasid, part->remote_act_phys_cpuid);
  1029. }
  1030.  
  1031. static inline void
  1032. xpc_IPI_send_reactivate(struct xpc_partition *part)
  1033. {
  1034.     xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
  1035.                 xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
  1036. }
  1037.  
  1038. static inline void
  1039. xpc_IPI_send_disengage(struct xpc_partition *part)
  1040. {
  1041.     xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
  1042.             part->remote_act_nasid, part->remote_act_phys_cpuid);
  1043. }
  1044.  
  1045.  
  1046. /*
  1047.  * IPIs associated with SGI_XPC_NOTIFY IRQ.
  1048.  */
  1049.  
  1050. /*
  1051.  * Send an IPI to the remote partition that is associated with the
  1052.  * specified channel.
  1053.  */
  1054. #define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
  1055.         xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
  1056.  
  1057. static inline void
  1058. xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
  1059.             unsigned long *irq_flags)
  1060. {
  1061.     struct xpc_partition *part = &xpc_partitions[ch->partid];
  1062.     enum xpc_retval ret;
  1063.  
  1064.  
  1065.     if (likely(part->act_state != XPC_P_DEACTIVATING)) {
  1066.         ret = xpc_IPI_send(part->remote_IPI_amo_va,
  1067.                     (u64) ipi_flag << (ch->number * 8),
  1068.                     part->remote_IPI_nasid,
  1069.                     part->remote_IPI_phys_cpuid,
  1070.                     SGI_XPC_NOTIFY);
  1071.         dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
  1072.             ipi_flag_string, ch->partid, ch->number, ret);
  1073.         if (unlikely(ret != xpcSuccess)) {
  1074.             if (irq_flags != NULL) {
  1075.                 spin_unlock_irqrestore(&ch->lock, *irq_flags);
  1076.             }
  1077.             XPC_DEACTIVATE_PARTITION(part, ret);
  1078.             if (irq_flags != NULL) {
  1079.                 spin_lock_irqsave(&ch->lock, *irq_flags);
  1080.             }
  1081.         }
  1082.     }
  1083. }
  1084.  
  1085.  
  1086. /*
  1087.  * Make it look like the remote partition, which is associated with the
  1088.  * specified channel, sent us an IPI. This faked IPI will be handled
  1089.  * by xpc_dropped_IPI_check().
  1090.  */
  1091. #define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
  1092.         xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
  1093.  
  1094. static inline void
  1095. xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
  1096.                 char *ipi_flag_string)
  1097. {
  1098.     struct xpc_partition *part = &xpc_partitions[ch->partid];
  1099.  
  1100.  
  1101.     FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),
  1102.             FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));
  1103.     dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
  1104.         ipi_flag_string, ch->partid, ch->number);
  1105. }
  1106.  
  1107.  
  1108. /*
  1109.  * The sending and receiving of IPIs includes the setting of an AMO variable
  1110.  * to indicate the reason the IPI was sent. The 64-bit variable is divided
  1111.  * up into eight bytes, ordered from right to left. Byte zero pertains to
  1112.  * channel 0, byte one to channel 1, and so on. Each byte is described by
  1113.  * the following IPI flags.
  1114.  */
  1115.  
  1116. #define    XPC_IPI_CLOSEREQUEST    0x01
  1117. #define    XPC_IPI_CLOSEREPLY    0x02
  1118. #define    XPC_IPI_OPENREQUEST    0x04
  1119. #define    XPC_IPI_OPENREPLY    0x08
  1120. #define    XPC_IPI_MSGREQUEST    0x10
  1121.  
  1122.  
  1123. /* given an AMO variable and a channel#, get its associated IPI flags */
  1124. #define XPC_GET_IPI_FLAGS(_amo, _c)    ((u8) (((_amo) >> ((_c) * 8)) & 0xff))
  1125. #define XPC_SET_IPI_FLAGS(_amo, _c, _f)    (_amo) |= ((u64) (_f) << ((_c) * 8))
  1126.  
  1127. #define    XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)
  1128. #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
  1129.  
  1130.  
  1131. static inline void
  1132. xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
  1133. {
  1134.     struct xpc_openclose_args *args = ch->local_openclose_args;
  1135.  
  1136.  
  1137.     args->reason = ch->reason;
  1138.  
  1139.     XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
  1140. }
  1141.  
  1142. static inline void
  1143. xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
  1144. {
  1145.     XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
  1146. }
  1147.  
  1148. static inline void
  1149. xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
  1150. {
  1151.     struct xpc_openclose_args *args = ch->local_openclose_args;
  1152.  
  1153.  
  1154.     args->msg_size = ch->msg_size;
  1155.     args->local_nentries = ch->local_nentries;
  1156.  
  1157.     XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
  1158. }
  1159.  
  1160. static inline void
  1161. xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
  1162. {
  1163.     struct xpc_openclose_args *args = ch->local_openclose_args;
  1164.  
  1165.  
  1166.     args->remote_nentries = ch->remote_nentries;
  1167.     args->local_nentries = ch->local_nentries;
  1168.     args->local_msgqueue_pa = __pa(ch->local_msgqueue);
  1169.  
  1170.     XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
  1171. }
  1172.  
  1173. static inline void
  1174. xpc_IPI_send_msgrequest(struct xpc_channel *ch)
  1175. {
  1176.     XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
  1177. }
  1178.  
  1179. static inline void
  1180. xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
  1181. {
  1182.     XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
  1183. }
  1184.  
  1185.  
  1186. /*
  1187.  * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
  1188.  * pages are located in the lowest granule. The lowest granule uses 4k pages
  1189.  * for cached references and an alternate TLB handler to never provide a
  1190.  * cacheable mapping for the entire region. This will prevent speculative
  1191.  * reading of cached copies of our lines from being issued which will cause
  1192.  * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
  1193.  * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
  1194.  * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
  1195.  * activation and 2 AMO variables for partition deactivation.
  1196.  */
  1197. static inline AMO_t *
  1198. xpc_IPI_init(int index)
  1199. {
  1200.     AMO_t *amo = xpc_vars->amos_page + index;
  1201.  
  1202.  
  1203.     (void) xpc_IPI_receive(amo);    /* clear AMO variable */
  1204.     return amo;
  1205. }
  1206.  
  1207.  
  1208.  
  1209. static inline enum xpc_retval
  1210. xpc_map_bte_errors(bte_result_t error)
  1211. {
  1212.     switch (error) {
  1213.     case BTE_SUCCESS:    return xpcSuccess;
  1214.     case BTEFAIL_DIR:    return xpcBteDirectoryError;
  1215.     case BTEFAIL_POISON:    return xpcBtePoisonError;
  1216.     case BTEFAIL_WERR:    return xpcBteWriteError;
  1217.     case BTEFAIL_ACCESS:    return xpcBteAccessError;
  1218.     case BTEFAIL_PWERR:    return xpcBtePWriteError;
  1219.     case BTEFAIL_PRERR:    return xpcBtePReadError;
  1220.     case BTEFAIL_TOUT:    return xpcBteTimeOutError;
  1221.     case BTEFAIL_XTERR:    return xpcBteXtalkError;
  1222.     case BTEFAIL_NOTAVAIL:    return xpcBteNotAvailable;
  1223.     default:        return xpcBteUnmappedError;
  1224.     }
  1225. }
  1226.  
  1227.  
  1228.  
  1229. /*
  1230.  * Check to see if there is any channel activity to/from the specified
  1231.  * partition.
  1232.  */
  1233. static inline void
  1234. xpc_check_for_channel_activity(struct xpc_partition *part)
  1235. {
  1236.     u64 IPI_amo;
  1237.     unsigned long irq_flags;
  1238.  
  1239.  
  1240.     IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
  1241.     if (IPI_amo == 0) {
  1242.         return;
  1243.     }
  1244.  
  1245.     spin_lock_irqsave(&part->IPI_lock, irq_flags);
  1246.     part->local_IPI_amo |= IPI_amo;
  1247.     spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
  1248.  
  1249.     dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
  1250.         XPC_PARTID(part), IPI_amo);
  1251.  
  1252.     xpc_wakeup_channel_mgr(part);
  1253. }
  1254.  
  1255.  
  1256. #endif /* _ASM_IA64_SN_XPC_H */
  1257.  
  1258.