PageRenderTime 105ms CodeModel.GetById 27ms app.highlight 63ms RepoModel.GetById 3ms app.codeStats 0ms

/drivers/misc/sgi-xp/xpc_sn2.c

http://github.com/mirrors/linux
C | 2462 lines | 1562 code | 425 blank | 475 comment | 222 complexity | f9e52eb63bb1695cc3995a59bfeebe9d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   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 <linux/slab.h>
  18#include <asm/uncached.h>
  19#include <asm/sn/mspec.h>
  20#include <asm/sn/sn_sal.h>
  21#include "xpc.h"
  22
  23/*
  24 * Define the number of u64s required to represent all the C-brick nasids
  25 * as a bitmap.  The cross-partition kernel modules deal only with
  26 * C-brick nasids, thus the need for bitmaps which don't account for
  27 * odd-numbered (non C-brick) nasids.
  28 */
  29#define XPC_MAX_PHYSNODES_SN2	(MAX_NUMALINK_NODES / 2)
  30#define XP_NASID_MASK_BYTES_SN2	((XPC_MAX_PHYSNODES_SN2 + 7) / 8)
  31#define XP_NASID_MASK_WORDS_SN2	((XPC_MAX_PHYSNODES_SN2 + 63) / 64)
  32
  33/*
  34 * Memory for XPC's amo variables is allocated by the MSPEC driver. These
  35 * pages are located in the lowest granule. The lowest granule uses 4k pages
  36 * for cached references and an alternate TLB handler to never provide a
  37 * cacheable mapping for the entire region. This will prevent speculative
  38 * reading of cached copies of our lines from being issued which will cause
  39 * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
  40 * amo variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of
  41 * NOTIFY IRQs, 128 amo variables (based on XP_NASID_MASK_WORDS_SN2) to identify
  42 * the senders of ACTIVATE IRQs, 1 amo variable to identify which remote
  43 * partitions (i.e., XPCs) consider themselves currently engaged with the
  44 * local XPC and 1 amo variable to request partition deactivation.
  45 */
  46#define XPC_NOTIFY_IRQ_AMOS_SN2		0
  47#define XPC_ACTIVATE_IRQ_AMOS_SN2	(XPC_NOTIFY_IRQ_AMOS_SN2 + \
  48					 XP_MAX_NPARTITIONS_SN2)
  49#define XPC_ENGAGED_PARTITIONS_AMO_SN2	(XPC_ACTIVATE_IRQ_AMOS_SN2 + \
  50					 XP_NASID_MASK_WORDS_SN2)
  51#define XPC_DEACTIVATE_REQUEST_AMO_SN2	(XPC_ENGAGED_PARTITIONS_AMO_SN2 + 1)
  52
  53/*
  54 * Buffer used to store a local copy of portions of a remote partition's
  55 * reserved page (either its header and part_nasids mask, or its vars).
  56 */
  57static void *xpc_remote_copy_buffer_base_sn2;
  58static char *xpc_remote_copy_buffer_sn2;
  59
  60static struct xpc_vars_sn2 *xpc_vars_sn2;
  61static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
  62
  63static int
  64xpc_setup_partitions_sn2(void)
  65{
  66	/* nothing needs to be done */
  67	return 0;
  68}
  69
  70static void
  71xpc_teardown_partitions_sn2(void)
  72{
  73	/* nothing needs to be done */
  74}
  75
  76/* SH_IPI_ACCESS shub register value on startup */
  77static u64 xpc_sh1_IPI_access_sn2;
  78static u64 xpc_sh2_IPI_access0_sn2;
  79static u64 xpc_sh2_IPI_access1_sn2;
  80static u64 xpc_sh2_IPI_access2_sn2;
  81static u64 xpc_sh2_IPI_access3_sn2;
  82
  83/*
  84 * Change protections to allow IPI operations.
  85 */
  86static void
  87xpc_allow_IPI_ops_sn2(void)
  88{
  89	int node;
  90	int nasid;
  91
  92	/* !!! The following should get moved into SAL. */
  93	if (is_shub2()) {
  94		xpc_sh2_IPI_access0_sn2 =
  95		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
  96		xpc_sh2_IPI_access1_sn2 =
  97		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
  98		xpc_sh2_IPI_access2_sn2 =
  99		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
 100		xpc_sh2_IPI_access3_sn2 =
 101		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
 102
 103		for_each_online_node(node) {
 104			nasid = cnodeid_to_nasid(node);
 105			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
 106			      -1UL);
 107			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
 108			      -1UL);
 109			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
 110			      -1UL);
 111			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
 112			      -1UL);
 113		}
 114	} else {
 115		xpc_sh1_IPI_access_sn2 =
 116		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
 117
 118		for_each_online_node(node) {
 119			nasid = cnodeid_to_nasid(node);
 120			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
 121			      -1UL);
 122		}
 123	}
 124}
 125
 126/*
 127 * Restrict protections to disallow IPI operations.
 128 */
 129static void
 130xpc_disallow_IPI_ops_sn2(void)
 131{
 132	int node;
 133	int nasid;
 134
 135	/* !!! The following should get moved into SAL. */
 136	if (is_shub2()) {
 137		for_each_online_node(node) {
 138			nasid = cnodeid_to_nasid(node);
 139			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
 140			      xpc_sh2_IPI_access0_sn2);
 141			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
 142			      xpc_sh2_IPI_access1_sn2);
 143			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
 144			      xpc_sh2_IPI_access2_sn2);
 145			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
 146			      xpc_sh2_IPI_access3_sn2);
 147		}
 148	} else {
 149		for_each_online_node(node) {
 150			nasid = cnodeid_to_nasid(node);
 151			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
 152			      xpc_sh1_IPI_access_sn2);
 153		}
 154	}
 155}
 156
 157/*
 158 * The following set of functions are used for the sending and receiving of
 159 * IRQs (also known as IPIs). There are two flavors of IRQs, one that is
 160 * associated with partition activity (SGI_XPC_ACTIVATE) and the other that
 161 * is associated with channel activity (SGI_XPC_NOTIFY).
 162 */
 163
 164static u64
 165xpc_receive_IRQ_amo_sn2(struct amo *amo)
 166{
 167	return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
 168}
 169
 170static enum xp_retval
 171xpc_send_IRQ_sn2(struct amo *amo, u64 flag, int nasid, int phys_cpuid,
 172		 int vector)
 173{
 174	int ret = 0;
 175	unsigned long irq_flags;
 176
 177	local_irq_save(irq_flags);
 178
 179	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
 180	sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
 181
 182	/*
 183	 * We must always use the nofault function regardless of whether we
 184	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 185	 * didn't, we'd never know that the other partition is down and would
 186	 * keep sending IRQs and amos to it until the heartbeat times out.
 187	 */
 188	ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
 189						     xp_nofault_PIOR_target));
 190
 191	local_irq_restore(irq_flags);
 192
 193	return (ret == 0) ? xpSuccess : xpPioReadError;
 194}
 195
 196static struct amo *
 197xpc_init_IRQ_amo_sn2(int index)
 198{
 199	struct amo *amo = xpc_vars_sn2->amos_page + index;
 200
 201	(void)xpc_receive_IRQ_amo_sn2(amo);	/* clear amo variable */
 202	return amo;
 203}
 204
 205/*
 206 * Functions associated with SGI_XPC_ACTIVATE IRQ.
 207 */
 208
 209/*
 210 * Notify the heartbeat check thread that an activate IRQ has been received.
 211 */
 212static irqreturn_t
 213xpc_handle_activate_IRQ_sn2(int irq, void *dev_id)
 214{
 215	unsigned long irq_flags;
 216
 217	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 218	xpc_activate_IRQ_rcvd++;
 219	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 220
 221	wake_up_interruptible(&xpc_activate_IRQ_wq);
 222	return IRQ_HANDLED;
 223}
 224
 225/*
 226 * Flag the appropriate amo variable and send an IRQ to the specified node.
 227 */
 228static void
 229xpc_send_activate_IRQ_sn2(unsigned long amos_page_pa, int from_nasid,
 230			  int to_nasid, int to_phys_cpuid)
 231{
 232	struct amo *amos = (struct amo *)__va(amos_page_pa +
 233					      (XPC_ACTIVATE_IRQ_AMOS_SN2 *
 234					      sizeof(struct amo)));
 235
 236	(void)xpc_send_IRQ_sn2(&amos[BIT_WORD(from_nasid / 2)],
 237			       BIT_MASK(from_nasid / 2), to_nasid,
 238			       to_phys_cpuid, SGI_XPC_ACTIVATE);
 239}
 240
 241static void
 242xpc_send_local_activate_IRQ_sn2(int from_nasid)
 243{
 244	unsigned long irq_flags;
 245	struct amo *amos = (struct amo *)__va(xpc_vars_sn2->amos_page_pa +
 246					      (XPC_ACTIVATE_IRQ_AMOS_SN2 *
 247					      sizeof(struct amo)));
 248
 249	/* fake the sending and receipt of an activate IRQ from remote nasid */
 250	FETCHOP_STORE_OP(TO_AMO((u64)&amos[BIT_WORD(from_nasid / 2)].variable),
 251			 FETCHOP_OR, BIT_MASK(from_nasid / 2));
 252
 253	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 254	xpc_activate_IRQ_rcvd++;
 255	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
 256
 257	wake_up_interruptible(&xpc_activate_IRQ_wq);
 258}
 259
 260/*
 261 * Functions associated with SGI_XPC_NOTIFY IRQ.
 262 */
 263
 264/*
 265 * Check to see if any chctl flags were sent from the specified partition.
 266 */
 267static void
 268xpc_check_for_sent_chctl_flags_sn2(struct xpc_partition *part)
 269{
 270	union xpc_channel_ctl_flags chctl;
 271	unsigned long irq_flags;
 272
 273	chctl.all_flags = xpc_receive_IRQ_amo_sn2(part->sn.sn2.
 274						  local_chctl_amo_va);
 275	if (chctl.all_flags == 0)
 276		return;
 277
 278	spin_lock_irqsave(&part->chctl_lock, irq_flags);
 279	part->chctl.all_flags |= chctl.all_flags;
 280	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
 281
 282	dev_dbg(xpc_chan, "received notify IRQ from partid=%d, chctl.all_flags="
 283		"0x%llx\n", XPC_PARTID(part), chctl.all_flags);
 284
 285	xpc_wakeup_channel_mgr(part);
 286}
 287
 288/*
 289 * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
 290 * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
 291 * than one partition, we use an amo structure per partition to indicate
 292 * whether a partition has sent an IRQ or not.  If it has, then wake up the
 293 * associated kthread to handle it.
 294 *
 295 * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IRQs sent by XPC
 296 * running on other partitions.
 297 *
 298 * Noteworthy Arguments:
 299 *
 300 *	irq - Interrupt ReQuest number. NOT USED.
 301 *
 302 *	dev_id - partid of IRQ's potential sender.
 303 */
 304static irqreturn_t
 305xpc_handle_notify_IRQ_sn2(int irq, void *dev_id)
 306{
 307	short partid = (short)(u64)dev_id;
 308	struct xpc_partition *part = &xpc_partitions[partid];
 309
 310	DBUG_ON(partid < 0 || partid >= XP_MAX_NPARTITIONS_SN2);
 311
 312	if (xpc_part_ref(part)) {
 313		xpc_check_for_sent_chctl_flags_sn2(part);
 314
 315		xpc_part_deref(part);
 316	}
 317	return IRQ_HANDLED;
 318}
 319
 320/*
 321 * Check to see if xpc_handle_notify_IRQ_sn2() dropped any IRQs on the floor
 322 * because the write to their associated amo variable completed after the IRQ
 323 * was received.
 324 */
 325static void
 326xpc_check_for_dropped_notify_IRQ_sn2(struct xpc_partition *part)
 327{
 328	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 329
 330	if (xpc_part_ref(part)) {
 331		xpc_check_for_sent_chctl_flags_sn2(part);
 332
 333		part_sn2->dropped_notify_IRQ_timer.expires = jiffies +
 334		    XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
 335		add_timer(&part_sn2->dropped_notify_IRQ_timer);
 336		xpc_part_deref(part);
 337	}
 338}
 339
 340/*
 341 * Send a notify IRQ to the remote partition that is associated with the
 342 * specified channel.
 343 */
 344static void
 345xpc_send_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
 346			char *chctl_flag_string, unsigned long *irq_flags)
 347{
 348	struct xpc_partition *part = &xpc_partitions[ch->partid];
 349	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 350	union xpc_channel_ctl_flags chctl = { 0 };
 351	enum xp_retval ret;
 352
 353	if (likely(part->act_state != XPC_P_AS_DEACTIVATING)) {
 354		chctl.flags[ch->number] = chctl_flag;
 355		ret = xpc_send_IRQ_sn2(part_sn2->remote_chctl_amo_va,
 356				       chctl.all_flags,
 357				       part_sn2->notify_IRQ_nasid,
 358				       part_sn2->notify_IRQ_phys_cpuid,
 359				       SGI_XPC_NOTIFY);
 360		dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
 361			chctl_flag_string, ch->partid, ch->number, ret);
 362		if (unlikely(ret != xpSuccess)) {
 363			if (irq_flags != NULL)
 364				spin_unlock_irqrestore(&ch->lock, *irq_flags);
 365			XPC_DEACTIVATE_PARTITION(part, ret);
 366			if (irq_flags != NULL)
 367				spin_lock_irqsave(&ch->lock, *irq_flags);
 368		}
 369	}
 370}
 371
 372#define XPC_SEND_NOTIFY_IRQ_SN2(_ch, _ipi_f, _irq_f) \
 373		xpc_send_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
 374
 375/*
 376 * Make it look like the remote partition, which is associated with the
 377 * specified channel, sent us a notify IRQ. This faked IRQ will be handled
 378 * by xpc_check_for_dropped_notify_IRQ_sn2().
 379 */
 380static void
 381xpc_send_local_notify_IRQ_sn2(struct xpc_channel *ch, u8 chctl_flag,
 382			      char *chctl_flag_string)
 383{
 384	struct xpc_partition *part = &xpc_partitions[ch->partid];
 385	union xpc_channel_ctl_flags chctl = { 0 };
 386
 387	chctl.flags[ch->number] = chctl_flag;
 388	FETCHOP_STORE_OP(TO_AMO((u64)&part->sn.sn2.local_chctl_amo_va->
 389				variable), FETCHOP_OR, chctl.all_flags);
 390	dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
 391		chctl_flag_string, ch->partid, ch->number);
 392}
 393
 394#define XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(_ch, _ipi_f) \
 395		xpc_send_local_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f)
 396
 397static void
 398xpc_send_chctl_closerequest_sn2(struct xpc_channel *ch,
 399				unsigned long *irq_flags)
 400{
 401	struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 402
 403	args->reason = ch->reason;
 404	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREQUEST, irq_flags);
 405}
 406
 407static void
 408xpc_send_chctl_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 409{
 410	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREPLY, irq_flags);
 411}
 412
 413static void
 414xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 415{
 416	struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 417
 418	args->entry_size = ch->entry_size;
 419	args->local_nentries = ch->local_nentries;
 420	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREQUEST, irq_flags);
 421}
 422
 423static void
 424xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 425{
 426	struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
 427
 428	args->remote_nentries = ch->remote_nentries;
 429	args->local_nentries = ch->local_nentries;
 430	args->local_msgqueue_pa = xp_pa(ch->sn.sn2.local_msgqueue);
 431	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREPLY, irq_flags);
 432}
 433
 434static void
 435xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch,
 436				unsigned long *irq_flags)
 437{
 438	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags);
 439}
 440
 441static void
 442xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch)
 443{
 444	XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL);
 445}
 446
 447static void
 448xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch)
 449{
 450	XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST);
 451}
 452
 453static enum xp_retval
 454xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch,
 455				unsigned long msgqueue_pa)
 456{
 457	ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa;
 458	return xpSuccess;
 459}
 460
 461/*
 462 * This next set of functions are used to keep track of when a partition is
 463 * potentially engaged in accessing memory belonging to another partition.
 464 */
 465
 466static void
 467xpc_indicate_partition_engaged_sn2(struct xpc_partition *part)
 468{
 469	unsigned long irq_flags;
 470	struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
 471					     (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
 472					     sizeof(struct amo)));
 473
 474	local_irq_save(irq_flags);
 475
 476	/* set bit corresponding to our partid in remote partition's amo */
 477	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
 478			 BIT(sn_partition_id));
 479
 480	/*
 481	 * We must always use the nofault function regardless of whether we
 482	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 483	 * didn't, we'd never know that the other partition is down and would
 484	 * keep sending IRQs and amos to it until the heartbeat times out.
 485	 */
 486	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 487							       variable),
 488						     xp_nofault_PIOR_target));
 489
 490	local_irq_restore(irq_flags);
 491}
 492
 493static void
 494xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part)
 495{
 496	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 497	unsigned long irq_flags;
 498	struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
 499					     (XPC_ENGAGED_PARTITIONS_AMO_SN2 *
 500					     sizeof(struct amo)));
 501
 502	local_irq_save(irq_flags);
 503
 504	/* clear bit corresponding to our partid in remote partition's amo */
 505	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 506			 ~BIT(sn_partition_id));
 507
 508	/*
 509	 * We must always use the nofault function regardless of whether we
 510	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 511	 * didn't, we'd never know that the other partition is down and would
 512	 * keep sending IRQs and amos to it until the heartbeat times out.
 513	 */
 514	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 515							       variable),
 516						     xp_nofault_PIOR_target));
 517
 518	local_irq_restore(irq_flags);
 519
 520	/*
 521	 * Send activate IRQ to get other side to see that we've cleared our
 522	 * bit in their engaged partitions amo.
 523	 */
 524	xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
 525				  cnodeid_to_nasid(0),
 526				  part_sn2->activate_IRQ_nasid,
 527				  part_sn2->activate_IRQ_phys_cpuid);
 528}
 529
 530static void
 531xpc_assume_partition_disengaged_sn2(short partid)
 532{
 533	struct amo *amo = xpc_vars_sn2->amos_page +
 534			  XPC_ENGAGED_PARTITIONS_AMO_SN2;
 535
 536	/* clear bit(s) based on partid mask in our partition's amo */
 537	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 538			 ~BIT(partid));
 539}
 540
 541static int
 542xpc_partition_engaged_sn2(short partid)
 543{
 544	struct amo *amo = xpc_vars_sn2->amos_page +
 545			  XPC_ENGAGED_PARTITIONS_AMO_SN2;
 546
 547	/* our partition's amo variable ANDed with partid mask */
 548	return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
 549		BIT(partid)) != 0;
 550}
 551
 552static int
 553xpc_any_partition_engaged_sn2(void)
 554{
 555	struct amo *amo = xpc_vars_sn2->amos_page +
 556			  XPC_ENGAGED_PARTITIONS_AMO_SN2;
 557
 558	/* our partition's amo variable */
 559	return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0;
 560}
 561
 562/* original protection values for each node */
 563static u64 xpc_prot_vec_sn2[MAX_NUMNODES];
 564
 565/*
 566 * Change protections to allow amo operations on non-Shub 1.1 systems.
 567 */
 568static enum xp_retval
 569xpc_allow_amo_ops_sn2(struct amo *amos_page)
 570{
 571	enum xp_retval ret = xpSuccess;
 572
 573	/*
 574	 * On SHUB 1.1, we cannot call sn_change_memprotect() since the BIST
 575	 * collides with memory operations. On those systems we call
 576	 * xpc_allow_amo_ops_shub_wars_1_1_sn2() instead.
 577	 */
 578	if (!enable_shub_wars_1_1())
 579		ret = xp_expand_memprotect(ia64_tpa((u64)amos_page), PAGE_SIZE);
 580
 581	return ret;
 582}
 583
 584/*
 585 * Change protections to allow amo operations on Shub 1.1 systems.
 586 */
 587static void
 588xpc_allow_amo_ops_shub_wars_1_1_sn2(void)
 589{
 590	int node;
 591	int nasid;
 592
 593	if (!enable_shub_wars_1_1())
 594		return;
 595
 596	for_each_online_node(node) {
 597		nasid = cnodeid_to_nasid(node);
 598		/* save current protection values */
 599		xpc_prot_vec_sn2[node] =
 600		    (u64)HUB_L((u64 *)GLOBAL_MMR_ADDR(nasid,
 601						  SH1_MD_DQLP_MMR_DIR_PRIVEC0));
 602		/* open up everything */
 603		HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
 604					     SH1_MD_DQLP_MMR_DIR_PRIVEC0),
 605		      -1UL);
 606		HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
 607					     SH1_MD_DQRP_MMR_DIR_PRIVEC0),
 608		      -1UL);
 609	}
 610}
 611
 612static enum xp_retval
 613xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
 614				   size_t *len)
 615{
 616	s64 status;
 617	enum xp_retval ret;
 618
 619	status = sn_partition_reserved_page_pa((u64)buf, cookie,
 620			(u64 *)rp_pa, (u64 *)len);
 621	if (status == SALRET_OK)
 622		ret = xpSuccess;
 623	else if (status == SALRET_MORE_PASSES)
 624		ret = xpNeedMoreInfo;
 625	else
 626		ret = xpSalError;
 627
 628	return ret;
 629}
 630
 631
 632static int
 633xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp)
 634{
 635	struct amo *amos_page;
 636	int i;
 637	int ret;
 638
 639	xpc_vars_sn2 = XPC_RP_VARS(rp);
 640
 641	rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2);
 642
 643	/* vars_part array follows immediately after vars */
 644	xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
 645							 XPC_RP_VARS_SIZE);
 646
 647	/*
 648	 * Before clearing xpc_vars_sn2, see if a page of amos had been
 649	 * previously allocated. If not we'll need to allocate one and set
 650	 * permissions so that cross-partition amos are allowed.
 651	 *
 652	 * The allocated amo page needs MCA reporting to remain disabled after
 653	 * XPC has unloaded.  To make this work, we keep a copy of the pointer
 654	 * to this page (i.e., amos_page) in the struct xpc_vars_sn2 structure,
 655	 * which is pointed to by the reserved page, and re-use that saved copy
 656	 * on subsequent loads of XPC. This amo page is never freed, and its
 657	 * memory protections are never restricted.
 658	 */
 659	amos_page = xpc_vars_sn2->amos_page;
 660	if (amos_page == NULL) {
 661		amos_page = (struct amo *)TO_AMO(uncached_alloc_page(0, 1));
 662		if (amos_page == NULL) {
 663			dev_err(xpc_part, "can't allocate page of amos\n");
 664			return -ENOMEM;
 665		}
 666
 667		/*
 668		 * Open up amo-R/W to cpu.  This is done on Shub 1.1 systems
 669		 * when xpc_allow_amo_ops_shub_wars_1_1_sn2() is called.
 670		 */
 671		ret = xpc_allow_amo_ops_sn2(amos_page);
 672		if (ret != xpSuccess) {
 673			dev_err(xpc_part, "can't allow amo operations\n");
 674			uncached_free_page(__IA64_UNCACHED_OFFSET |
 675					   TO_PHYS((u64)amos_page), 1);
 676			return -EPERM;
 677		}
 678	}
 679
 680	/* clear xpc_vars_sn2 */
 681	memset(xpc_vars_sn2, 0, sizeof(struct xpc_vars_sn2));
 682
 683	xpc_vars_sn2->version = XPC_V_VERSION;
 684	xpc_vars_sn2->activate_IRQ_nasid = cpuid_to_nasid(0);
 685	xpc_vars_sn2->activate_IRQ_phys_cpuid = cpu_physical_id(0);
 686	xpc_vars_sn2->vars_part_pa = xp_pa(xpc_vars_part_sn2);
 687	xpc_vars_sn2->amos_page_pa = ia64_tpa((u64)amos_page);
 688	xpc_vars_sn2->amos_page = amos_page;	/* save for next load of XPC */
 689
 690	/* clear xpc_vars_part_sn2 */
 691	memset((u64 *)xpc_vars_part_sn2, 0, sizeof(struct xpc_vars_part_sn2) *
 692	       XP_MAX_NPARTITIONS_SN2);
 693
 694	/* initialize the activate IRQ related amo variables */
 695	for (i = 0; i < xpc_nasid_mask_nlongs; i++)
 696		(void)xpc_init_IRQ_amo_sn2(XPC_ACTIVATE_IRQ_AMOS_SN2 + i);
 697
 698	/* initialize the engaged remote partitions related amo variables */
 699	(void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO_SN2);
 700	(void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO_SN2);
 701
 702	return 0;
 703}
 704
 705static int
 706xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
 707{
 708	return test_bit(partid, heartbeating_to_mask);
 709}
 710
 711static void
 712xpc_allow_hb_sn2(short partid)
 713{
 714	DBUG_ON(xpc_vars_sn2 == NULL);
 715	set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
 716}
 717
 718static void
 719xpc_disallow_hb_sn2(short partid)
 720{
 721	DBUG_ON(xpc_vars_sn2 == NULL);
 722	clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
 723}
 724
 725static void
 726xpc_disallow_all_hbs_sn2(void)
 727{
 728	DBUG_ON(xpc_vars_sn2 == NULL);
 729	bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions);
 730}
 731
 732static void
 733xpc_increment_heartbeat_sn2(void)
 734{
 735	xpc_vars_sn2->heartbeat++;
 736}
 737
 738static void
 739xpc_offline_heartbeat_sn2(void)
 740{
 741	xpc_increment_heartbeat_sn2();
 742	xpc_vars_sn2->heartbeat_offline = 1;
 743}
 744
 745static void
 746xpc_online_heartbeat_sn2(void)
 747{
 748	xpc_increment_heartbeat_sn2();
 749	xpc_vars_sn2->heartbeat_offline = 0;
 750}
 751
 752static void
 753xpc_heartbeat_init_sn2(void)
 754{
 755	DBUG_ON(xpc_vars_sn2 == NULL);
 756
 757	bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
 758	xpc_online_heartbeat_sn2();
 759}
 760
 761static void
 762xpc_heartbeat_exit_sn2(void)
 763{
 764	xpc_offline_heartbeat_sn2();
 765}
 766
 767static enum xp_retval
 768xpc_get_remote_heartbeat_sn2(struct xpc_partition *part)
 769{
 770	struct xpc_vars_sn2 *remote_vars;
 771	enum xp_retval ret;
 772
 773	remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
 774
 775	/* pull the remote vars structure that contains the heartbeat */
 776	ret = xp_remote_memcpy(xp_pa(remote_vars),
 777			       part->sn.sn2.remote_vars_pa,
 778			       XPC_RP_VARS_SIZE);
 779	if (ret != xpSuccess)
 780		return ret;
 781
 782	dev_dbg(xpc_part, "partid=%d, heartbeat=%lld, last_heartbeat=%lld, "
 783		"heartbeat_offline=%lld, HB_mask[0]=0x%lx\n", XPC_PARTID(part),
 784		remote_vars->heartbeat, part->last_heartbeat,
 785		remote_vars->heartbeat_offline,
 786		remote_vars->heartbeating_to_mask[0]);
 787
 788	if ((remote_vars->heartbeat == part->last_heartbeat &&
 789	    !remote_vars->heartbeat_offline) ||
 790	    !xpc_hb_allowed_sn2(sn_partition_id,
 791				remote_vars->heartbeating_to_mask)) {
 792		ret = xpNoHeartbeat;
 793	} else {
 794		part->last_heartbeat = remote_vars->heartbeat;
 795	}
 796
 797	return ret;
 798}
 799
 800/*
 801 * Get a copy of the remote partition's XPC variables from the reserved page.
 802 *
 803 * remote_vars points to a buffer that is cacheline aligned for BTE copies and
 804 * assumed to be of size XPC_RP_VARS_SIZE.
 805 */
 806static enum xp_retval
 807xpc_get_remote_vars_sn2(unsigned long remote_vars_pa,
 808			struct xpc_vars_sn2 *remote_vars)
 809{
 810	enum xp_retval ret;
 811
 812	if (remote_vars_pa == 0)
 813		return xpVarsNotSet;
 814
 815	/* pull over the cross partition variables */
 816	ret = xp_remote_memcpy(xp_pa(remote_vars), remote_vars_pa,
 817			       XPC_RP_VARS_SIZE);
 818	if (ret != xpSuccess)
 819		return ret;
 820
 821	if (XPC_VERSION_MAJOR(remote_vars->version) !=
 822	    XPC_VERSION_MAJOR(XPC_V_VERSION)) {
 823		return xpBadVersion;
 824	}
 825
 826	return xpSuccess;
 827}
 828
 829static void
 830xpc_request_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
 831				     unsigned long remote_rp_pa, int nasid)
 832{
 833	xpc_send_local_activate_IRQ_sn2(nasid);
 834}
 835
 836static void
 837xpc_request_partition_reactivation_sn2(struct xpc_partition *part)
 838{
 839	xpc_send_local_activate_IRQ_sn2(part->sn.sn2.activate_IRQ_nasid);
 840}
 841
 842static void
 843xpc_request_partition_deactivation_sn2(struct xpc_partition *part)
 844{
 845	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 846	unsigned long irq_flags;
 847	struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa +
 848					     (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
 849					     sizeof(struct amo)));
 850
 851	local_irq_save(irq_flags);
 852
 853	/* set bit corresponding to our partid in remote partition's amo */
 854	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
 855			 BIT(sn_partition_id));
 856
 857	/*
 858	 * We must always use the nofault function regardless of whether we
 859	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 860	 * didn't, we'd never know that the other partition is down and would
 861	 * keep sending IRQs and amos to it until the heartbeat times out.
 862	 */
 863	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 864							       variable),
 865						     xp_nofault_PIOR_target));
 866
 867	local_irq_restore(irq_flags);
 868
 869	/*
 870	 * Send activate IRQ to get other side to see that we've set our
 871	 * bit in their deactivate request amo.
 872	 */
 873	xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
 874				  cnodeid_to_nasid(0),
 875				  part_sn2->activate_IRQ_nasid,
 876				  part_sn2->activate_IRQ_phys_cpuid);
 877}
 878
 879static void
 880xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part)
 881{
 882	unsigned long irq_flags;
 883	struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa +
 884					     (XPC_DEACTIVATE_REQUEST_AMO_SN2 *
 885					     sizeof(struct amo)));
 886
 887	local_irq_save(irq_flags);
 888
 889	/* clear bit corresponding to our partid in remote partition's amo */
 890	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
 891			 ~BIT(sn_partition_id));
 892
 893	/*
 894	 * We must always use the nofault function regardless of whether we
 895	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
 896	 * didn't, we'd never know that the other partition is down and would
 897	 * keep sending IRQs and amos to it until the heartbeat times out.
 898	 */
 899	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
 900							       variable),
 901						     xp_nofault_PIOR_target));
 902
 903	local_irq_restore(irq_flags);
 904}
 905
 906static int
 907xpc_partition_deactivation_requested_sn2(short partid)
 908{
 909	struct amo *amo = xpc_vars_sn2->amos_page +
 910			  XPC_DEACTIVATE_REQUEST_AMO_SN2;
 911
 912	/* our partition's amo variable ANDed with partid mask */
 913	return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
 914		BIT(partid)) != 0;
 915}
 916
 917/*
 918 * Update the remote partition's info.
 919 */
 920static void
 921xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
 922			      unsigned long *remote_rp_ts_jiffies,
 923			      unsigned long remote_rp_pa,
 924			      unsigned long remote_vars_pa,
 925			      struct xpc_vars_sn2 *remote_vars)
 926{
 927	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
 928
 929	part->remote_rp_version = remote_rp_version;
 930	dev_dbg(xpc_part, "  remote_rp_version = 0x%016x\n",
 931		part->remote_rp_version);
 932
 933	part->remote_rp_ts_jiffies = *remote_rp_ts_jiffies;
 934	dev_dbg(xpc_part, "  remote_rp_ts_jiffies = 0x%016lx\n",
 935		part->remote_rp_ts_jiffies);
 936
 937	part->remote_rp_pa = remote_rp_pa;
 938	dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
 939
 940	part_sn2->remote_vars_pa = remote_vars_pa;
 941	dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
 942		part_sn2->remote_vars_pa);
 943
 944	part->last_heartbeat = remote_vars->heartbeat - 1;
 945	dev_dbg(xpc_part, "  last_heartbeat = 0x%016llx\n",
 946		part->last_heartbeat);
 947
 948	part_sn2->remote_vars_part_pa = remote_vars->vars_part_pa;
 949	dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
 950		part_sn2->remote_vars_part_pa);
 951
 952	part_sn2->activate_IRQ_nasid = remote_vars->activate_IRQ_nasid;
 953	dev_dbg(xpc_part, "  activate_IRQ_nasid = 0x%x\n",
 954		part_sn2->activate_IRQ_nasid);
 955
 956	part_sn2->activate_IRQ_phys_cpuid =
 957	    remote_vars->activate_IRQ_phys_cpuid;
 958	dev_dbg(xpc_part, "  activate_IRQ_phys_cpuid = 0x%x\n",
 959		part_sn2->activate_IRQ_phys_cpuid);
 960
 961	part_sn2->remote_amos_page_pa = remote_vars->amos_page_pa;
 962	dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
 963		part_sn2->remote_amos_page_pa);
 964
 965	part_sn2->remote_vars_version = remote_vars->version;
 966	dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
 967		part_sn2->remote_vars_version);
 968}
 969
 970/*
 971 * Prior code has determined the nasid which generated a activate IRQ.
 972 * Inspect that nasid to determine if its partition needs to be activated
 973 * or deactivated.
 974 *
 975 * A partition is considered "awaiting activation" if our partition
 976 * flags indicate it is not active and it has a heartbeat.  A
 977 * partition is considered "awaiting deactivation" if our partition
 978 * flags indicate it is active but it has no heartbeat or it is not
 979 * sending its heartbeat to us.
 980 *
 981 * To determine the heartbeat, the remote nasid must have a properly
 982 * initialized reserved page.
 983 */
 984static void
 985xpc_identify_activate_IRQ_req_sn2(int nasid)
 986{
 987	struct xpc_rsvd_page *remote_rp;
 988	struct xpc_vars_sn2 *remote_vars;
 989	unsigned long remote_rp_pa;
 990	unsigned long remote_vars_pa;
 991	int remote_rp_version;
 992	int reactivate = 0;
 993	unsigned long remote_rp_ts_jiffies = 0;
 994	short partid;
 995	struct xpc_partition *part;
 996	struct xpc_partition_sn2 *part_sn2;
 997	enum xp_retval ret;
 998
 999	/* pull over the reserved page structure */
1000
1001	remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer_sn2;
1002
1003	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
1004	if (ret != xpSuccess) {
1005		dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
1006			 "which sent interrupt, reason=%d\n", nasid, ret);
1007		return;
1008	}
1009
1010	remote_vars_pa = remote_rp->sn.sn2.vars_pa;
1011	remote_rp_version = remote_rp->version;
1012	remote_rp_ts_jiffies = remote_rp->ts_jiffies;
1013
1014	partid = remote_rp->SAL_partid;
1015	part = &xpc_partitions[partid];
1016	part_sn2 = &part->sn.sn2;
1017
1018	/* pull over the cross partition variables */
1019
1020	remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
1021
1022	ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
1023	if (ret != xpSuccess) {
1024		dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
1025			 "which sent interrupt, reason=%d\n", nasid, ret);
1026
1027		XPC_DEACTIVATE_PARTITION(part, ret);
1028		return;
1029	}
1030
1031	part->activate_IRQ_rcvd++;
1032
1033	dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
1034		"%lld:0x%lx\n", (int)nasid, (int)partid,
1035		part->activate_IRQ_rcvd,
1036		remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
1037
1038	if (xpc_partition_disengaged(part) &&
1039	    part->act_state == XPC_P_AS_INACTIVE) {
1040
1041		xpc_update_partition_info_sn2(part, remote_rp_version,
1042					      &remote_rp_ts_jiffies,
1043					      remote_rp_pa, remote_vars_pa,
1044					      remote_vars);
1045
1046		if (xpc_partition_deactivation_requested_sn2(partid)) {
1047			/*
1048			 * Other side is waiting on us to deactivate even though
1049			 * we already have.
1050			 */
1051			return;
1052		}
1053
1054		xpc_activate_partition(part);
1055		return;
1056	}
1057
1058	DBUG_ON(part->remote_rp_version == 0);
1059	DBUG_ON(part_sn2->remote_vars_version == 0);
1060
1061	if (remote_rp_ts_jiffies != part->remote_rp_ts_jiffies) {
1062
1063		/* the other side rebooted */
1064
1065		DBUG_ON(xpc_partition_engaged_sn2(partid));
1066		DBUG_ON(xpc_partition_deactivation_requested_sn2(partid));
1067
1068		xpc_update_partition_info_sn2(part, remote_rp_version,
1069					      &remote_rp_ts_jiffies,
1070					      remote_rp_pa, remote_vars_pa,
1071					      remote_vars);
1072		reactivate = 1;
1073	}
1074
1075	if (part->disengage_timeout > 0 && !xpc_partition_disengaged(part)) {
1076		/* still waiting on other side to disengage from us */
1077		return;
1078	}
1079
1080	if (reactivate)
1081		XPC_DEACTIVATE_PARTITION(part, xpReactivating);
1082	else if (xpc_partition_deactivation_requested_sn2(partid))
1083		XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
1084}
1085
1086/*
1087 * Loop through the activation amo variables and process any bits
1088 * which are set.  Each bit indicates a nasid sending a partition
1089 * activation or deactivation request.
1090 *
1091 * Return #of IRQs detected.
1092 */
1093int
1094xpc_identify_activate_IRQ_sender_sn2(void)
1095{
1096	int l;
1097	int b;
1098	unsigned long nasid_mask_long;
1099	u64 nasid;		/* remote nasid */
1100	int n_IRQs_detected = 0;
1101	struct amo *act_amos;
1102
1103	act_amos = xpc_vars_sn2->amos_page + XPC_ACTIVATE_IRQ_AMOS_SN2;
1104
1105	/* scan through activate amo variables looking for non-zero entries */
1106	for (l = 0; l < xpc_nasid_mask_nlongs; l++) {
1107
1108		if (xpc_exiting)
1109			break;
1110
1111		nasid_mask_long = xpc_receive_IRQ_amo_sn2(&act_amos[l]);
1112
1113		b = find_first_bit(&nasid_mask_long, BITS_PER_LONG);
1114		if (b >= BITS_PER_LONG) {
1115			/* no IRQs from nasids in this amo variable */
1116			continue;
1117		}
1118
1119		dev_dbg(xpc_part, "amo[%d] gave back 0x%lx\n", l,
1120			nasid_mask_long);
1121
1122		/*
1123		 * If this nasid has been added to the machine since
1124		 * our partition was reset, this will retain the
1125		 * remote nasid in our reserved pages machine mask.
1126		 * This is used in the event of module reload.
1127		 */
1128		xpc_mach_nasids[l] |= nasid_mask_long;
1129
1130		/* locate the nasid(s) which sent interrupts */
1131
1132		do {
1133			n_IRQs_detected++;
1134			nasid = (l * BITS_PER_LONG + b) * 2;
1135			dev_dbg(xpc_part, "interrupt from nasid %lld\n", nasid);
1136			xpc_identify_activate_IRQ_req_sn2(nasid);
1137
1138			b = find_next_bit(&nasid_mask_long, BITS_PER_LONG,
1139					  b + 1);
1140		} while (b < BITS_PER_LONG);
1141	}
1142	return n_IRQs_detected;
1143}
1144
1145static void
1146xpc_process_activate_IRQ_rcvd_sn2(void)
1147{
1148	unsigned long irq_flags;
1149	int n_IRQs_expected;
1150	int n_IRQs_detected;
1151
1152	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1153	n_IRQs_expected = xpc_activate_IRQ_rcvd;
1154	xpc_activate_IRQ_rcvd = 0;
1155	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1156
1157	n_IRQs_detected = xpc_identify_activate_IRQ_sender_sn2();
1158	if (n_IRQs_detected < n_IRQs_expected) {
1159		/* retry once to help avoid missing amo */
1160		(void)xpc_identify_activate_IRQ_sender_sn2();
1161	}
1162}
1163
1164/*
1165 * Setup the channel structures that are sn2 specific.
1166 */
1167static enum xp_retval
1168xpc_setup_ch_structures_sn2(struct xpc_partition *part)
1169{
1170	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1171	struct xpc_channel_sn2 *ch_sn2;
1172	enum xp_retval retval;
1173	int ret;
1174	int cpuid;
1175	int ch_number;
1176	struct timer_list *timer;
1177	short partid = XPC_PARTID(part);
1178
1179	/* allocate all the required GET/PUT values */
1180
1181	part_sn2->local_GPs =
1182	    xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
1183					  &part_sn2->local_GPs_base);
1184	if (part_sn2->local_GPs == NULL) {
1185		dev_err(xpc_chan, "can't get memory for local get/put "
1186			"values\n");
1187		return xpNoMemory;
1188	}
1189
1190	part_sn2->remote_GPs =
1191	    xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
1192					  &part_sn2->remote_GPs_base);
1193	if (part_sn2->remote_GPs == NULL) {
1194		dev_err(xpc_chan, "can't get memory for remote get/put "
1195			"values\n");
1196		retval = xpNoMemory;
1197		goto out_1;
1198	}
1199
1200	part_sn2->remote_GPs_pa = 0;
1201
1202	/* allocate all the required open and close args */
1203
1204	part_sn2->local_openclose_args =
1205	    xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
1206					  GFP_KERNEL, &part_sn2->
1207					  local_openclose_args_base);
1208	if (part_sn2->local_openclose_args == NULL) {
1209		dev_err(xpc_chan, "can't get memory for local connect args\n");
1210		retval = xpNoMemory;
1211		goto out_2;
1212	}
1213
1214	part_sn2->remote_openclose_args_pa = 0;
1215
1216	part_sn2->local_chctl_amo_va = xpc_init_IRQ_amo_sn2(partid);
1217
1218	part_sn2->notify_IRQ_nasid = 0;
1219	part_sn2->notify_IRQ_phys_cpuid = 0;
1220	part_sn2->remote_chctl_amo_va = NULL;
1221
1222	sprintf(part_sn2->notify_IRQ_owner, "xpc%02d", partid);
1223	ret = request_irq(SGI_XPC_NOTIFY, xpc_handle_notify_IRQ_sn2,
1224			  IRQF_SHARED, part_sn2->notify_IRQ_owner,
1225			  (void *)(u64)partid);
1226	if (ret != 0) {
1227		dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
1228			"errno=%d\n", -ret);
1229		retval = xpLackOfResources;
1230		goto out_3;
1231	}
1232
1233	/* Setup a timer to check for dropped notify IRQs */
1234	timer = &part_sn2->dropped_notify_IRQ_timer;
1235	init_timer(timer);
1236	timer->function =
1237	    (void (*)(unsigned long))xpc_check_for_dropped_notify_IRQ_sn2;
1238	timer->data = (unsigned long)part;
1239	timer->expires = jiffies + XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
1240	add_timer(timer);
1241
1242	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
1243		ch_sn2 = &part->channels[ch_number].sn.sn2;
1244
1245		ch_sn2->local_GP = &part_sn2->local_GPs[ch_number];
1246		ch_sn2->local_openclose_args =
1247		    &part_sn2->local_openclose_args[ch_number];
1248
1249		mutex_init(&ch_sn2->msg_to_pull_mutex);
1250	}
1251
1252	/*
1253	 * Setup the per partition specific variables required by the
1254	 * remote partition to establish channel connections with us.
1255	 *
1256	 * The setting of the magic # indicates that these per partition
1257	 * specific variables are ready to be used.
1258	 */
1259	xpc_vars_part_sn2[partid].GPs_pa = xp_pa(part_sn2->local_GPs);
1260	xpc_vars_part_sn2[partid].openclose_args_pa =
1261	    xp_pa(part_sn2->local_openclose_args);
1262	xpc_vars_part_sn2[partid].chctl_amo_pa =
1263	    xp_pa(part_sn2->local_chctl_amo_va);
1264	cpuid = raw_smp_processor_id();	/* any CPU in this partition will do */
1265	xpc_vars_part_sn2[partid].notify_IRQ_nasid = cpuid_to_nasid(cpuid);
1266	xpc_vars_part_sn2[partid].notify_IRQ_phys_cpuid =
1267	    cpu_physical_id(cpuid);
1268	xpc_vars_part_sn2[partid].nchannels = part->nchannels;
1269	xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC1_SN2;
1270
1271	return xpSuccess;
1272
1273	/* setup of ch structures failed */
1274out_3:
1275	kfree(part_sn2->local_openclose_args_base);
1276	part_sn2->local_openclose_args = NULL;
1277out_2:
1278	kfree(part_sn2->remote_GPs_base);
1279	part_sn2->remote_GPs = NULL;
1280out_1:
1281	kfree(part_sn2->local_GPs_base);
1282	part_sn2->local_GPs = NULL;
1283	return retval;
1284}
1285
1286/*
1287 * Teardown the channel structures that are sn2 specific.
1288 */
1289static void
1290xpc_teardown_ch_structures_sn2(struct xpc_partition *part)
1291{
1292	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1293	short partid = XPC_PARTID(part);
1294
1295	/*
1296	 * Indicate that the variables specific to the remote partition are no
1297	 * longer available for its use.
1298	 */
1299	xpc_vars_part_sn2[partid].magic = 0;
1300
1301	/* in case we've still got outstanding timers registered... */
1302	del_timer_sync(&part_sn2->dropped_notify_IRQ_timer);
1303	free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
1304
1305	kfree(part_sn2->local_openclose_args_base);
1306	part_sn2->local_openclose_args = NULL;
1307	kfree(part_sn2->remote_GPs_base);
1308	part_sn2->remote_GPs = NULL;
1309	kfree(part_sn2->local_GPs_base);
1310	part_sn2->local_GPs = NULL;
1311	part_sn2->local_chctl_amo_va = NULL;
1312}
1313
1314/*
1315 * Create a wrapper that hides the underlying mechanism for pulling a cacheline
1316 * (or multiple cachelines) from a remote partition.
1317 *
1318 * src_pa must be a cacheline aligned physical address on the remote partition.
1319 * dst must be a cacheline aligned virtual address on this partition.
1320 * cnt must be cacheline sized
1321 */
1322/* ??? Replace this function by call to xp_remote_memcpy() or bte_copy()? */
1323static enum xp_retval
1324xpc_pull_remote_cachelines_sn2(struct xpc_partition *part, void *dst,
1325			       const unsigned long src_pa, size_t cnt)
1326{
1327	enum xp_retval ret;
1328
1329	DBUG_ON(src_pa != L1_CACHE_ALIGN(src_pa));
1330	DBUG_ON((unsigned long)dst != L1_CACHE_ALIGN((unsigned long)dst));
1331	DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
1332
1333	if (part->act_state == XPC_P_AS_DEACTIVATING)
1334		return part->reason;
1335
1336	ret = xp_remote_memcpy(xp_pa(dst), src_pa, cnt);
1337	if (ret != xpSuccess) {
1338		dev_dbg(xpc_chan, "xp_remote_memcpy() from partition %d failed,"
1339			" ret=%d\n", XPC_PARTID(part), ret);
1340	}
1341	return ret;
1342}
1343
1344/*
1345 * Pull the remote per partition specific variables from the specified
1346 * partition.
1347 */
1348static enum xp_retval
1349xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1350{
1351	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1352	u8 buffer[L1_CACHE_BYTES * 2];
1353	struct xpc_vars_part_sn2 *pulled_entry_cacheline =
1354	    (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer);
1355	struct xpc_vars_part_sn2 *pulled_entry;
1356	unsigned long remote_entry_cacheline_pa;
1357	unsigned long remote_entry_pa;
1358	short partid = XPC_PARTID(part);
1359	enum xp_retval ret;
1360
1361	/* pull the cacheline that contains the variables we're interested in */
1362
1363	DBUG_ON(part_sn2->remote_vars_part_pa !=
1364		L1_CACHE_ALIGN(part_sn2->remote_vars_part_pa));
1365	DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2);
1366
1367	remote_entry_pa = part_sn2->remote_vars_part_pa +
1368	    sn_partition_id * sizeof(struct xpc_vars_part_sn2);
1369
1370	remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
1371
1372	pulled_entry = (struct xpc_vars_part_sn2 *)((u64)pulled_entry_cacheline
1373						    + (remote_entry_pa &
1374						    (L1_CACHE_BYTES - 1)));
1375
1376	ret = xpc_pull_remote_cachelines_sn2(part, pulled_entry_cacheline,
1377					     remote_entry_cacheline_pa,
1378					     L1_CACHE_BYTES);
1379	if (ret != xpSuccess) {
1380		dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
1381			"partition %d, ret=%d\n", partid, ret);
1382		return ret;
1383	}
1384
1385	/* see if they've been set up yet */
1386
1387	if (pulled_entry->magic != XPC_VP_MAGIC1_SN2 &&
1388	    pulled_entry->magic != XPC_VP_MAGIC2_SN2) {
1389
1390		if (pulled_entry->magic != 0) {
1391			dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
1392				"partition %d has bad magic value (=0x%llx)\n",
1393				partid, sn_partition_id, pulled_entry->magic);
1394			return xpBadMagic;
1395		}
1396
1397		/* they've not been initialized yet */
1398		return xpRetry;
1399	}
1400
1401	if (xpc_vars_part_sn2[partid].magic == XPC_VP_MAGIC1_SN2) {
1402
1403		/* validate the variables */
1404
1405		if (pulled_entry->GPs_pa == 0 ||
1406		    pulled_entry->openclose_args_pa == 0 ||
1407		    pulled_entry->chctl_amo_pa == 0) {
1408
1409			dev_err(xpc_chan, "partition %d's XPC vars_part for "
1410				"partition %d are not valid\n", partid,
1411				sn_partition_id);
1412			return xpInvalidAddress;
1413		}
1414
1415		/* the variables we imported look to be valid */
1416
1417		part_sn2->remote_GPs_pa = pulled_entry->GPs_pa;
1418		part_sn2->remote_openclose_args_pa =
1419		    pulled_entry->openclose_args_pa;
1420		part_sn2->remote_chctl_amo_va =
1421		    (struct amo *)__va(pulled_entry->chctl_amo_pa);
1422		part_sn2->notify_IRQ_nasid = pulled_entry->notify_IRQ_nasid;
1423		part_sn2->notify_IRQ_phys_cpuid =
1424		    pulled_entry->notify_IRQ_phys_cpuid;
1425
1426		if (part->nchannels > pulled_entry->nchannels)
1427			part->nchannels = pulled_entry->nchannels;
1428
1429		/* let the other side know that we've pulled their variables */
1430
1431		xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC2_SN2;
1432	}
1433
1434	if (pulled_entry->magic == XPC_VP_MAGIC1_SN2)
1435		return xpRetry;
1436
1437	return xpSuccess;
1438}
1439
1440/*
1441 * Establish first contact with the remote partititon. This involves pulling
1442 * the XPC per partition variables from the remote partition and waiting for
1443 * the remote partition to pull ours.
1444 */
1445static enum xp_retval
1446xpc_make_first_contact_sn2(struct xpc_partition *part)
1447{
1448	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1449	enum xp_retval ret;
1450
1451	/*
1452	 * Register the remote partition's amos with SAL so it can handle
1453	 * and cleanup errors within that address range should the remote
1454	 * partition go down. We don't unregister this range because it is
1455	 * difficult to tell when outstanding writes to the remote partition
1456	 * are finished and thus when it is safe to unregister. This should
1457	 * not result in wasted space in the SAL xp_addr_region table because
1458	 * we should get the same page for remote_amos_page_pa after module
1459	 * reloads and system reboots.
1460	 */
1461	if (sn_register_xp_addr_region(part_sn2->remote_amos_page_pa,
1462				       PAGE_SIZE, 1) < 0) {
1463		dev_warn(xpc_part, "xpc_activating(%d) failed to register "
1464			 "xp_addr region\n", XPC_PARTID(part));
1465
1466		ret = xpPhysAddrRegFailed;
1467		XPC_DEACTIVATE_PARTITION(part, ret);
1468		return ret;
1469	}
1470
1471	/*
1472	 * Send activate IRQ to get other side to activate if they've not
1473	 * already begun to do so.
1474	 */
1475	xpc_send_activate_IRQ_sn2(part_sn2->remote_amos_page_pa,
1476				  cnodeid_to_nasid(0),
1477				  part_sn2->activate_IRQ_nasid,
1478				  part_sn2->activate_IRQ_phys_cpuid);
1479
1480	while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
1481		if (ret != xpRetry) {
1482			XPC_DEACTIVATE_PARTITION(part, ret);
1483			return ret;
1484		}
1485
1486		dev_dbg(xpc_part, "waiting to make first contact with "
1487			"partition %d\n", XPC_PARTID(part));
1488
1489		/* wait a 1/4 of a second or so */
1490		(void)msleep_interruptible(250);
1491
1492		if (part->act_state == XPC_P_AS_DEACTIVATING)
1493			return part->reason;
1494	}
1495
1496	return xpSuccess;
1497}
1498
1499/*
1500 * Get the chctl flags and pull the openclose args and/or remote GPs as needed.
1501 */
1502static u64
1503xpc_get_chctl_all_flags_sn2(struct xpc_partition *part)
1504{
1505	struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1506	unsigned long irq_flags;
1507	union xpc_channel_ctl_flags chctl;
1508	enum xp_retval ret;
1509
1510	/*
1511	 * See if there are any chctl flags to be handled.
1512	 */
1513
1514	spin_lock_irqsave(&part->chctl_lock, irq_flags);
1515	chctl = part->chctl;
1516	if (chctl.all_flags != 0)
1517		part->chctl.all_flags = 0;
1518
1519	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
1520
1521	if (xpc_any_openclose_chctl_flags_set(&chctl)) {
1522		ret = xpc_pull_remote_cachelines_sn2(part, part->
1523						     remote_openclose_args,
1524						     part_sn2->
1525						     remote_openclose_args_pa,
1526						     XPC_OPENCLOSE_ARGS_SIZE);
1527		if (ret != xpSuccess) {
1528			XPC_DEACTIVATE_PARTITION(part, ret);
1529
1530			dev_dbg(xpc_chan, "failed to pull openclose args from "
1531				"partition %d, ret=%d\n", XPC_PARTID(part),
1532				ret);
1533
1534			/* don't bother processing chctl flags anymore */
1535			chctl.all_flags = 0;
1536		}
1537	}
1538
1539	if (xpc_any_msg_chctl_flags_set(&chctl)) {
1540		ret = xpc_pull_remote_cachelines_sn2(part, part_sn2->remote_GPs,
1541						     part_sn2->remote_GPs_pa,
1542						     XPC_GP_SIZE);
1543		if (ret != xpSuccess) {
1544			XPC_DEACTIVATE_PARTITION(part, ret);
1545
1546			dev_dbg(xpc_chan, "failed to pull GPs from partition "
1547				"%d, ret=%d\n", XPC_PARTID(part), ret);
1548
1549			/* don't bother processing chctl flags anymore */
1550			chctl.all_flags = 0;
1551		}
1552	}
1553
1554	return chctl.all_flags;
1555}
1556
1557/*
1558 * Allocate the local message queue and the notify queue.
1559 */
1560static enum xp_retval
1561xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
1562{
1563	struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1564	unsigned long irq_flags;
1565	int nentries;
1566	size_t nbytes;
1567
1568	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
1569
1570		nbytes = nentries * ch->entry_size;
1571		ch_sn2->local_msgqueue =
1572		    xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL,
1573						  &ch_sn2->local_msgqueue_base);
1574		if (ch_sn2->local_msgqueue == NULL)
1575			continue;
1576
1577		nbytes = nentries * sizeof(struct xpc_notify_sn2);
1578		ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL);
1579		if (ch_sn2->notify_queue == NULL) {
1580			kfree(ch_sn2->local_msgqueue_base);
1581			ch_sn2->local_msgqueue = NULL;
1582			continue;
1583		}
1584
1585		spin_lock_irqsave(&ch->lock, irq_flags);
1586		if (nentries < ch->local_nentries) {
1587			dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
1588				"partid=%d, channel=%d\n", nentries,
1589				ch->local_nentries, ch->partid, ch->number);
1590
1591			ch->local_nentries = nentries;
1592		}
1593		spin_unlock_irqrestore(&ch->lock, irq_flags);
1594		return xpSuccess;
1595	}
1596
1597	dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
1598		"queue, partid=%d, channel=%d\n", ch->partid, ch->number);
1599	return xpNoMemory;
1600}
1601
1602/*
1603 * Allocate the cached remote message queue.
1604 */
1605static enum xp_retval
1606xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
1607{
1608	struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1609	unsigned long irq_flags;
1610	int nentries;
1611	size_t nbytes;
1612
1613	DBUG_ON(ch->remote_nentries <= 0);
1614
1615	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
1616
1617		nbytes = nentries * ch->entry_size;
1618		ch_sn2->remote_msgqueue =
1619		    xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2->
1620						  remote_msgqueue_base);
1621		if (ch_sn2->remote_msgqueue == NULL)
1622			continue;
1623
1624		spin_lock_irqsave(&ch->lock, irq_flags);
1625		if (nentries < ch->remote_nentries) {
1626			dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
1627				"partid=%d, channel=%d\n", nentries,
1628				ch->remote_nentries, ch->partid, ch->number);
1629
1630			ch->remote_nentries = nentries;
1631		}
1632		spin_unlock_irqrestore(&ch->lock, irq_flags);
1633		return xpSuccess;
1634	}
1635
1636	dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
1637		"partid=%d, channel=%d\n", ch->partid, ch->number);
1638	return xpNoMemory;
1639}
1640
1641/*
1642 * Allocate message queues and other stuff associated with a channel.
1643 *
1644 * Note: Assumes all of the channel sizes are filled in.
1645 */
1646static enum xp_retval
1647xpc_setup_msg_structures_sn2(struct xpc_channel *ch)
1648{
1649	struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1650	enum xp_retval ret;
1651
1652	DBUG_ON(ch->flags & XPC_C_SETUP);
1653
1654	ret = xpc_allocate_local_msgqueue_sn2(ch);
1655	if (ret == xpSuccess) {
1656
1657		ret = xpc_allocate_remote_msgqueue_sn2(ch);
1658		if (ret != xpSuccess) {
1659			kfree(ch_sn2->local_msgqueue_base);
1660			ch_sn2->local_msgqueue = NULL;
1661			kfree(ch_sn2->notify_queue);
1662			ch_sn2->notify_queue = NULL;
1663		}
1664	}
1665	return ret;
1666}
1667
1668/*
1669 * Free up message queues and other stuff that were allocated for the specified
1670 * channel.
1671 */
1672static void
1673xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
1674{
1675	struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1676
1677	DBUG_ON(!spin_is_locked(&ch->lock));
1678
1679	ch_sn2->remote_msgqueue_pa = 0;
1680
1681	ch_sn2->local_GP->get = 0;
1682	ch_sn2->local_GP->put = 0;
1683	ch_sn2->remote_GP.get = 0;
1684	ch_sn2->remote_GP.put = 0;
1685	ch_sn2->w_local_GP.get = 0;
1686	ch_sn2->w_local_GP.put = 0;
1687	ch_sn2->w_remote_GP.get = 0;
1688	ch_sn2->w_remote_GP.put = 0;
1689	ch_sn2->next_msg_to_pull = 0;
1690
1691	if (ch->flags & XPC_C_SETUP) {
1692		dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
1693			ch->flags, ch->partid, ch->number);
1694
1695		kfree(ch_sn2->local_msgqueue_base);
1696		ch_sn2->local_msgqueue = NULL;
1697		kfree(ch_sn2->remote_msgqueue_base);
1698		ch_sn2->remote_msgqueue = NULL;
1699		kfree(ch_sn2->notify_queue);
1700		ch_sn2->notify_queue = NULL;
1701	}
1702}
1703
1704/*
1705 * Notify those who wanted to be notified upon delivery of their message.
1706 */
1707static void
1708xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
1709{
1710	struct xpc_notify_sn2 *notify;
1711	u8 notify_type;
1712	s64 get = ch->sn.sn2.w_remote_GP.get - 1;
1713
1714	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
1715
1716		notify = &ch->sn.sn2.notify_queue[get % ch->local_nentries];
1717
1718		/*
1719		 * See if the notify entry indicates it was associated with
1720		 * a message who's sender wants to be notified. It is possible
1721		 * that it is, but someone else is doing or has done the
1722		 * notification.
1723		 */
1724		notify_type = notify->type;
1725		if (notify_type == 0 ||
1726		    cmpxchg(&notify->type, notify_type, 0) != notify_type) {
1727			continue;
1728		}
1729
1730		DBUG_ON(notify_type != XPC_N_CALL);
1731
1732		atomic_dec(&ch->n_to_notify);
1733
1734		if (notify->func != NULL) {
1735			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p "
1736				"msg_number=%lld partid=%d channel=%d\n",
1737

Large files files are truncated, but you can click here to view the full file