linux/drivers/misc/sgi-xp/xpc_sn2.c
<<
>>
Prefs
   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) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
   7 */
   8
   9/*
  10 * Cross Partition Communication (XPC) sn2-based functions.
  11 *
  12 *     Architecture specific implementation of common functions.
  13 *
  14 */
  15
  16#include <linux/delay.h>
  17#include <asm/uncached.h>
  18#include <asm/sn/mspec.h>
  19#include <asm/sn/sn_sal.h>
  20#include "xpc.h"
  21
  22/*
  23 * Define the number of u64s required to represent all the C-brick nasids
  24 * as a bitmap.  The cross-partition kernel modules deal only with
  25 * C-brick nasids, thus the need for bitmaps which don't account for
  26 * odd-numbered (non C-brick) nasids.
  27 */
  28#define XPC_MAX_PHYSNODES_SN2   (MAX_NUMALINK_NODES / 2)
  29#define XP_NASID_MASK_BYTES_SN2 ((XPC_MAX_PHYSNODES_SN2 + 7) / 8)
  30#define XP_NASID_MASK_WORDS_SN2 ((XPC_MAX_PHYSNODES_SN2 + 63) / 64)
  31
  32/*
  33 * Memory for XPC's amo variables is allocated by the MSPEC driver. These
  34 * pages are located in the lowest granule. The lowest granule uses 4k pages
  35 * for cached references and an alternate TLB handler to never provide a
  36 * cacheable mapping for the entire region. This will prevent speculative
  37 * reading of cached copies of our lines from being issued which will cause
  38 * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
  39 * amo variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of
  40 * NOTIFY IRQs, 128 amo variables (based on XP_NASID_MASK_WORDS_SN2) to identify
  41 * the senders of ACTIVATE IRQs, 1 amo variable to identify which remote
  42 * partitions (i.e., XPCs) consider themselves currently engaged with the
  43 * local XPC and 1 amo variable to request partition deactivation.
  44 */
  45#define XPC_NOTIFY_IRQ_AMOS_SN2         0
  46#define XPC_ACTIVATE_IRQ_AMOS_SN2       (XPC_NOTIFY_IRQ_AMOS_SN2 + \
  47                                         XP_MAX_NPARTITIONS_SN2)
  48#define XPC_ENGAGED_PARTITIONS_AMO_SN2  (XPC_ACTIVATE_IRQ_AMOS_SN2 + \
  49                                         XP_NASID_MASK_WORDS_SN2)
  50#define XPC_DEACTIVATE_REQUEST_AMO_SN2  (XPC_ENGAGED_PARTITIONS_AMO_SN2 + 1)
  51
  52/*
  53 * Buffer used to store a local copy of portions of a remote partition's
  54 * reserved page (either its header and part_nasids mask, or its vars).
  55 */
  56static void *xpc_remote_copy_buffer_base_sn2;
  57static char *xpc_remote_copy_buffer_sn2;
  58
  59static struct xpc_vars_sn2 *xpc_vars_sn2;
  60static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
  61
  62static int
  63xpc_setup_partitions_sn2(void)
  64{
  65        /* nothing needs to be done */
  66        return 0;
  67}
  68
  69static void
  70xpc_teardown_partitions_sn2(void)
  71{
  72        /* nothing needs to be done */
  73}
  74
  75/* SH_IPI_ACCESS shub register value on startup */
  76static u64 xpc_sh1_IPI_access_sn2;
  77static u64 xpc_sh2_IPI_access0_sn2;
  78static u64 xpc_sh2_IPI_access1_sn2;
  79static u64 xpc_sh2_IPI_access2_sn2;
  80static u64 xpc_sh2_IPI_access3_sn2;
  81
  82/*
  83 * Change protections to allow IPI operations.
  84 */
  85static void
  86xpc_allow_IPI_ops_sn2(void)
  87{
  88        int node;
  89        int nasid;
  90
  91        /* !!! The following should get moved into SAL. */
  92        if (is_shub2()) {
  93                xpc_sh2_IPI_access0_sn2 =
  94                    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
  95                xpc_sh2_IPI_access1_sn2 =
  96                    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
  97                xpc_sh2_IPI_access2_sn2 =
  98                    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
  99                xpc_sh2_IPI_access3_sn2 =
 100                    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
 101
 102                for_each_online_node(node) {
 103                        nasid = cnodeid_to_nasid(node);
 104                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
 105                              -1UL);
 106                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
 107                              -1UL);
 108                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
 109                              -1UL);
 110                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
 111                              -1UL);
 112                }
 113        } else {
 114                xpc_sh1_IPI_access_sn2 =
 115                    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
 116
 117                for_each_online_node(node) {
 118                        nasid = cnodeid_to_nasid(node);
 119                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
 120                              -1UL);
 121                }
 122        }
 123}
 124
 125/*
 126 * Restrict protections to disallow IPI operations.
 127 */
 128static void
 129xpc_disallow_IPI_ops_sn2(void)
 130{
 131        int node;
 132        int nasid;
 133
 134        /* !!! The following should get moved into SAL. */
 135        if (is_shub2()) {
 136                for_each_online_node(node) {
 137                        nasid = cnodeid_to_nasid(node);
 138                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
 139                              xpc_sh2_IPI_access0_sn2);
 140                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
 141                              xpc_sh2_IPI_access1_sn2);
 142                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
 143                              xpc_sh2_IPI_access2_sn2);
 144                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
 145                              xpc_sh2_IPI_access3_sn2);
 146                }
 147        } else {
 148                for_each_online_node(node) {
 149                        nasid = cnodeid_to_nasid(node);
 150                        HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
 151                              xpc_sh1_IPI_access_sn2);
 152                }
 153        }
 154}
 155
 156/*
 157 * The following set of functions are used for the sending and receiving of
 158 * IRQs (also known as IPIs). There are two flavors of IRQs, one that is
 159 * associated with partition activity (SGI_XPC_ACTIVATE) and the other that
 160 * is associated with channel activity (SGI_XPC_NOTIFY).
 161 */
 162
 163static u64
 164xpc_receive_IRQ_amo_sn2(struct amo *amo)
 165{
 166        return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
 167}
 168
 169static enum xp_retval
 170xpc_send_IRQ_sn2(struct amo *amo, u64 flag, int nasid, int phys_cpuid,
 171                 int vector)
 172{
 173        int ret = 0;
 174        unsigned long irq_flags;
 175
 176        local_irq_save(irq_flags);
 177
 178        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
 179        sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
 180
 181        /*
 182         * We must always use the nofault function regardless of whether we
 183         * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 184         * didn't, we'd never know that the other partition is down and would
 185         * keep sending IRQs and amos to it until the heartbeat times out.
 186         */
 187        ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
 188                                                     xp_nofault_PIOR_target));
 189
 190        local_irq_restore(irq_flags);
 191
 192        return (ret == 0) ? xpSuccess : xpPioReadError;
 193}
 194
 195static struct amo *
 196xpc_init_IRQ_amo_sn2(int index)
 197{
 198        struct amo *amo = xpc_vars_sn2->amos_page + index;
 199
 200        (void)xpc_receive_IRQ_amo_sn2(amo);     /* clear amo variable */
 201        return amo;
 202}
 203
 204/*
 205 * Functions associated with SGI_XPC_ACTIVATE IRQ.
 206 */
 207
 208/*
 209 * Notify the heartbeat check thread that an activate IRQ has been received.
 210 */
 211static irqreturn_t
 212xpc_handle_activate_IRQ_sn2(int irq, void *dev_id)
 213{
 214        unsigned long irq_flags;
 215
 216        spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 217        xpc_activate_IRQ_rcvd++;
 218        spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 219
 220        wake_up_interruptible(&xpc_activate_IRQ_wq);
 221        return IRQ_HANDLED;
 222}
 223
 224/*
 225 * Flag the appropriate amo variable and send an IRQ to the specified node.
 226 */
 227static void
 228xpc_send_activate_IRQ_sn2(unsigned long amos_page_pa, int from_nasid,
 229                          int to_nasid, int to_phys_cpuid)
 230{
 231        struct amo *amos = (struct amo *)__va(amos_page_pa +
 232                                              (XPC_ACTIVATE_IRQ_AMOS_SN2 *
 233                                              sizeof(struct amo)));
 234
 235        (void)xpc_send_IRQ_sn2(&amos[BIT_WORD(from_nasid / 2)],
 236                               BIT_MASK(from_nasid / 2), to_nasid,
 237                               to_phys_cpuid, SGI_XPC_ACTIVATE);
 238}
 239
 240static void
 241xpc_send_local_activate_IRQ_sn2(int from_nasid)
 242{
 243        unsigned long irq_flags;
 244        struct amo *amos = (struct amo *)__va(xpc_vars_sn2->amos_page_pa +
 245                                              (XPC_ACTIVATE_IRQ_AMOS_SN2 *
 246                                              sizeof(struct amo)));
 247
 248        /* fake the sending and receipt of an activate IRQ from remote nasid */
 249        FETCHOP_STORE_OP(TO_AMO((u64)&amos[BIT_WORD(from_nasid / 2)].variable),
 250                         FETCHOP_OR, BIT_MASK(from_nasid / 2));
 251
 252        spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 253        xpc_activate_IRQ_rcvd++;
 254        spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 255
 256        wake_up_interruptible(&xpc_activate_IRQ_wq);
 257}
 258
 259/*
 260 * Functions associated with SGI_XPC_NOTIFY IRQ.
 261 */
 262
 263/*
 264 * Check to see if any chctl flags were sent from the specified partition.
 265 */
 266static void
 267xpc_check_for_sent_chctl_flags_sn2(struct xpc_partition *part)
 268{
 269        union xpc_channel_ctl_flags chctl;
 270        unsigned long irq_flags;
 271
 272        chctl.all_flags = xpc_receive_IRQ_amo_sn2(part->sn.sn2.
 273                                                  local_chctl_amo_va);
 274        if (chctl.all_flags == 0)
 275                return;
 276
 277        spin_lock_irqsave(&part->chctl_lock, irq_flags);
 278        part->chctl.all_flags |= chctl.all_flags;
 279        spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
 280
 281        dev_dbg(xpc_chan, "received notify IRQ from partid=%d, chctl.all_flags="
 282                "0x%llx\n", XPC_PARTID(part), chctl.all_flags);
 283
 284        xpc_wakeup_channel_mgr(part);
 285}
 286
 287/*
 288 * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
 289 * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
 290 * than one partition, we use an amo structure per partition to indicate
 291 * whether a partition has sent an IRQ or not.  If it has, then wake up the
 292 * associated kthread to handle it.
 293 *
 294 * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IRQs sent by XPC
 295 * running on other partitions.
 296 *
 297 * Noteworthy Arguments:
 298 *
 299 *      irq - Interrupt ReQuest number. NOT USED.
 300 *
 301 *      dev_id - partid of IRQ's potential sender.
 302 */
 303static irqreturn_t
 304xpc_handle_notify_IRQ_sn2(int irq, void *dev_id)
 305{
 306        short partid = (short)(u64)dev_id;
 307        struct xpc_partition *part = &xpc_partitions[partid];
 308
 309        DBUG_ON(partid < 0 || partid >= XP_MAX_NPARTITIONS_SN2);
 310
 311        if (xpc_part_ref(part)) {
 312                xpc_check_for_sent_chctl_flags_sn2(part);
 313
 314                xpc_part_deref(part);
 315        }
 316        return IRQ_HANDLED;
 317}
 318
 319/*
 320 * Check to see if xpc_handle_notify_IRQ_sn2() dropped any IRQs on the floor
 321 * because the write to their associated amo variable completed after the IRQ
 322 * was received.
 323 */
 324static void
 325xpc_check_for_dropped_notify_IRQ_sn2(struct xpc_partition *part)
 326{
 327        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 328
 329        if (xpc_part_ref(part)) {
 330                xpc_check_for_sent_chctl_flags_sn2(part);
 331
 332                part_sn2->dropped_notify_IRQ_timer.expires = jiffies +
 333                    XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
 334                add_timer(&part_sn2->dropped_notify_IRQ_timer);
 335                xpc_part_deref(part);
 336        }
 337}
 338
 339/*
 340 * Send a notify IRQ to the remote partition that is associated with the
 341 * specified channel.
 342 */
 343static void
 344xpc_send_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
 345                        char *chctl_flag_string, unsigned long *irq_flags)
 346{
 347        struct xpc_partition *part = &xpc_partitions[ch->partid];
 348        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 349        union xpc_channel_ctl_flags chctl = { 0 };
 350        enum xp_retval ret;
 351
 352        if (likely(part->act_state != XPC_P_AS_DEACTIVATING)) {
 353                chctl.flags[ch->number] = chctl_flag;
 354                ret = xpc_send_IRQ_sn2(part_sn2->remote_chctl_amo_va,
 355                                       chctl.all_flags,
 356                                       part_sn2->notify_IRQ_nasid,
 357                                       part_sn2->notify_IRQ_phys_cpuid,
 358                                       SGI_XPC_NOTIFY);
 359                dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
 360                        chctl_flag_string, ch->partid, ch->number, ret);
 361                if (unlikely(ret != xpSuccess)) {
 362                        if (irq_flags != NULL)
 363                                spin_unlock_irqrestore(&ch->lock, *irq_flags);
 364                        XPC_DEACTIVATE_PARTITION(part, ret);
 365                        if (irq_flags != NULL)
 366                                spin_lock_irqsave(&ch->lock, *irq_flags);
 367                }
 368        }
 369}
 370
 371#define XPC_SEND_NOTIFY_IRQ_SN2(_ch, _ipi_f, _irq_f) \
 372                xpc_send_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
 373
 374/*
 375 * Make it look like the remote partition, which is associated with the
 376 * specified channel, sent us a notify IRQ. This faked IRQ will be handled
 377 * by xpc_check_for_dropped_notify_IRQ_sn2().
 378 */
 379static void
 380xpc_send_local_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
 381                              char *chctl_flag_string)
 382{
 383        struct xpc_partition *part = &xpc_partitions[ch->partid];
 384        union xpc_channel_ctl_flags chctl = { 0 };
 385
 386        chctl.flags[ch->number] = chctl_flag;
 387        FETCHOP_STORE_OP(TO_AMO((u64)&part->sn.sn2.local_chctl_amo_va->
 388                                variable), FETCHOP_OR, chctl.all_flags);
 389        dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
 390                chctl_flag_string, ch->partid, ch->number);
 391}
 392
 393#define XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(_ch, _ipi_f) \
 394                xpc_send_local_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f)
 395
 396static void
 397xpc_send_chctl_closerequest_sn2(struct xpc_channel *ch,
 398                                unsigned long *irq_flags)
 399{
 400        struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 401
 402        args->reason = ch->reason;
 403        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREQUEST, irq_flags);
 404}
 405
 406static void
 407xpc_send_chctl_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 408{
 409        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREPLY, irq_flags);
 410}
 411
 412static void
 413xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 414{
 415        struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 416
 417        args->entry_size = ch->entry_size;
 418        args->local_nentries = ch->local_nentries;
 419        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREQUEST, irq_flags);
 420}
 421
 422static void
 423xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 424{
 425        struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 426
 427        args->remote_nentries = ch->remote_nentries;
 428        args->local_nentries = ch->local_nentries;
 429        args->local_msgqueue_pa = xp_pa(ch->sn.sn2.local_msgqueue);
 430        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREPLY, irq_flags);
 431}
 432
 433static void
 434xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch,
 435                                unsigned long *irq_flags)
 436{
 437        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags);
 438}
 439
 440static void
 441xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch)
 442{
 443        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL);
 444}
 445
 446static void
 447xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch)
 448{
 449        XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST);
 450}
 451
 452static enum xp_retval
 453xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch,
 454                                unsigned long msgqueue_pa)
 455{
 456        ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa;
 457        return xpSuccess;
 458}
 459
 460/*
 461 * This next set of functions are used to keep track of when a partition is
 462 * potentially engaged in accessing memory belonging to another partition.
 463 */
 464
 465static void
 466xpc_indicate_partition_engaged_sn2(struct xpc_partition *part)
 467{
 468        unsigned long irq_flags;
 469        struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
 470                                             (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
 471                                             sizeof(struct amo)));
 472
 473        local_irq_save(irq_flags);
 474
 475        /* set bit corresponding to our partid in remote partition's amo */
 476        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
 477                         BIT(sn_partition_id));
 478
 479        /*
 480         * We must always use the nofault function regardless of whether we
 481         * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 482         * didn't, we'd never know that the other partition is down and would
 483         * keep sending IRQs and amos to it until the heartbeat times out.
 484         */
 485        (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 486                                                               variable),
 487                                                     xp_nofault_PIOR_target));
 488
 489        local_irq_restore(irq_flags);
 490}
 491
 492static void
 493xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part)
 494{
 495        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 496        unsigned long irq_flags;
 497        struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
 498                                             (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
 499                                             sizeof(struct amo)));
 500
 501        local_irq_save(irq_flags);
 502
 503        /* clear bit corresponding to our partid in remote partition's amo */
 504        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 505                         ~BIT(sn_partition_id));
 506
 507        /*
 508         * We must always use the nofault function regardless of whether we
 509         * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 510         * didn't, we'd never know that the other partition is down and would
 511         * keep sending IRQs and amos to it until the heartbeat times out.
 512         */
 513        (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 514                                                               variable),
 515                                                     xp_nofault_PIOR_target));
 516
 517        local_irq_restore(irq_flags);
 518
 519        /*
 520         * Send activate IRQ to get other side to see that we've cleared our
 521         * bit in their engaged partitions amo.
 522         */
 523        xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
 524                                  cnodeid_to_nasid(0),
 525                                  part_sn2->activate_IRQ_nasid,
 526                                  part_sn2->activate_IRQ_phys_cpuid);
 527}
 528
 529static void
 530xpc_assume_partition_disengaged_sn2(short partid)
 531{
 532        struct amo *amo = xpc_vars_sn2->amos_page +
 533                          XPC_ENGAGED_PARTITIONS_AMO_SN2;
 534
 535        /* clear bit(s) based on partid mask in our partition's amo */
 536        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 537                         ~BIT(partid));
 538}
 539
 540static int
 541xpc_partition_engaged_sn2(short partid)
 542{
 543        struct amo *amo = xpc_vars_sn2->amos_page +
 544                          XPC_ENGAGED_PARTITIONS_AMO_SN2;
 545
 546        /* our partition's amo variable ANDed with partid mask */
 547        return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
 548                BIT(partid)) != 0;
 549}
 550
 551static int
 552xpc_any_partition_engaged_sn2(void)
 553{
 554        struct amo *amo = xpc_vars_sn2->amos_page +
 555                          XPC_ENGAGED_PARTITIONS_AMO_SN2;
 556
 557        /* our partition's amo variable */
 558        return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0;
 559}
 560
 561/* original protection values for each node */
 562static u64 xpc_prot_vec_sn2[MAX_NUMNODES];
 563
 564/*
 565 * Change protections to allow amo operations on non-Shub 1.1 systems.
 566 */
 567static enum xp_retval
 568xpc_allow_amo_ops_sn2(struct amo *amos_page)
 569{
 570        enum xp_retval ret = xpSuccess;
 571
 572        /*
 573         * On SHUB 1.1, we cannot call sn_change_memprotect() since the BIST
 574         * collides with memory operations. On those systems we call
 575         * xpc_allow_amo_ops_shub_wars_1_1_sn2() instead.
 576         */
 577        if (!enable_shub_wars_1_1())
 578                ret = xp_expand_memprotect(ia64_tpa((u64)amos_page), PAGE_SIZE);
 579
 580        return ret;
 581}
 582
 583/*
 584 * Change protections to allow amo operations on Shub 1.1 systems.
 585 */
 586static void
 587xpc_allow_amo_ops_shub_wars_1_1_sn2(void)
 588{
 589        int node;
 590        int nasid;
 591
 592        if (!enable_shub_wars_1_1())
 593                return;
 594
 595        for_each_online_node(node) {
 596                nasid = cnodeid_to_nasid(node);
 597                /* save current protection values */
 598                xpc_prot_vec_sn2[node] =
 599                    (u64)HUB_L((u64 *)GLOBAL_MMR_ADDR(nasid,
 600                                                  SH1_MD_DQLP_MMR_DIR_PRIVEC0));
 601                /* open up everything */
 602                HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
 603                                             SH1_MD_DQLP_MMR_DIR_PRIVEC0),
 604                      -1UL);
 605                HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
 606                                             SH1_MD_DQRP_MMR_DIR_PRIVEC0),
 607                      -1UL);
 608        }
 609}
 610
 611static enum xp_retval
 612xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
 613                                   size_t *len)
 614{
 615        s64 status;
 616        enum xp_retval ret;
 617
 618        status = sn_partition_reserved_page_pa((u64)buf, cookie,
 619                        (u64 *)rp_pa, (u64 *)len);
 620        if (status == SALRET_OK)
 621                ret = xpSuccess;
 622        else if (status == SALRET_MORE_PASSES)
 623                ret = xpNeedMoreInfo;
 624        else
 625                ret = xpSalError;
 626
 627        return ret;
 628}
 629
 630
 631static int
 632xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp)
 633{
 634        struct amo *amos_page;
 635        int i;
 636        int ret;
 637
 638        xpc_vars_sn2 = XPC_RP_VARS(rp);
 639
 640        rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2);
 641
 642        /* vars_part array follows immediately after vars */
 643        xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
 644                                                         XPC_RP_VARS_SIZE);
 645
 646        /*
 647         * Before clearing xpc_vars_sn2, see if a page of amos had been
 648         * previously allocated. If not we'll need to allocate one and set
 649         * permissions so that cross-partition amos are allowed.
 650         *
 651         * The allocated amo page needs MCA reporting to remain disabled after
 652         * XPC has unloaded.  To make this work, we keep a copy of the pointer
 653         * to this page (i.e., amos_page) in the struct xpc_vars_sn2 structure,
 654         * which is pointed to by the reserved page, and re-use that saved copy
 655         * on subsequent loads of XPC. This amo page is never freed, and its
 656         * memory protections are never restricted.
 657         */
 658        amos_page = xpc_vars_sn2->amos_page;
 659        if (amos_page == NULL) {
 660                amos_page = (struct amo *)TO_AMO(uncached_alloc_page(0, 1));
 661                if (amos_page == NULL) {
 662                        dev_err(xpc_part, "can't allocate page of amos\n");
 663                        return -ENOMEM;
 664                }
 665
 666                /*
 667                 * Open up amo-R/W to cpu.  This is done on Shub 1.1 systems
 668                 * when xpc_allow_amo_ops_shub_wars_1_1_sn2() is called.
 669                 */
 670                ret = xpc_allow_amo_ops_sn2(amos_page);
 671                if (ret != xpSuccess) {
 672                        dev_err(xpc_part, "can't allow amo operations\n");
 673                        uncached_free_page(__IA64_UNCACHED_OFFSET |
 674                                           TO_PHYS((u64)amos_page), 1);
 675                        return -EPERM;
 676                }
 677        }
 678
 679        /* clear xpc_vars_sn2 */
 680        memset(xpc_vars_sn2, 0, sizeof(struct xpc_vars_sn2));
 681
 682        xpc_vars_sn2->version = XPC_V_VERSION;
 683        xpc_vars_sn2->activate_IRQ_nasid = cpuid_to_nasid(0);
 684        xpc_vars_sn2->activate_IRQ_phys_cpuid = cpu_physical_id(0);
 685        xpc_vars_sn2->vars_part_pa = xp_pa(xpc_vars_part_sn2);
 686        xpc_vars_sn2->amos_page_pa = ia64_tpa((u64)amos_page);
 687        xpc_vars_sn2->amos_page = amos_page;    /* save for next load of XPC */
 688
 689        /* clear xpc_vars_part_sn2 */
 690        memset((u64 *)xpc_vars_part_sn2, 0, sizeof(struct xpc_vars_part_sn2) *
 691               XP_MAX_NPARTITIONS_SN2);
 692
 693        /* initialize the activate IRQ related amo variables */
 694        for (i = 0; i < xpc_nasid_mask_nlongs; i++)
 695                (void)xpc_init_IRQ_amo_sn2(XPC_ACTIVATE_IRQ_AMOS_SN2 + i);
 696
 697        /* initialize the engaged remote partitions related amo variables */
 698        (void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO_SN2);
 699        (void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO_SN2);
 700
 701        return 0;
 702}
 703
 704static int
 705xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
 706{
 707        return test_bit(partid, heartbeating_to_mask);
 708}
 709
 710static void
 711xpc_allow_hb_sn2(short partid)
 712{
 713        DBUG_ON(xpc_vars_sn2 == NULL);
 714        set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
 715}
 716
 717static void
 718xpc_disallow_hb_sn2(short partid)
 719{
 720        DBUG_ON(xpc_vars_sn2 == NULL);
 721        clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
 722}
 723
 724static void
 725xpc_disallow_all_hbs_sn2(void)
 726{
 727        DBUG_ON(xpc_vars_sn2 == NULL);
 728        bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions);
 729}
 730
 731static void
 732xpc_increment_heartbeat_sn2(void)
 733{
 734        xpc_vars_sn2->heartbeat++;
 735}
 736
 737static void
 738xpc_offline_heartbeat_sn2(void)
 739{
 740        xpc_increment_heartbeat_sn2();
 741        xpc_vars_sn2->heartbeat_offline = 1;
 742}
 743
 744static void
 745xpc_online_heartbeat_sn2(void)
 746{
 747        xpc_increment_heartbeat_sn2();
 748        xpc_vars_sn2->heartbeat_offline = 0;
 749}
 750
 751static void
 752xpc_heartbeat_init_sn2(void)
 753{
 754        DBUG_ON(xpc_vars_sn2 == NULL);
 755
 756        bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
 757        xpc_online_heartbeat_sn2();
 758}
 759
 760static void
 761xpc_heartbeat_exit_sn2(void)
 762{
 763        xpc_offline_heartbeat_sn2();
 764}
 765
 766static enum xp_retval
 767xpc_get_remote_heartbeat_sn2(struct xpc_partition *part)
 768{
 769        struct xpc_vars_sn2 *remote_vars;
 770        enum xp_retval ret;
 771
 772        remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
 773
 774        /* pull the remote vars structure that contains the heartbeat */
 775        ret = xp_remote_memcpy(xp_pa(remote_vars),
 776                               part->sn.sn2.remote_vars_pa,
 777                               XPC_RP_VARS_SIZE);
 778        if (ret != xpSuccess)
 779                return ret;
 780
 781        dev_dbg(xpc_part, "partid=%d, heartbeat=%lld, last_heartbeat=%lld, "
 782                "heartbeat_offline=%lld, HB_mask[0]=0x%lx\n", XPC_PARTID(part),
 783                remote_vars->heartbeat, part->last_heartbeat,
 784                remote_vars->heartbeat_offline,
 785                remote_vars->heartbeating_to_mask[0]);
 786
 787        if ((remote_vars->heartbeat == part->last_heartbeat &&
 788            !remote_vars->heartbeat_offline) ||
 789            !xpc_hb_allowed_sn2(sn_partition_id,
 790                                remote_vars->heartbeating_to_mask)) {
 791                ret = xpNoHeartbeat;
 792        } else {
 793                part->last_heartbeat = remote_vars->heartbeat;
 794        }
 795
 796        return ret;
 797}
 798
 799/*
 800 * Get a copy of the remote partition's XPC variables from the reserved page.
 801 *
 802 * remote_vars points to a buffer that is cacheline aligned for BTE copies and
 803 * assumed to be of size XPC_RP_VARS_SIZE.
 804 */
 805static enum xp_retval
 806xpc_get_remote_vars_sn2(unsigned long remote_vars_pa,
 807                        struct xpc_vars_sn2 *remote_vars)
 808{
 809        enum xp_retval ret;
 810
 811        if (remote_vars_pa == 0)
 812                return xpVarsNotSet;
 813
 814        /* pull over the cross partition variables */
 815        ret = xp_remote_memcpy(xp_pa(remote_vars), remote_vars_pa,
 816                               XPC_RP_VARS_SIZE);
 817        if (ret != xpSuccess)
 818                return ret;
 819
 820        if (XPC_VERSION_MAJOR(remote_vars->version) !=
 821            XPC_VERSION_MAJOR(XPC_V_VERSION)) {
 822                return xpBadVersion;
 823        }
 824
 825        return xpSuccess;
 826}
 827
 828static void
 829xpc_request_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
 830                                     unsigned long remote_rp_pa, int nasid)
 831{
 832        xpc_send_local_activate_IRQ_sn2(nasid);
 833}
 834
 835static void
 836xpc_request_partition_reactivation_sn2(struct xpc_partition *part)
 837{
 838        xpc_send_local_activate_IRQ_sn2(part->sn.sn2.activate_IRQ_nasid);
 839}
 840
 841static void
 842xpc_request_partition_deactivation_sn2(struct xpc_partition *part)
 843{
 844        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 845        unsigned long irq_flags;
 846        struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
 847                                             (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
 848                                             sizeof(struct amo)));
 849
 850        local_irq_save(irq_flags);
 851
 852        /* set bit corresponding to our partid in remote partition's amo */
 853        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
 854                         BIT(sn_partition_id));
 855
 856        /*
 857         * We must always use the nofault function regardless of whether we
 858         * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 859         * didn't, we'd never know that the other partition is down and would
 860         * keep sending IRQs and amos to it until the heartbeat times out.
 861         */
 862        (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 863                                                               variable),
 864                                                     xp_nofault_PIOR_target));
 865
 866        local_irq_restore(irq_flags);
 867
 868        /*
 869         * Send activate IRQ to get other side to see that we've set our
 870         * bit in their deactivate request amo.
 871         */
 872        xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
 873                                  cnodeid_to_nasid(0),
 874                                  part_sn2->activate_IRQ_nasid,
 875                                  part_sn2->activate_IRQ_phys_cpuid);
 876}
 877
 878static void
 879xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part)
 880{
 881        unsigned long irq_flags;
 882        struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
 883                                             (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
 884                                             sizeof(struct amo)));
 885
 886        local_irq_save(irq_flags);
 887
 888        /* clear bit corresponding to our partid in remote partition's amo */
 889        FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 890                         ~BIT(sn_partition_id));
 891
 892        /*
 893         * We must always use the nofault function regardless of whether we
 894         * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 895         * didn't, we'd never know that the other partition is down and would
 896         * keep sending IRQs and amos to it until the heartbeat times out.
 897         */
 898        (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 899                                                               variable),
 900                                                     xp_nofault_PIOR_target));
 901
 902        local_irq_restore(irq_flags);
 903}
 904
 905static int
 906xpc_partition_deactivation_requested_sn2(short partid)
 907{
 908        struct amo *amo = xpc_vars_sn2->amos_page +
 909                          XPC_DEACTIVATE_REQUEST_AMO_SN2;
 910
 911        /* our partition's amo variable ANDed with partid mask */
 912        return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
 913                BIT(partid)) != 0;
 914}
 915
 916/*
 917 * Update the remote partition's info.
 918 */
 919static void
 920xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
 921                              unsigned long *remote_rp_ts_jiffies,
 922                              unsigned long remote_rp_pa,
 923                              unsigned long remote_vars_pa,
 924                              struct xpc_vars_sn2 *remote_vars)
 925{
 926        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 927
 928        part->remote_rp_version = remote_rp_version;
 929        dev_dbg(xpc_part, "  remote_rp_version = 0x%016x\n",
 930                part->remote_rp_version);
 931
 932        part->remote_rp_ts_jiffies = *remote_rp_ts_jiffies;
 933        dev_dbg(xpc_part, "  remote_rp_ts_jiffies = 0x%016lx\n",
 934                part->remote_rp_ts_jiffies);
 935
 936        part->remote_rp_pa = remote_rp_pa;
 937        dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
 938
 939        part_sn2->remote_vars_pa = remote_vars_pa;
 940        dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
 941                part_sn2->remote_vars_pa);
 942
 943        part->last_heartbeat = remote_vars->heartbeat - 1;
 944        dev_dbg(xpc_part, "  last_heartbeat = 0x%016llx\n",
 945                part->last_heartbeat);
 946
 947        part_sn2->remote_vars_part_pa = remote_vars->vars_part_pa;
 948        dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
 949                part_sn2->remote_vars_part_pa);
 950
 951        part_sn2->activate_IRQ_nasid = remote_vars->activate_IRQ_nasid;
 952        dev_dbg(xpc_part, "  activate_IRQ_nasid = 0x%x\n",
 953                part_sn2->activate_IRQ_nasid);
 954
 955        part_sn2->activate_IRQ_phys_cpuid =
 956            remote_vars->activate_IRQ_phys_cpuid;
 957        dev_dbg(xpc_part, "  activate_IRQ_phys_cpuid = 0x%x\n",
 958                part_sn2->activate_IRQ_phys_cpuid);
 959
 960        part_sn2->remote_amos_page_pa = remote_vars->amos_page_pa;
 961        dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
 962                part_sn2->remote_amos_page_pa);
 963
 964        part_sn2->remote_vars_version = remote_vars->version;
 965        dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
 966                part_sn2->remote_vars_version);
 967}
 968
 969/*
 970 * Prior code has determined the nasid which generated a activate IRQ.
 971 * Inspect that nasid to determine if its partition needs to be activated
 972 * or deactivated.
 973 *
 974 * A partition is considered "awaiting activation" if our partition
 975 * flags indicate it is not active and it has a heartbeat.  A
 976 * partition is considered "awaiting deactivation" if our partition
 977 * flags indicate it is active but it has no heartbeat or it is not
 978 * sending its heartbeat to us.
 979 *
 980 * To determine the heartbeat, the remote nasid must have a properly
 981 * initialized reserved page.
 982 */
 983static void
 984xpc_identify_activate_IRQ_req_sn2(int nasid)
 985{
 986        struct xpc_rsvd_page *remote_rp;
 987        struct xpc_vars_sn2 *remote_vars;
 988        unsigned long remote_rp_pa;
 989        unsigned long remote_vars_pa;
 990        int remote_rp_version;
 991        int reactivate = 0;
 992        unsigned long remote_rp_ts_jiffies = 0;
 993        short partid;
 994        struct xpc_partition *part;
 995        struct xpc_partition_sn2 *part_sn2;
 996        enum xp_retval ret;
 997
 998        /* pull over the reserved page structure */
 999
1000        remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer_sn2;
1001
1002        ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
1003        if (ret != xpSuccess) {
1004                dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
1005                         "which sent interrupt, reason=%d\n", nasid, ret);
1006                return;
1007        }
1008
1009        remote_vars_pa = remote_rp->sn.sn2.vars_pa;
1010        remote_rp_version = remote_rp->version;
1011        remote_rp_ts_jiffies = remote_rp->ts_jiffies;
1012
1013        partid = remote_rp->SAL_partid;
1014        part = &xpc_partitions[partid];
1015        part_sn2 = &part->sn.sn2;
1016
1017        /* pull over the cross partition variables */
1018
1019        remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
1020
1021        ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
1022        if (ret != xpSuccess) {
1023                dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
1024                         "which sent interrupt, reason=%d\n", nasid, ret);
1025
1026                XPC_DEACTIVATE_PARTITION(part, ret);
1027                return;
1028        }
1029
1030        part->activate_IRQ_rcvd++;
1031
1032        dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
1033                "%lld:0x%lx\n", (int)nasid, (int)partid,
1034                part->activate_IRQ_rcvd,
1035                remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
1036
1037        if (xpc_partition_disengaged(part) &&
1038            part->act_state == XPC_P_AS_INACTIVE) {
1039
1040                xpc_update_partition_info_sn2(part, remote_rp_version,
1041                                              &remote_rp_ts_jiffies,
1042                                              remote_rp_pa, remote_vars_pa,
1043                                              remote_vars);
1044
1045                if (xpc_partition_deactivation_requested_sn2(partid)) {
1046                        /*
1047                         * Other side is waiting on us to deactivate even though
1048                         * we already have.
1049                         */
1050                        return;
1051                }
1052
1053                xpc_activate_partition(part);
1054                return;
1055        }
1056
1057        DBUG_ON(part->remote_rp_version == 0);
1058        DBUG_ON(part_sn2->remote_vars_version == 0);
1059
1060        if (remote_rp_ts_jiffies != part->remote_rp_ts_jiffies) {
1061
1062                /* the other side rebooted */
1063
1064                DBUG_ON(xpc_partition_engaged_sn2(partid));
1065                DBUG_ON(xpc_partition_deactivation_requested_sn2(partid));
1066
1067                xpc_update_partition_info_sn2(part, remote_rp_version,
1068                                              &remote_rp_ts_jiffies,
1069                                              remote_rp_pa, remote_vars_pa,
1070                                              remote_vars);
1071                reactivate = 1;
1072        }
1073
1074        if (part->disengage_timeout > 0 && !xpc_partition_disengaged(part)) {
1075                /* still waiting on other side to disengage from us */
1076                return;
1077        }
1078
1079        if (reactivate)
1080                XPC_DEACTIVATE_PARTITION(part, xpReactivating);
1081        else if (xpc_partition_deactivation_requested_sn2(partid))
1082                XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
1083}
1084
1085/*
1086 * Loop through the activation amo variables and process any bits
1087 * which are set.  Each bit indicates a nasid sending a partition
1088 * activation or deactivation request.
1089 *
1090 * Return #of IRQs detected.
1091 */
1092int
1093xpc_identify_activate_IRQ_sender_sn2(void)
1094{
1095        int l;
1096        int b;
1097        unsigned long nasid_mask_long;
1098        u64 nasid;              /* remote nasid */
1099        int n_IRQs_detected = 0;
1100        struct amo *act_amos;
1101
1102        act_amos = xpc_vars_sn2->amos_page + XPC_ACTIVATE_IRQ_AMOS_SN2;
1103
1104        /* scan through activate amo variables looking for non-zero entries */
1105        for (l = 0; l < xpc_nasid_mask_nlongs; l++) {
1106
1107                if (xpc_exiting)
1108                        break;
1109
1110                nasid_mask_long = xpc_receive_IRQ_amo_sn2(&act_amos[l]);
1111
1112                b = find_first_bit(&nasid_mask_long, BITS_PER_LONG);
1113                if (b >= BITS_PER_LONG) {
1114                        /* no IRQs from nasids in this amo variable */
1115                        continue;
1116                }
1117
1118                dev_dbg(xpc_part, "amo[%d] gave back 0x%lx\n", l,
1119                        nasid_mask_long);
1120
1121                /*
1122                 * If this nasid has been added to the machine since
1123                 * our partition was reset, this will retain the
1124                 * remote nasid in our reserved pages machine mask.
1125                 * This is used in the event of module reload.
1126                 */
1127                xpc_mach_nasids[l] |= nasid_mask_long;
1128
1129                /* locate the nasid(s) which sent interrupts */
1130
1131                do {
1132                        n_IRQs_detected++;
1133                        nasid = (l * BITS_PER_LONG + b) * 2;
1134                        dev_dbg(xpc_part, "interrupt from nasid %lld\n", nasid);
1135                        xpc_identify_activate_IRQ_req_sn2(nasid);
1136
1137                        b = find_next_bit(&nasid_mask_long, BITS_PER_LONG,
1138                                          b + 1);
1139                } while (b < BITS_PER_LONG);
1140        }
1141        return n_IRQs_detected;
1142}
1143
1144static void
1145xpc_process_activate_IRQ_rcvd_sn2(void)
1146{
1147        unsigned long irq_flags;
1148        int n_IRQs_expected;
1149        int n_IRQs_detected;
1150
1151        spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1152        n_IRQs_expected = xpc_activate_IRQ_rcvd;
1153        xpc_activate_IRQ_rcvd = 0;
1154        spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1155
1156        n_IRQs_detected = xpc_identify_activate_IRQ_sender_sn2();
1157        if (n_IRQs_detected < n_IRQs_expected) {
1158                /* retry once to help avoid missing amo */
1159                (void)xpc_identify_activate_IRQ_sender_sn2();
1160        }
1161}
1162
1163/*
1164 * Setup the channel structures that are sn2 specific.
1165 */
1166static enum xp_retval
1167xpc_setup_ch_structures_sn2(struct xpc_partition *part)
1168{
1169        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1170        struct xpc_channel_sn2 *ch_sn2;
1171        enum xp_retval retval;
1172        int ret;
1173        int cpuid;
1174        int ch_number;
1175        struct timer_list *timer;
1176        short partid = XPC_PARTID(part);
1177
1178        /* allocate all the required GET/PUT values */
1179
1180        part_sn2->local_GPs =
1181            xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
1182                                          &part_sn2->local_GPs_base);
1183        if (part_sn2->local_GPs == NULL) {
1184                dev_err(xpc_chan, "can't get memory for local get/put "
1185                        "values\n");
1186                return xpNoMemory;
1187        }
1188
1189        part_sn2->remote_GPs =
1190            xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
1191                                          &part_sn2->remote_GPs_base);
1192        if (part_sn2->remote_GPs == NULL) {
1193                dev_err(xpc_chan, "can't get memory for remote get/put "
1194                        "values\n");
1195                retval = xpNoMemory;
1196                goto out_1;
1197        }
1198
1199        part_sn2->remote_GPs_pa = 0;
1200
1201        /* allocate all the required open and close args */
1202
1203        part_sn2->local_openclose_args =
1204            xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
1205                                          GFP_KERNEL, &part_sn2->
1206                                          local_openclose_args_base);
1207        if (part_sn2->local_openclose_args == NULL) {
1208                dev_err(xpc_chan, "can't get memory for local connect args\n");
1209                retval = xpNoMemory;
1210                goto out_2;
1211        }
1212
1213        part_sn2->remote_openclose_args_pa = 0;
1214
1215        part_sn2->local_chctl_amo_va = xpc_init_IRQ_amo_sn2(partid);
1216
1217        part_sn2->notify_IRQ_nasid = 0;
1218        part_sn2->notify_IRQ_phys_cpuid = 0;
1219        part_sn2->remote_chctl_amo_va = NULL;
1220
1221        sprintf(part_sn2->notify_IRQ_owner, "xpc%02d", partid);
1222        ret = request_irq(SGI_XPC_NOTIFY, xpc_handle_notify_IRQ_sn2,
1223                          IRQF_SHARED, part_sn2->notify_IRQ_owner,
1224                          (void *)(u64)partid);
1225        if (ret != 0) {
1226                dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
1227                        "errno=%d\n", -ret);
1228                retval = xpLackOfResources;
1229                goto out_3;
1230        }
1231
1232        /* Setup a timer to check for dropped notify IRQs */
1233        timer = &part_sn2->dropped_notify_IRQ_timer;
1234        init_timer(timer);
1235        timer->function =
1236            (void (*)(unsigned long))xpc_check_for_dropped_notify_IRQ_sn2;
1237        timer->data = (unsigned long)part;
1238        timer->expires = jiffies + XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
1239        add_timer(timer);
1240
1241        for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
1242                ch_sn2 = &part->channels[ch_number].sn.sn2;
1243
1244                ch_sn2->local_GP = &part_sn2->local_GPs[ch_number];
1245                ch_sn2->local_openclose_args =
1246                    &part_sn2->local_openclose_args[ch_number];
1247
1248                mutex_init(&ch_sn2->msg_to_pull_mutex);
1249        }
1250
1251        /*
1252         * Setup the per partition specific variables required by the
1253         * remote partition to establish channel connections with us.
1254         *
1255         * The setting of the magic # indicates that these per partition
1256         * specific variables are ready to be used.
1257         */
1258        xpc_vars_part_sn2[partid].GPs_pa = xp_pa(part_sn2->local_GPs);
1259        xpc_vars_part_sn2[partid].openclose_args_pa =
1260            xp_pa(part_sn2->local_openclose_args);
1261        xpc_vars_part_sn2[partid].chctl_amo_pa =
1262            xp_pa(part_sn2->local_chctl_amo_va);
1263        cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
1264        xpc_vars_part_sn2[partid].notify_IRQ_nasid = cpuid_to_nasid(cpuid);
1265        xpc_vars_part_sn2[partid].notify_IRQ_phys_cpuid =
1266            cpu_physical_id(cpuid);
1267        xpc_vars_part_sn2[partid].nchannels = part->nchannels;
1268        xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC1_SN2;
1269
1270        return xpSuccess;
1271
1272        /* setup of ch structures failed */
1273out_3:
1274        kfree(part_sn2->local_openclose_args_base);
1275        part_sn2->local_openclose_args = NULL;
1276out_2:
1277        kfree(part_sn2->remote_GPs_base);
1278        part_sn2->remote_GPs = NULL;
1279out_1:
1280        kfree(part_sn2->local_GPs_base);
1281        part_sn2->local_GPs = NULL;
1282        return retval;
1283}
1284
1285/*
1286 * Teardown the channel structures that are sn2 specific.
1287 */
1288static void
1289xpc_teardown_ch_structures_sn2(struct xpc_partition *part)
1290{
1291        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1292        short partid = XPC_PARTID(part);
1293
1294        /*
1295         * Indicate that the variables specific to the remote partition are no
1296         * longer available for its use.
1297         */
1298        xpc_vars_part_sn2[partid].magic = 0;
1299
1300        /* in case we've still got outstanding timers registered... */
1301        del_timer_sync(&part_sn2->dropped_notify_IRQ_timer);
1302        free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
1303
1304        kfree(part_sn2->local_openclose_args_base);
1305        part_sn2->local_openclose_args = NULL;
1306        kfree(part_sn2->remote_GPs_base);
1307        part_sn2->remote_GPs = NULL;
1308        kfree(part_sn2->local_GPs_base);
1309        part_sn2->local_GPs = NULL;
1310        part_sn2->local_chctl_amo_va = NULL;
1311}
1312
1313/*
1314 * Create a wrapper that hides the underlying mechanism for pulling a cacheline
1315 * (or multiple cachelines) from a remote partition.
1316 *
1317 * src_pa must be a cacheline aligned physical address on the remote partition.
1318 * dst must be a cacheline aligned virtual address on this partition.
1319 * cnt must be cacheline sized
1320 */
1321/* ??? Replace this function by call to xp_remote_memcpy() or bte_copy()? */
1322static enum xp_retval
1323xpc_pull_remote_cachelines_sn2(struct xpc_partition *part, void *dst,
1324                               const unsigned long src_pa, size_t cnt)
1325{
1326        enum xp_retval ret;
1327
1328        DBUG_ON(src_pa != L1_CACHE_ALIGN(src_pa));
1329        DBUG_ON((unsigned long)dst != L1_CACHE_ALIGN((unsigned long)dst));
1330        DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
1331
1332        if (part->act_state == XPC_P_AS_DEACTIVATING)
1333                return part->reason;
1334
1335        ret = xp_remote_memcpy(xp_pa(dst), src_pa, cnt);
1336        if (ret != xpSuccess) {
1337                dev_dbg(xpc_chan, "xp_remote_memcpy() from partition %d failed,"
1338                        " ret=%d\n", XPC_PARTID(part), ret);
1339        }
1340        return ret;
1341}
1342
1343/*
1344 * Pull the remote per partition specific variables from the specified
1345 * partition.
1346 */
1347static enum xp_retval
1348xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1349{
1350        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1351        u8 buffer[L1_CACHE_BYTES * 2];
1352        struct xpc_vars_part_sn2 *pulled_entry_cacheline =
1353            (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer);
1354        struct xpc_vars_part_sn2 *pulled_entry;
1355        unsigned long remote_entry_cacheline_pa;
1356        unsigned long remote_entry_pa;
1357        short partid = XPC_PARTID(part);
1358        enum xp_retval ret;
1359
1360        /* pull the cacheline that contains the variables we're interested in */
1361
1362        DBUG_ON(part_sn2->remote_vars_part_pa !=
1363                L1_CACHE_ALIGN(part_sn2->remote_vars_part_pa));
1364        DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2);
1365
1366        remote_entry_pa = part_sn2->remote_vars_part_pa +
1367            sn_partition_id * sizeof(struct xpc_vars_part_sn2);
1368
1369        remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
1370
1371        pulled_entry = (struct xpc_vars_part_sn2 *)((u64)pulled_entry_cacheline
1372                                                    + (remote_entry_pa &
1373                                                    (L1_CACHE_BYTES - 1)));
1374
1375        ret = xpc_pull_remote_cachelines_sn2(part, pulled_entry_cacheline,
1376                                             remote_entry_cacheline_pa,
1377                                             L1_CACHE_BYTES);
1378        if (ret != xpSuccess) {
1379                dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
1380                        "partition %d, ret=%d\n", partid, ret);
1381                return ret;
1382        }
1383
1384        /* see if they've been set up yet */
1385
1386        if (pulled_entry->magic != XPC_VP_MAGIC1_SN2 &&
1387            pulled_entry->magic != XPC_VP_MAGIC2_SN2) {
1388
1389                if (pulled_entry->magic != 0) {
1390                        dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
1391                                "partition %d has bad magic value (=0x%llx)\n",
1392                                partid, sn_partition_id, pulled_entry->magic);
1393                        return xpBadMagic;
1394                }
1395
1396                /* they've not been initialized yet */
1397                return xpRetry;
1398        }
1399
1400        if (xpc_vars_part_sn2[partid].magic == XPC_VP_MAGIC1_SN2) {
1401
1402                /* validate the variables */
1403
1404                if (pulled_entry->GPs_pa == 0 ||
1405                    pulled_entry->openclose_args_pa == 0 ||
1406                    pulled_entry->chctl_amo_pa == 0) {
1407
1408                        dev_err(xpc_chan, "partition %d's XPC vars_part for "
1409                                "partition %d are not valid\n", partid,
1410                                sn_partition_id);
1411                        return xpInvalidAddress;
1412                }
1413
1414                /* the variables we imported look to be valid */
1415
1416                part_sn2->remote_GPs_pa = pulled_entry->GPs_pa;
1417                part_sn2->remote_openclose_args_pa =
1418                    pulled_entry->openclose_args_pa;
1419                part_sn2->remote_chctl_amo_va =
1420                    (struct amo *)__va(pulled_entry->chctl_amo_pa);
1421                part_sn2->notify_IRQ_nasid = pulled_entry->notify_IRQ_nasid;
1422                part_sn2->notify_IRQ_phys_cpuid =
1423                    pulled_entry->notify_IRQ_phys_cpuid;
1424
1425                if (part->nchannels > pulled_entry->nchannels)
1426                        part->nchannels = pulled_entry->nchannels;
1427
1428                /* let the other side know that we've pulled their variables */
1429
1430                xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC2_SN2;
1431        }
1432
1433        if (pulled_entry->magic == XPC_VP_MAGIC1_SN2)
1434                return xpRetry;
1435
1436        return xpSuccess;
1437}
1438
1439/*
1440 * Establish first contact with the remote partititon. This involves pulling
1441 * the XPC per partition variables from the remote partition and waiting for
1442 * the remote partition to pull ours.
1443 */
1444static enum xp_retval
1445xpc_make_first_contact_sn2(struct xpc_partition *part)
1446{
1447        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1448        enum xp_retval ret;
1449
1450        /*
1451         * Register the remote partition's amos with SAL so it can handle
1452         * and cleanup errors within that address range should the remote
1453         * partition go down. We don't unregister this range because it is
1454         * difficult to tell when outstanding writes to the remote partition
1455         * are finished and thus when it is safe to unregister. This should
1456         * not result in wasted space in the SAL xp_addr_region table because
1457         * we should get the same page for remote_amos_page_pa after module
1458         * reloads and system reboots.
1459         */
1460        if (sn_register_xp_addr_region(part_sn2->remote_amos_page_pa,
1461                                       PAGE_SIZE, 1) < 0) {
1462                dev_warn(xpc_part, "xpc_activating(%d) failed to register "
1463                         "xp_addr region\n", XPC_PARTID(part));
1464
1465                ret = xpPhysAddrRegFailed;
1466                XPC_DEACTIVATE_PARTITION(part, ret);
1467                return ret;
1468        }
1469
1470        /*
1471         * Send activate IRQ to get other side to activate if they've not
1472         * already begun to do so.
1473         */
1474        xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
1475                                  cnodeid_to_nasid(0),
1476                                  part_sn2->activate_IRQ_nasid,
1477                                  part_sn2->activate_IRQ_phys_cpuid);
1478
1479        while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
1480                if (ret != xpRetry) {
1481                        XPC_DEACTIVATE_PARTITION(part, ret);
1482                        return ret;
1483                }
1484
1485                dev_dbg(xpc_part, "waiting to make first contact with "
1486                        "partition %d\n", XPC_PARTID(part));
1487
1488                /* wait a 1/4 of a second or so */
1489                (void)msleep_interruptible(250);
1490
1491                if (part->act_state == XPC_P_AS_DEACTIVATING)
1492                        return part->reason;
1493        }
1494
1495        return xpSuccess;
1496}
1497
1498/*
1499 * Get the chctl flags and pull the openclose args and/or remote GPs as needed.
1500 */
1501static u64
1502xpc_get_chctl_all_flags_sn2(struct xpc_partition *part)
1503{
1504        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1505        unsigned long irq_flags;
1506        union xpc_channel_ctl_flags chctl;
1507        enum xp_retval ret;
1508
1509        /*
1510         * See if there are any chctl flags to be handled.
1511         */
1512
1513        spin_lock_irqsave(&part->chctl_lock, irq_flags);
1514        chctl = part->chctl;
1515        if (chctl.all_flags != 0)
1516                part->chctl.all_flags = 0;
1517
1518        spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
1519
1520        if (xpc_any_openclose_chctl_flags_set(&chctl)) {
1521                ret = xpc_pull_remote_cachelines_sn2(part, part->
1522                                                     remote_openclose_args,
1523                                                     part_sn2->
1524                                                     remote_openclose_args_pa,
1525                                                     XPC_OPENCLOSE_ARGS_SIZE);
1526                if (ret != xpSuccess) {
1527                        XPC_DEACTIVATE_PARTITION(part, ret);
1528
1529                        dev_dbg(xpc_chan, "failed to pull openclose args from "
1530                                "partition %d, ret=%d\n", XPC_PARTID(part),
1531                                ret);
1532
1533                        /* don't bother processing chctl flags anymore */
1534                        chctl.all_flags = 0;
1535                }
1536        }
1537
1538        if (xpc_any_msg_chctl_flags_set(&chctl)) {
1539                ret = xpc_pull_remote_cachelines_sn2(part, part_sn2->remote_GPs,
1540                                                     part_sn2->remote_GPs_pa,
1541                                                     XPC_GP_SIZE);
1542                if (ret != xpSuccess) {
1543                        XPC_DEACTIVATE_PARTITION(part, ret);
1544
1545                        dev_dbg(xpc_chan, "failed to pull GPs from partition "
1546                                "%d, ret=%d\n", XPC_PARTID(part), ret);
1547
1548                        /* don't bother processing chctl flags anymore */
1549                        chctl.all_flags = 0;
1550                }
1551        }
1552
1553        return chctl.all_flags;
1554}
1555
1556/*
1557 * Allocate the local message queue and the notify queue.
1558 */
1559static enum xp_retval
1560xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
1561{
1562        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1563        unsigned long irq_flags;
1564        int nentries;
1565        size_t nbytes;
1566
1567        for (nentries = ch->local_nentries; nentries > 0; nentries--) {
1568
1569                nbytes = nentries * ch->entry_size;
1570                ch_sn2->local_msgqueue =
1571                    xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL,
1572                                                  &ch_sn2->local_msgqueue_base);
1573                if (ch_sn2->local_msgqueue == NULL)
1574                        continue;
1575
1576                nbytes = nentries * sizeof(struct xpc_notify_sn2);
1577                ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL);
1578                if (ch_sn2->notify_queue == NULL) {
1579                        kfree(ch_sn2->local_msgqueue_base);
1580                        ch_sn2->local_msgqueue = NULL;
1581                        continue;
1582                }
1583
1584                spin_lock_irqsave(&ch->lock, irq_flags);
1585                if (nentries < ch->local_nentries) {
1586                        dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
1587                                "partid=%d, channel=%d\n", nentries,
1588                                ch->local_nentries, ch->partid, ch->number);
1589
1590                        ch->local_nentries = nentries;
1591                }
1592                spin_unlock_irqrestore(&ch->lock, irq_flags);
1593                return xpSuccess;
1594        }
1595
1596        dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
1597                "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
1598        return xpNoMemory;
1599}
1600
1601/*
1602 * Allocate the cached remote message queue.
1603 */
1604static enum xp_retval
1605xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
1606{
1607        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1608        unsigned long irq_flags;
1609        int nentries;
1610        size_t nbytes;
1611
1612        DBUG_ON(ch->remote_nentries <= 0);
1613
1614        for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
1615
1616                nbytes = nentries * ch->entry_size;
1617                ch_sn2->remote_msgqueue =
1618                    xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2->
1619                                                  remote_msgqueue_base);
1620                if (ch_sn2->remote_msgqueue == NULL)
1621                        continue;
1622
1623                spin_lock_irqsave(&ch->lock, irq_flags);
1624                if (nentries < ch->remote_nentries) {
1625                        dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
1626                                "partid=%d, channel=%d\n", nentries,
1627                                ch->remote_nentries, ch->partid, ch->number);
1628
1629                        ch->remote_nentries = nentries;
1630                }
1631                spin_unlock_irqrestore(&ch->lock, irq_flags);
1632                return xpSuccess;
1633        }
1634
1635        dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
1636                "partid=%d, channel=%d\n", ch->partid, ch->number);
1637        return xpNoMemory;
1638}
1639
1640/*
1641 * Allocate message queues and other stuff associated with a channel.
1642 *
1643 * Note: Assumes all of the channel sizes are filled in.
1644 */
1645static enum xp_retval
1646xpc_setup_msg_structures_sn2(struct xpc_channel *ch)
1647{
1648        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1649        enum xp_retval ret;
1650
1651        DBUG_ON(ch->flags & XPC_C_SETUP);
1652
1653        ret = xpc_allocate_local_msgqueue_sn2(ch);
1654        if (ret == xpSuccess) {
1655
1656                ret = xpc_allocate_remote_msgqueue_sn2(ch);
1657                if (ret != xpSuccess) {
1658                        kfree(ch_sn2->local_msgqueue_base);
1659                        ch_sn2->local_msgqueue = NULL;
1660                        kfree(ch_sn2->notify_queue);
1661                        ch_sn2->notify_queue = NULL;
1662                }
1663        }
1664        return ret;
1665}
1666
1667/*
1668 * Free up message queues and other stuff that were allocated for the specified
1669 * channel.
1670 */
1671static void
1672xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
1673{
1674        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1675
1676        DBUG_ON(!spin_is_locked(&ch->lock));
1677
1678        ch_sn2->remote_msgqueue_pa = 0;
1679
1680        ch_sn2->local_GP->get = 0;
1681        ch_sn2->local_GP->put = 0;
1682        ch_sn2->remote_GP.get = 0;
1683        ch_sn2->remote_GP.put = 0;
1684        ch_sn2->w_local_GP.get = 0;
1685        ch_sn2->w_local_GP.put = 0;
1686        ch_sn2->w_remote_GP.get = 0;
1687        ch_sn2->w_remote_GP.put = 0;
1688        ch_sn2->next_msg_to_pull = 0;
1689
1690        if (ch->flags & XPC_C_SETUP) {
1691                dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
1692                        ch->flags, ch->partid, ch->number);
1693
1694                kfree(ch_sn2->local_msgqueue_base);
1695                ch_sn2->local_msgqueue = NULL;
1696                kfree(ch_sn2->remote_msgqueue_base);
1697                ch_sn2->remote_msgqueue = NULL;
1698                kfree(ch_sn2->notify_queue);
1699                ch_sn2->notify_queue = NULL;
1700        }
1701}
1702
1703/*
1704 * Notify those who wanted to be notified upon delivery of their message.
1705 */
1706static void
1707xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
1708{
1709        struct xpc_notify_sn2 *notify;
1710        u8 notify_type;
1711        s64 get = ch->sn.sn2.w_remote_GP.get - 1;
1712
1713        while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
1714
1715                notify = &ch->sn.sn2.notify_queue[get % ch->local_nentries];
1716
1717                /*
1718                 * See if the notify entry indicates it was associated with
1719                 * a message who's sender wants to be notified. It is possible
1720                 * that it is, but someone else is doing or has done the
1721                 * notification.
1722                 */
1723                notify_type = notify->type;
1724                if (notify_type == 0 ||
1725                    cmpxchg(&notify->type, notify_type, 0) != notify_type) {
1726                        continue;
1727                }
1728
1729                DBUG_ON(notify_type != XPC_N_CALL);
1730
1731                atomic_dec(&ch->n_to_notify);
1732
1733                if (notify->func != NULL) {
1734                        dev_dbg(xpc_chan, "notify->func() called, notify=0x%p "
1735                                "msg_number=%lld partid=%d channel=%d\n",
1736                                (void *)notify, get, ch->partid, ch->number);
1737
1738                        notify->func(reason, ch->partid, ch->number,
1739                                     notify->key);
1740
1741                        dev_dbg(xpc_chan, "notify->func() returned, notify=0x%p"
1742                                " msg_number=%lld partid=%d channel=%d\n",
1743                                (void *)notify, get, ch->partid, ch->number);
1744                }
1745        }
1746}
1747
1748static void
1749xpc_notify_senders_of_disconnect_sn2(struct xpc_channel *ch)
1750{
1751        xpc_notify_senders_sn2(ch, ch->reason, ch->sn.sn2.w_local_GP.put);
1752}
1753
1754/*
1755 * Clear some of the msg flags in the local message queue.
1756 */
1757static inline void
1758xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
1759{
1760        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1761        struct xpc_msg_sn2 *msg;
1762        s64 get;
1763
1764        get = ch_sn2->w_remote_GP.get;
1765        do {
1766                msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
1767                                             (get % ch->local_nentries) *
1768                                             ch->entry_size);
1769                DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
1770                msg->flags = 0;
1771        } while (++get < ch_sn2->remote_GP.get);
1772}
1773
1774/*
1775 * Clear some of the msg flags in the remote message queue.
1776 */
1777static inline void
1778xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
1779{
1780        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1781        struct xpc_msg_sn2 *msg;
1782        s64 put, remote_nentries = ch->remote_nentries;
1783
1784        /* flags are zeroed when the buffer is allocated */
1785        if (ch_sn2->remote_GP.put < remote_nentries)
1786                return;
1787
1788        put = max(ch_sn2->w_remote_GP.put, remote_nentries);
1789        do {
1790                msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
1791                                             (put % remote_nentries) *
1792                                             ch->entry_size);
1793                DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
1794                DBUG_ON(!(msg->flags & XPC_M_SN2_DONE));
1795                DBUG_ON(msg->number != put - remote_nentries);
1796                msg->flags = 0;
1797        } while (++put < ch_sn2->remote_GP.put);
1798}
1799
1800static int
1801xpc_n_of_deliverable_payloads_sn2(struct xpc_channel *ch)
1802{
1803        return ch->sn.sn2.w_remote_GP.put - ch->sn.sn2.w_local_GP.get;
1804}
1805
1806static void
1807xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
1808{
1809        struct xpc_channel *ch = &part->channels[ch_number];
1810        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1811        int npayloads_sent;
1812
1813        ch_sn2->remote_GP = part->sn.sn2.remote_GPs[ch_number];
1814
1815        /* See what, if anything, has changed for each connected channel */
1816
1817        xpc_msgqueue_ref(ch);
1818
1819        if (ch_sn2->w_remote_GP.get == ch_sn2->remote_GP.get &&
1820            ch_sn2->w_remote_GP.put == ch_sn2->remote_GP.put) {
1821                /* nothing changed since GPs were last pulled */
1822                xpc_msgqueue_deref(ch);
1823                return;
1824        }
1825
1826        if (!(ch->flags & XPC_C_CONNECTED)) {
1827                xpc_msgqueue_deref(ch);
1828                return;
1829        }
1830
1831        /*
1832         * First check to see if messages recently sent by us have been
1833         * received by the other side. (The remote GET value will have
1834         * changed since we last looked at it.)
1835         */
1836
1837        if (ch_sn2->w_remote_GP.get != ch_sn2->remote_GP.get) {
1838
1839                /*
1840                 * We need to notify any senders that want to be notified
1841                 * that their sent messages have been received by their
1842                 * intended recipients. We need to do this before updating
1843                 * w_remote_GP.get so that we don't allocate the same message
1844                 * queue entries prematurely (see xpc_allocate_msg()).
1845                 */
1846                if (atomic_read(&ch->n_to_notify) > 0) {
1847                        /*
1848                         * Notify senders that messages sent have been
1849                         * received and delivered by the other side.
1850                         */
1851                        xpc_notify_senders_sn2(ch, xpMsgDelivered,
1852                                               ch_sn2->remote_GP.get);
1853                }
1854
1855                /*
1856                 * Clear msg->flags in previously sent messages, so that
1857                 * they're ready for xpc_allocate_msg().
1858                 */
1859                xpc_clear_local_msgqueue_flags_sn2(ch);
1860
1861                ch_sn2->w_remote_GP.get = ch_sn2->remote_GP.get;
1862
1863                dev_dbg(xpc_chan, "w_remote_GP.get changed to %lld, partid=%d, "
1864                        "channel=%d\n", ch_sn2->w_remote_GP.get, ch->partid,
1865                        ch->number);
1866
1867                /*
1868                 * If anyone was waiting for message queue entries to become
1869                 * available, wake them up.
1870                 */
1871                if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
1872                        wake_up(&ch->msg_allocate_wq);
1873        }
1874
1875        /*
1876         * Now check for newly sent messages by the other side. (The remote
1877         * PUT value will have changed since we last looked at it.)
1878         */
1879
1880        if (ch_sn2->w_remote_GP.put != ch_sn2->remote_GP.put) {
1881                /*
1882                 * Clear msg->flags in previously received messages, so that
1883                 * they're ready for xpc_get_deliverable_payload_sn2().
1884                 */
1885                xpc_clear_remote_msgqueue_flags_sn2(ch);
1886
1887                smp_wmb(); /* ensure flags have been cleared before bte_copy */
1888                ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put;
1889
1890                dev_dbg(xpc_chan, "w_remote_GP.put changed to %lld, partid=%d, "
1891                        "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid,
1892                        ch->number);
1893
1894                npayloads_sent = xpc_n_of_deliverable_payloads_sn2(ch);
1895                if (npayloads_sent > 0) {
1896                        dev_dbg(xpc_chan, "msgs waiting to be copied and "
1897                                "delivered=%d, partid=%d, channel=%d\n",
1898                                npayloads_sent, ch->partid, ch->number);
1899
1900                        if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
1901                                xpc_activate_kthreads(ch, npayloads_sent);
1902                }
1903        }
1904
1905        xpc_msgqueue_deref(ch);
1906}
1907
1908static struct xpc_msg_sn2 *
1909xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1910{
1911        struct xpc_partition *part = &xpc_partitions[ch->partid];
1912        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1913        unsigned long remote_msg_pa;
1914        struct xpc_msg_sn2 *msg;
1915        u32 msg_index;
1916        u32 nmsgs;
1917        u64 msg_offset;
1918        enum xp_retval ret;
1919
1920        if (mutex_lock_interruptible(&ch_sn2->msg_to_pull_mutex) != 0) {
1921                /* we were interrupted by a signal */
1922                return NULL;
1923        }
1924
1925        while (get >= ch_sn2->next_msg_to_pull) {
1926
1927                /* pull as many messages as are ready and able to be pulled */
1928
1929                msg_index = ch_sn2->next_msg_to_pull % ch->remote_nentries;
1930
1931                DBUG_ON(ch_sn2->next_msg_to_pull >= ch_sn2->w_remote_GP.put);
1932                nmsgs = ch_sn2->w_remote_GP.put - ch_sn2->next_msg_to_pull;
1933                if (msg_index + nmsgs > ch->remote_nentries) {
1934                        /* ignore the ones that wrap the msg queue for now */
1935                        nmsgs = ch->remote_nentries - msg_index;
1936                }
1937
1938                msg_offset = msg_index * ch->entry_size;
1939                msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
1940                    msg_offset);
1941                remote_msg_pa = ch_sn2->remote_msgqueue_pa + msg_offset;
1942
1943                ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa,
1944                                                     nmsgs * ch->entry_size);
1945                if (ret != xpSuccess) {
1946
1947                        dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
1948                                " msg %lld from partition %d, channel=%d, "
1949                                "ret=%d\n", nmsgs, ch_sn2->next_msg_to_pull,
1950                                ch->partid, ch->number, ret);
1951
1952                        XPC_DEACTIVATE_PARTITION(part, ret);
1953
1954                        mutex_unlock(&ch_sn2->msg_to_pull_mutex);
1955                        return NULL;
1956                }
1957
1958                ch_sn2->next_msg_to_pull += nmsgs;
1959        }
1960
1961        mutex_unlock(&ch_sn2->msg_to_pull_mutex);
1962
1963        /* return the message we were looking for */
1964        msg_offset = (get % ch->remote_nentries) * ch->entry_size;
1965        msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue + msg_offset);
1966
1967        return msg;
1968}
1969
1970/*
1971 * Get the next deliverable message's payload.
1972 */
1973static void *
1974xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
1975{
1976        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1977        struct xpc_msg_sn2 *msg;
1978        void *payload = NULL;
1979        s64 get;
1980
1981        do {
1982                if (ch->flags & XPC_C_DISCONNECTING)
1983                        break;
1984
1985                get = ch_sn2->w_local_GP.get;
1986                smp_rmb();      /* guarantee that .get loads before .put */
1987                if (get == ch_sn2->w_remote_GP.put)
1988                        break;
1989
1990                /* There are messages waiting to be pulled and delivered.
1991                 * We need to try to secure one for ourselves. We'll do this
1992                 * by trying to increment w_local_GP.get and hope that no one
1993                 * else beats us to it. If they do, we'll we'll simply have
1994                 * to try again for the next one.
1995                 */
1996
1997                if (cmpxchg(&ch_sn2->w_local_GP.get, get, get + 1) == get) {
1998                        /* we got the entry referenced by get */
1999
2000                        dev_dbg(xpc_chan, "w_local_GP.get changed to %lld, "
2001                                "partid=%d, channel=%d\n", get + 1,
2002                                ch->partid, ch->number);
2003
2004                        /* pull the message from the remote partition */
2005
2006                        msg = xpc_pull_remote_msg_sn2(ch, get);
2007
2008                        if (msg != NULL) {
2009                                DBUG_ON(msg->number != get);
2010                                DBUG_ON(msg->flags & XPC_M_SN2_DONE);
2011                                DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
2012
2013                                payload = &msg->payload;
2014                        }
2015                        break;
2016                }
2017
2018        } while (1);
2019
2020        return payload;
2021}
2022
2023/*
2024 * Now we actually send the messages that are ready to be sent by advancing
2025 * the local message queue's Put value and then send a chctl msgrequest to the
2026 * recipient partition.
2027 */
2028static void
2029xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
2030{
2031        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2032        struct xpc_msg_sn2 *msg;
2033        s64 put = initial_put + 1;
2034        int send_msgrequest = 0;
2035
2036        while (1) {
2037
2038                while (1) {
2039                        if (put == ch_sn2->w_local_GP.put)
2040                                break;
2041
2042                        msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
2043                                                     local_msgqueue + (put %
2044                                                     ch->local_nentries) *
2045                                                     ch->entry_size);
2046
2047                        if (!(msg->flags & XPC_M_SN2_READY))
2048                                break;
2049
2050                        put++;
2051                }
2052
2053                if (put == initial_put) {
2054                        /* nothing's changed */
2055                        break;
2056                }
2057
2058                if (cmpxchg_rel(&ch_sn2->local_GP->put, initial_put, put) !=
2059                    initial_put) {
2060                        /* someone else beat us to it */
2061                        DBUG_ON(ch_sn2->local_GP->put < initial_put);
2062                        break;
2063                }
2064
2065                /* we just set the new value of local_GP->put */
2066
2067                dev_dbg(xpc_chan, "local_GP->put changed to %lld, partid=%d, "
2068                        "channel=%d\n", put, ch->partid, ch->number);
2069
2070                send_msgrequest = 1;
2071
2072                /*
2073                 * We need to ensure that the message referenced by
2074                 * local_GP->put is not XPC_M_SN2_READY or that local_GP->put
2075                 * equals w_local_GP.put, so we'll go have a look.
2076                 */
2077                initial_put = put;
2078        }
2079
2080        if (send_msgrequest)
2081                xpc_send_chctl_msgrequest_sn2(ch);
2082}
2083
2084/*
2085 * Allocate an entry for a message from the message queue associated with the
2086 * specified channel.
2087 */
2088static enum xp_retval
2089xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
2090                     struct xpc_msg_sn2 **address_of_msg)
2091{
2092        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2093        struct xpc_msg_sn2 *msg;
2094        enum xp_retval ret;
2095        s64 put;
2096
2097        /*
2098         * Get the next available message entry from the local message queue.
2099         * If none are available, we'll make sure that we grab the latest
2100         * GP values.
2101         */
2102        ret = xpTimeout;
2103
2104        while (1) {
2105
2106                put = ch_sn2->w_local_GP.put;
2107                smp_rmb();      /* guarantee that .put loads before .get */
2108                if (put - ch_sn2->w_remote_GP.get < ch->local_nentries) {
2109
2110                        /* There are available message entries. We need to try
2111                         * to secure one for ourselves. We'll do this by trying
2112                         * to increment w_local_GP.put as long as someone else
2113                         * doesn't beat us to it. If they do, we'll have to
2114                         * try again.
2115                         */
2116                        if (cmpxchg(&ch_sn2->w_local_GP.put, put, put + 1) ==
2117                            put) {
2118                                /* we got the entry referenced by put */
2119                                break;
2120                        }
2121                        continue;       /* try again */
2122                }
2123
2124                /*
2125                 * There aren't any available msg entries at this time.
2126                 *
2127                 * In waiting for a message entry to become available,
2128                 * we set a timeout in case the other side is not sending
2129                 * completion interrupts. This lets us fake a notify IRQ
2130                 * that will cause the notify IRQ handler to fetch the latest
2131                 * GP values as if an interrupt was sent by the other side.
2132                 */
2133                if (ret == xpTimeout)
2134                        xpc_send_chctl_local_msgrequest_sn2(ch);
2135
2136                if (flags & XPC_NOWAIT)
2137                        return xpNoWait;
2138
2139                ret = xpc_allocate_msg_wait(ch);
2140                if (ret != xpInterrupted && ret != xpTimeout)
2141                        return ret;
2142        }
2143
2144        /* get the message's address and initialize it */
2145        msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
2146                                     (put % ch->local_nentries) *
2147                                     ch->entry_size);
2148
2149        DBUG_ON(msg->flags != 0);
2150        msg->number = put;
2151
2152        dev_dbg(xpc_chan, "w_local_GP.put changed to %lld; msg=0x%p, "
2153                "msg_number=%lld, partid=%d, channel=%d\n", put + 1,
2154                (void *)msg, msg->number, ch->partid, ch->number);
2155
2156        *address_of_msg = msg;
2157        return xpSuccess;
2158}
2159
2160/*
2161 * Common code that does the actual sending of the message by advancing the
2162 * local message queue's Put value and sends a chctl msgrequest to the
2163 * partition the message is being sent to.
2164 */
2165static enum xp_retval
2166xpc_send_payload_sn2(struct xpc_channel *ch, u32 flags, void *payload,
2167                     u16 payload_size, u8 notify_type, xpc_notify_func func,
2168                     void *key)
2169{
2170        enum xp_retval ret = xpSuccess;
2171        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2172        struct xpc_msg_sn2 *msg = msg;
2173        struct xpc_notify_sn2 *notify = notify;
2174        s64 msg_number;
2175        s64 put;
2176
2177        DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
2178
2179        if (XPC_MSG_SIZE(payload_size) > ch->entry_size)
2180                return xpPayloadTooBig;
2181
2182        xpc_msgqueue_ref(ch);
2183
2184        if (ch->flags & XPC_C_DISCONNECTING) {
2185                ret = ch->reason;
2186                goto out_1;
2187        }
2188        if (!(ch->flags & XPC_C_CONNECTED)) {
2189                ret = xpNotConnected;
2190                goto out_1;
2191        }
2192
2193        ret = xpc_allocate_msg_sn2(ch, flags, &msg);
2194        if (ret != xpSuccess)
2195                goto out_1;
2196
2197        msg_number = msg->number;
2198
2199        if (notify_type != 0) {
2200                /*
2201                 * Tell the remote side to send an ACK interrupt when the
2202                 * message has been delivered.
2203                 */
2204                msg->flags |= XPC_M_SN2_INTERRUPT;
2205
2206                atomic_inc(&ch->n_to_notify);
2207
2208                notify = &ch_sn2->notify_queue[msg_number % ch->local_nentries];
2209                notify->func = func;
2210                notify->key = key;
2211                notify->type = notify_type;
2212
2213                /* ??? Is a mb() needed here? */
2214
2215                if (ch->flags & XPC_C_DISCONNECTING) {
2216                        /*
2217                         * An error occurred between our last error check and
2218                         * this one. We will try to clear the type field from
2219                         * the notify entry. If we succeed then
2220                         * xpc_disconnect_channel() didn't already process
2221                         * the notify entry.
2222                         */
2223                        if (cmpxchg(&notify->type, notify_type, 0) ==
2224                            notify_type) {
2225                                atomic_dec(&ch->n_to_notify);
2226                                ret = ch->reason;
2227                        }
2228                        goto out_1;
2229                }
2230        }
2231
2232        memcpy(&msg->payload, payload, payload_size);
2233
2234        msg->flags |= XPC_M_SN2_READY;
2235
2236        /*
2237         * The preceding store of msg->flags must occur before the following
2238         * load of local_GP->put.
2239         */
2240        smp_mb();
2241
2242        /* see if the message is next in line to be sent, if so send it */
2243
2244        put = ch_sn2->local_GP->put;
2245        if (put == msg_number)
2246                xpc_send_msgs_sn2(ch, put);
2247
2248out_1:
2249        xpc_msgqueue_deref(ch);
2250        return ret;
2251}
2252
2253/*
2254 * Now we actually acknowledge the messages that have been delivered and ack'd
2255 * by advancing the cached remote message queue's Get value and if requested
2256 * send a chctl msgrequest to the message sender's partition.
2257 *
2258 * If a message has XPC_M_SN2_INTERRUPT set, send an interrupt to the partition
2259 * that sent the message.
2260 */
2261static void
2262xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
2263{
2264        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2265        struct xpc_msg_sn2 *msg;
2266        s64 get = initial_get + 1;
2267        int send_msgrequest = 0;
2268
2269        while (1) {
2270
2271                while (1) {
2272                        if (get == ch_sn2->w_local_GP.get)
2273                                break;
2274
2275                        msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
2276                                                     remote_msgqueue + (get %
2277                                                     ch->remote_nentries) *
2278                                                     ch->entry_size);
2279
2280                        if (!(msg->flags & XPC_M_SN2_DONE))
2281                                break;
2282
2283                        msg_flags |= msg->flags;
2284                        get++;
2285                }
2286
2287                if (get == initial_get) {
2288                        /* nothing's changed */
2289                        break;
2290                }
2291
2292                if (cmpxchg_rel(&ch_sn2->local_GP->get, initial_get, get) !=
2293                    initial_get) {
2294                        /* someone else beat us to it */
2295                        DBUG_ON(ch_sn2->local_GP->get <= initial_get);
2296                        break;
2297                }
2298
2299                /* we just set the new value of local_GP->get */
2300
2301                dev_dbg(xpc_chan, "local_GP->get changed to %lld, partid=%d, "
2302                        "channel=%d\n", get, ch->partid, ch->number);
2303
2304                send_msgrequest = (msg_flags & XPC_M_SN2_INTERRUPT);
2305
2306                /*
2307                 * We need to ensure that the message referenced by
2308                 * local_GP->get is not XPC_M_SN2_DONE or that local_GP->get
2309                 * equals w_local_GP.get, so we'll go have a look.
2310                 */
2311                initial_get = get;
2312        }
2313
2314        if (send_msgrequest)
2315                xpc_send_chctl_msgrequest_sn2(ch);
2316}
2317
2318static void
2319xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
2320{
2321        struct xpc_msg_sn2 *msg;
2322        s64 msg_number;
2323        s64 get;
2324
2325        msg = container_of(payload, struct xpc_msg_sn2, payload);
2326        msg_number = msg->number;
2327
2328        dev_dbg(xpc_chan, "msg=0x%p, msg_number=%lld, partid=%d, channel=%d\n",
2329                (void *)msg, msg_number, ch->partid, ch->number);
2330
2331        DBUG_ON((((u64)msg - (u64)ch->sn.sn2.remote_msgqueue) / ch->entry_size) !=
2332                msg_number % ch->remote_nentries);
2333        DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
2334        DBUG_ON(msg->flags & XPC_M_SN2_DONE);
2335
2336        msg->flags |= XPC_M_SN2_DONE;
2337
2338        /*
2339         * The preceding store of msg->flags must occur before the following
2340         * load of local_GP->get.
2341         */
2342        smp_mb();
2343
2344        /*
2345         * See if this message is next in line to be acknowledged as having
2346         * been delivered.
2347         */
2348        get = ch->sn.sn2.local_GP->get;
2349        if (get == msg_number)
2350                xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
2351}
2352
2353static struct xpc_arch_operations xpc_arch_ops_sn2 = {
2354        .setup_partitions = xpc_setup_partitions_sn2,
2355        .teardown_partitions = xpc_teardown_partitions_sn2,
2356        .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2,
2357        .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2,
2358        .setup_rsvd_page = xpc_setup_rsvd_page_sn2,
2359
2360        .allow_hb = xpc_allow_hb_sn2,
2361        .disallow_hb = xpc_disallow_hb_sn2,
2362        .disallow_all_hbs = xpc_disallow_all_hbs_sn2,
2363        .increment_heartbeat = xpc_increment_heartbeat_sn2,
2364        .offline_heartbeat = xpc_offline_heartbeat_sn2,
2365        .online_heartbeat = xpc_online_heartbeat_sn2,
2366        .heartbeat_init = xpc_heartbeat_init_sn2,
2367        .heartbeat_exit = xpc_heartbeat_exit_sn2,
2368        .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2,
2369
2370        .request_partition_activation =
2371                xpc_request_partition_activation_sn2,
2372        .request_partition_reactivation =
2373                xpc_request_partition_reactivation_sn2,
2374        .request_partition_deactivation =
2375                xpc_request_partition_deactivation_sn2,
2376        .cancel_partition_deactivation_request =
2377                xpc_cancel_partition_deactivation_request_sn2,
2378
2379        .setup_ch_structures = xpc_setup_ch_structures_sn2,
2380        .teardown_ch_structures = xpc_teardown_ch_structures_sn2,
2381
2382        .make_first_contact = xpc_make_first_contact_sn2,
2383
2384        .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2,
2385        .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2,
2386        .send_chctl_closereply = xpc_send_chctl_closereply_sn2,
2387        .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2,
2388        .send_chctl_openreply = xpc_send_chctl_openreply_sn2,
2389        .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2,
2390        .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2,
2391
2392        .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2,
2393
2394        .setup_msg_structures = xpc_setup_msg_structures_sn2,
2395        .teardown_msg_structures = xpc_teardown_msg_structures_sn2,
2396
2397        .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2,
2398        .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2,
2399        .partition_engaged = xpc_partition_engaged_sn2,
2400        .any_partition_engaged = xpc_any_partition_engaged_sn2,
2401        .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2,
2402
2403        .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2,
2404        .send_payload = xpc_send_payload_sn2,
2405        .get_deliverable_payload = xpc_get_deliverable_payload_sn2,
2406        .received_payload = xpc_received_payload_sn2,
2407        .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2,
2408};
2409
2410int
2411xpc_init_sn2(void)
2412{
2413        int ret;
2414        size_t buf_size;
2415
2416        xpc_arch_ops = xpc_arch_ops_sn2;
2417
2418        if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) {
2419                dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is "
2420                        "larger than %d\n", XPC_MSG_HDR_MAX_SIZE);
2421                return -E2BIG;
2422        }
2423
2424        buf_size = max(XPC_RP_VARS_SIZE,
2425                       XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES_SN2);
2426        xpc_remote_copy_buffer_sn2 = xpc_kmalloc_cacheline_aligned(buf_size,
2427                                                                   GFP_KERNEL,
2428                                              &xpc_remote_copy_buffer_base_sn2);
2429        if (xpc_remote_copy_buffer_sn2 == NULL) {
2430                dev_err(xpc_part, "can't get memory for remote copy buffer\n");
2431                return -ENOMEM;
2432        }
2433
2434        /* open up protections for IPI and [potentially] amo operations */
2435        xpc_allow_IPI_ops_sn2();
2436        xpc_allow_amo_ops_shub_wars_1_1_sn2();
2437
2438        /*
2439         * This is safe to do before the xpc_hb_checker thread has started
2440         * because the handler releases a wait queue.  If an interrupt is
2441         * received before the thread is waiting, it will not go to sleep,
2442         * but rather immediately process the interrupt.
2443         */
2444        ret = request_irq(SGI_XPC_ACTIVATE, xpc_handle_activate_IRQ_sn2, 0,
2445                          "xpc hb", NULL);
2446        if (ret != 0) {
2447                dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
2448                        "errno=%d\n", -ret);
2449                xpc_disallow_IPI_ops_sn2();
2450                kfree(xpc_remote_copy_buffer_base_sn2);
2451        }
2452        return ret;
2453}
2454
2455void
2456xpc_exit_sn2(void)
2457{
2458        free_irq(SGI_XPC_ACTIVATE, NULL);
2459        xpc_disallow_IPI_ops_sn2();
2460        kfree(xpc_remote_copy_buffer_base_sn2);
2461}
2462